Initial public source release

Split reusable rendering and format support into vectorail-core and vectorail-gc.
This commit is contained in:
2026-08-02 17:05:27 +02:00
commit 831d96e562
109 changed files with 20558 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
# 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.