Over the past year, I have been writing an emulator for the original IBM PC Model 5150, and its slightly more advanced brother, the IBM XT Model 5160. These systems are the original ancestors of the modern PC, both released in the early 1980's. This project is both my first emulator, and my first project in the Rust programming language. A lot to learn all at once.
I had a tiny bit of assembly language experience from reading Randall Hyde's Art of Assembly ages ago, and in the 00's had reverse-engineered a bytecode interpreter for an adventure game engine (that would eventually make its way into ScummVM), so I felt I had enough experience to feel confident enough approaching PC emulation directly.
Fortunately, Rust was fairly easy to pick up from a background in C despite occasional frustrations with the borrow checker, and my initial guesses at emulator design turned out to be mostly feasible, if not always optimal. My initial implementation was purely instruction based, with no cycle-counts, and converting that to a cycle-accurate emulator was a bit of a challenge. More on that topic perhaps in a future article.
Background
I didn't grow up with an original IBM PC, but instead a popular clone, the Compaq Portable. It was a heavy beast, and was often described as a "luggable" system instead of "portable". With the keyboard affixed and the unit slid into its protective case, it could pass for a very large and unwieldy briefcase.
I spent many hours fascinated in front of the eerie glow of its green phosphor CRT. We had this machine for a long time, far past the point where it was grossly obsolete. I have fond memories of exploring the countless diskettes my father collected from PC User Group meetings and software I downloaded from BBS systems. It was this machine that spawned my love of computing, so a machine from this era that could run the same software seemed like a logical target. Nostalgia is a big motivator.
I chose the IBM PC, because it really was the first, and the fact that the BIOS source code for the IBM PC was available. IBM had published it in their Technical Reference for the machine, and others had performed OCR and cleanup on those source listings. This meant debugging the IBM PC's boot process was much easier than it otherwise would have been.
MartyPC is Born
Naming an emulator is notoriously difficult, and made more so by the popularity of a given platform. I'd hate to have to name an NES emulator at this point, given the hundreds of NES emulator projects out there in various stages of completion. PC is not anywhere near as popular a platform as the NES, but even so, we have emulators like DosBox, PCem, 86Box, PCBox, VirtualXT, PCE, UniPCEmu, PCjs and others. It felt like every permutation of "PC" and "86" had some sort of emulator attached to it.
Like many others with nostalgia for the IBM PC, I was entranced by the release of the PC demo 8088MPH:
This demo pushed the original IBM PC hardware well past its known limits, and rightfully blew quite a few minds in the process. At the time of it release, no emulator could really run it. I can't say I had any expectation of ever being able to run 8088MPH, but as an intangible, long-term goal it seemed an appropriate target. The End Boss of IBM PC emulation, so to speak. 8088MPH is chock full Back to the Future references, and so I thought I would name my emulator as a nod to this infamous demo. I picked the name Marty from the protagonist of the series, Marty McFly.
Sometime during development I discovered that there was a computer system called the FM Towns Marty, and I realized Googling "Marty Emulator" was never going to lead back to my project. Worse, I worried it would be considered rude to muddy the waters. I was fond of the name at that point, so I came up with a compromise, and now call the emulator MartyPC. I hope that the FM Towns emulation community doesn't come after me still. I have the alternate name "McFly" in my back pocket, just in case!
Last year, the developers of 8088MPH released a follow-up demo called Area 5150. Again this demo would do the impossible with the original IBM PC hardware, and won the demo competition Evoke 2022. Appearing in the middle of my development, it appeared that I had a new end goal already. Area 5150 broke every extant emulator again, even the popular and highly-accurate 86Box failed to run its end credits. An impressive effect that combined a water effect with a PCM sound player and text slideshow, the end credits of Area 5150 would turn out to require absolutely perfect cycle-accuracy.
At the time of its release, my emulator couldn't even display the introduction scene.
Almost exactly a year after I started development, in April of 2023, MartyPC could run the entire 8088MPH demo from start to finish with no major glitches.
A month later, it manages to run Area 5150 in its entirety:
Not to toot my own horn, but this was the first time Area 5150 had been emulated successfully from start to finish with no major glitches.
There are a few reasons I was able to succeed. One would be the development of many internal real-time debugging facilities, another was utilizing the technique of "hardware validation", a subject I intend to cover in a future blog article.
During development I have made very little attempt at making any optimizations, although there are surely many to make. Instead, I have focused on making my code clear to read and well commented. If you have a relatively fast PC you should have no issues running it, but it takes up more resources that you might expect to emulate a 40 year old computer. I plan to make some optimizations going forward. It will be interesting to see where I can save time while not sacrificing accuracy or clarity.
It would have been more useful to start a dev blog to document this process from the beginning, but as the saying goes: better late than never. I plan to document at least some of the more interesting efforts undertaken during its year-long development, and provide resources for future PC emulator developers. These articles may not be in the order that features were developed chronologically, but just written up as I find the time and motivation for a certain subject.
The Book8088 is an interesting little machine. It is essentially a 1980's computer in a laptop form factor. With apologies to Sergey Kiselev , whom the manufacturers of the Book8088 did a little dirty , I couldn't resist ordering one myself to tinker with. The Book8088 is trying hard to basically be compatible with the original IBM PC, containing some of the same or equivalent chips. It's natural to want to put it through its paces, and one of the best tests for IBM PC compatibility has to be the 8088MPH demo . If 8088MPH will run we must be operating pretty darn close to the original. Looking at the specs of the Book8088, there's good reason to be optimistic. The machine supports a real 8088 CPU. Even better, there's a socketed CRTC chip, so the complex CRTC abuse the demo performs doesn't need to be emulated in any fashion. My Book8088 came with an NEC V20 CPU. This CPU is a lot faster than the 8088, we'll need to replace it: Additionally, the CRTC c
Writing a cycle-accurate emulator for a computer system is more than just understanding all the CPU instruction timings. A computer is a complete system with peripherals, interrupts, IO bus signals, and DMA. All this comes with an array of different timings and quirks. When software like Area 5150 is written that requires perfect cycle timing, it can be a challenge to provide the level of accuracy needed for the software to function. Area 5150 in particular requires precise coordination with the CGA's CRTC chip and timer interrupts to begin the end credits demo effect at precisely the right time. Getting this right is crucial to whether the demo effect produces this: Artwork by VileR Or this: It would be very handy then if we could somehow peek into the operation of the system while it was running and understand how all these parts interact. As it turns out, we can! This process is typically referred to as 'bus sniffing', and there's a lot of a technical information ou
In a previous article , I described a simple state machine to explain the prefetch behavior and miscellaneous observed bus delays of the Intel 8088. I now believe that the model I described there - although successful in modelling the 8088's behavior - was unnecessarily complex. There are in fact far fewer legitimate bus "delays", and they do not relate to internal state transitions. I have also slightly revised my description of the BIU's prefetching logic - I now believe that the prefetching decision happens at the end of T2, instead of the beginning of T3. There may not be much of a distinction between the end of one cycle and the beginning of the next, but it lines up better in our new diagrams. Introduction If you were interested enough to click on this article, you are probably already familiar with the 8088's bus cycle timings. A single bus cycle on the 8088 takes a minimum of 4 CPU cycles, consisting of 4 T-states numbered T1, T2, T3 and T4. Wait states (T
Comments
Post a Comment