This is a guest post by CaptainWillStarblazer
Hello, everyone. This is a continuation of my previous blogpost on EmuWoW (formerly win32emu) found here, but to summarize, I’m the 18-year-old developer behind a project that allows running applications compiled for the MIPS/Alpha version of Windows NT on standard x86 PCs through emulation, but without requiring a full system emulator. Since that last post, the project has made some substantial strides.
Since then, I’ve adapted the MIPS emulator from MAME, which is both more accurate and faster than my own (writing my own was a fun exercise but to the end of running applications, borrowing an emulator was a better decision). This alone enabled WinMine to function, which can be seen below.
Around the same time, another VirtuallyFun member named x86matthew entered the scene. His prior credits include a similar project, for Win16. He was inspired by the initial win32emu blog post, created his own similar project called WoWMIPS, which quickly started running a few simple apps, such as WinMine, Solitaire, and Notepad. Be sure to check out WoWMIPS – MIPS Emulator for Windows, Part 1: Introduction, and parts 2,3,4,5,6!
This had actually been what I was hoping for from the beginning; I always saw win32emu as a proof of concept for a smarter person (either myself in the future or someone else altogether) to come back later and do it better, and this is a massive undertaking for a single individual. What makes x86matthew’s WoWMIPS so incredible is its clean design. For one, there’s no thunk DLLs required. When an application tries to import a DLL, the host x86 DLL is first loaded, and then any attempts to get the address of an exported procedure from it are then redirected to an auto-generated stub of MIPS code which invokes the emulator to call the function. In other words, the thunk DLLs are generated at load time. Additionally, there’s no window procedure thunks required either. Instead, MIPS code pages are marked as non-executable, causing an access violation when Windows attempts to call them. Using an exception handler implemented via Windows XP’s Vectored Exception Handling feature, one can detect this and then invoke the emulator to execute the callback. Storing the CPU state in thread-local-storage allowed proper support for multithreading. I duplicated these design choices into EmuWoW, and the results largely speak for themselves. Unlike WoWMIPS (at time of writing), EmuWoW is still capable of loading MIPS DLLs (and will prefer to do so if possible), however.
To aid the process of fixing faults in the emulator, I hacked up a quick, minimal debugger into EmuWoW. First of all, there’s a “crash screen” which will indicate the type of error and dump registers and the current instruction if there’s a fault, and a running disassembly can be printed as you go, but most crucially, there’s a limited degree of interactive debugging functionality.
The main capabilities contained herein are dumping registers and memory to the screen, disassembling regions of memory, listing loaded modules, getting import entry points, setting breakpoints, and single-stepping, along with printing functions. It’s no gdb (especially for the lack of PDB symbol support), but it’s something.
MIPS is all well and good, however, but we can already emulate Windows NT for MIPS. MIPS is a fairly clean, simple architecture, often used for teaching, and short of weirdness like delay slots, is dead simple to emulate. And it fits the bill for what I’m trying to do here – a RISC architecture Microsoft abandoned, fixed-length 32-bit instructions, the works. However, adding support for the DEC Alpha AXP will finally get this project to where it was intended to be from the beginning, and I hope for it to eventually be able to run the Visual C++ compiler toolchain under EmuWoW. Being able to compile (and even test!) Alpha apps on readily available modern PCs will be a game-changer, and I intentionally wrote EmuWoW to be CPU-agnostic, so adding rudimentary support for the Alpha wasn’t difficult. Like with MIPS, I lifted the emulator from MAME. This admittedly did pose some challenges, due to MAME’s use of C++ features such as
- Classes (which I had to substitute for passing pointers to structs)
- Templates (which I had to substitute for macros)
- Function-style casts (which I had to change into C-style casts)
There was a lot of weirdness in how Alpha function calls, but it was my misunderstanding of the calling convention, and when to consider values to be 32-bit vs 64-bit posed a modest issue, but I got it to the point where some very simple DEC Alpha programs started to run, though many of them have various issues.
This is the first time this has ever been possible; emulation of AXP NT programs on standard PCs has just become possible now. I’m hoping to see EmuWoW continue to evolve, and I welcome contributions, whether that be improving support for the CPUs I already have, adding support for another (such as PowerPC) or anything else. To take a look at the code, go to github.com/bhty/emuwow and to download EmuWoW and try it out for yourself, click here.