Originally published on: Sun, 08 Nov 2009 17:24:55 +0000
I've recently begun to use TRS-80 Model I emulators to recapture some of the programming experiences of my younger days. The emulator I'm currently using under Windows is trs80gp which can be found here:
http://members.shaw.ca/gp2000/trs80gp.html
I invoke the emulator with the command-line parameters -m1 to force Model I emulation and -na for non-authentic display.
While trs80gp does not support any of the Disk-Operating-Systems of yesteryear, it does provide a menu option that will load /CMD executable files and BASIC files. You really can't save any information back to the Windows filesystem, but that's okay. For my purposes, I want to write some programs in a cross-assembler or cross-compiler environment and will just load the files to try them out. At some point, I will either look for or will build a utility that will tokenize a text listing to a BASIC listing so that I can create BASIC programs as well.
My initial goal, however, is to write Z-80 code and run it on the emulator.
My first task was to find a cross-assembler for the Z-80 that would run under Windows. The trs80gp site references ZMac which sounds like a great editor, but it doesn't appear to compile in its current form under Windows.
I found a utility called Pasmo here:
http://www.arrakis.es/~ninsesabe/pasmo/
Like some of the others I tried, Pasmo basically generates a binary machine-image file. I chose Pasmo because of the -d option which shows an assembly listing on the standard output device.
I would like to be able to package up anything I write into a standard /CMD file so that it can be used with other emulators or on the real hardware itself. In order to do that, I was going to have to determine how to convert a machine-image file into a /CMD file.
As a test program, I would use the example routine I published in my post http://www.mailsend-online.com/blog?p=54. That routine fills the video memory with the all-white character (191) and then returns.
I have several /CMD images of games that I have on cassette and began looking through them. I could see some control-codes and such, but my initial stab at trying to interpret them was not successful. After a little searching on the web, I found a reference to an article from The LDOS Journal volume 1, issue 4. Tim Mann has copies of this issue and others on his site here:
http://www.tim-mann.org/misosys.html
The article that describes the format is in the column Roy's Technical Corner.
Roy describes the record formats permissible in a /CMD file. The format is not unlike the binary tag-based system used in the TIFF graphical image file format. The first byte one encounters is a record-type byte. The next byte is a length of bytes that will follow ... sort of. The remainder of bytes should match the length specified in the length byte. The next record in sequence should be another record ID / length / payload sequence, but that doesn't seem to hold true either.
I wrote a short C program readcmd.exe that lists each record in a /CMD file. While number of my /CMD files parsed correctly just fine, some did not.
Roy explains that the 01 record indicates a loadable block of binary data. The length byte in many of my /CMD files was zero, which I correctly assumed would yield a 256-byte block. However some of the /CMD files in my possession use a value of two in the length byte and seem to have a payload bigger than two bytes in length.
The article further explains that each loadable block of data first contains a load-address and states that zero and one are special values that indicate a two-byte load-address will be followed by 254 and 255 bytes of data respectively. The article doesn't mention the value two, but I assume that since the 01 record will always have a load-address, two bytes will always follow. The values zero, one, and two are then used for machine-images of size 254, 255, and 256 respectively. The value three is a complete mystery to me. I have seen a small block with a length of four and the payload that follows the load-address is four bytes in length. I'll tinker later and see how the emulators load a record with a length value of three.
I should state that my readcmd program is dependent on the Intel representation of a 16-bit integer ( Least Significant Byte followed by Most Significant Byte ). An unsigned short integer must be 16-bits in width in order for the program below to run correctly.
readcmd.c
I found that after the 02 record is encountered, all kinds of garbage data can follow. I assume that most /CMD loaders halt interpretation of the file after the 02 record is encountered. You'll notice a break out of the main input loop when readcmd encounters this record.
My readcmd program was able to parse through all of the /CMD files in my possession. Now that I have a way to verify the correctness of a /CMD file, it's time to try and build my own.
I really can't remember where the first bytes of free memory really start on a Model I. Address 17129 looks to be the spot where BASIC begins, but I've never owned a DOS on a Model I, so I don't know if that address can change.
I noticed that a lot of the games I have begin at address 6C00H, so I chose that as the starting-address for my program.
Here is the slightly modified source code from my prior post:
fill.asm
I then assembled it with the command: pasmo -d fill.asm fill.out The output from Pasmo is as follows:
My load-module is fifteen bytes in size. I need to create a load-record that accommodates fifteen plus two bytes for the load address. My 01 record will have a length of seventeen ( or 11H ) bytes. Here's how the 01 record should look in hex:
The total space occupied by the 01 record is nineteen bytes.
I then needed to add a 02 record to state the transfer address of 6C00H:
The total size of the two records is twenty-three (17H) bytes in length.
I manually created the /CMD file using the Windows console DEBUG utility.
I first used readcmd to ascertain that the records looked reasonable: readcmd fill.cmd
I loaded fill.cmd in trs80gp and it correctly filled the screen with whitespace.
I had expected the RET instruction to drop me back into BASIC, but it did not. I'm not sure if that's an idiosyncrasy of trs80gp or if all emulators and the actual hardware/software will behave in this manner. ( NOTE: after fixing my code to use 1023 bytes to move instead of 4095 as George Phillips, author of trs80gp notes in the comments to the post, I did indeed drop into BASIC, but received a ?SN ERROR message at the prompt. I may try George's suggestion of JP-ing to 1A19H at a later time. )
In the near future, I will write a program that will convert a larger memory-image file ( such as the one produced by Pasmo ) into a /CMD file.
The source and EXE files for readcmd can be found here, along with the source and /CMD file for the fill program.
http://www.mailsend-online.com/wp/readcmd.zip
Unless otherwise noted, all code and text entries are Copyright ©2009 by James K. Lawless
Save to del.icio.us
Save to StumbleUpon
Digg it
Save to Reddit
Share on Facebook
Share on Twitter
More bookmarks
Subscribe!
Auto Save Clipboard Images Redux
Extending SpiderMonkey JavaScript on Windows
Rhino JavaScript to EXE with launch4j
Compiling Rhino JavaScript to Java
Directory Traversal in Rhino JavaScript
A Command-Line MP3 Player for Windows
Auto Save Images from the Clipboard
Java in a Windows EXE with launch4j
An Interview with Tom Zimmer: Forth System Developer
Setting Windows Console Text Colors in C
Speeding up JRuby with NailGun
JRuby as a Java Obfuscation Utility
Yet Another Enhanced Echo Command
Extending SpiderMonkey JavaScript on Windows
An Interview with Brad Templeton
MicroISV on a Shoestring
DadHacker
The Bottom Feeder
Writin' That Code!
The Recursive ISV
The Thomsen Blog
Prototypically Speaking
The Reinvigorated Programmer