trs80gp - A TRS-80 Model 1,2,3,4 Emulator
trs80gp emulates the "gray" line of TRS-80 computers made by Tandy in the late 1970s and early 1980s. They are known as the Model I, Model II, Model III, Model 4, Model 4P and Model 4D. It is generally easier to refer to them as the Model 1, Model 2, Model 3 and Model 4. The Model 1, 3 and 4 are a line of compatible computers. The Model 2 has its own line of compatibles including the Model 12, 16 and 6000 which are not yet emulated by trs80gp.
The emulator runs under Windows 10 and probably works on Windows 8, 7, Vista or XP. I've also heard it runs fine on OSX and Linux machines using Wine. It should run well on any machine produced in the past 7 or 8 years.
trs80gp provides accurate and near complete emulation with excellent programmer support. The source code is fully organic and hand-crafted by myself and my brother Peter.
- Emulates floppy disk, cassette, hires graphics, orchestra 80 and printer.
- Window scalable to any size with realistic phosphor-dot rendering.
- Near perfect video emulation including beam drop-outs, wait states and various other subtle effects.
- Can visually indicate Z-80 video memory conflicts.
- Cycle perfect sub-instruction Z-80 and video timing.
- Built-in Z-80 debugger with source level debugging using zmac .bds output.
- Switchable turbo mode for high speed yet still accurate operation.
- Auto-turbo modes to go fast during slow operations (e.g., disk, cassette) and back to normal when typing.
- AVI and FLV (Flash) video capture.
- GIF and animated GIF screenshot capture.
- Audio capture to WAV file.
- Load programs directly from command line for fast development and testing.
- Can both "paste" and send files as input to keyboard (aka "fast type").
- "Cut" to copy the screen in ASCII, Unicode or graphics format.
- Keyboard selectable between normal and game mode.
- Software keyboard to get around limits of PC keyboards.
- Brightness, contrast and display colour controls.
- Batch mode and command line input to automate tasks.
- Can open files and disk images within .zip archives.
- Optional emulator extensions provide memory protection and timing to the Z-80. And emulator exit.
- Bus tracing, disassembling, profiling, memory dumping and other features for reverse engineering and debugging.
OverviewBy default trs80gp comes up in Model 3 mode with a full 48K of memory and all supported hardware attached. Command line arguments are used to select different models, hardware configurations and startup options. Run "trs80gp -?" or use the "Help → Command Line Options..." menu to get the latest information on them.
Programs can be loaded directly on the command line. Doing so loads them much faster than reading from virtual cassette files and without the hassle of writing them to a virtual disk image. It only works for programs that run outside of TRS-DOS but it still very useful for program development and and cassette-based program, especially games.
trs80gp ball.zipOr you can extract the virtual cassette file yourself and run it:
trs80gp ball.casYou can load machine language progrems in .cmd, .hex and .bds formats. My Z-80 cross assembler zmac produces all three formats and with .bds you get full source-level debugging (see Debug → Z-80 Debugger... and Debug → Source Code...).
It also can load BASIC programs in tokenized form or plain ASCII.
There's so much more! But I'll leave it at that and spend the rest of this page more in "reference manual" mode.
|-m1||Emulate Model I|
|-m2||Emulate Model II|
|-m3||Emulate Model III (default)|
|-m4||Emulate Model 4 (-m4a, -m4b, -m4c for board revisions)|
|-m4p||Emulate Model 4P|
|-m4ss||Emulate Model 4 Student Station|
|-l1||Run Level I BASIC ROM|
|-l2||Run Level II BASIC ROM (default)|
|-r0||Use ROM revision 0|
|-r1||Use ROM revision 1|
|-r2||Use ROM revision 2|
|-nlc||No lowercase for Model I|
|-alt||Use alternate character set|
|-50||Set frame rate to 50 Hz|
|-gX||Hires graphics: -g0 none, -gt Tandy, -gg Grafyx, -gc Grafyx clone|
|-dx||Disable floppy disk controller (boot into ROM BASIC).|
|-mem n||Emulate n KB of RAM|
|-mem16 n||Emulate n KB of 68000 RAM|
|-c file.cas||Insert cassette file.cas|
|-dN file.dsk||Insert disk into drive N (0,1,2,3)|
|-td||Boot TRS-DOS (default)|
|-ld||Boot LDOS or LS-DOS|
|-d0 -||Don't insert TRS-DOS disk|
|file||One or more files to load after auto-boot|
|-bd||Turn beam debugging on|
|-na||Turn off authentic display|
|-win WxH||Set window width and height|
|-turbo||Run at top speed|
|-batch||Have "Record" menu save files without prompting.|
|-fa hex||Update FPS when Z-80 hits address|
|-ta hex||Turbo for 5 frames at Z-80 address|
|-i str||Send str as keyboard input (as if it were pasted)|
|-if file||Send file contents as keyboard input.|
|-iw str||Wait until str appears on screen|
|-ix||Exit emulator when command line input has been sent|
|-it||Write text VRAM to file|
|-im dump N file||Save ASCII image of disk N to file.|
|-b hex||Set Z-80 debugger breakpoint|
|-b label||Set breakpoint at label (if .bds file loaded)|
|-h||Start in halted state|
|-ee||Enable emulator extensions (debugging oriented)|
|-trace||Start with tracing on (Record → Trace)|
|-sync||Try to maintain frame rate exactly (uses excessive CPU)|
|-frehd||Minimal FreHD emulation (read time, read files)|
|Mainly just to demonstrate trsvid|
|-time render|frame|emulation||Show timing in title bar|
|-showkey||Show Windows key code in title bar|
Logical Layout means that what you see on the key is what gets sent to the TRS-80. This is as your would expect but there are two things to keep in mind. None of the TRS-80 Models sport the full variety of keys on a modern PC. The Model 2 comes closest where the Model 1,3,4 machines lack even square brackets, curly braces and many others. They did, however, have some keys with have no analogue on the PC. Both had a BREAK for interrupting programs. Models 1,3,4 had CLEAR to clear the screen. The Model 2 had HOLD to pause display.
|To Get||Model 1,3,4 Press||On Model 2 Press|
|BREAK||Esc, Pause/Break, F9||ctl-C, Pause/Break|
|HOLD||n/a||ctl-shift-@ or Scroll Lock|
|Break||Esc, Pause/Break or F9|
|Clear||\ or Home|
Physical Layout is generally only needed for games where a key activated at a different position can make the game unplayable. Note that the Model 2 does not support Physical Layout.
Special KeysYou can hold F11 to make the TRS-80 run faster. Pressing shift-F11 will keep it in fast (turbo) mode without having to hold F11. Tapping F11 will put the emulator back to normal speed.
F12 works in the same way except it makes the TRS-80 run even faster by skippin screen draws. Screen updates will look "chunkier". The -turbo command line option has the same effect.
In turbo mode keyboard input can get very difficult with characters repeated frequently. trs80gp addresses this by dropping out of turbo mode whenever a key is pressed. This automated return to normal speed can be turned on or off by Keyboard → Auto De-Turbo menu.
Soft KeyboardIn unusual circumstances you may need to use the Keyboard → Soft Keyboard... in order to press several keys at once. Most PC keyboard can only show 3 or 4 keys held down at once but some TRS-80 games have easter eggs that require holding down as many as 8 keys. The Soft Keyboard makes this easy as each keyboard button stays pressed when clicked and only releases when clicked again. Or if the corresponding PC key is released.
If nothing else it is laid out the same as the original TRS-80 keyboard so you can see the idea behind Physical Layout mode. And the buttons go up and down as you type. Put the Soft Keyboard window underneath the main one and you'll feel like you're on a real TRS-80. Minutes of fun.
Each drive has a sub-menu that lets you eject diskettes, insert diskettes, save them to a new file or turn off their write protection. This isn't the read-only flag of the PC file system but an internal one corresponding to the physical write protect notch on the real floppy disks.
The -d0, -d1, -d2, -d3, -td and -ld command line options allow you to select disks to insert into the floppy drives when the emulator starts. The default is to put a TRS-DOS floppy in drive :0 so that the TRS-80 will boot into TRS-DOS (which is the same as the -td option).
Whenever a floppy is accessed trsg80p will go into turbo mode automatically. This can be enabled or disabled with the Diskette → Auto Turbo menu. Running in turbo mode has no harmful effect on diskette usage as the necessary relative timing remains the same. Generally you'd only want to turn the feature off to experience the original pace of the machine or when faster disk operations make it hard to read text. Or to keep the TRS-80's real time clock in sync with the current time.
When the TRS-80 goes to read the cassette (usually as the result of a CLOAD or SYSTEM command) the emulator will send the data to the TRS-80 and go into turbo mode to load the data as quickly as possible. Cassette → Auto Turbo can be used to disable this feature.
When the TRS-80 saves a cassette file (e.g., a CSAVE"A" command is entered) the emulator switches to turbo mode and will prompt you for a PC file in which to save the .cas image. If you'd rather just hear the cassette send to the speaker turn off Cassette → Auto Save.
In batch mode and TRS-80 printer output is written to a file called trs80-printer.txt.
Use Record → Animated GIF to start and stop recording of the screen in animated GIF format. The window title will flash *gif* to let you know GIF recording is in progress. The resulting files are large and not exactly the same frame rate as the TRS-80.
For a screen shot you can either use Edit → Copy which puts an ASCII text, Unicode and bitmap version of the screen to be clipboard. You can then paste it in Notepad or Paint (or pretty much anything else). Or use Record → Screenshot to save the screen in GIF format.
Audio output can be captured in .WAV format using Record → Audio with *wav* flashing in the title bar to let you know it is recording. This is fine for sound effects but unfortunately does not work as a way to create files that can be loaded on real TRS-80's. Instead you should rely on the automatic Cassette → Auto Save feature and use my trld program to convert the .CAS file to .WAV format.
The rest of the Record menu entries are meant for programmers and are documented in the programming section. I will note that Record → MHz Audio records audio files with a very high sampling rate equal to the Z-80 processor speed. Most times you do not need that level of fidelity.
The -batch command line option causes all the Record menu entries to save to a specific file name to allow for fully automated testing of trs80gp itself. It also can be thought of as a way for the emulated TRS-80 to act as a batch processor. More on this in the programming section.
Use the -turbo command line option to have it run constantly in turbo mode. Or hold the F12 key for a temporary speed boost. shift-F12 will keep turbo mode active with having to hold F12 and will turn off when you release F12.
The F11 key operates in a similar fashion to F12 but does not speed the TRS-80 up quite as much. It emulates each frame as fast as possible but looses time by still drawing every frame.
In order to let you experience the TRS-80 in the best light trs80gp automatically enters turbo mode when doing cassette of diskette I/O. That can be turned off with the Cassette → Auto Turbo and Diskette → Auto Turbo menus.
Normally a turbo mode would cause massive key repeats because your normal typing speed will appear to the TRS-80 as if each key has been held down for a very long time. This is mitigated by trs80gp dropping out of turbo mode whenever a key is pressed. Use Keyboard → Auto De-turbo to turn off this feature if it isn't a problem for your application. Typically games still work fine and you can challenge yourself by playing them at high speed.emulator extensions to make trs80gp exit. You can then run it using:
trs80gp -m4 -ee program.cmdAnd it will go through its paces writing output to trs80-printer.txt. If trs80gp doesn't exit then you know your program went wrong.
In batch mode many of the menu entries switch to saving files without prompting. In most cases those files are named in sequence starting with file-0.txt, file-1.txt and so on. Those are represented by file-%d.txt.
|Cassette → Auto Save||trs80-cassette-%d.bin|
The debugger will also activate if the Emulator Extensions are used and the Z-80 tries to access a protected area of memory. In that case the Disassembly sub-window will show a > as usual to indicate the instruction that caused the fault but also some additional letter codes indicating what kind of fault or faults occurred.
R Read protected memory W Write protected memory E Execute protected memory S Stack protected memory I Input protected I/O O Output protected I/OVarious sub-windows show the current Z-80 register contents with them displayed in red if they changed during the previous step. All values are displayed in hexadecimal. There is also a view of the top of the stack and a T-state counter which can be changed as desired to measure intervals interactively.
The Step button move execution forward a single instruction. Step Over sets a breakpoint after the current instruction and resumes execution. This is useful for CALLs to run quickly though a subroutine. Grizzled Z-80 programs know there's no guarantee a CALL will return right after itself so caveat emptor. "Go" resumes execution until the next breakpoint or protection violation. The "Bus Fault Enabled" checkbox may be turned off to disable protection checks.
When single stepping the display will turn gray to give an indication where the CRT beam is at that moment in execution. There are also boxes in the lower left which obscurely give the CRT beam Y and X coordinates. The debugger is still operational when the TRS-80 is running. You can change registers and memory locations which will show a light-blue background to indicate you've frozen your view of them so you may change it.
Since the screen shows the contents of the previous frame and the drawing of the current frame you will not usually see an immediate change when writing to screen memory. It only shows up when the CRT beam reads and draws it. The debugger memory view gives you the ability to see immediate changes to the various different RAM systems. The defaults is "Z-80 Memory" which shows the Z-80's view of its 65536 memory locations. In the Model 1 and 3 this will show the BASIC ROM in the first 12 or 14 K or memory, they keyboard matrix from $3800 to $3BFF, the video RAM from $3C00 to $3FFF and ordinary RAM from $4000 up to $FFFF or less if a value lower than 48 was given to the -mem command line option.
You can also select just the RAM to focus on the 48K or memory. But keep in mind these other view uses their own addressing. The RAM view starts at 0 but that is seen (by the Model 1 and 3) as starting at $4000. The amount and type of each varies depending on the Model but you'll typically see Text VRAM for the usual character display, and Hires VRAM for the high resolution graphics option (which is usually only accessible to the Z-80 through I/O ports).
In a clunky way RAM can be changed. The easiest approach to to select a memory byte and write a new hexadecimal value for it. The emulator simply reads back the memory dump so you can also delete a line and enter any address followed by a colon and a series of space-separated hexadecimal bytes to change memory locations without having to look at them.
A few pseudo-memory regions are viewable but not changeable. They are intended to give a partial view of the TRS-80 hardware state.
Z-80 Device What the Z-80 would return if an I/O were read. Z-80 Port Writes The last value written by the Z-80 to a port. Z-80 Port Reads The last value read from an I/O port by the Z-80.
At the bottom of the window are line of check boxes and drop-downs to control bus tracing which is dicussed later.zmac cross assembler will output machine language programs in .bds format. It is a text format so by looking at it and the zmac source code you can probably figure out how to generate it yourself. But the important part here is that loading .bds files from the command line will enable source level debugging.
Use Debug → Source Code to bring up the source code that has been loaded. It will look a bit like an assembler listing file. The current program location will be highlighted and follow the execution of the Z-80.
The format also defines symbolic labels so you can type these labels in to the breakpoint or register windows instead of having to look up the hexadecimal values yourself. You can also use labels for the -b command line option to set breakpoints.
The normal recording options can assist debugging. It may be helpful to step through a video a frame at a time to see some graphical glitch in detail. The "MHz Audio" option takes this to the extreme by recording audio output a sample rate equal to the speed of the Z-80. In effect this lets you see exactly when the audio changes.
The Trace option is the most useful so I've dedicated section to it. The other options attempt to self-document in their output. Unlike the Trace option these other options don't record everything. Typically they'll just track the PC values to keep overhead low. When they do their final output the use whatever value is in RAM at the time for the disassembly. If the program changes you may seen confusing output. This gets even worse if the memory mapping changes.
All these recording options can be activated and stopped at any time. It is useful and often desirable to start them when the program is stopped in the debugger and then stop them at the next breakpoint after an interesting subroutine or full step of a game simulation has run.
Record → Z-80 Profile tracks every instruction executed and shows you a list of those instructions, the number of times each instruction was executed and the total T-States spent on each instruction. It is intended to help measure where your program spends its time to be used as a guide for optimization. It can also be used to simply track what a program as done during an interval. However, "Bus Use" is better for that task and Trace will show every instruction in order.
Record → Backtrace show the last 65536 instructions executed. In theory you can use this to respond to a crash. But practically speaking that many instructions is at most a tenth of a second so you're not likely to be quick enough to catch it.
Record → Bus Use tracks the execution of a program. The output is much like a disassembler but with markup indicating how memory was accessed: read, written, executed, jumped to, called and so on. The disassembly tends to be better than a static disassembly since it uses the Z-80's execution path to point out what is code and what is data.
The disassembly will be entirely commented out except for any areas where a program was loaded by the command line (or using File → Load/Run) into memory. The intent here is to distinguish the loaded program from the ROM or operating system routines it uses. If the program is sufficiently put through its paces the result should be a good disassembly that can be assembled to produce the original code. Unlike the other trace options any data uncommented in the disassembly is based on the original data loaded so it won't be fooled by simple self-modifying code. However, this is a problem if the program relocates itself. In which case you'll have to get a relocated version of the program loaded. At least "Bus Use" will help understand the relocator code.
0 Set bus permissions for address HL to DE to B 2 Trigger bus fault B 3 Disable (B=0) or enable (B=1) bus permissions 4 Trigger execute fault (i.e., drop into the debugger) 5 Reset (B=0) or get (B=1, into DEHL) T-state counter 128 exit emulator with return code BC 255 set carry flag (to detect if extensions active)Function 5 allows for automated profiling of Z-80 code. Function 128 is typically used to end a test in batch mode. The bus permissions are very helpful in tracking down nasty bugs. For example, you can set your code section to execute-only. The emulator will trap into the debugger the instant something tries to overwrite over your code. Or even read it. Another useful technique is turning off stack permissions at the bottom and top of your stack to detect stack overflow or underflow.
For function 0 the lower 6 bits in B are set to indicate what Z-80 operation is allowed on that memory location. Or for the first 256 addresses what I/O operation is allowed on a port. Those bits are:
Mask Operation Z-80 Debugger letter indicator 1 Read R 2 Write W 4 Execute E 8 Stack S 16 In I 32 Out OStack permission is required for CALL, RET, PUSH, POP, RETI and RETN.
The output can be voluminous. You'll want to use breakpoints to turn tracing on and off for as short a period as possible. The "Tracing" checkpoint in the Z-80 Debugger is a convenient shortcut. And there are additional check boxes to enable or disable tracing for Z-80 instruction, I/O accesses, memory accesses and interrupts.
For even finer control I/O logging can be enabled on a per-device basis. This is handled by the device drop-down. The interface is awkward. As you select each device in the drop-down the checkmark to the right changes to indicate if that device is being logged. But you still must check the I/O box to enable I/O logging. To make it more confusing but usable the best course is to turn I/O off, select the device you're interested in, enable it and then turn I/O back on. If you turn I/O on first it will enable all devices by default.
Yes, it's bad but at least it gives some way to target particular devices. Obviously these controls should be in some other window but the debugger happened to be handy at the time. trs80gp wasn't built in a day.
The actual logging looks something like this:
8033317 @3018 z ex jp $35c2 8033327 @35c2 z ex push af +11 @35c2 z wr _ffb4 00 ram[ffb4] +11 @35c2 z wr _ffb3 44 ram[ffb3] 8033338 @35c3 z ex in a,($e0) +11 @35c3 z in _e0 fb 8033349 @35c5 z ex rra 8033353 @35c6 z ex jp nc,$3365 8033363 @35c9 z ex rra 8033367 @35ca z ex jp nc,$3369 8033377 @35cd z ex push bc +11 @35cd z wr _ffb2 38 ram[ffb2] +11 @35cd z wr _ffb1 80 ram[ffb1]The first column is the T-State counter. The second is the PC of the Z-80 when the operation occurred. Next a letter code shows the device responsible ('z' for Z-80 and 'd' for DMA chip). The type of access follows. Most are "ex" for instruction execution with a disassembly of the instruction following. But for reads, writes, ins and outs (rd, wr, in, ot) the memory or I/O address is shown followed by the value read or written. Other possible operations are:
ht Fetch during Z-80 halt i0 Interrupt mode 0 bus read i1 Interrupt mode 1 bus read i2 Interrupt mode 2 bus read ni NMI (non-maskable interrupt) bus readAfter any access there may be a description of what the value means to that device and possibly the internal state of the device. A good example is the CRTC video controller chip used in the Model 2 and 4. A I/O write (out) to its address register will be annotated with the name of the register selected. An I/O write will show the name of the register changed and its current value. Some devices are very simple in that any byte read or written can only have one meaning. But for the CRTC a write to a register depends on which register was previously selected. Without the annotation you would have to search backwards for the last register selection. And if the register is 16 bits wide you'd also have to look back for the last time that other 8 bits were changed. This is tedious and may not even appear in the bus trace you've made.
Not all devices provide annotations. If they do then you can bet they were giving us trouble in developing the emulator. Most of the Model 2 devices have annotations.
By the way, the underscore and @ signs in front of addresses are intentional and useful. vi (and maybe other editors) make it easy to search on words. So starting a search on _ffb2 will only find other references to that memory location being read or written. But searching the word ffb2 will find instructions that reference the address. Or you can search for @ffb2 explicitly to restrict your search to only instructions executed at that address.
The EndPretty much anything else depends on knowing how to operate a TRS-80 or program a Z-80. While it surely would be good to provide links to documentation I'll just leave your with your prior knowledge and good hunting in your web searches.
George Phillips, August 27, 2018. george -at- 48k.ca