Muscle Dome
An arena contest fought as a ladder of ordinary battles. The player picks one of three courses and fights its fixed sequence of rounds, one real monster per round, with one party character. Between rounds the arena shows a tally that heals the fighter and banks casino coins; a finished contest pays the coins out.
Three things it is not
- Not a card battle. The four “cards” are the four direction commands, always the same four, each at that fighter’s own AP cost. Nothing is drawn, discarded or reshuffled.
- Not turn-limited. A leg ends on a knockout and on nothing else. The “Turns Left” strip in the same overlay belongs to a timed boss fight.
- Not part of the minigame-hub family. It shares no controller library with fishing, the slot machine, dance or Baka Fighter.
At a glance
- Contest init / re-entry
FUN_801CEA6C, PROT 0977 at base0x801CE818- Contest hub
FUN_801CF870, state byteDAT_801D1A78, 51-entry jump table0x801CE990(fourteen real states)- Opponent installer
FUN_801D1510- Tally screen / row maths
FUN_801CF074/FUN_801D1184- Settlement
FUN_801D0F60- Leg
- The shared battle round driver
FUN_801D0748and action SMFUN_801E295C, PROT 0898 - Contest cursor
_DAT_8007BAC0: low byte packs(course, round); bits0x100/0x200restrict items / Ra-Seru- Coins
- Running tally
_DAT_80084440, coin bank0x800845A4 - Tables
- Roster
0x801D1920, course descriptors0x801D1A08, score table0x801D1860 - Port
engine-minigames::muscle_dome,muscle_ringside;engine-battle-menus::muscle_dome_session;engine-minigame-scenes::muscle_dome_scene
Getting there
The door is the mode-24 minigame warp: field-VM op 0x3E with op0 = 105 (sub-id 5) 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.
Every dome door on the disc is in one casino record - the course menu. Each arm debits its entry fee and latches a course flag before its own warp. The battle exit selector is the second of only two writers of game mode 24: with the contest bit set it stores the arena mode instead of the field’s, which is what returns a finished round to the arena.
The contest hub
What a leg’s end routes to
| Leg | Next hub state |
|---|---|
| survived, course not exhausted | 0x0A - the between-leg tally |
| survived, course exhausted | 0x32 - settle, continuing |
| not survived | 0x32 - settle |
| ran | 0x32 - settle, gave up |
“Survived” is a single bit test on re-entry. “Continuing” is derived, not prompted - there is no continue prompt; the latch is raised on the one path where the course is exhausted and the fighter survived.
The tally heals
| Row | Value | Drains into |
|---|---|---|
| round | round * 2 * max_hp / 100 | the HP accumulator |
| turns | min(turns_taken, 8) * max_hp / 100 | the HP accumulator |
| outcome | [8, 12, 4, 2][min(outcome, 3)] * max_hp / 100 | the HP accumulator |
| score | score_table[course][round - 1] | the coin tally |
Three of the four lanes are healing, not score; only the fourth is coins. So a contest costs no permanent HP. The lanes drain one after another, one scaled step per frame with a voice blip per step.
The roll can be fast-forwarded. The tally arm opens by testing the press mask against 0xF4 and latching DAT_801D1AB4 (0x801CFD60..0x801CFD7C). That word is the step scaler’s bypass: while it is up a lane moves its whole remainder in one step, so one press rolls out everything left. Its only clear is the arena init.
Hub screens are envelopes
Each hub screen is a fade-in at its own rate, a hold and a fade-out. The counters are brightness levels clamped at 0x80 - a textured primitive’s neutral modulation - not durations, and every step is scaled by the adaptive frame-skip factor. The two card holds end early on any bit of pad & 0xF4. A port that counts frames ends the screens at the wrong instants and cannot be ended early by a button; one that draws them at 0x100 is twice retail’s brightness.
Settlement
| Case | Effect |
|---|---|
| Continuing | keeps the tally and adds the final score cell |
| Not continuing | halves the tally |
| Gave up | zeroes the tally |
| Gave up on round 1 | also sets a per-course flag - the trigger for running from the first battle in all three difficulties |
| Master course final fight, first time | awards the War God Icon, once per save |
A leg plays out as a battle
Nothing about a leg’s choreography is the dome’s own: a turn acts out on the battle’s animation and locomotion code, and the port plays it on the same kernels its battles use.
| Piece | What decides it |
|---|---|
| Clip speed | the anim tick’s rate law: rate / 4 keyframes a vsync at the normal speed byte |
| Where the walk stops | the range law FUN_8004E2F0: the attacker’s live position against the target’s body pair, the monster’s size class and the party reach offset |
| Travel | each clip’s own root speed and end step; a reaction slides its body back |
| The hit | the swing’s event frame; a flinch, or a knockdown on the killing hit |
| Walking home | none - the next string starts where the last one left the pair |
A walk that stopped on a margin of its own rather than on the range law is what left daylight between a fist and its target.
See also
The cursor packing, the course ladder, both restores, the arena data file and ringside stills, the round driver’s phases, the command input and the sound are in docs/subsystems/minigame-muscle-dome.md.