Most of emulators run on a single thread, partly because they were built long time ago when dual core wasn't common, partly because the framework they use (like SDL) is a monolithic thread architecture. Recent development in ARM based tablets shows that dual core becomes the trend while cpu speed may stay at 1GHz~1.5GHz for quite a long time. To take advantage of new hardware, we must go multithread, and that means moving Graphics/Audio out of the emulation thread, so that CPU emulation can do as much job as possible.
Not all software likes faster CPU. Some can only work at a certain speed. Therefore we must provide a way to measure and to adjust cpu emulation speed. We don't want to be cycle accurate (which is impossible by the way when pipeline/cache comes in), instead we use MIPS (million instructions per second) as a metric. It is easier to reason with, and has little overhead. Usually every instruction including memory/io counts as 1. Exception is string instructions where each transfer counts as 1.
To push CPU emulation speed to its full potential, hand optimized assembler is the only choice. Surely it is very expensive to write, but it is good to make sure no cycles are wasted. The only complain I have is xcode ships with an ancient GAS, which doesn't even support macro with arguments.
Accurate VGA emulation is also very important because it is critical for games to work right. Games are like art, they may still be interesting after many many years. So game compatibility is super important for this project from the very beginning. VGA emulation takes a great effort since I have zero experience in VGA programming before. Michael Abrash's book "Zen of Graphics Programming", which a friend bought me from Amazon, is where I really get started. There are many books and online resources on this topic, but only this book I can trust 100%, because it has runnable samples. While I am testing, I would take the executables from this book, run them and compare the screen output with DOSBox. DOSBox is so far the best in PC graphics emulation, it supports all kinds of features including those weird ones. For example, there is a feature that lets you update palette during line scanning, and we cut it for a simpler and more efficient design. DOSBox also has dedicated support for CGA/EGA. In Aemula, we decide to support VGA only, and support it well. VGA module is designed as a standalone ANSI C library that can be reused when porting old softwares.
The emulator has a scriptable interface. Although it doesn't expose to user (we may do that if there is a need), it deserves its place here. I actually spent quite a lot of time writing the scheme-like intepreter. For example, the initialization of the memory area can be scripted as below:
;; after-init will be called right before cpu starts running (define (after-init) (orig #xFFFF0) (db #xEA #x5B #xE0 #x00 #xF0) ;; JMP F000:E05B (db #x30 #x34 #x2F #x32 #x34 #x2F #x38 #x31) ;; 04/24/81 (db #xFF #xFF #xEB) (loadbin "VGABIOS.bin" #xC0000) (loadbin "rombios.bin" #xF0000) )
There are also some other built-in commands to let you step through a test program and comparing results. That is how I do basic instruction testing on it.
Aemula is just started. CPU only supports real mode now. VGA is very close to complete. It has basic sound output, floppy drive, joystick, keyboard/mouse. After all, it is still far far away from the ultimate goal:
A 486PC that runs CIV2 smoothly on iPad2 class tablets.
(Last Update: 2012-06-26)