My new emulator
Posted: Mon Oct 03, 2011 1:50 pm
If you'll indulge me...
As I've said over on the hardware section of this forum, I'm working on a new emulator. It's structured quite differently from existing emulators, being based on the concept of completely sealed modules that communicate by signal wires — aping the original hardware rather than the normal structure of an emulator. So, for example, the Z80 emulation exposes 40 pins and devices interface with it by communicating on those pins. That's designed to be accurate to half a cycle, as per the timing diagrams provided on the Z80 data sheet. So I believe that should be the first Z80 emulation to be completely accurate to the data sheet.
For the purposes of emulation a ZX80, I have a fictional module that I've called a ULA which does all of the logic of the machine outside of the Z80 and a free-running CRT emulation that a video signal is passed to (unrealistically without a PAL encode and decode in between).
The emulation stuff is written in C99 for platform neutrality. I'm using the delegate and observer patterns widely, which I think is another structural difference between my code and other emulators. The user interface is platform specific and hooks itself in by providing appropriate delegates leaving the actual emulation stuff completely sealed and conformant with the model-view-controller pattern. I'm a Mac owner so the only user interface I've written so far is Cocoa based.
The advantages of this design are:
The current build has some performance areas I'd like to address but operates at about 35% CPU on my i3 2010 iMac. That compares with 3% at most for ZXSP. Though to put things in perspective, that means I could run about 12 emulated ZX80 machines before performance became a problem. Partly because I've not implemented a fast loading hack, tape input is currently echoed to output (in a scratchy way since I've done something wrong with my audio queue) when running and that costs a further 10%. At present the incoming signal is sampled at 6.5Mhz then a Kaiser window is used to strip inaudible frequencies before it's point sampled down to a more reasonable 44100Hz. I've been arguably gratuitous on that detail for the sake of testing code paths and so as to follow my rule that original logic is to be expressed where possible. The current build is attached for the curious, operation should be straightforward though I think the debugging panel can possibly still throw the emulator into an infinite loop so watch for that. In theory it'll work on any Intel machine with at least 10.6 but I've tested it only on a 10.7 machine, and haven't yet written an alternative code path to go fullscreen the old fashioned way. You may also need to rename your tape files to .80. And I'm already aware of several user interface bugs.
Clock Signal is the working title and I've vague aspirations to make the first accurate multi-machine emulator but no real plans. ZX81 support will definitely be forthcoming. Since all code is brand new, it's very likely currently to have inaccuracies due to errors. It's all written very cleanly and copiously commented, with the intention of going open source — I'm hopeful that means someone else will be able to deal with writing Windows, QT, KDE, etc front ends. On a soap opera front, I've no home Internet access for at least three weeks so I'm limited to commenting infrequently and only with such files as I remember to bring from home until then.
Relevant questions for forum posters:
EDITED: a couple of screenshots are now also attached, since Mac users are probably in the minority. They don't show anything all that interesting though.
As I've said over on the hardware section of this forum, I'm working on a new emulator. It's structured quite differently from existing emulators, being based on the concept of completely sealed modules that communicate by signal wires — aping the original hardware rather than the normal structure of an emulator. So, for example, the Z80 emulation exposes 40 pins and devices interface with it by communicating on those pins. That's designed to be accurate to half a cycle, as per the timing diagrams provided on the Z80 data sheet. So I believe that should be the first Z80 emulation to be completely accurate to the data sheet.
For the purposes of emulation a ZX80, I have a fictional module that I've called a ULA which does all of the logic of the machine outside of the Z80 and a free-running CRT emulation that a video signal is passed to (unrealistically without a PAL encode and decode in between).
The emulation stuff is written in C99 for platform neutrality. I'm using the delegate and observer patterns widely, which I think is another structural difference between my code and other emulators. The user interface is platform specific and hooks itself in by providing appropriate delegates leaving the actual emulation stuff completely sealed and conformant with the model-view-controller pattern. I'm a Mac owner so the only user interface I've written so far is Cocoa based.
The advantages of this design are:
- original machine logic can usually be implemented clearly and directly, leading to shorter code that is more likely to be bug free and accurate.
- all modules are genuinely modular without introducing unrealistic timing characteristics.
- the delegate pattern neatly separates platform-specific from platform-neutral code.
The current build has some performance areas I'd like to address but operates at about 35% CPU on my i3 2010 iMac. That compares with 3% at most for ZXSP. Though to put things in perspective, that means I could run about 12 emulated ZX80 machines before performance became a problem. Partly because I've not implemented a fast loading hack, tape input is currently echoed to output (in a scratchy way since I've done something wrong with my audio queue) when running and that costs a further 10%. At present the incoming signal is sampled at 6.5Mhz then a Kaiser window is used to strip inaudible frequencies before it's point sampled down to a more reasonable 44100Hz. I've been arguably gratuitous on that detail for the sake of testing code paths and so as to follow my rule that original logic is to be expressed where possible. The current build is attached for the curious, operation should be straightforward though I think the debugging panel can possibly still throw the emulator into an infinite loop so watch for that. In theory it'll work on any Intel machine with at least 10.6 but I've tested it only on a 10.7 machine, and haven't yet written an alternative code path to go fullscreen the old fashioned way. You may also need to rename your tape files to .80. And I'm already aware of several user interface bugs.
Clock Signal is the working title and I've vague aspirations to make the first accurate multi-machine emulator but no real plans. ZX81 support will definitely be forthcoming. Since all code is brand new, it's very likely currently to have inaccuracies due to errors. It's all written very cleanly and copiously commented, with the intention of going open source — I'm hopeful that means someone else will be able to deal with writing Windows, QT, KDE, etc front ends. On a soap opera front, I've no home Internet access for at least three weeks so I'm limited to commenting infrequently and only with such files as I remember to bring from home until then.
Relevant questions for forum posters:
- what's the minimum amount of emulated hardware you'd consider acceptable in a ZX80 and ZX81 emulator?
- what other pieces of hardware would it be nice to have?
- what's the overall feeling with respect to the usual emulator fictions; debugging panels, instant loading, etc?
- what about file format support? Presumably p/80/o/81 and TZX?
EDITED: a couple of screenshots are now also attached, since Mac users are probably in the minority. They don't show anything all that interesting though.