Files

114 lines
4.2 KiB
Markdown

# GC 4.71 song catalog reverse notes
The Windows build loads its master song catalog from
`data/boot/stage_param.dat`. `LevelList.dat` is a different fixed-record table:
its 9002 bytes are a big-endian `u16` count of 1000 followed by 1000 records of
9 bytes, and it is not the song/asset relation table.
## Confirmed loader
`FUN_005e66a0` opens `data/boot/stage_param.dat`. It reads a big-endian `u16`
record count, allocates `count * 0xb4` bytes, and deserializes every variable-size
disk record into one `0xb4`-byte runtime entry. The dumped file contains 924
records. IDs are explicit and can have gaps; they are not array indices.
The loader stops after the declared record count; it does not require EOF.
GC 4.75 catalogs can append a version-specific metadata block after the song
array (one observed 917-record catalog has 4116 trailing bytes). The clean-room
reader therefore validates every declared record but intentionally leaves such
post-array data uninterpreted.
The game's primitives used by this loader are:
- `FUN_005d8bc0`: big-endian `u32`;
- `FUN_005d8cc0`: `u8`;
- `FUN_005d97d0`: `u8 byteLength` followed by that many string bytes;
- `FUN_005d96d0`: CP932-to-current-Windows-codepage conversion, used for display
strings but not asset identifiers.
The recovered runtime entry is:
```text
offset type confirmed/current meaning
0x00 u32 numeric song ID
0x04 string* display title
0x08 string* image/asset key
0x0c string* artist
0x10 string* source/subtitle
0x14 string* normalized sort key
0x18 u8 genre ID (1 anime, 2 Vocaloid, 3 rhythm game, 4 game,
5 variety, 6 original, 7 Touhou)
0x1c string* duration, e.g. "2:03"
0x20 u8[4] EASY/NORMAL/HARD/EXTRA ratings
0x30 string* BPM text
0x34 u8[4] per-difficulty BGM volume percentage
0x44 u8[4] per-difficulty SHOT volume percentage
0x54 u32[3] timing values (exact roles not yet named)
0x60 u8[2] not yet named
0x68 string* BGM base name
0x6c string*[4] alternate chart group (mostly empty in current songs)
0x7c string*[4] auxiliary chart suffixes
0x8c string*[4] EASY/NORMAL/HARD/EXTRA chart IDs
0x9c string* not yet named
0xa0 u32 not yet named
0xa4 u8[2] not yet named
0xac string* not yet named
0xb0 u8 not yet named
```
The clean-room implementation is in `src/gc/StageCatalog.cpp`; the old
nearby-string search used by `--track-info` has been replaced by this exact
record parser.
## Asset relation
For `Oshama Scramble!`, the catalog record contains:
```text
title Oshama Scramble!
image key oshama
artist t+pazolite
ratings 1, 7, 13, 0
BGM base bgm_b-879_oshama
charts ac_oshama_easy
ac_oshama_normal
ac_oshama_hard
```
The executable derives paths rather than storing full paths in the catalog:
```text
chart ID -> data/stage/<chart ID>.dat
data/stage/<chart ID>_ext.dat
data/stage/<chart ID>_clip.dat
BGM base -> data/stage/sound/<BGM base><BGM difficulty suffix>_BGM.wav
data/stage/sound/<BGM base><SHOT difficulty suffix>_SHOT.wav
data/stage/sound/<BGM base>_VIB.csv
image key -> data/stage/2d/<image key>_menu.dds
data/stage/2d/<image key>_start.dds
```
`FUN_0063ea70` confirms the three chart formats. `FUN_005b3980` and
`FUN_005b3850` build the `_menu.dds` path from runtime offset `+0x08`.
For English UI they first try `data/stage/2d/eng/<key>_menu.dds` and fall back to
the non-language directory. `_start.dds` follows the same rule.
`FUN_00613710` prefixes stage audio with `data/stage/sound/` and appends the
suffixes. If the stage-specific BGM cannot be found, it also has a legacy
fallback under `data/sound/`.
The stage `.dat` then supplies the playable geometry, notes, camera, authored
background color table, particles, visualizer data and object/model scene. The
`*_menu.dds` image is selection/game UI artwork, not the gameplay background.
## Inspecting a record
```sh
./build/openroller GC/data/boot/stage_param.dat --track-info ac_oshama_hard
```
This prints metadata, all difficulty chart IDs, and every derived stage, sound,
menu and start-image path with a missing-file marker where applicable.