Close

Minor Cassette Enhancement

A project log for TRS-80 Model 1 on a PIC32

TRS-80 Model I emulated on a PIC32MX processor; VGA, PS/2, and SD for tape and disk images. Oh, and glourious cassette sound.

ziggurat29ziggurat29 05/06/2018 at 14:460 Comments

The cassette I/O functionality has, since the beginning, been realized with traps in the ROM routines that are serviced on the host side of the emulator.  This saved me the trouble of trying to emulate the pulses with the correct timing for the Z-80 code, and had the side benefit of being some 160x faster than native cassette.

A user had reported that EDTASM did not seem to do anything useful when trying to save and load programs from the cassette, and it was hypothesized that it might be doing it's own I/O directly, without using the ROM routines (and thereby my traps did no good).  A quick disassembly verified that this was the case.  In fact, it also has it's own copies of the keyboard, video, and printer device drivers, and it doesn't use any ROM routines!

Upon closer inspection of the disassembly, I noticed that the routines were very similar to the same ones in ROM.  At a source level, they were identical except for a very few omissions that were pertinent to the BASIC environment.  One would think this is wasteful, since they are right there in the ROM, but it occurred to me that EDTASM may have been produced /before/ the ROM was created, and that the device drivers may have been platform-specific code given to Microsoft to integrate into their BASIC codebase to result in what became "Level II BASIC".

In any event, because the code was so similar, it occurred to me that it might be possible to simply patch EDTASM to forward the key parts of the cassette implementation to the ROM, and then it would benefit from the existing traps.

This plan was underway until I noticed a snag:  while at a source level, the code is identical, the machine code is not.  In particular, there is a state variable stored in RAM that is placed differently between the EDTASM and the ROM.  (a software copy of port 0xff).  For most of the cassette implementation, this doesn't matter, but it did for the cassette on/off, and for the video functions which are also on port 0xff.

I could have said 'Hail, Mary', and just hoped for the best -- I suspect it would have been OK -- but then again it might not have.  After a while, it dawned on me that I could patch most of the code -- the data I/O, and leave the cassette on/off code unmodified, and avoid there being changed assumptions about the location of the state variable (in ROM, at 4028, in EDTASM, at 403d).

In the emulator, I had already virtualized the cassette relay bit, and also the drive select latch at 37e4, but I had never provided implementation.  So, this update provides implementation for those two things, allowing me to make my patched EDTASM.

I tested it out by entering a small program (the example from the manual), saving the source to tape, clearing memory, loading the source back in, assembling and saving the binary to another tape.  The resulting tape images looked fine, so I conclude that works as-expected.

I placed my modified EDTASM in the SD image under the name 'edtasm-p.cas' ('p' for 'patched').  You load it just as you would the original.  It is derived from version 1.2.

Discussions