english groove.exe (2000-10-17) supported next to the german one: named exe sites found by signatures per build (german patches byte-identical), base patch and every exe mod on both, unknown builds get a clear message; display diagnostics moved to troubleshooting with a warning (it flashes every monitor black)
This commit is contained in:
1 parent
f984019199
commit
ca22c75fac
26 files changed
+1285
-253
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
+57
-4
@@ -123,8 +123,8 @@ on Windows. German CD (`groove.exe` MD5 697d67a31c20079838c662d8187dbd86, 1,642,
|
||||
file offsets of the changed bytes: **0x579B, 0x57D0, 0x5810, 0x5859, 0x5880** (original 02,
|
||||
new 01; MD5 with only this part 6199a42eb7582b2a70b1ac6e29f00f43; the base patch also relocates the
|
||||
world-9 level records, see "groove.exe patches" below). The patcher searches the pattern
|
||||
(push of the subkey string VA + push HKLM) instead of fixed offsets, so other language builds work
|
||||
if their code is the same.
|
||||
(push of the subkey string VA + push HKLM) instead of fixed offsets; the English build has the
|
||||
changed bytes at the same file offsets. Supported builds: see "groove.exe versions" below.
|
||||
|
||||
File lookup (FUN_00415690): tries `HDPath\dir\file`, then `CDPath\dir\file` (checked with
|
||||
`_access`), and only then loops over drive letters with `GetDriveTypeA == DRIVE_CDROM`. A plain
|
||||
@@ -225,8 +225,9 @@ reads a CD folder, collects writes in `ctx.written`, resolves options (defaults
|
||||
(`platform/ExePatcher`, owner "base", always first) → exe changes of the enabled mods in apply
|
||||
order. Without exe mods the result is byte-identical to `ExePatcher.patch` (installer output);
|
||||
"Restore original" goes back to it. The base patch (REVISION 2) = HKCU + `relocateLevelRecords`
|
||||
(world-9 coin/flag arrays moved into .data's page slack, 4-byte address operands only, see
|
||||
testlevel-chapters.md); `ExePatcher.changes` lists both as byte runs. A mod gets the shared image with `ctx.exe()`; all changes are
|
||||
(world-9 coin/flag arrays moved into .data's page slack – English build: .rdata's page slack, and
|
||||
.rdata's section flags get the write bit, because its .data slack is only 43 bytes; 4-byte address
|
||||
operands only, see testlevel-chapters.md); `ExePatcher.changes` lists both as byte runs. A mod gets the shared image with `ctx.exe()`; all changes are
|
||||
attributed to the mod id, journaled into the mod's cache manifest (`"exe": [...]`) and replayed
|
||||
(with full verification) on a cache hit. Every patch/allocation is logged in apply.log
|
||||
(`exe <mod>: patch 0x… n bytes – label`).
|
||||
@@ -270,6 +271,58 @@ in cave code are fine). Tests: `exe/ExeImageTest` (real exe, re-parse + `objdump
|
||||
`mods/ModOptionsAndExeTest`; in-game check: `mods/ExeSmokeMod` (test classes, see below; its call
|
||||
counter is an `allocateData` block).
|
||||
|
||||
### groove.exe versions (`exe/GameExe`, `exe/Site`)
|
||||
|
||||
Two builds are supported; their code is the same but shifted, and the .data globals are laid
|
||||
out differently, so **no patch uses a fixed address**:
|
||||
|
||||
| Build | PE date | Size | SHA-256 |
|
||||
|---|---|---|---|
|
||||
| German (reference, all RE notes) | 2001-02-12 | 1,642,496 | `7832eda4ee47a717e94441f21b75a9f30d11445c9f2408c6135a8fc01812e95b` |
|
||||
| English first release ("Start Game", "Chapter") | 2000-10-17 | 1,634,304 | `bf0eb8829ed3e371c4e951ece0a7753acf2c28d07001b842e079b098576403b0` |
|
||||
|
||||
`exe.game()` (a `GameExe`, cached per `ExeImage`) identifies the build by SHA-256 (`build()`,
|
||||
`describe()` – logged in apply.log as `groove.exe: English version of 2000-10-17`) and resolves
|
||||
each named `Site` on the file **as parsed** (before any patch): `va(site)`, `original(site, n)` =
|
||||
the original bytes there (expected bytes for `patch`/`hookCall`, and the stolen bytes a detour
|
||||
re-emits, e.g. the frame handlers' `mov eax,[global]`). Rules in `Site`: `code(sig)` = unique
|
||||
match in .text, `??` masking absolute addresses and rel32 operands; `operand(sig, off)` /
|
||||
`operandAt(site, off)` = the absolute address an instruction uses (must lie in .data – globals
|
||||
are always read from code, never guessed); `callTarget(site)` = target of a call; `.calling(s)`
|
||||
also checks that the call at the site goes to `s`. Each site lists its German and English VA:
|
||||
`exe/GameExeTest` checks that both builds resolve to them and that every site disassembles
|
||||
(objdump) to the expected instruction; `mods/ExeVersionsTest` checks that the German output of
|
||||
every exe mod and option set is **byte-identical** to the output before the version layer (SHA-256
|
||||
golden values) and that every mod makes the same patches in the English exe;
|
||||
`ExeModCombinationsTest` runs all combinations on both. The English exe is read from
|
||||
`-Dllamamod.exeEn` (default `re/groove_en.exe`, gitignored – never commit it or add it to test
|
||||
resources); tests skip without it.
|
||||
|
||||
An unknown build fails on the first site that does not match exactly once, e.g.
|
||||
`groove.exe (unknown version (PE date …, … bytes)): MENU_FRAME (state 2 (main menu) frame handler …)
|
||||
not found – unknown program version. LlamaMod supports: German version of 2001-02-12, English
|
||||
version of 2000-10-17.` The base patch stays lenient (HKCU by pattern, relocation skipped).
|
||||
The mod cache key includes the exe hash for every build except the German one (whose keys did
|
||||
not change).
|
||||
|
||||
**In game** (apptest :25, 2026-11-07, English exe in `original/hd` with the **German CD data** –
|
||||
the English exe runs with it; menus are English because the strings are in the exe): main menu
|
||||
without logos after 17 s and no attract demo after 100 s (intro skip); boot to level (Village 2,
|
||||
TestLevel 9); practice F5/F8 restores the position; free camera F7 flies away from the llama;
|
||||
cheats: winedbg showed cheat flags 0x583DA0 = the chosen bits, energy 0x584500 stayed 0x5000
|
||||
after falls into water with `health`, dropped to 0x4000 without it; TestLevel chapter 9 → "Quit to
|
||||
Map Select" gives a sane map (Village / Chapter 1 / 55) instead of the broken progress.
|
||||

|
||||
|
||||
**Adding a build:** copy it to `re/` (gitignored), add a `GameExe.Build` (language, PE date, size,
|
||||
SHA-256), run `GameExeTest`: every failing site needs a longer/other signature (keep it unique in
|
||||
all builds; mask only addresses and rel32). For the new column, read each address off the
|
||||
resolved sites (or with a script that pairs relocation entries of matched instructions, as done
|
||||
for the English build: an operand is accepted only if most references to the German global agree),
|
||||
then add the column to `Site` and a case to `Build.va`. Check the base patch's free space
|
||||
(`ExePatcher.SLACK_SECTIONS`) and run `ExeVersionsTest` / `ExeModCombinationsTest`; then test in
|
||||
game.
|
||||
|
||||
### Antivirus false positives
|
||||
|
||||
A changed groove.exe with extra code may be flagged by antivirus programs (Windows Defender).
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ diagnostics) → `jmp 0x41C050`. The cave writes only game globals, so it needs
|
||||
|
||||
| Feature | State | In the mod |
|
||||
|---|---|---|
|
||||
| `-display_diagnostics` (DAT_005834D0) | works: writes `<COMPUTER>.dispdiag` (DDraw/D3D enumeration) into the game folder | option `diagnostics` (tested: ELIASPC.dispdiag, 60 KB) |
|
||||
| `-display_diagnostics` (DAT_005834D0) | works: writes `<COMPUTER>.dispdiag` (DDraw/D3D enumeration) into the game folder; FUN_0040f4f0 opens **every display mode of every DirectDraw device × D3D device** (FUN_00410550/FUN_00410700 = mode switch, FUN_00411000), logs caps and texture formats, closes it again, then returns and the game starts normally. On Windows with two monitors both screens flashed black for 30+ s (tester, 2026-11); invisible under Wine | option `diagnostics`, label "Troubleshooting: write display diagnostics", off by default, warning in its description (tested: ELIASPC.dispdiag, 60 KB) |
|
||||
| `c:\kingdom_dbg.txt` | dead: FUN_0040d2c0 (called from FUN_0043c220) only creates the file with "Logfile %s started now/today (write this code!)"; the 43 debug prints (FUN_00414600) go to OutputDebugStringA (0x6DC3E8), never to the file | no |
|
||||
| FrameAdvanceDelay (FUN_0043cb40) | slide show `In\001.bmp…` + `In\In.wav` at start, `Out\…` at exit, delay from registry `FrameAdvanceDelay` (default 1.0 s); folders are empty | no (data, not a cheat) |
|
||||
| F4 in game | requests state 0x0C (world map) – the normal "back to map" | no |
|
||||
|
||||
Reference in new issue
Block a user