155 lines
5.6 KiB
Markdown
155 lines
5.6 KiB
Markdown
# 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/<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:
|
|
|
|
```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.
|