At a glance

Overlay
Extraction PROT 0980 at base 0x801CE818, 0x8000 bytes; init FUN_801CEF54
Per-frame tick
FUN_801CF470: state machine on DAT_801D5334, beat clock, song end, grading
Judge
FUN_801D1960: window 0xD2 of a 0x119-unit beat
CPU input
FUN_801D1820 (chart lookup) into FUN_801D4040 (symbol to pad bit)
Step chart
0x801D509C, 3 rows of 0x20 beats, one byte per beat
Scoring tables
Bonus points 0x801D41A4; CPU triangle schedule 0x801D41E4
Win flag
Story flag 0x50A: set on entry, cleared on a loss
Port
Rules engine-minigames::dance; parsers minigame-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

acceptance window, phase 0..0xD2 dead zone weight 0x1000 on the beat 0 at the edge phase 0 0xD2 0x119 one 8-beat bar beat 0 beat 1 beat 2 beat 3 beat 4 beat 5 beat 6 beat 7 combo slot combo slot chain cleared beat & 3 == 3 is a combo slot: the only place the Triangle wildcard pays its multiplier
Hit quality is continuous: there is no Perfect / Good tier in the judge, only the weight. It scales the human’s bonus from half the table value at the window edge to the full value on the beat; a CPU dancer takes the flat table value.
QuantityValue
Beat period0x119 (281) phase units
Acceptance windowphase 0..=0xD2; the remaining 71 units are dead
Chart cycle32 beats
Song length92 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

SymbolMeaningPad bit
0restnone
1Square0x80
2Circle0x20
3Triangle - produced only by the CPU feed0x10

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

ConditionResultScoreGauge
outside the windowmiss--
in window, wrong directionmiss--
in window, match, chain still openhitnothing-
in window, match, chain closeschain closedthe 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) * 25 and steps the gauge a full +1000 - one whole lane. Anywhere else it pays (lane + 1) * 3 and 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 + 1 full 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.