Documentation improvements
This commit is contained in:
parent
d78808d6b5
commit
c34f481c3a
34 changed files with 2800 additions and 20 deletions
200
docs/jp-remorse-windows9x-investigation.md
Normal file
200
docs/jp-remorse-windows9x-investigation.md
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# 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 as `BEGTEXT`, `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 - 004003ff`
|
||||
- `BEGTEXT: 00401000 - 0047afff`
|
||||
- `DGROUP: 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`, and `flicpath` from `HKEY_LOCAL_MACHINE`
|
||||
- reads user preferences such as `video`, `subtitles`, `limitblasts`, `animation`, `frameskip`, `musicvolume`, `soundvolume`, and `mousespeed` from `HKEY_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`, and `0x47c0a1`
|
||||
|
||||
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 `0x8000` bit set, it retries while the TLS slot is less than `3`
|
||||
|
||||
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:
|
||||
|
||||
- `WINNLSEnableIME`
|
||||
- `IsDBCSLeadByte`
|
||||
- `GetCPInfo`
|
||||
|
||||
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:
|
||||
|
||||
- `joyGetDevCapsA`
|
||||
- `joyGetPosEx`
|
||||
- `timeGetTime`
|
||||
|
||||
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 `GetVersion` branch 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_context`
|
||||
- `00476616` -> `win32_tls_alloc_with_win9x_guard`
|
||||
- `00445f40` -> `win32_create_main_window`
|
||||
- `004459b0` -> `video_init_directdraw_and_directsound`
|
||||
- `004138e8` -> `config_load_registry_and_cfg`
|
||||
- `00413760` -> `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
|
||||
|
||||
1. Run the JP executable under an actual Windows 95 target or a faithful Win95 VM to confirm runtime behavior.
|
||||
2. Identify the expected DirectX version from installer files or runtime error strings.
|
||||
3. Trace the message pump and main game loop entry after window creation for a fuller WinMain reconstruction.
|
||||
4. Locate the import thunks or callsites for `GetCPInfo` and `IsDBCSLeadByte` to document the JP text path more precisely.
|
||||
5. Check whether the JP installer writes the same `J1.21` registry branch or whether the executable can self-heal missing keys.
|
||||
6. Compare the JP Windows binary against the English DOS binary to isolate which subsystems were ported versus shared.
|
||||
Loading…
Add table
Add a link
Reference in a new issue