The code

The whole game lives inside the interrupt

INIT sets mode 1, hooks H.KEYI (0xFD9A) with a jp 0x402C, clears the RAM and then sits forever on the jr $ at 0x40A9. Everything else happens in the hook, once per frame: sound first, then the controls, then the scene. The lock at 0xE005 counts overlapping interrupts: if a frame runs long, the next one is served on the way out, without going back through the stack.

Tables sit right behind the call

despacha_por_tabla (0x404E) takes its own return address with pop hl, and that is where the table starts. That is how the scenes are dispatched, and the five set-ups (0x5FEF), the five starts (0x60B6) and the five frames (0x4C93).

Three data machines

Rewritten in Python in tools/:

And the ring, from the tables

tools/pista.py is the game frame routine by routine: it starts from the state left by 0x604C and each act's start-up (0x60B6), and every frame it moves and draws what the game moves and draws. Against 43 openMSX dumps: 0 bytes different (make coteja_pista). tools/corre_circus.py, which runs the cartridge on the Z80 in tools/z80run.py, stays as a second check (make coteja_arranque), not as the source of the pictures.