8.7 KiB
Japanese No Remorse Windows 9x Investigation
Question
Investigate the claim that the Japanese build of Crusader: No Remorse supports Windows 9x and can run natively on Windows 95 instead of requiring a DOS boot path.
Active Ghidra target for this note: /ja/CRUSADER.EXE.
Verdict
Current static-analysis verdict: strongly supports the claim.
The loaded Japanese executable is not just a DOS executable with a small helper around it. It is a native flat Win32 image with Windows API startup, Windows registry configuration, DirectDraw/DirectSound initialization, and one explicit Win9x-aware compatibility branch.
What is proven from static analysis:
- the Japanese binary is a PE-style Win32 program loaded at
00400000, with sections such asBEGTEXT,DGROUP,.idata,.reloc, and.rsrc - it creates a real top-level Windows game window and runs through Win32 startup code
- it initializes DirectDraw and DirectSound directly
- it reads and writes settings in the Windows registry
- it contains Japanese/Win9x-facing support clues, including IME handling and a
GetVersion-based compatibility branch
What is not proven by this pass:
- an actual runtime launch on real Windows 95 hardware or emulation
- whether extra runtime prerequisites such as the expected DirectX version are always present on a bare Windows 95 install
- whether every shipped JP build variant behaves the same way
So the safest wording is:
The claim that the Japanese release has a native Windows 9x execution path is strongly supported by the code. The stricter claim that it will always run on a stock Windows 95 machine without additional runtime requirements is not fully closed by static analysis alone.
Main Evidence
1. The loaded JP executable is a Win32 image, not the old DOS/NE game binary
Ghidra reports the active program as /ja/CRUSADER.EXE with entry at 004729e0.
Relevant image layout recovered from Ghidra:
Headers: 00400000 - 004003ffBEGTEXT: 00401000 - 0047afffDGROUP: 0047b000 - 00481bff.bss: 00482000 - 00495fff.idata: 00496000 - 00496dff.reloc: 00497000 - 0049e3ff.rsrc: 0049f000 - 004a03ff
That is a normal PE/Win32 layout, not the segmented NE or DOS-extender layout used by the original DOS executable.
2. The import table is decisively Windows-native
Recovered imports include all the major Windows subsystems expected of a native Win9x game executable:
- process and OS:
GetVersion,CreateThread,ExitProcess,TlsAlloc,VirtualAlloc,GetCommandLineA,GetModuleHandleA,GetModuleFileNameA - window/UI:
CreateWindowExA,RegisterClassA,DefWindowProcA,DispatchMessageA,PeekMessageA,ShowWindow,RegisterWindowMessageA,MessageBoxA - graphics:
DirectDrawCreate,CreateBitmap,CreateCompatibleDC,CreatePalette,TextOutA - audio/timing/input:
DirectSoundCreate,DirectSoundEnumerateA/W,timeGetTime,joyGetDevCapsA,joyGetPosEx - configuration/storage:
RegCreateKeyExA,RegOpenKeyExA,RegQueryValueExA,RegSetValueExA,CreateFileA,ReadFile,WriteFile - Japanese text/input support:
IsDBCSLeadByte,GetCPInfo,WINNLSEnableIME
This is not a DOS launcher plus one or two helper calls. It is a full Windows application stack.
3. The main window path is explicit and native
00445f40 is now named win32_create_main_window.
Key behavior recovered from decompilation:
- registers a window class with
RegisterClassA - creates a fullscreen popup window with
CreateWindowExA - uses the title string
"Crusader: No Remorse" - calls
ShowWindow(..., 10) - calls
WINNLSEnableIME(0,0)immediately after successful creation - registers
"MSWHEEL_ROLLMSG"
This is direct evidence of a native Windows UI path. The IME call is especially relevant in a Japanese build because it shows the executable is consciously managing Windows-side JP text/input behavior.
4. DirectDraw and DirectSound are initialized directly by the game
004459b0 is now named video_init_directdraw_and_directsound.
Recovered behavior:
- calls
DirectDrawCreate() - sets cooperative level and display mode on the DirectDraw object
- creates the palette and primary surface
- calls
DirectSoundCreate() - hides the cursor with
ShowCursor(0)
This is a classic Windows 9x era DirectX setup path. It strongly supports the idea that this build was intended to run as a native Windows game executable.
5. Registry-backed configuration is built in
String at 0047b178:
Software\Electronic Arts\Crusader: No Remorse\J1.21
004138e8 is now named config_load_registry_and_cfg.
Recovered behavior:
- reads
installpath,cdpath, andflicpathfromHKEY_LOCAL_MACHINE - reads user preferences such as
video,subtitles,limitblasts,animation,frameskip,musicvolume,soundvolume, andmousespeedfromHKEY_CURRENT_USER - falls back to parsing
crusader.cfg
00413760 is now named config_write_registry_string and writes string values back into the same registry branch.
This is strong evidence of a normal Windows-installed configuration model rather than a DOS-only setup flow.
6. There is a real Win9x-specific compatibility branch
00472c41 is now named win32_runtime_capture_process_context.
Recovered behavior:
- captures environment strings
- captures module filename and command line
- calls
GetVersion() - stores split version fields into globals at
0x47c09f,0x47c0a0, and0x47c0a1
The more important follow-up is 00476616, now named win32_tls_alloc_with_win9x_guard.
Recovered behavior:
- calls
TlsAlloc() - checks the saved
GetVersion()word - if the version word has the high
0x8000bit set, it retries while the TLS slot is less than3
That is not generic Windows code. It is exactly the kind of branch you expect when a program needs to behave differently on the Win9x line, where GetVersion() reports the platform using the high bit and some low TLS slots are treated specially.
This is the strongest single code-level clue that the executable was designed with Win9x behavior in mind, not just NT-family Windows.
Secondary Evidence
Japanese-specific Windows integration
The import set and main-window path together show several JP-specific Windows integration points:
WINNLSEnableIMEIsDBCSLeadByteGetCPInfo
That does not by itself prove Windows 95 compatibility, but it does reinforce that this is a localized Windows build, not a DOS build being loosely wrapped.
WinMM and joystick APIs
The import table also includes:
joyGetDevCapsAjoyGetPosExtimeGetTime
These are ordinary Windows multimedia/input APIs and fit the same native-executable picture.
Interpretation
The claim can be split into two parts.
Part A: "The Japanese version supports Windows 9x"
This is strongly supported.
The binary:
- is a Win32 image
- uses Win32 startup and window management
- uses DirectX-era Windows multimedia APIs
- uses Windows registry storage
- has a
GetVersionbranch that specifically distinguishes Win9x-style version reporting
Part B: "It can run on Windows 95 natively without switching to DOS first"
This is also strongly supported, but with one caveat.
The executable is clearly built to run as a native Windows application, and the version/TLS branch is the best evidence that Win9x behavior was considered explicitly. The remaining uncertainty is practical, not architectural: an actual Windows 95 runtime may still need the expected DirectX/runtime environment installed.
So the architectural answer is yes; the deployment answer is very likely yes, but not fully closed until runtime-tested on a Win95 environment.
Ghidra Changes Made During This Pass
Renamed and commented in the active /ja/CRUSADER.EXE database:
00472c41->win32_runtime_capture_process_context00476616->win32_tls_alloc_with_win9x_guard00445f40->win32_create_main_window004459b0->video_init_directdraw_and_directsound004138e8->config_load_registry_and_cfg00413760->config_write_registry_string
Each of those now has a decompiler comment explaining why it matters to the Win9x/native-Windows investigation.
Remaining Follow-Up
- Run the JP executable under an actual Windows 95 target or a faithful Win95 VM to confirm runtime behavior.
- Identify the expected DirectX version from installer files or runtime error strings.
- Trace the message pump and main game loop entry after window creation for a fuller WinMain reconstruction.
- Locate the import thunks or callsites for
GetCPInfoandIsDBCSLeadByteto document the JP text path more precisely. - Check whether the JP installer writes the same
J1.21registry branch or whether the executable can self-heal missing keys. - Compare the JP Windows binary against the English DOS binary to isolate which subsystems were ported versus shared.