experimental/shotmeter.s

Download file

Release 2026-11-04-r2 · SHA256 a8693679dfe04ef26268935517079f8fb542e45fa5be9e5d986e915eceffa43b · 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| r31: 8x5 shot panel, exactly the score box's size, directly above it:8| HUD plane E000 rows18..22 cols32..39. Smooth charge sprite centered inside;9| native KMH/MPH text uses six interior cells. Full = native raw charge31.10| Preserve recorded speed/charge through automatic replay; use resident HUD11| dash segments there because REPLAY temporarily borrows the crowd meter tiles.12| Clear on the first normal-rink frame after replay (including skip), or after13| the existing240-frame lifetime for ordinary shots. No new pattern VRAM/DMA.14| +0 logic from crowd.s; +4 sprite append (existing80-sprite bound).15    .equ MAGIC,0xFFF64016    .equ SHOOT,0xFFF642                | shooter object + 117    .equ CHG,0xFFF64418    .equ SHOW,0xFFF64619    .equ LIVE,0xFFF64820    .equ BLINK,0xFFF64A21    .equ OBJ,0xFFFFB04A22    .equ TILE,0x7E1                    | crowd.s bar tiles: +0 black 32x8, +4 white, +8 red, partials23    .equ PANEL,0xFFF64C                | 1 while the panel is in the HUD plane24    .equ ROW0,1825    .if WITH_LEFT_PANEL26    .equ COL0,027    .else28    .equ COL0,3229    .endif30    .equ HELD,0xFFF64E                 | last shot held throughout automatic replay31    .equ KMH,0xFFF65032    .equ MPH,0xFFF65233    .equ STILE,0x7E1                   | r38: the bar's own 4 tiles (crowd.s mkbar), HUD-plane cells34    .equ SBUF,0xFFEA00                 | crowd.s BBUF+25635    .equ BX,272+128                   | original smooth bar centered inside the 48px interior36    .equ BY,152+12837    .equ VDATA,0xC0000038    .equ VCTRL,0xC0000439    .text40    .globl _start41_start:42    bra.w logic43    bra.w draw44    .if WITH_STARS_HUD45    bra.w stars_prepare                 | +8 called BEFORE original Stars window drawing46    .else47    .if WITH_LEFT_PANEL48    rts49    nop50    .endif51    .endif52    .if WITH_LEFT_PANEL53    bra.w shotbar                      | +C shared native bar renderer54    bra.w erase                        | +10 ownership-aware clear55    bra.w panel_above                  | +14 native-font fallback56    .endif5758skip:                                  | C set: not on the normal rink view / in the automatic replay59    btst #7,0xFFFFC2EC60    bne.s 1f61    move.l %d0,-(%sp)62    move.w 0xFFF738,%d063    subi.w #0xA502,%d064    .if WITH_STARS_HUD65    cmpi.w #6,%d0                      | postgame A507 is a foreign HUD owner, not replay playback66    .else67    cmpi.w #5,%d068    .endif69    movem.l (%sp)+,%d070    bcs.s 1f71    andi.b #0xFE,%ccr72    rts731:  ori.b #1,%ccr74    rts7576logic:77    movem.l %d0-%d7/%a0-%a1,-(%sp)78    cmpi.w #0x534D,MAGIC79    beq.s 1f80    move.w #0x534D,MAGIC81    clr.l SHOOT82    clr.l SHOW83    clr.w BLINK84    clr.w HELD85    .if WITH_REFINEMENTS86    clr.w 0xFFFFF8DC87    .endif881:  move.w 0xFFF738,%d089    subi.w #0xA502,%d090    cmpi.w #4,%d091    bhi.s not_replay92    tst.w SHOW93    beq.w 9f94    move.w #1,HELD                    | freeze measured speed and charge, ignore replayed actors95    bra.w 9f96not_replay:97    tst.w HELD98    beq.s normal_view99    clr.w HELD100    clr.w SHOW101    clr.w SHOOT102    clr.w LIVE103    bsr.w erase                        | replay finished: remove the panel immediately104    bra.w 9f105normal_view:106    bsr.w skip107    bcc.s 11f108    clr.w SHOW                         | ordinary pause/menus keep no stale panel109    clr.w SHOOT110    clr.w LIVE111    bsr.w erase112    bra.w 9f11311: addq.w #1,BLINK114    tst.w SHOW115    beq.s 2f116    subq.w #1,SHOW117    bne.s 2f118    bsr.w erase                        | time is up1192:  clr.w LIVE120    .if WITH_REFINEMENTS121    jsr 0x258010                        | actual held human pass, same native charge bar122    tst.w %d0123    bmi.s no_pass_bar124    move.w %d0,CHG125    move.w #1,LIVE126    move.w #1,0xFFFFF8DC127    clr.w SHOW128    clr.w SHOOT                        | releasing a pass must not be measured as a shot129    bra.w 9f130no_pass_bar:131    tst.w 0xFFFFF8DC132    beq.s shot_scan133    clr.w 0xFFFFF8DC134    clr.w SHOW135    clr.w SHOOT136    bsr.w erase137shot_scan:138    .endif139    moveq #0,%d6                       | the pads' own players only (C320.., sides C328..)1403:  lea 0xFFFFC328,%a1141    tst.w (%a1,%d6.w)142    beq.s 4f143    lea 0xFFFFC320,%a1144    move.w (%a1,%d6.w),%d7145    cmpi.w #11,%d7146    bhi.s 4f147    move.w %d7,%d0148    lsl.w #7,%d0149    lea OBJ,%a0150    adda.w %d0,%a0151    cmpi.w #0x7FC,0x58(%a0)            | winding up a slapshot with the puck152    beq.s 31f153    cmpi.w #0x92E,0x58(%a0)154    bne.s 4f15531: cmp.w 0xFFFFB7AA,%d7156    bne.s 4f157    move.w %d7,%d0158    addq.w #1,%d0159    move.w %d0,SHOOT160    move.w 0xFFFFBEDE,%d0161    cmpi.w #31,%d0162    bls.s 32f163    moveq #31,%d016432: move.w %d0,CHG165    move.w #1,LIVE166    clr.w SHOW167    bra.w 9f1684:  addq.w #2,%d6169    cmpi.w #8,%d6170    bcs.s 3b171    move.w SHOOT,%d7                   | released?172    beq.w 9f173    subq.w #1,%d7174    move.w 0xFFFFB7AA,%d0175    cmp.w %d7,%d0176    beq.w 9f                           | still his (final swing frames)177    clr.w SHOOT178    tst.w %d0179    bpl.w 9f                           | someone else has it: no shot180    cmp.w 0xFFFFBED8,%d7               | the shooter of the loose puck181    bne.w 9f182    move.w 0xFFFFB772,%d0              | |v| = isqrt(vx^2 + vy^2)183    muls.w %d0,%d0184    move.w 0xFFFFB774,%d1185    muls.w %d1,%d1186    add.l %d1,%d0187    bsr.w isqrt188    move.l %d0,%d3189    mulu.w #763,%d0                    | km/h = V * 763 / 2^17190    moveq #17,%d1191    lsr.l %d1,%d0192    move.l %d3,%d4193    mulu.w #237,%d4                    | mph = V * 237 / 2^16194    swap %d4195    move.w %d0,KMH196    move.w %d4,MPH197    move.w #240,SHOW1989:  bsr.w refresh199    movem.l (%sp)+,%d0-%d7/%a0-%a1200    rts201202| panel: d0 = km/h, d4 = mph -> the score-box panel in the HUD plane203panel:204    .if WITH_LEFT_PANEL205    jmp 0x227000206    .endif207panel_above:208    movem.l %d0-%d7/%a0-%a1,-(%sp)209    move.w %sr,-(%sp)210    ori.w #0x700,%sr211    lea VDATA,%a1212    move.w %d0,%d5213    moveq #0,%d3                       | top frame214    bsr.w cellcmd215    move.w #0xA3FF,(%a1)216    moveq #5,%d22171:  move.w #0xA400,(%a1)218    dbra %d2,1b219    move.w #0xA401,(%a1)220    moveq #1,%d3                       | bar inside the first interior row221    bsr.w cellcmd222    move.w #0xA402,(%a1)223    tst.w HELD                         | r38 (jdc: skaters passed over the sprite bar): live, the224    bne.s held_bar                     | bar is four HUD-plane cells of its own, in front of them225coloured_bar:226    bsr.w shotbar227    move.w #0xA403,(%a1)228    move.w %d0,(%a1)229    addq.w #1,%d0230    move.w %d0,(%a1)231    addq.w #1,%d0232    move.w %d0,(%a1)233    addq.w #1,%d0234    move.w %d0,(%a1)235    move.w #0xA403,(%a1)236    bra.s bar_done237held_bar:238    .if WITH_REPLAY_HUD239    bra.w coloured_bar240    .endif241    moveq #0,%d6                       | replay uses six resident HUD dash segments242    tst.w HELD243    beq.s bar_empty244    move.w CHG,%d6245    subi.w #15,%d6246    bpl.s dash_positive247    moveq #0,%d6248dash_positive:249    cmpi.w #16,%d6250    bls.s dash_clamped251    moveq #16,%d6252dash_clamped:253    mulu.w #6,%d6254    addi.w #15,%d6255    divu.w #16,%d6256bar_empty:257    moveq #0,%d2258bar_cells:259    move.w #0xA403,%d0260    cmp.w %d6,%d2261    bcc.s dash_ready262    move.w #0x841B,%d0                  | native HUD minus, never shares replay-title pattern tiles263dash_ready:264    move.w %d0,(%a1)265    addq.w #1,%d2266    cmpi.w #6,%d2267    bcs.s bar_cells268bar_done:269    move.w #0xA404,(%a1)270    moveq #2,%d3                       | native six-cell text: 184KMH / 114MPH271    bsr.w cellcmd272    move.w #0xA402,(%a1)273    tst.w SHOW274    beq.s blank_speeds275    .if WITH_REFINEMENTS276    cmpi.w #1,0xFFFFF8D8277    beq.s selected_mph278    .endif279    move.w %d5,%d0280    bsr.w num3281    move.w #0x8438,(%a1)282    move.w #0x843A,(%a1)283    move.w #0x8435,(%a1)284    .if WITH_REFINEMENTS285    bra.s selected_speed_done286selected_mph:287    move.w %d4,%d0288    bsr.w num3289    move.w #0x843A,(%a1)290    move.w #0x843C,(%a1)291    move.w #0x8435,(%a1)292selected_speed_done:293    move.w #0xA404,(%a1)294    moveq #3,%d3295    bsr.w cellcmd296    move.w #0xA402,(%a1)297    moveq #5,%d2298selected_blank_row:299    move.w #0xA403,(%a1)300    dbra %d2,selected_blank_row301    bra.w speed_end302    .endif303    move.w #0xA404,(%a1)304    moveq #3,%d3305    bsr.w cellcmd306    move.w #0xA402,(%a1)307    move.w %d4,%d0308    bsr.w num3309    move.w #0x843A,(%a1)310    move.w #0x843C,(%a1)311    move.w #0x8435,(%a1)312    bra.s speed_end313blank_speeds:314    moveq #5,%d2315blank_first:316    move.w #0xA403,(%a1)317    dbra %d2,blank_first318    move.w #0xA404,(%a1)319    moveq #3,%d3320    bsr.w cellcmd321    move.w #0xA402,(%a1)322    moveq #5,%d2323blank_second:324    move.w #0xA403,(%a1)325    dbra %d2,blank_second326speed_end:327    move.w #0xA404,(%a1)328    moveq #4,%d3329    bsr.w cellcmd330    move.w #0xA405,(%a1)331    moveq #5,%d23322:  move.w #0xA406,(%a1)333    dbra %d2,2b334    move.w #0xA407,(%a1)335    .if WITH_LEFT_PANEL336    move.w #2,PANEL337    .else338    move.w #1,PANEL339    .endif340    move.w (%sp)+,%sr341    movem.l (%sp)+,%d0-%d7/%a0-%a1342    rts343| shotbar: white at low charge, native orange through the middle, solid red at full.344| No palette writes or blink; compose into SBUF -> d0 = first HUD map word.345shotbar:346    movem.l %d1-%d5/%a0,-(%sp)347    move.w CHG,%d5348    subi.w #15,%d5349    bpl.s 1f350    moveq #0,%d53511:  mulu.w #30,%d5352    divu.w #16,%d5353    cmpi.w #30,%d5354    bls.s 2f355    moveq #30,%d53562:  moveq #1,%d1357    moveq #4,%d2358    move.w #0x8000+STILE,%d4359    cmpi.w #10,%d5                    | first third white; native palette 1 colour 5 = orange360    bcs.s 4f361    moveq #5,%d1362    moveq #7,%d2363    move.w #0xA000+STILE,%d4364    cmpi.w #30,%d5365    bcs.s 4f366    moveq #0xA,%d1                     | maximum stays red throughout the windup/release3674:  move.w %d1,%d3                     | key: colour, fill; compose only on a change, or when368    lsl.w #8,%d3                       | the panel is new (after a replay REPLAY used $7E1..)369    or.w %d5,%d3370    tst.w PANEL371    beq.s 5f372    cmp.w 0xFFE8F4,%d3373    beq.s 6f3745:  move.w %d3,0xFFE8F4375    move.w %d5,%d0376    moveq #2,%d3                       | solid top/bottom rows inside the panel (r39)377    lea SBUF,%a0378    jsr 0x2E0024                       | crowd.s mkbar379    move.l #SBUF,(%a5)+380    move.w #64,(%a5)+381    move.w #STILE*32,(%a5)+3826:  move.w %d4,%d0383    movem.l (%sp)+,%d1-%d5/%a0384    rts385erase:                                 | the panel's 8x5 cells back to transparent $07FF386    tst.w PANEL387    beq.s 9f388    .if WITH_LEFT_PANEL389    cmpi.w #1,PANEL390    bne.s erase_above391    movem.l %d0-%d2/%a1,-(%sp)392    jsr 0x227004393    tst.w %d0394    beq.s compact_erased395    jsr 0x22700C396compact_erased:397    clr.w PANEL398    movem.l (%sp)+,%d0-%d2/%a1399    rts400erase_above:401    movem.l %d0-%d1,-(%sp)402    jsr 0x227010                       | native foreign windows may now own this rectangle403    tst.w %d0404    movem.l (%sp)+,%d0-%d1405    bne.s erase_owned_above406    clr.w PANEL407    rts408erase_owned_above:409    .endif410    movem.l %d0-%d3/%a1,-(%sp)411    move.w %sr,-(%sp)412    ori.w #0x700,%sr413    lea VDATA,%a1414    moveq #0,%d34151:  bsr.s cellcmd416    moveq #7,%d24172:  move.w #0x07FF,(%a1)418    dbra %d2,2b419    addq.w #1,%d3420    cmpi.w #5,%d3421    bcs.s 1b422    clr.w PANEL423    move.w (%sp)+,%sr424    movem.l (%sp)+,%d0-%d3/%a14259:  rts426cellcmd:                               | d3 = panel row 0..4 -> VDP write at (ROW0+d3, COL0) of the HUD plane427    movem.l %d0-%d1,-(%sp)428    moveq #ROW0,%d0                    | HUD plane $E000, 64 cells wide (VRAM dump r28)429    add.w %d3,%d0430    lsl.w #7,%d0431    addi.w #COL0*2,%d0                 | offset in the plane (< $2000)432    moveq #0,%d1433    move.w %d0,%d1434    swap %d1435    ori.l #0x60000003,%d1              | VRAM write at $E000 + offset436    move.w #0x8F02,VCTRL               | auto-increment 2437    move.l %d1,VCTRL438    movem.l (%sp)+,%d0-%d1439    rts440num3:                                  | d0 = 0..999 -> three HUD digit cells (leading blanks)441    movem.l %d0-%d2,-(%sp)442    andi.l #0xFFFF,%d0443    cmpi.w #999,%d0444    bls.s 1f445    move.w #999,%d04461:  divu.w #100,%d0447    move.w %d0,%d1                     | hundreds448    swap %d0449    andi.l #0xFFFF,%d0450    divu.w #10,%d0                     | tens in d0.w, ones in the high word451    move.w #0xA403,%d2452    tst.w %d1453    beq.s 2f454    move.w #0x841E,%d2455    add.w %d1,%d24562:  move.w %d2,(%a1)457    move.w #0xA403,%d2458    tst.w %d1459    bne.s 3f460    tst.w %d0461    beq.s 4f4623:  move.w #0x841E,%d2463    add.w %d0,%d24644:  move.w %d2,(%a1)465    swap %d0466    addi.w #0x841E,%d0467    move.w %d0,(%a1)468    movem.l (%sp)+,%d0-%d2469    rts470isqrt:                                 | d0.l unsigned -> d0 = floor(sqrt)471    movem.l %d1-%d3,-(%sp)472    moveq #0,%d1                       | result473    move.l #0x40000000,%d2             | bit4741:  cmp.l %d0,%d2475    bls.s 2f476    lsr.l #2,%d2477    bne.s 1b478    bra.s 4f4792:  move.l %d1,%d3480    add.l %d2,%d3481    cmp.l %d3,%d0482    bcs.s 3f483    sub.l %d3,%d0484    lsr.l #1,%d1485    add.l %d2,%d1486    bra.s 5f4873:  lsr.l #1,%d14885:  lsr.l #2,%d2489    bne.s 2b4904:  move.l %d1,%d0491    movem.l (%sp)+,%d1-%d3492    rts493494| Keep native HUD map/pattern memory intact. In play the original smooth495| crowd-tile sprite bar sits inside the box; in replay those tiles belong to496| REPLAY, so the fixed recorded charge is shown with native HUD dash glyphs.497refresh:498    .if WITH_LEFT_PANEL499    bsr.w skip500    bcs.s refresh_body501    jsr 0x227008502refresh_body:503    .endif504    tst.w SHOW505    bne.s visible506    tst.w LIVE507    bne.s visible508    tst.w SHOOT509    beq.s refresh_done510visible:511    move.w KMH,%d0512    move.w MPH,%d4513    bsr.w panel514refresh_done:515    rts516517draw:                                  | r38: no sprites (the bar is in the panel's HUD cells)518    rts519olddraw:520    cmpi.w #0x534D,MAGIC521    bne.w 9f522    bsr.w skip523    bcs.w 9f524    tst.w LIVE525    bne.s 1f526    tst.w SHOOT                        | the last swing frames before the release527    bne.s 1f528    tst.w SHOW529    beq.w 9f5301:  movem.l %d0-%d5,-(%sp)531    move.w CHG,%d5                     | fill 0..30 px of (CHG - 15) / 16532    subi.w #15,%d5533    bpl.s 2f534    moveq #0,%d55352:  mulu.w #30,%d5536    divu.w #16,%d5537    move.w #0x8000+TILE+4,%d3          | white538    cmpi.w #30,%d5539    bcs.s 3f540    move.w #0xA000+TILE+8,%d3          | full: red (palette 1), blinking while still winding up541    tst.w SHOW542    bne.s 3f543    btst #2,BLINK+1544    bne.w 6f5453:  move.w #BY,%d2546    move.w %d5,%d0547    lsr.w #3,%d0                       | whole tiles548    beq.s 4f549    move.w %d0,%d1550    subq.w #1,%d1551    lsl.w #2,%d1552    move.b %d1,%d0553    move.w #BX+1,%d1554    bsr.w sprs5554:  moveq #7,%d0                       | partial width 1..7 after them (crowd.s tile order)556    and.w %d5,%d0557    beq.s 6f558    move.w %d3,%d4559    add.w #11,%d4560    add.w %d0,%d4561    subq.w #4,%d4562    cmpi.w #0xA000,%d3563    bcs.s 5f564    addq.w #3,%d45655:  move.w %d3,-(%sp)566    move.w %d4,%d3567    move.w %d5,%d1568    andi.w #0xFFF8,%d1569    add.w #BX+1,%d1570    moveq #0,%d0571    bsr.w sprs572    move.w (%sp)+,%d35736:  move.w #0x8000+TILE,%d3            | black 32x8 background574    moveq #0x0C,%d0575    move.w #BX,%d1576    move.w #BY,%d2577    bsr.w sprs5788:  movem.l (%sp)+,%d0-%d55799:  rts580sprs:                                  | d0 size, d1 x, d2 y, d3 attribute (as crowd.s)581    cmpa.w #0xC298,%a6582    bcc.s 9f583    move.w %d2,(%a6)+584    move.b %d0,(%a6)+585    move.b %d6,(%a6)+586    move.w %d3,(%a6)+587    move.w %d1,(%a6)+588    addq.w #1,%d65899:  rts590    .even591592    .if WITH_STARS_HUD593stars_prepare:594    movem.l %d0-%d7/%a0-%a1,-(%sp)595    clr.l SHOOT596    clr.l SHOW597    clr.w HELD598    bsr.w erase                         | still our map cells: native Stars has not drawn yet599    movem.l (%sp)+,%d0-%d7/%a0-%a1600    rts601    .endif602603