A2 Racer
Port nativo de A2 Racer para PC.
A2 Racer
Port nativo basado en xvilo/a2-racer-davilex-decomp.
README del repositorio
A2 Racer — static decompilation
Static reverse engineering of the Dutch CD-ROM release of A2 Racer (Davilex Entertainment, 1997), using REA with Ghidra as the decompiler backend.
This repo holds only tooling and decompiled output. The CD dump and the files unpacked from it are not committed. Keep them outside the repo, by default in ../A2Racer-dump/.
Layout
| Path | Contents |
|---|---|
tools/ | Scripts to unpack the dump and to decompile the game modules |
decompiled/<module>/ | Per module: decompiled.c (every function), functions.tsv, strings.tsv, and REA's overview.json |
decompiled/<module>/src/ | The same functions split into the original source files (opponent.c, camera.c, …; C runtime under crt/). sources.tsv says how each function was placed: A2MENU's debug info, a name match with A2MENU, a .cpp name in an assert string, or its neighbours |
build/ | Ghidra projects, REA snapshots and logs (not committed) |
The dump (not in this repo)
Expected input is A2RACER_AMST.BIN, with SHA-256 a6710ba40ea107cd822d5622d0cb564d02540e16dadf43ecb68202a60e3279ab. It has 46,245 raw 2352-byte sectors (CD-ROM XA Mode 2, one data track) and came without a .cue file.
Unpack it next to the repo:
D=../A2Racer-dump
python3 -I tools/bin2iso.py $D/A2RACER_AMST.BIN $D/A2RACER_AMST.iso
python3 -I tools/isoextract.py $D/A2RACER_AMST.iso $D/disc
bin2iso.py takes the 2048-byte user data from each sector. isoextract.py reads the Joliet directory tree and strips the ;1 version suffixes.
Decompile
export JAVA_HOME=~/opt/jdk-21.0.12.1+1
export GHIDRA_INSTALL_DIR=~/opt/ghidra_12.1.4_PUBLIC
tools/decompile_all.sh # all modules
tools/decompile_all.sh A2MENU.DAT # one module
A2_DISC=/elsewhere/disc tools/decompile_all.sh
For each module the script runs rea analyze (Ghidra provider, with a snapshot in build/). It then runs Ghidra headless with these scripts:
| Script | Does |
|---|---|
ApplyWatcom.java | Applies names, signatures and structures from symbols/, and parses symbols/directx.h, the DirectX 3/5 interfaces and structures the game uses. It also adds Watcom's register calling conventions, names shared tails, and defines short strings and float constants |
InferSignatures.java | For functions with no known signature, finds the register parameters (EAX, EDX, EBX, ECX) from the machine code, then the return type from the call sites. Each function gets __watcall0…__watcall4 by its register-parameter count, since Watcom preserves every argument register a function doesn't take. Each variadic call gets its real argument count |
TypeFromCalls.java | Gives each COM call (through the vtables in symbols/directx.h) a call-site signature so the decompiler knows the callee pops its arguments. It also types locals and globals whose address is passed to a struct-pointer parameter |
AutoNameVariables.java | Names variables from argument roles, call results, loop counters and types |
ExportDecompiled.java | Writes decompiled.c, functions.tsv (with each prototype) and strings.tsv |
tools/split_sources.py then splits the C export into the original source files.
Port
port/ is a clean Rust rewrite on SDL2 and OpenGL for Windows, Linux, macOS and the browser, built from the decompiled reference. The menus, movies and the race all run. The browser version is on GitHub Pages It downloads the CD image from the Internet Archive, or plays from your own copy. See port/README.md.
Game data
tools/a2extract.py <disc> <out> unpacks the resource archives and converts images to PNG (standard library only). Keep its output out of the repo, since it is the game's own data.
| Archive | Kind | Contents |
|---|---|---|
A2MRCS.IND/.IMG | named | Menu screens (PCX) and menu sounds and music (WAV) |
A2MRC.IND/.IMG | sprites | Menu buttons, labels and animation frames |
RCS.IND/.IMG | named | Race 3D models (.D3D), textures (PCX) and sounds (WAV) |
GAMESPR.IND/.IMG | sprites | Race dashboard and overlay sprites |
The formats:
- Named archive: the
.INDholds au16count followed by 24-byte entries{char name[16]; u32 unused; u32 offset}. - Sprite archive: the
.INDholds au16count followed byu32offsets into the.IMG. Each.IMGentry is{u16 width, height, center_x, center_y; u8 pixels[width*height]}, with 8-bit palette indices; the palette comes from the screen's PCX.
Tracks are ETAPPE<n>.TRK and ETAPPE<n>.OMP, one pair per stage. Movies are Smacker (.SMK).
Game modules
All are 32-bit x86 PE files built with Watcom C/C++ in 1997.
| File | Role |
|---|---|
A2.EXE | Launcher: reads infio.ini, then starts the modules below |
A2MENU.DAT | Menus, options, controls, save slots, scores |
A2SPEL.DAT | The race itself (Direct3D) |
A2MOVIE.DAT | Smacker video player for *.SMK |
Toolchain
- REA (
rea-agents) 6.7.0 - Ghidra 12.1.4
- Temurin JDK 21.0.12
Comentarios (0)
Inicia sesión para dejar un comentario.
Sé el primero en comentar sobre este juego.