Doom for the Pocket PC is an interesting port of the game, while it performs well I can’t help but feel that they didn’t spend long testing the game or that they rushed a few things. There are a few easily noticed bugs along with what appears to be a few oversights when it comes to its installation. Because of this I decided to see if I can fix some things and bypass the annoying Serial Numbers Don't Match! error message.

Doom for Pocket PC installation media.

The Bugs

The most obvious bug can be seen when just launching the game and watching the title screen demos. After the second demo has completed playing the game will crash back to the home screen. The second bug, which is likely the most annoying is when launching the game the error message Serial Numbers Don't Match! appears. I have had this happen straight from installation or more commonly is after doing a re-install/sync using ActiveSync.

Demo Crash

How this bug was missed by the developers I don’t know as you just need to leave the game running at the title screen for a couple of minutes. Luckily when the game runs it writes log lines to \Program Files\DoomPDA\DOOMCE.DBG and when the game crashes the last couple of lines are:

ST_Init: Init status bar.
W_GetNumForName: HELP2
W_GetNumForName: %s not found!

From my previous knowledge of Doom and it’s resource files (known as ‘WADs’) I could tell that the game was trying to load the image ‘lump’ HELP2 and it is unable to do so as it did not exist. A ‘lump’ is basically a data object/resource within the main resource file doom1.wad, read more about Doom ‘lumps’ at the doomwiki.

This bug was relatively easily to fix and there are a couple of ways to fix it. We can either add a HELP2 lump to the games doom1.wad resource file or find where it tries to load the resource within Doom.exe. The simplest way was to use a WAD file editor such as SLADE to add a HELP2 lump to doom1.wad. The original HELP2 lump can be found in the original non-Ultimate doom1.wad, in the shareware version or can be download here. Later on I will go into detail on how to edit the main executable.

The HELP2 lump.

Installation Path

During installation the user can choose to install the game to the devices main memory or to an SD card if one is available. Installing to an SD card would have been the preferred option for a lot of uses as the game is relatively large when it comes to Pocket PC games (doom1.wad itself is 13mb). Unfortunately while the game will let you install to the SD card the game’s DRM requires the game to be installed onto the device’s memory. I will come back to this later on.

Serial Numbers Don’t Match!

This has to be one of the most frustrating implementation of copy protection for game that I have come across. On a freshly factory reset device and installation of Doom from the CD I still encountered the Serial Numbers Don't Match! error message. Unlike the missing HELP2 lump, there was no message in the \Program Files\DoomPDA\DOOMCE.DBG file.

Reversing with Ghidra and Binary Ninja

Something that I hadn’t done before but been interested in is reverse engineering applications, so I decided to try reverse engineering Doom.exe to see what was causing the Serial Numbers Don't Match! error message. To do this I used the Open Source application Ghidra and the free version of Binary Ninja.

Once importing Doom.exe into Ghidra, I looked in the strings table for string Serial Numbers Don't Match! and checked to see where it was used. This string is used at the end of a large function that does various checks on different files.

From the decomplied code we can see that function Ordinal_1113 is called multiple times with the path to the following files:

\Windows\wind.opt
\Program Files\DoomPDA\doom1.wad
\Windows\Start Menu\Doom.exe

Some kind of validation logic is perform on the result of each function call. If it succeeds then it will perform:

goto joined_r0x00038630

Otherwise, it displays the error message, performs a couple of function calls and exits.

Ordinal_858(0,u_Serial_Numbers_Don't_Match!_00064ab0,u_FATAL_ERROR_00064a98,0);
FUN_00038bb8();
FUN_00019ee4();
Ordinal_868(DAT_00066868,0x10,0,0);
return 0;

This will explain why the game can’t be installed to the device’s SD card as it is hard coded to look at the above file locations. I was curious about wind.opt as this file seems a bit out of place when it comes to Doom. Copying the three files to my PC (wind.opt is marked as hidden) I opened them up in a hex editor to see what they contained. wind.opt is only 4 bytes in size while the other files looked as they should. I decided to search for the 4 bytes in wind.opt inside doom1.wad and Doom.exe. The 4 bytes can be found at the very end of each of the files. Based on this find, the DRM checks must be doing a basic check to see if the 4 bytes in wind.opt can be found at the end of the other files and if they are then launch the game other wise display an error message.

One side effect of hard coding the location of Doom.exe to the start menu is that Windows Mobile limits how many applications or shortcuts can be in the start menu and if you place more there then they are moved by the operating system into the Programs directory. So unless you allow space for Doom to be in the start menu then you cannot launch the game even on a legitimate install. This was cause of the error that I encountered after a fresh install on a factory reset device.

Installer

Now that I know how the DRM checks are performed when the game launches it doesn’t explain where the wind.opt file comes from. For this I looked into the game installer itself. Using Universal Extractor 2 I extracted all the files within the installer DoomPDA.exe:

UNINSTALL_PATH
MAINDIR\Main.PPC_2577.CAB
MAINDIR\Main.INI
WIN\setup.exe

UNINSTALL_PATH is just the uninstall application that runs on the host Windows PC. The files Main.PPC_2577.CAB and setup.exe are the interesting files here. Main.PPC_2577.CAB is the installation file that is launched on the Pocket PC and can be further extracted:

MAINPP~1.000 -> CAB manifest file?
0000doom.001 -> Doom.exe
000doom1.002 -> doom1.wad
doomskin.003 -> doomskin.bmp
00readme.004 -> ReadME.doc
DOOMSK~1.005 -> doomskin1.bmp
DOOMSK~2.006 -> doomskin2.bmp
DOOMSK~3.007 -> doomskin3.bmp
DOOMSK~4.008 -> doomskin4.bmp
000000cp.009 -> cp.exe
000000gx.010 -> gx.dll

These files are mostly self-explanatory except for cp.exe. It isn’t installed into the same locations as the others but is installed to \Windows\cp.exe. Running it does nothing visually as it just closes straight away. Inspecting cp.exe in Ghidra it looks like this is the application that is writing to wind.opt file (along with Doom.exe and doom1.wad). Interestingly if you run cp.exe when the game is not installed (or in the wrong location) it will create the files Doom.exe and doom1.wad with just the 4 bytes in it.

cp.exe open in Ghidra.

So now I know what is creating/modifying the files I want to know what is actually launching cp.exe on device itself. I figured it had to be triggered from the PC side as nothing was standing out within Main.PPC_2577.CAB. The only other file from the installer is WIN\setup.exe. Again opening this in Ghidra it references cp.exe and passes the path to the function CeCreateProcess. Looking at the Microsoft documentation for CeCreateProcess it describes it as:

CeCreateProcess is a remote application programming interface (RAPI), which enables an application
running on a desktop computer to make function calls on a Windows CE–based device. This function is
used to run a new program. It creates a new process and its primary thread. The new process 
executes the specified executable file.
Creating the process cp.exe.

If you are quick enough, or your machine is slow enough, then during installation a dialog pops up with the doom title screen with the window title Hell Awaits You. This is WIN\setup.exe launching cp.exe on your device.

Hell Awaits You.

Modifications

Bypass Serial Numbers Don't Match! check

Now that I know how the DRM works, I can try to get around them. Looking at the first check in Binary Ninja’s Graph view it nicely shows how the code is branching:

First check in Binary Ninja.

This shows that at address 0x000384f0 it is performing a conditional check (beq) on the wind.opt file and if it is true then it jumps to 0x0038758 where it displays the error message before exiting. I could mess around with the code and what it is checking, but an easier option is to have it so that both results of the beq check go to the same path. To do this, I change the instruction from:

0x000384f0 beq 0x38758

To be:

0x000384f0 beq 0x384f4

Now looking at the same location in Binary Ninja we can see that both arrows now jump to the next check (doom1.wad) and the block that displays the error message is now no longer visible.

First check patched in Binary Ninja.

This bypasses the first check but there are a couple more. The instructions to change are:

Original Instruction Patched Instruction
0x000384f0 beq 0x38758 0x000384f0 beq 0x384f4
0x00038524 beq 0x38758 0x00038524 beq 0x38528
0x00038568 bne 0x38758 0x00038568 bne 0x38604

Missing HELP2 lump

Other than adding the missing HELP2 lump to doom1.wad we can update the Doom.exe application using Ghidra or simply using a hex editor such as HxD. Simply searching for HELP2 within HxD and replacing the 2 with 1 is enough (or change the 32 to 31 if you are looking at the hex values). Alternatively you can add the missing HELP2 lump back in using SLADE.

doom1.exe open in HxD.

Install to SD Card

Even with the DRM checks, the game still requires doom1.wad to be located in \Program Files\DoomPDA\doom1.wad (along with some UI images). This can be a problem as this file is large, around 14mb, taking a majority of the internal storage of the device. Fortunately this is easily changed however it does have a limitation where the path cannot have more characters than the original value (at least without more hacking).

In Ghidra, search the strings panel for Program Files. There should be 10 values. Simply changes these to the path that you prefer. I changed the location to be Storage Card.

Running the game from the SD card appears to be fine, but it does take a bit longer to load than it does from main memory.

doom1.wad and WinTex

The developers of this port of Doom appear to have used WinTex to modify the doom1.wad and from what I can tell they have modified the WAD so that a couple of graphic lumps so that they display nicer on a Windows Mobile device. An example of this is the TITLEPIC lump which is the main title screen image. It is squashed horizontally to have black bars on the sides. The image itself is also a bit odd as it is from the shareware version of Doom as it has the text at the bottom of the image. The image on the left is from the PocketPC version while the one on the right is from the PC shareware release.

There are some other interesting things to found in the WAD file. The first is that the file identifies as a PWAD rather than an IWAD. This might be so that they could get around WAD editors blocking users from editing or creating IWADs. There is no difference in structure but IWADs are usually the main game file with PWADs being maps or mods that are loaded in addition to the IWAD. This can be seen at the start of the file in a hex editor along with the WinTex string.

PWAD and WinTex header.

The Doom.exe also references a lump called HELP2 which can be found in the shareware and non-Ultimate Doom IWAD but is not present in the provided WAD file. This makes me think that they may have started with either the shareware version and added in the missing content from the Ultimate Doom WAD file or only received the ‘full’ version later on and added in the updated TITLEPIC lump. The filename doom1.wad is also from the shareware version with doom.wad being the filename for the registered and Ultimate Doom versions. It does at least have the updated E1M4 map that removed the swastika reference. The fourth episode from the Ultimate Doom Thy Flesh Consumed is also present but cannot be accessed even with cheats.

Something that the developers may not have known is that when making changes using WinTex, it saves a history of changes to the WAD to the end of the file. This allows the user to ‘undo’ changes or mistakes that they have made. While it is a nice feature to have it does mean that there is roughly 2MB of extra data at the end of the WAD file that doesn’t need to be there. Combine this with the content from the inaccessible fourth episode doom1.wad could be a bit smaller. It is easy to remove this extra data if you would like to save more space, simply open the WAD in the editor SLADE and save it again. This drops the extra junk. To save even more bytes there is a list of unused lumps that can be removed on my GitHub repo. I have tried to check what was in this history but either I haven’t done it right, or I am using the wrong version of WinTex as I couldn’t see any differences.

Download Patch Files

While I can’t provide the updated Doom.exe and doom1.wad files I have uploaded VCDIFF patches that can be applied to the original files using an application such as xdelta. These can be found in my GitHub repo.