5.6 KiB
Groove Coaster Wai Wai Party Switch reverse notes
Status: work in progress. These notes describe the base title
0100EB500D92E000; update and DLC content have not yet been merged into the
analysis corpus.
Executable and engine lineage
The program NCA contains an AArch64 NSO (main). Converting it to ELF and
importing it into Ghidra exposes a stripped executable with relocations, RTTI,
and exception unwind data.
This is the same custom GC engine lineage as the arcade and Android builds,
not a Unity rewrite. Direct evidence in main includes:
- RTTI name
13CTuneGameData; - assertion/source paths under
D:/project/GC/svn/latest/Program/Main/Src/GCMain/Tune/Functions/; TuneGameData.cpp,TuneGameManager.cpp, andTuneGameManager_Draw.cppsource names;- the assertion label
LoadStageData; - stage paths
stage/data_gz/%s.dat.gz,%s_ext.dat.gz, and%s_clip.dat.gz.
Initial function mapping in the base Switch executable (Ghidra image addresses):
001456a0 CTuneGameData constructor
001457f0 CTuneGameData destructor
00145f60 CTuneGameData deleting destructor
0014a3d0 CTuneGameData::GetWayPosition
0014a560 CTuneGameData::GetCameraData
00134af0 asynchronous stage .dat/.ext/.clip loader
00155b50 TuneGameManager::LoadStageData owner/assert site
The names after the destructors are cross-matched against the symbol-bearing Android ARM64 build and then checked from their decompiled behavior.
RomFS inventory
The base RomFS contains 8,976 files (about 1.6 GiB). Important families are:
3421 .tumo scene models
2136 .gz compressed stage data
1790 .opus audio, normally named *.wav.opus
1052 .bntx Switch textures
104 .tusc
88 .bnvib
85 .dat boot/catalog tables
69 .efcb2
65 .uvb
57 .rvb
57 .mtx
19 .bnsh shaders
Gameplay audio names explicitly distinguish tap, slide-hold, scratch, critical, beat, and adlib hit effects. This makes the Switch assets useful for validating the note-type-to-sound mapping even where the arcade catalog uses numeric IDs.
Stage data compatibility
Each chart still consists of the familiar three files, now gzip-compressed:
stage/data_gz/<chart>.dat.gz
stage/data_gz/<chart>_ext.dat.gz
stage/data_gz/<chart>_clip.dat.gz
After gzip decompression the normal .dat is accepted directly by
OpenRoller's arcade StageDat and StagePattern parsers. For example,
sw_adr_hard_1.dat decodes as:
track points: 240
notes: 529
camera keys: 67
draw-distance keys: 21
background models: 8
background objects: 199
The parser also recovers all expected note types, authored camera modes, particle/visualizer keys, colors, and object animation. This is strong structural confirmation that the arcade field interpretations are not merely heuristics.
The Switch _clip.dat can be much larger than the main chart because it
contains baked per-frame object visibility/animation data, just like the
arcade clip stream.
All 712 main chart files in the extracted base-game RomFS parse successfully with the current OpenRoller stage parser. A chart can be staged and launched directly by ID:
tools/run_switch_stage.sh /path/to/decoded/romfs sw_adr_hard_1
List the available chart IDs with:
tools/run_switch_stage.sh /path/to/decoded/romfs --list
The launcher decompresses the chart, extension, and clip streams into
build/nsw_runtime, links the common model directory, converts the matching
Nintendo Switch OPUS stream with vgmstream-cli, and starts the Linux player.
Set VGMSTREAM_CLI=/path/to/vgmstream-cli if it is not on PATH or in the
repository build directory.
This currently provides chart, camera, note, clip, model geometry, and BGM
loading. The .bntx texture/material pipeline and the newer Switch song
catalog are not implemented yet, so a successfully running stage is not yet a
pixel-identical Switch presentation and there is no Switch-native song menu.
The BGM resolver finds a shipped audio stream for 711 of the 712 chart files,
including charts whose internal authoring-time BGM name differs from the
release filename. The sole exception is sw_shoukon_hard_1: it is absent from
the base stage_param.dat catalog and the base RomFS contains no matching BGM,
so this orphan chart can only be launched silently from that data set.
boot/stage_param.dat is a newer catalog revision. The current arcade catalog
parser does not consume it completely and must not be treated as compatible
until its extra fields are mapped from the Switch loader.
Camera cross-check
The Switch CTuneGameData::GetCameraData stores key timestamps in a separate
array and uses a 0x44-byte runtime camera payload rather than Android's
interleaved 0x48-byte record. Despite that storage change, its behavior is the
same:
- the active camera key is selected by timestamp;
fMode1 evaluates both endpoint cameras, rebuilds endpoint up vectors, then interpolates the complete camera states;fMode2 interpolates raw key fields before evaluation;aModehas the same seven branches0..6;- projection type and projection blend are separate results;
- the mode-2 hold branch samples the state one millisecond before the key.
This independently validates the camera evaluator currently documented in
re_gc_camera.md and implemented in the Linux player.
The projection/FOV policy remains platform-specific. The Android build calls
SwitchAspectValue(60.0, 68.5, 75.0) and selects the value for its 3:2,
16:9, or iPhone-X layout. The arcade executable instead establishes a normal
75-degree gameplay FOV. Therefore Android's aspect presets must not replace
the arcade target behavior in the Linux player.