• Please review our updated Terms and Rules here

IBM 5150 Cassette Generation

The offset of 100h in .COM files leaves room for the PSP goodies, including default FCBs and the command line tail buffer. This was done to make the conversion from CP/M .COM files as painless as possible. You'll even note that the PSP has a hook so that you can invoke the DOS API by putting the function in CL and doing a jump to 0005h, just like CP/M-80. Similarly a .COM program can terminate by jumping to 0000h, just like CP/M-80.
 
Since no commercial program was ever made available on cassette, other than IBM Cassette Diagnostics,

Actually this is not accurate. Aside from the two diagnostic programs (regular and advanced diagnostics) the program Typing Tutor was also available for purchase on tape. You can find a discussion on it here. There is a question as to if the program was actually ever produced on tape but marketing material was definitely out there. There is also mention of a game that ran off of disk but allowed you to save your data on to tape.
 
Last edited:
I finally got time to try out these Python scripts. SHORT VERSION: They worked :)


So here goes my story...



I was trying to understand what happened to Wheel of Fortune 1. We still enjoy playing Wheel of Fortune 2, as it works with CGA and 256KB RAM systems. I'm still trying to understand how, by 1988, WOF2 was still a CGA game. WOF3 finally went EGA, but still neglected any Adlib/SB support (and anyhow runs too slow for my 4.77mhz, so we stick with WOF2).

Apparently there WAS an earlier WOF from 1987, from Sharedata - with roughly the same gameplay/style as WOF2, but even WORSE (more orange) graphics. So, WOF2 is the best.


And then.... I came across what I will call WOF0. The "original" 1984 "text-based" WOF written by Phil Katz (yes, of PKZIP). And it was written in BASIC.


So then it hit me: what a perfect time to test this BASIC to WAV conversion Python script. Which, incidentally, I knew this WOF0 wouldn't run from ROM BASIC -- because it references an external file to get all the categories and puzzles. This .BAS was intended for use by BASICA.COM. Still, it is basically just a text file, so I decided to try it out.


So here we go:
(and yes, I installed Python 3....)


F:\IBMPC\GAMEs\WHEEL_OF_FORTUNE\WOF0>asciiwrite.py fortune.bas test.wav
255 bytes written.
510 bytes written.
...
7650 bytes written.
7905 bytes written.
End of file reached.
8103 bytes written. <-- this checks out, that's the size of the BAS file.
(this resulted in a 11.5MB WAV file)


Then, while I was at it, I also decided to try the same experiment I did with 5150caxx and use the other script to write PTROOPER.COM.

(to keep example simple, I previously copied the PTROOPER.COM file into this same WOF0 working directory)

F:\IBMPC\GAMEs\WHEEL_OF_FORTUNE\WOF0>binwrite.py ptrooper.com ptrooper.tap 0 0
Silence finished at 0:00:03.496636
Basic header finished at 0:00:04.809484
Written bytes: 256
Written bytes: 512
Written bytes: 768
...
Written bytes: 16128
Written bytes: 16384 <-- ok, checks out, same size as the .COM file
Finished at 0:01:48.548295
(this resulted in a 7.8MB WAV file)



I then brought the TRS-80 cassette recorder to the (modern) PC. Double checked things, it was recording the WAV files out of the headphone jack just fine.


SIDEBAR:
krebizfan

While I was at it, I decided to also record the two WAV files archon11k25.wav and bdash11k25.wav that were referenced here
Basically, quick story on this is that neither of these two WAVs worked for me. ROM BASIC just said "Device Error" when trying to load. When I inspected the raw data using 5150caxx, it just loaded a 256 byte header and said there was some CRC error (and this header didn't look quite right to me). Are these PCjr-only games? (although I wouldn't expect the ROM BASIC for the PCjr to not really be different - in terms of how BASIC loads and saves; I'd understand if the game didn't run, but it still should have loaded something). Anyhow, no luck for me on these particular WAV files.



Results:

(#1 PTROOPER binary)
So... I tried loading PTROOPER first, from the WAV recording created by binwrite.py. I was bummed because at first it didn't work. I even loaded the binary package using 5150caxx, and it reconstructed the .COM just fine. So I felt like the data was there, it was very close.... Then I figured it out: I was loading at offset decimal 100 instead of hex 100 (i.e. should have been loading at offset decimal 256).

So, upon creating the WAV using Python, and physically recording it to a tape at 1:1 real time playback.... Then here is what I had to do, to load that binary back using ROM BASIC:
def seg=&H2000 ' I just picked a segment, I'm not sure if it really matters which one
bload " ",256 ' this is where I went wrong, I was using ,100 instead of ,256
(press play on tape, wait for ptrooper.M to be found)
A=256 ' set some variable to the starting offset ($100 or &H100 or 0x100 = decimal 256, for most .COM programs)
call A

Brilliant, this is essentially how we do it on the Commodore PET from '77 ;) (just in the PET the command is SYS instead of CALL).


Click image for larger version  Name:	IMG_7263A.jpg Views:	0 Size:	233.0 KB ID:	1222952

Boom! It passed execution to the binary that was loaded into memory, and Paratrooper was up and running via ROM BASIC loaded from a tape. That's a bit exciting, except I have to say that I still like the 5150caxx 32-byte pre-loader a bit better (just avoids having to do a CALL).




(#2 fortune.bas)
Next I tried the FORTUNE BASIC program that was recorded to the tape via the WAV created by the asciiwrite.py script (sorry, I still call them scripts, not programs :p ).


Click image for larger version  Name:	IMG_7162A.jpg Views:	0 Size:	155.8 KB ID:	1222953

And that worked too! I can tell you, for sure I didn't type this ~200 lines of BASIC myself. As expected, it didn't run - LINE 40 works, that's about it. It does an OPEN statement right after that, so the program eventually just times out ("Device Not Found" or something). So that's pretty cool too.

Only observation I have is: while loading the BASIC program, the Cassette relay clicked quite a few times - is the program saved in "chunks" of like 500 bytes? Not sure if there was any actual pause in the playback, but I could certainly hear the clicks.


Click image for larger version  Name:	IMG_7167A.jpg Views:	0 Size:	168.3 KB ID:	1222955








So that's pretty neat, Python to make WAV files that are recordable and loadable.


5150caxx is a little more "seamless" in that it can encode a file directly to tape, pre-fixed with an appropriate "pre-loader" so you don't really have to think about how to load it -- you just do load " ",r and go. And that it runs directly in "real-mode" as a DOS program (essentially use the BIOS ROM as its API for doing the actual audio output). I'm up to about 20 .COM programs recorded to tape and verified reloadable from tape.


I guess only one thing left for me to try: will it load using my iPhone as playback instead of that massive TRS-80 tape deck? :) Need to find a place to host a 10MB WAV file, hmm....

EDIT: Answer, yes it does (load when playedback from phone). WAV is hosted here until I'm forced to move it. Don't need a DOS, just x86 it up and go ;)
 

Attachments

  • IMG_7263A.jpg
    IMG_7263A.jpg
    233 KB · Views: 1
  • IMG_7167A.jpg
    IMG_7167A.jpg
    168.3 KB · Views: 1
Last edited:
It looks like Wheel of Fortune is using a BASIC data file. IIRC, BASIC stops the cassette after each data block (256 bytes) is read and restarts the cassette to read the next block once an Input command accesses data in the next block. This works well with classic BASIC programs that do a lot of processing on each record before moving to the next but is quite inefficient with bulk data reads.

Boulder Dash and Archon are IBM PC CGA games. Other than Boulder Dash needing 128K, they seem fairly standard. The WAV should have two files: the short BASIC stub that loads the longer game file. I am not sure what went wrong.
 
I see, ",B" loads in the 256 blocks fashion? (as opposed to something that's ",M") None of the BASIC ROM assembly code was ever released, is that right? (was curious to verify the load code)



AND... I got BDASH and ARCHON working! I loaded them using the phone instead of the TRS-80 tape deck.


I've saved and loaded-back (and ran successfully) ~20 .COM programs now, using 5150caxx. So I don't think there is a real issue with that process, or the tape deck equipment, or the tapes themselves (new tapes).

I was wondering why the Python generated WAVs were so much larger (~8mb) than the BDASH and ARCHON WAVs (~2mb).


If the file details are correct, BDASH and ARCHON are 88kbps bitrate. (worked playing out of iPhone headphone jack into EAR jack of the 5-pin DIN cassette port -- but you have to manually pause the playback after the initial ".B" loader is finished, then do "run" and then resume the playback {luckily the player shows the little blank between these two data streams, to help know where to stop})

Whereas the WAVs generated by the Python scripts are reported as 705kbps bitrate. (these worked, playing from modern PC headphone into the MIC jack of the TRS-80 tape deck, then loaded in ROM BASIC from said TRS-80 tape)



So, all good. The BDASH and ARCHON programs work a little differently than .COM files (by executing from offset 0 instead of 256 -- which I suppose a true "auto boot loader" would?). But the WAV quality might be insufficient for physical audio tape?



EDIT: I don't think Flightsimulator 1.0 from tape will work. Or at least, not at all straight forward. While it can run with 64KB RAM system, the IMG file has a lot of disjointed data streams. We'd have to figure which stream goes into which segment and make quite a custom loader for it. We also have to see if the game accesses the disk at any time after it is loaded, to see if it is dynamically initializing segments at any time -- if it doesn't and it iniitializes all the segments in one go, then there might be a chance.




Click image for larger version  Name:	IMG_7273A.jpg Views:	0 Size:	138.4 KB ID:	1223051 Click image for larger version  Name:	IMG_7277A.jpg Views:	0 Size:	141.9 KB ID:	1223052
 
Last edited:
deanimator

Shadow Lord





I've finished an article and notes to summarize all my "findings" about the IBM PC cassette port.

5150: Setting up Tape Deck Connection (because the 5150 can)

https://voidstar.blog/5150-setting-u...-the-5150-can/

Contents, for future reference

Significance of the IBM PC 5150 Tape Support
History of IBM PC Cassette Software Support
Introduction to the Cassette Port of the IBM PC 5150
How to Encode a .COM to Tape Using 5150CAXX.EXE
How to Load a .COM that was Saved Using 5150CAXX
Using Python to Make Tape Loadable Binaries
EXAMPLE 1: Using ASCII (BASIC) [ asciiwrite.py ]
Saving WAV to Tape: Using TRS-80 Tape Deck (or similar)
To LOAD this ASCII (BASIC) file into IBM PC 5150 ROM BASIC
EXAMPLE 2: Using binary [ binwrite.py ]
To BLOAD this binary data or program using 5150 ROM BASIC
Playing BDASH and ARCHON from WAV (using smartphone)
Successful .COM to Tape Conversions


(not meant as a historical document, just reference notes on how some of this stuff works in case anyone else wants to try)
 
This has been ported to C++. The executables are available on github for both windows and linux. The functionality is incredibly similar, except much faster.
 
Back
Top