I offer up for your consideration Nybl, a Science Fair Microcomputer Emulator for the Intellivision. Perhaps the first emulator for the Intellivision, almost certainly its first emulator emulator.
nybl.rom 27.56KB 147 downloads
For more information on the Science Fair Microcomputer Trainer (SFMT), including a PDF version of the 180 page manual, I recommend:
To use the emulator, simply move the cursor around the on-screen keypad with the D-pad, and select the current key with any action button.
Unlike the real SFMT, Nybl comes preprogrammed with a simple demo program. To run it, select 1, followed by the run / play button on the keypad. Somehow I don't think it will be the start of a burgeoning SFMT demo scene.
I should stress that this code has been developed and tested on Jzintv, and has not been run on an Intellivision. Therefore, your mileage may vary when running on real hardware.
Any and all feedback is most welcome, enjoy!
And now, for the dweebs, some technical details.
Why do this?
For a long time I have wanted to write an emulator for the Intellivision. Not an emulator of the Intellivision, it was pretty clear from early on that Joe has this nailed, but an emulator for the Intellivision. I thought it might be an interesting challenge.
Why the SFMT?
There is a significant problem in writing any emulator for the Intellivision, the CP1610 at its heart is slow, unbelievably slow, even when compared with its 1970s peers like the 8080, 6502 and Z80.
Theoretically it can chew through between 75,000 and 225,000 instructions per second (75 – 225kips) in an NTSC Intellivision. Owing to different screen timing, these numbers are about 12% higher on PAL or SECAM Intellivisions. However, in typical use the NTSC values are even lower, probably somewhere around 100kips, owing to STIC cycle stealing and the fact that commonly used instructions like branches are not necessarily the fastest. This compares to more than 200kips for an 8080 clocked at 2MHz, 400kips for a 1MHz 6502 and over 500kips for a Z80 clocked at 4MHz. Although the relative sophistication of the CP1610's 16 bit registers and instruction set can be a benefit, when writing an emulator they are no real substitute for instruction throughput.
So the key to writing an emulator for the Intellivision is finding a subject where the CPU is even slower than the CP1610, but is still used in an interesting application.
Enter the TMS-1000 and its many variants. This is the first micro-controller, developed by Texas Instruments in the early 1970's. It was used in all kinds of interesting toys and devices you may remember from your youth, including
- MB Simon
- Parker Brothers Merlin / Master Merlin
- MB Big Trak
- TI Speak & Spell / Speak & Math / Little Professor
- MB Microvision
- Lots of TI calculators
The TMS-1000 is a 4 bit Harvard architecture micro-controller with 1K - 4K of 8 bit mask ROM and 64 or 128 nibbles of 4 bit RAM. According to the datasheet it is clocked at between 250KHz and 350KHz and, as each instruction takes 6 cycles, it has a throughput of between 42kips and 58kips. Still not very hopeful, an emulator would need to process each TMS-1000 instructions with around 2 CP1610 instructions, but more doable than most.
On the plus side, the Harvard architecture and mask ROM means that self modifying code is not possible, allowing the program ROM to be placed in an Intellivision ROM cartridge, and opening the door to a simple instruction decode and dispatch strategy. The small RAM size means it should be possible to model the CPU in a stock Intellivision, despite its limited RAM.
The other problem is that being a micro-controller, TMS-1000 programs are not typically available, and for a long time they were effectively undumpable. However, in the last couple of years Kevin Horton (Kevtris) and Sean Riddle have worked out ways of both visually and electrically dumping some of the TMS-1000 range, allowing games such as Simon and Merlin to be properly emulated in MESS.
OK, but why the SFMT and not Simon or Merlin?
The SFMT is an electronics kit sold by Radio Shack / Tandy from about 1985 onward. It is a reworking of an earlier kit sold by Gakken in Japan, the FX R-165. Both kits teach the basics of computer programming using 4bit machine code. As far as I can tell (I don't own the rarer Gakken version) the kits are based around the same TMS-1100 CPU running the same firmware, certainly they are software compatible.
Now here is the interesting bit. Using only the 4bit TMS-1100, with its built in 2K of ROM and 128 nibbles of RAM the authors implemented a virtual machine and basic machine code monitor. Unbelievably, the TMS-1100 in the SFMT is emulating another, different, 4bit computer!
I think this is incredible. I wanted to get a look at the code which did this, and thanks to Kevtris and Sean we can now do that. And having peered into its brain it is a great job, especially as at least a third of the code is taken up with some ancillary games, rather than the core VM and monitor.
How does Nybl work?
So the SFMT makes an interesting, if not necessarily plausible target. Things are made worse by the fact that the TMS-1100 at its heart is clocked at 400KHz (overclocking on a toy from 1985, who would have thought it?), giving 67kips throughput. To match the pace of the original, this would require Nybl to simulate each TMS-1100 instruction with an average of a little less than 1.5 CP1610 instructions. Hmm.
Now, I hope I'm an OK programmer, and I've written a few simple interpreting emulators in C, but the best I have achieved is 15 - 20 host instructions per emulated instruction. So this looks to be mission impossible, but perhaps it does not matter. In this instance if the emulator runs slowly it does not necessarily ruin the experience. Your program just takes longer to complete. It is true that the SFMT has sound output and running it more slowly might cause problems, but I thought it was worth a punt.
In its current form Nybl runs at about one third of the speed of the real SFMT, with a throughput of about 21.5kips. It takes an average of 5 CP1610 instructions to process a single TMS-1100 instruction. It is so slow I have not bothered with timing control, so obviously it is not exactly what you would call cycle accurate. While this is some way off the required 1.5 instructions, it is significantly better than anything I have managed before.
The UI, which runs in the VBLANK ISR, takes less than 2% of the Intellivision's cycles, and everything else is given over to the TMS-1100 emulator running off the main post EXEC initialisation thread.
Sound emulation is achieved by bit bashing the PSG volume register to create PWM sound, just as it is on the real SFMT, and as described here:
I was surprised that this PWM "just worked", and it is a real credit to the accuracy of Jzintv that it does. As always, kudos to Joe.
In terms of the emulation, there is no cheating, the full SFMT ROM is present (there are 2 copies, each preprocessed slightly differently, at $9000 and $a000 for branch optimisation purposes) and every instruction is individually interpreted. Although it would be possible to implement SFMT specific pseudo-instructions to process chunks of SFMT code natively in CP1610 machine code; or indeed to statically recompile the entire ROM, I've chosen not to do this.
The changes made to the SFMT ROM image are:
- Reordering of instructions to correct for the TMS-1100 LFSR based program counter
- Replacement of opcodes with direct jump addresses of instruction implementations, meaning instruction decode and dispatch resolves to a single MOV@ R4, R7 instruction
- Creation of 2 ROM versions with differing branch implementations, executed based on whether the branch occurs within a subroutine call or not
- Spacing out of ROM pages and the introduction of a page fault pseudo-instruction to speed handling of the paged program memory model
It has been a joy to explore the SFMT and put Nybl together. Like all software it is not complete, rather it is on a journey to who knows where. I may look to improve it further, or investigate using the TMS-1100 core to play with some other emulations. This really requires other applications to clock the CPU below 150KHz, or for there being timing loops to tweak, to make things usable. Otherwise I guess there are always other things to waste time on.