An Altair Emulator for the TRS-80 Model III
Preface
Assembly language aficionado Philip Avery is a long time TRS-80 user who has a keen interest in vintage computers. He's recently exercised his mind creating an Altair emulator for the venerable TRS-80 Model III.
I've given Philip this web space to make the emulator available to those who might want to check it out. Here's the story in Philip's own words...
Tez
Background
While reading Paul Allen’s book Idea Man, I had the idea to create an emulator of the 8080 Altair on my TRS-80 Model III. The history is well known whereby in 1975 Bill Gates, Paul Allen & Monte Davidoff created Altair 4K BASIC to run on the newly developed microcomputer – the Altair – produced by MITS of Albuquerque, USA.
Figure 1. The Altair (image sourced from old-computers.com)
As Gates & Allen didn’t possess the recently released Intel 8080 CPU, let alone a developer’s kit for such a device, Allen set about emulating the 8080 machine instructions on a PDP-10 minicomputer. He had previously used a PDP-10 to emulate the much lesser 8008 CPU.
The result was fantastic. Gates & Allen were able to write their BASIC interpreter without using a real 8080 microprocessor CPU, then load it into a real Altair, whereby it ran faultlessly. Quite remarkable.
My emulator
My idea was to use my Model III where Allen used a PDP-10. I would write in Z80 assembly language an 8080/Altair emulator that would execute 4K BASIC in high memory of the TRS-80. I wouldn’t go as far as depicting the Altair’s front panel of flashing lights as other emulators do, but would expect the BASIC to run & ultimately run any Altair BASIC program.
I hadn’t any previous experience with emulation, and while the 8080’s instruction set is compatible to the Z80’s, I quickly discovered it would take many instructions by the Z80 to emulate an 8080 instruction. What’s worse, is that the TRS-80’s clock speed is similar to that of the Altair (in contrast to the power of the PDP-10), so the TRS-80 emulator would be considerably slower than the real machine.
I wrote this on a real, disk-based TRS-80 Model III running MultiDOS & used Misosys EDAS-352 editor/assembler. Two years on for ver 1.3, my TRS-80 system is: Model III with FreHD (hard drive emulator), LDOS 5.3.1 and Misosys EDAS-4 editor assembler.
Getting started
If you’d like to see what Altair BASIC is like, and you have a 48K disk-based TRS-80 Model III, Model I, System 80 (or other such clone/emulator) then download the emulator zip file and follow these steps: (NB I’d like to point out that this isn’t as user-friendly as it could be. When I wrote the program I wasn’t expecting interest and didn’t envisage putting it up on the net).
- Unpack the zip and move the 8080 emulator (EM8080/CMD) and 4K BASIC (BAS4K) across to your TRS-80
- On your TRS-80: Load BAS4K. Execute EM8080/CMD
- You’ll be prompted with Altair start-up message:
MEMORY SIZE? Enter size in bytes. (<Return> = 8K). Max for this emulator is 32K
TERMINAL WIDTH? (<Return> = 72)
SIN? <Y or N> (must be upper case). Same with RND, SQR
You’ll be greeted with a flashing cursor. Note: 4K BASIC accepts upper case only. Also, there are no strings but there is floating point (binary).
Figure 2. 4k Altair BASIC on the TRS-80 Model III
You can also try out 8K BASIC. Load BAS8K instead of BAS4K. 8K BASIC accepts lower case and does strings.
A manual for these BASICs can be found on Rich Cini’s excellent Altair32.com under Instruction Manuals.
To exit Altair BASIC you have to reboot.
Speed
On a Model III the EM8080 emulator is about 27-times slower than a real standard Altair. Interestingly I first had it running at a much better 20-times slower. However I needed to correct my approach dealing with the Parity flag difference between 8080 & Z80. Originally for any 8080 instruction that acted on the Parity flag, I merely did an OR A to set Parity. This it duly did, but I overlooked that OR also reset the Carry flag. The Parity flag is only used once in Altair 4K BASIC, which I could have worked-around, but in the interests of having a correct emulator, I did a proper fix by setting the Parity flag correctly when doing ADD, SUB, etc.
Ver 1.3: With improvements to the Instruction Dispatcher, the speed has improved to 14.9 times slower.
Incidentally, Bill Gates is recorded as saying their PDP-10 emulator ran 5-times slower than a real Altair.
Changes to 4K BASIC
I made 2 changes: bypassing much of the Initialisation code that establishes which I/O ports are used (I think), and the default of 8K RAM for MEMORY SIZE? for the 4K BASIC version, (16K default for 8K BASIC). On a real Altair, pressing Return on MEMORY SIZE? will let BASIC establish how much RAM is available.
As my aim was to create an 8080 emulator as opposed to an entire Altair emulator, I feel these compromises are reasonable. Note though that the binaries BAS4K & BAS8K on this site have these changes implemented so will differ from other sources of these binaries.
Loading & Saving
As in the original release of these BASICs, there were no inbuilt commands to Load & Save programs. However if a teletype was used as an I/O device, there was a work-around. The user could re-direct output on the teletype to paper tape for a LIST command – this would save. For loading, input could be directed from the paper tape, instead of the keyboard. The BASIC interpreter merely sees this as someone typing very fast entering their program!
I have included similar work-arounds in EM8080. These require knowledge of how to use the Debug program included with your DOS. My examples are for MultiDOS:
LOAD (TIC TAC TOE as an example)
- From the zip, move TICTAC across to your TRS-80
- At DOS, LOAD TICTAC (this loads the BASIC ASCII into high memory)
- Enable Debug
- Initialise Altair BASIC (as above)
- At cursor-prompt, enter Debug
- D(isplay) 550BH. M(odify) byte 550BH from 00 to 01. Modify the next 4 bytes to: 00 C0 DE C9 {Explanation: 550BH is a mode-select for EM8080: 00 means do nothing, ie don’t load or save. 01 = load. FF = save. The next two bytes are the start byte in RAM of the BASIC program – C000H in this case. (Note: convention of lsb, msb). The last two bytes to modify are the ending-address for the BASIC program – C9DEH for TICTAC}
- G(o) 5200H. Resume Altair BASIC. The emulator is bringing down from high memory the BASIC program & entering it, character by character. Altair BASIC sees this as typed-input on the keyboard
- At ‘OK’ prompt, TICTAC is available to LIST, RUN, etc.
SAVE (TIC TAC TOE as an example)
- Enable Debug
- Initialise Altair BASIC (as above)
- At cursor-prompt, enter Debug
- D(isplay) 550BH. M(odify) byte 550BH from 00 to FF. Ensure next 2 bytes are: 00 C0 {Where in RAM to start Save to}
- G(o) 5200H. Resume Altair BASIC
- Type LIST {With mode byte set to FF, output to screen is copied to RAM}
- When LIST has finished enter Debug
- D(isplay) C000H. Establish end of program location after C000H. Look for END statement or the last program line. The next instance of 0AH is the last program byte
- G(o) 402DH {Enter DOS}
- DUMP TICTAC (START=X’C010’,END=X’C9DE’) {MultiDOS command which dumps memory to a disk file. Note: First byte of program to Save is at C010H}
Where to find Altair BASIC programs
One place is Rich Cini’s Altair32.com. Download Current Release of his emulator. It includes the folder: Files/BASIC programs
These program files are in ASCII. It’s worth mentioning that these programs will run natively under the TRS-80’s Microsoft BASIC. Just load the ASCII version & run. Seldom is any change required, usually just RND statements.
For the emulator they need to be converted into “LOAD” file format. I have a BASIC program to do this:
- Set BASIC top of memory to 32000, eg BASIC 32000
- Load CONALT/BAS
- E(dit)120 and change the file name. Type RUN
- The End Address will be displayed on completion
- E(dit)230 (the DUMP command) with Name and End Address. (See example in SAVE above). Type GOTO 230
Here are 3 popular Altair programs which have been converted and are ready to load. (With Start & End addresses)
- TIC TAC TOE C000H – C9DEH (painfully slow)
- HAMURABI C000H – CAF1H (speed good, need RND)
- HUNT THE WUMPUS C000H – E5D6H (Set mem to 8K, need RND)
- HUNT THE WUMPUS (TRS-80/BAS version)
Some emulator detail
This was my first attempt at emulation. EM8080 loads & runs at 5200H. It requires the code to be emulated (eg 4K BASIC) to be loaded at 8000H (32K decimal). This is a convenient base address as I’m always flicking between it and a base address of zero, where 4K BASIC was assembled to run. I can switch to this 8000H base address merely by SET 7,H (setting the msb of the address), instead of a time-consuming 16-bit addition.
EM8080 source is available in the zip file. Immediately obvious is how long the code is - I went this way intentionally. I wanted it to be as fast as possible and so instead of having code to determine which registers were used for any given opcode, I just hard-coded the registers used into every opcode. This seemed acceptable as I had lots of memory available for EM8080, 5200H-8000H (11.5KB). It currently consumes 3,512 bytes.
I made use of the Z80’s alternate A & F registers (AF’) to store what is the 8080’s A and PSW, but chose to use memory locations for the rest of the registers as opposed to using the Z80 alternate set (EXX). I’m still undecided as which would be the best approach. While for many instructions (register-register, MOVs, etc) the alternate registers would be ideal, however for memory & immediate instructions, the alternates are not so good. The overhead involved in passing immediate & memory data to the alternate set may outweigh its advantage held elsewhere.
My Z80 register use is:
AF – free to use anytime
AF’ – 8080 A & PSW
BC – 8080 program’s “PC”
HL – free to use anytime
DE – free to use anytime
I’d appreciate any comments or suggestions, especially from those who have experience in 8-bit emulation. Ver 1.3 Thanks to George Phillips who suggested the speed improvements.
Philip Avery
Originally posted October 2012
Updated Sept 2014 - Upgraded program to ver 1.3
Tweet |