Files
openroller/docs/re_gc_catalog.md
tsuki 831d96e562 Initial public source release
Split reusable rendering and format support into vectorail-core and vectorail-gc.
2026-08-02 17:05:27 +02:00

3.9 KiB

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 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:

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:

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:

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

./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.