# 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`, and `TuneGameManager_Draw.cpp` source 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): ```text 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: ```text 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: ```text stage/data_gz/.dat.gz stage/data_gz/_ext.dat.gz stage/data_gz/_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: ```text 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: ```sh tools/run_switch_stage.sh /path/to/decoded/romfs sw_adr_hard_1 ``` List the available chart IDs with: ```sh 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; - `fMode` 1 evaluates both endpoint cameras, rebuilds endpoint up vectors, then interpolates the complete camera states; - `fMode` 2 interpolates raw key fields before evaluation; - `aMode` has the same seven branches `0..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.