forked from tsuki/openroller
Initial public source release
Split reusable rendering and format support into vectorail-core and vectorail-gc.
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user