I’ve been working on adding text-based input and output to my 65C816 computer prototype, but it’s not yet working reliably.
To unblock software development, I decided to put together an emulator, so that I can test my code while the hardware is out of action.
Choosing a base project
There were three main options I considered for running 65C816 programs on a modern computer,
- Write a new emulator from scratch
- Extract the useful parts of an open source Super Nintendo or Apple IIgs emulator and adapt them
- Find a 65C816 CPU emulator, and extend it.
I found a good candidate for the third option in Lib65816 by Francesco Rigoni, which is a C++ library for emulating a 65C816 CPU. The code is GPLv3 licensed, and I could see where I would need to make changes to match the design of my computer.
Process
After reading the code, I could see some places where I would need to modify the library, so I copied it in to a new folder, together with its logging dependency and sample program, and refactored it into one project.
I started by extending RAM up to 16 banks (1 megabyte), and mapping in a ROM device which serves bytes from a file. I also updated the handling of interrupt vectors, so that the CPU would retrieve them from the system bus.
Adding 65C22 support
My first test program was an example of preemptive multi-tasking from my previous blog post. At this point it ran, but did not switch between tasks, since that requires extra hardware support.
I implemented a minimal support for the 65C22 VIA used in my computer design, just enough to log changes to the outputs, and to fire interrupts from a timer.
The Lib65816
library does not support NMI interrupts, which are used in this test program. I added edge detection, and connected the interrupt output of the 65C22 to the CPU NMI input in code.
This screen capture shows the test program during switching between two tasks, with a different VIA port being accessed before and after the switch.
This gave me some confidence that the CPU emulation was good enough to develop on, so I moved on to the next test program.
Adding serial support
The second test program is also from an earlier blog post, and tests printing and reading characters from an NXP SC16C752 UART.
I added a very minimal emulation of the UART chip I’m using, suppressed all of the logging, and converted output to use the curses library. This last step enabled character-by-character I/O, instead of the default line-buffered I/O.
This screen capture shows the program running under emulation. It simply prints “Hello world”, then echoes back the next 3 characters that the user types.
Wrap-up
I didn’t plan to write an emulator for my custom computer, but I am currently debugging some tricky hardware problems, and this detour will allow me to continue to make progress in other areas while I try to find a solution.
I plan to keep the emulator up to date with hardware changes, since it will make it possible to demonstrate the system without any hardware access. It’s also easier to debug issues now that I can choose two different execution environments.
The hardware design, software and emulator for this computer are online at mike42/65816-computer. I would like to again acknowledge Francesco Rigoni’s work on Lib65816. I’m very grateful that he chose to release this under the GPL, since it allows me to re-use the code for my project.