Dance minigame
A rhythm game. A beat counter advances with the music, a step chart says which button to press on each beat, and a press counts only inside a timing window around the beat. Closing a chain of correct presses pays points and fills a groove gauge, which promotes the dancer to a denser, higher-scoring chart row. Two rivals play the same chart through the same judge, so their scores are real runs rather than a scripted curve.
At a glance
- Overlay
- Extraction PROT 0980 at base
0x801CE818,0x8000bytes; initFUN_801CEF54 - Per-frame tick
FUN_801CF470: state machine onDAT_801D5334, beat clock, song end, grading- Judge
FUN_801D1960: window0xD2of a0x119-unit beat- CPU input
FUN_801D1820(chart lookup) intoFUN_801D4040(symbol to pad bit)- Step chart
0x801D509C, 3 rows of0x20beats, one byte per beat- Scoring tables
- Bonus points
0x801D41A4; CPU triangle schedule0x801D41E4 - Win flag
- Story flag
0x50A: set on entry, cleared on a loss - Port
- Rules
engine-minigames::dance; parsersminigame-formats::dance_chart,dance_cast,dance_art
Getting there
The door is the mode-24 minigame warp: field-VM op 0x3E with op0 = 106 (sub-id 6) sets game mode 0x18 and loads the overlay. It is the ordinary scene-backup, overlay-load, return-to-field sequence, so the game returns to the exact field state it suspended. The mechanism is on the field / event VM page.
This is the one sub-id where the loader’s index arithmetic steps: sub-ids of 6 and above add two, so sub-id 6 resolves to PROT 0980 rather than 0978. Every dance door on the disc is in one casino scene; the hall’s own scene module carries no genuine warp.
The beat clock
| Quantity | Value |
|---|---|
| Beat period | 0x119 (281) phase units |
| Acceptance window | phase 0..=0xD2; the remaining 71 units are dead |
| Chart cycle | 32 beats |
| Song length | 92 beats, or 60 in mode 2 |
The clock adds frame_delta * 10 per frame, so it is frame-rate compensated; the hall runs at a delta of 3. It advances only in the play, finish-countdown and result-wipe states.
The chart and the lanes
| Symbol | Meaning | Pad bit |
|---|---|---|
0 | rest | none |
1 | Square | 0x80 |
2 | Circle | 0x20 |
3 | Triangle - produced only by the CPU feed | 0x10 |
A dancer’s chart row is its difficulty lane, gauge / 1000, so the three rows are three tiers and every dancer reads the row its own gauge has promoted it to. Lane 0 places every one of its steps on a combo slot. All three tables are baked into the overlay image; nothing is loaded per song.
Judging a press
| Condition | Result | Score | Gauge |
|---|---|---|---|
| outside the window | miss | - | - |
| in window, wrong direction | miss | - | - |
| in window, match, chain still open | hit | nothing | - |
| in window, match, chain closes | chain closed | the bonus points | +250 |
A chain is lane + 1 matched notes in a row and must close inside one 8-beat bar. So a matching press that does not close a chain scores nothing - points come from completing a figure, not from individual notes.
The judged cell is not the fed symbol. The CPU feed can substitute a triangle on a combo slot; the judge always reads the raw cell. For anything that draws the chart, the note the player must press is the judged cell.
The triangle wildcard
Triangle matches no chart cell. It is a three-per-song wildcard with its own branch:
- On a combo slot inside the window it pays
(lane + 1) * 25and steps the gauge a full+1000- one whole lane. Anywhere else it pays(lane + 1) * 3and still spends a use. - The stock is set to 3 per dancer at the run reset and never replenished.
- The move spins the dancer
lane + 1full turns, and nothing that dancer presses is judged until the move’s clip ends. At the higher lanes that lockout covers the whole next combo slot.
The CPU dancers spend theirs on a schedule keyed to how many combo slots they have banked; the human’s row of that table is all zeros, because the human presses.
Score, gauge and the result
Score is clamped to 999 and has exactly two sources: the triangle and a closed chain. The groove gauge is clamped to [0, 2999] and no path in the overlay lowers it - not a miss, not a dropped chain. The level only rises.
The result state copies the three scores out, grades the run and clears the win flag on a loss: in modes 0 and 1 when the human loses the score comparison, in mode 2 against a fixed threshold of 300. Mode 3 leaves it untouched. The field script that follows tests the flag.
See also
The state machine state by state, the count-in, the dancer bodies and face stamps, the floor and step-marker rendering, the camera track and the HUD widget table are in docs/subsystems/minigame-dance.md.