experimental/replay.s

Download file

Release 2026-11-04-r2 · SHA256 bbf6536b597a6f6527973d2d07570507e34012f93c3dd256b4fa6ce398d91e35 · Click a line number for a direct link.

1    .ifndef WITH_REFINEMENTS2    .equ WITH_REFINEMENTS,03    .endif4    .ifndef WITH_REPLAY_HUD5    .equ WITH_REPLAY_HUD,06    .endif7    .ifndef WITH_FRAMED_PP_REPLAY8    .equ WITH_FRAMED_PP_REPLAY,09    .endif10    .if WITH_FRAMED_PP_REPLAY11    .equ PANEL_BYTES,180             | rows18..27: PP/fallback plus original clock/shot12    .else13    .equ PANEL_BYTES,9014    .endif15| Automatic goal replay (jdc 2026-10-25-r25): 1.5 s after every goal the game's own16| Instant Replay ($9FD0, the pause menu's VCR) starts by itself, plays the buffer with a17| scripted C press (r4: was "hold C", a still picture), then leaves with Start, Start (options menu, return to game).18| A + C held on either pad (Xbox X + B, as Abandon Season) skips to the end at once.19| +0 tick: called every frame by crowd.s (score watch, countdown, pause request)20| +4 pause: replaces bsr $7CF8 / bra $7938 at $7948 (the main loop's pause call)21| +8 pad: replaces tst.w $D046 / bne.w $A434 at $A41E (the replay's pad read)22    .equ ARST,0xFFF738                 | $A500 idle, $A501 requested, $A502 playing, $A503..$A506 exit23                                       | (2026-10-26-r3: anything else = idle. Menu screens write text over24                                       | $FFF7xx; a stale 1..6 made the pad hook feed fake input to the25                                       | pre-game menu after the season results: "Start Game" hung)26| Maintenance HUD code uses A507 for postgame ownership; it never scripts input.27    .equ ARCNT,0xFFF73A28    .equ CNTDN,0xFFF73C29    .equ LASTG,0xFFF73E30    .equ PLAYLEN,540                   | frames of play: the whole buffer (about 520)31    .text32    .globl _start33_start:34    bra.w tick35    bra.w pause36    bra.w pad3738tick:39    movem.l %d0,-(%sp)40    move.w 0xFFFFC6DA,%d0              | goals of both teams41    add.w 0xFFFFCA3E,%d042    andi.w #0xFF,%d043    ori.w #0xA500,%d0                  | r30: tagged; at the final horn the game zeroes this44    cmpi.w #1,0xFFFFF0DE               | Auto Replays Off: resync, discard pending countdown45    bne.s enabled46    move.w %d0,LASTG47    clr.w CNTDN48    bra.w 9f49enabled:50    cmp.w LASTG,%d0                    | RAM (LASTG 0 looked like 3 new goals: a replay after51    beq.s 3f                           | the game), so an untagged LASTG only resyncs52    cmpi.b #0xA5,LASTG53    bne.s 2f54    cmp.w LASTG,%d055    bcs.s 2f                           | fewer (a new game): no replay56    btst #0,0xFFFFC2FA                 | shootout: no replay57    bne.s 2f58    move.w #90,CNTDN592:  move.w %d0,LASTG603:  tst.w CNTDN61    beq.s 9f62    subq.w #1,CNTDN63    bne.s 9f64    move.w ARST,%d0                    | a replay already requested / running?65    subi.w #0xA501,%d066    cmpi.w #5,%d067    bls.s 9f68    move.w #0xA501,ARST                | ask the main loop for a pause: ours69    bset #0,0xFFFFC2EC709:  movem.l (%sp)+,%d071    rts7273pause:74    cmpi.w #0xA501,ARST75    beq.s 1f76    jsr 0x7CF8                         | an ordinary Start: the pause menu77    jmp 0x7938781:  bsr.s auto79    jmp 0x793880auto:                                  | the pause routine's frame, with the replay instead of the menu81    move.w #0xA502,ARST82    clr.w ARCNT83    jsr 0x10F3284    move.w %d0,-(%sp)85    move.w 0xFFFFB03E,%d0861:  cmp.w 0xFFFFB03E,%d087    beq.s 1b88    move.w (%sp)+,%d089    jsr 0x1A26490    move.w 0xFFFFC2EC,-(%sp)91    .if WITH_REPLAY_HUD92    suba.w #PANEL_BYTES+4,%sp93    move.l %a0,PANEL_BYTES(%sp)94    movea.l %sp,%a095    jsr 0x2EC004                       | save the actual lower-left panel before native clear96    movea.l PANEL_BYTES(%sp),%a097    .endif98    jsr 0x7E0E99    jsr 0x9FD0                         | Instant Replay100    .if WITH_REPLAY_HUD101    adda.w #PANEL_BYTES+4,%sp102    clr.l 0xFFFFF670103    .endif104    bclr #1,0xFFFFC2F6                 | consume replay's redraw latch; no menu dispatcher ran here105    move.w #0xA500,ARST106    clr.w 0xFFF728                     | crowd.s TICK: its meter tiles (replaced by REPLAY) next frame107    jmp 0x7D66                         | the pause routine's own exit (pops $C2EC, rts to pause)108109pad:110    move.l %d0,-(%sp)111    move.w ARST,%d0                    | scripted only while our replay runs ($A502..$A506)112    subi.w #0xA502,%d0113    cmpi.w #4,%d0114    movem.l (%sp)+,%d0                 | (movem keeps the flags)115    bls.s 1f116    .if WITH_REFINEMENTS117    | A41E is the native MENU/VCR input reader (enumerated16 UI callers),118    | separate from skating input. Preserve native non-input registers/status.119    tst.w 0xFFFFD046120    beq.s menu_single_pad121    jsr 0xA434122    bra.s menu_input_ready123menu_single_pad:124    jsr 0xA426125menu_input_ready:126    move.w %sr,-(%sp)127    jsr 0x25B038                      | explicit native caller -> contextual footer128    jsr 0x25B028                      | XboxA/nativeB aliases native Start/back129    move.w (%sp)+,%sr130    rts131    .else132    tst.w 0xFFFFD046                   | native133    beq.s 0f134    jmp 0xA4341350:  jmp 0xA426136    .endif1371:  movem.l %d4,-(%sp)138    jsr 0x11340                        | both real pads: A + C held = skip139    move.w %d3,%d4140    jsr 0x11358141    or.w %d3,%d4142    andi.w #0x60,%d4143    cmpi.w #0x60,%d4144    bne.s 2f145    cmpi.w #0xA502,ARST146    bne.s 2f147    move.w #0xA503,ARST1482:  movem.l (%sp)+,%d4149    moveq #8,%d0                       | no direction150    moveq #0,%d1151    moveq #0,%d2152    moveq #0,%d3153    cmpi.w #0xA502,ARST154    bne.s 3f155    addq.w #1,ARCNT                    | playing156    cmpi.w #PLAYLEN,ARCNT157    bcs.s 21f158    move.w #0xA503,ARST15921: jsr 0x2EC000                       | replaytitle.s: big "REPLAY" instead of the VCR box (r23)160    cmpi.w #2,ARCNT                    | 2026-10-26-r4: a NEW C press (d1 bit5, $A25E) toggles161    bne.s 22f                          | play; holding C (d3) only showed the first frame162    moveq #0x20,%d1163    moveq #0x20,%d2164    moveq #0x20,%d316522: rts1663:  cmpi.w #0xA503,ARST                 | r25: one Start leaves at once: with $C2F6 bit0 (options menu167    bne.s 5f                           | open) the native loop exits on Start ($A358 -> $A39E); the168    bset #0,0xFFFFC2F6                 | Options / Reverse Angle box no longer flashes before the game1694:  move.w #0x80,%d1170    move.w #0x80,%d2171    move.w #0x80,%d31725:  cmpi.w #0xA506,ARST173    bcc.s 6f174    addq.w #1,ARST1756:  rts176