Files
ReaperOfVeriod 1f903efe23 An external decomp turns two overlay constants from measured into named
OpenRAC/rac2-gc-decomp is the same disc as ours, verified rather than assumed:

  ours    3,828,350,976  9db2e33e...b1ce5
  theirs  3,828,350,976  9db2e33e...b1ce5

Vendored read-only under vendor/ (already gitignored) and added to PROVENANCE.

It names two constants this parser had measured but never explained:

  * overlay.bin +0x00 = 1,735,808 = 0x1A7C80, the .lit load base. It is constant
    across all 27 levels because every level's literal section loads at the same
    address. So the first header word is the load base of the section the file IS,
    which also establishes that overlay.bin is that section -- it holds both code
    and the debug string pool. $gp = 0x1AEFF0 comes with it, and that closes the
    roadmap's open "$gp for this game" item.

The program around it is seven sections -- .lit .bss .data vtbl camvtbl sndvtbl
.text -- which is precisely the "seven-section parser and relocation" Phase 3
item for this format. Known target now rather than a guess.

I then tested the obvious follow-up and it is wrong: if +0x00 is the .lit load
base, +0x0c ought to be the .lit size. It is SMALLER than the file on 16 of 27
levels, by up to 8.9% (level11: file 3,151,128 vs 2,870,792). Excluded by sign,
not by a near miss. Still unnamed.

Collision: still blocked, but no longer blocked on tooling. The decomp names
Camera_CollPrimTest(void *prim, void *grid) without decompiling it, so the cell
layout is not handed over. What it does supply is $gp, and that is enough to
start. "Camera_CollPrimTest WARNING! - grid out of bounds! (RAR)" is at
overlay+0xd18, the only copy in the file, so:

    string  overlay+0xd18 -> RAM 0x1a8998;  delta to $gp -0x6658;  $lo 0x99a8

MIPS puts the $lo half in bytes 1..3 of a 4-byte instruction. Searching the whole
overlay instruction-aligned gives exactly ONE hit:

    0x354cc8    (overlay+0x1ad048)

One occurrence in 2.75 MB of code is unambiguous: that is the instruction
materialising the assert string, and its enclosing function is
Camera_CollPrimTest. That is the route in, and it needs no symbols.

tools/overlay-anchors does this step, dependency-free. I started this with
capstone for the disassembly proper and dropped it: capstone 0.14 does not
re-export Mode/Endian from a public path, and an excluded-from-the-workspace
native dependency is a poor trade for a step that does not need one yet. The
anchor search is pure byte work, so it is pure Rust. No native dependency is
added anywhere, and the tool is an ordinary workspace member.

Surveyed the rest of that project against our open items: no volume structures,
no tie vertex layouts, no SBlk/DAW fields, no wavelet tables. It is a guide to
the code, not a replacement for reading it.
2026-10-13 07:07:21 +02:00

92 lines
2.5 KiB
TOML

[workspace]
resolver = "2"
members = [
"crates/gc-formats",
"crates/gc-extract",
"crates/gc-engine",
"crates/gc-game",
"crates/gc-video",
"tools/trace",
"tools/overlay-anchors",
]
[workspace.package]
version = "0.1.0"
edition = "2021"
rust-version = "1.85"
license = "MIT OR ISC"
publish = false
# The PS2's Emotion Engine is a MIPS R5900 with a 128-bit vector unit and a
# float model that differs from x86 in ways that matter for this game (no
# denormals, specific rounding). Every ported routine must reproduce that model
# rather than Rust's native f32, or the game will subtly not feel right.
# See docs/plan/float-model.md.
[workspace.dependencies]
gc-formats = { path = "crates/gc-formats" }
gc-extract = { path = "crates/gc-extract" }
gc-engine = { path = "crates/gc-engine" }
gc-game = { path = "crates/gc-game" }
gc-video = { path = "crates/gc-video" }
gc-trace = { path = "tools/trace" }
# Dev tools. PCSX2's savestates are zip archives whose entries are
# zstd- or deflate-compressed; both backends are pure Rust and are already
# in the lockfile through Bevy, so the trace tool adds no new sources.
ruzstd = "0.8"
flate2 = { version = "1", default-features = false, features = ["rust_backend"] }
anyhow = "1"
thiserror = "2"
bytemuck = { version = "1", features = ["derive", "min_const_generics"] }
sha1 = "0.10"
# Bevy 0.19.1 is the engine ReRAC uses; matching it keeps the GS/VU work portable.
#
# default-features = false avoids the cpal audio backend, which needs system
# ALSA development headers on Fedora (alsa-lib-devel). Audio decode lives in
# gc-video and is the last phase of the port, so the host audio backend is not
# needed to build. Re-enable "audio" and install alsa-lib-devel when it is.
bevy = { version = "0.19.1", default-features = false, features = [
"std",
"bevy_asset",
"bevy_color",
"bevy_core_pipeline",
"bevy_gizmos",
"bevy_log",
"bevy_mesh",
"bevy_pbr",
"bevy_render",
"bevy_shader",
"bevy_sprite",
"bevy_state",
"bevy_text",
"bevy_ui",
"bevy_window",
"bevy_winit",
"bevy_animation",
"bevy_gltf",
"png",
"ktx2",
"zlib",
"zstd_rust",
"tonemapping_luts",
"multi_threaded",
"x11",
"wayland",
"keyboard",
"mouse",
"gamepad",
] }
[profile.dev]
# Iterate fast on our own code; do not rebuild dependencies unoptimised.
opt-level = 1
[profile.dev.package."*"]
opt-level = 3
debug = false
[profile.release]
lto = "thin"
codegen-units = 1