Release 2026-11-04-r2 · SHA256 0f1ea83d8f67cdc29c2dab9ee71ce2120749614df8b74b8409089ccf3bbde555 · Click a line number for a direct link.
1 .ifndef WITH_REFINEMENTS2 .equ WITH_REFINEMENTS,03 .endif4 .ifndef WITH_TRANSFERS5 .equ WITH_TRANSFERS,06 .endif7 .equ TRANSFER_ROW_SHIFT,2*WITH_TRANSFERS8 .ifndef WITH_MOMENTUM9 .equ WITH_MOMENTUM,010 .endif11 .ifndef WITH_FACEOFF_DOTS12 .equ WITH_FACEOFF_DOTS,013 .endif14 .ifndef WITH_AI_SHOT_PLAN15 .equ WITH_AI_SHOT_PLAN,016 .endif17 .ifndef WITH_STRICT_SO18 .equ WITH_STRICT_SO,019 .endif20 .ifndef WITH_ALT_GOALIES21 .equ WITH_ALT_GOALIES,022 .endif23 .ifndef WITH_PICKUP_DELAY24 .equ WITH_PICKUP_DELAY,025 .endif26 .ifndef WITH_PASS_CHARGE27 .equ WITH_PASS_CHARGE,028 .endif29 .ifndef WITH_PENALTY_RATE30 .equ WITH_PENALTY_RATE,031 .endif32| Optional human B-input dispatch and continuous human receiver-cone geometry.33| CPU dopass, outlet and both CPU scan branches retain original r6 instructions.34| +0 input dispatcher, +4 cone, +8 custom human pass, +12 menu writer,35| +16 mapped load, +20 mapped record put, +24 human keeper fallback, +28 legacy cone.36| RAM F0FC/F0FE; existing complemented preference record1EEE/4D20.37 .equ MODE,0xFFFFF0FC38 .equ CONE,0xFFFFF0FE39 .equ HEIGHT,0xFFFFF0DC40 .equ SPEED,0xFFFFF0E841 .equ VIEW,0xFFFFF06C42 .equ MAP,0xA130F143 .text44 .globl _start45_start:46 bra.w input_dispatch47 bra.w cone48 bra.w custom_pass49 bra.w writer50 bra.w load51 bra.w put52 bra.w keeper_fallback53 bra.w legacy_cone54 .if WITH_PASS_CHARGE55 bra.w legacy_input_dispatch | +32, private charging fall-through56 bra.w emit | +36, charged release57 .endif5859human_allowed: | D0=0 allowed, -1 native; caller saves registers60 btst #3,0x62(%a3)61 beq.s not_human62 tst.w 0x34(%a3)63 bmi.s not_human64 btst #0,0xFFFFC2FA65 bne.s not_human66 btst #2,0xFFFFC2F267 bne.s not_human68 moveq #0,%d069 rts70not_human:71 moveq #-1,%d072 rts7374input_dispatch: | human input BC40; CPU calls BC64 directly75 .if WITH_PASS_CHARGE76 jmp 0x2E820477legacy_input_dispatch:78 .endif79 btst #4,%d280 bne.s emit81 btst #3,0xFFFFC2F682 bne.s emit83 btst #3,%d084 bne.w no_emit85 andi.w #7,%d086 move.w %d0,0xFFFFBEDC87 bset #3,%d088emit:89 .if WITH_PICKUP_DELAY90 jsr 0x220000 | only an actual human release, never a held charge91 .endif92 move.w %sr,-(%sp)93 move.l %d0,-(%sp)94 bsr.w human_allowed95 bne.s native_emit96 btst #3,0xFFFFC2F697 bne.s native_emit | native forced/special pass path retains its behavior98 cmpi.w #1,MODE99 beq.s directional_emit100 move.w CONE,%d0101 subq.w #1,%d0102 cmpi.w #2,%d0103 bhi.s native_emit104 move.w #-1,0xFFFFBEE0 | no stale target if this explicit cone finds nobody105native_emit:106 move.l (%sp)+,%d0107 move.w (%sp)+,%sr108 .if WITH_PASS_CHARGE109 jmp 0x2E8218110 .else111 jmp 0xBC64112 .endif113no_emit:114 jmp 0xBC3E115116directional_emit:117 move.l (%sp)+,%d0118 move.w (%sp)+,%sr119 bra.w custom_pass120121cone:122 move.w %sr,-(%sp)123 movem.l %d0-%d7/%a0-%a6,-(%sp)124 bsr.w human_allowed125 bne.w native_cone126 move.w CONE,%d7127 subq.w #1,%d7128 cmpi.w #2,%d7129 bhi.w native_cone | Default or invalid: exact old human/co-op octant test130 | D1/D2 are actual dx/dy, before native angle quantization. Use the sign-only131 | 8-direction basis: dot/cross ratio does not depend on vector normalization.132 move.w 0xFFFFBEDC,%d0133 andi.w #7,%d0134 lsl.w #2,%d0135 lea vectors(%pc),%a0136 move.w (%a0,%d0.w),%d3137 move.w 2(%a0,%d0.w),%d4138 move.w %d1,%d0139 muls.w %d3,%d0140 move.w %d2,%d5141 muls.w %d4,%d5142 add.l %d5,%d0 | forward dot, positive only143 ble.w reject144 move.w %d1,%d5145 muls.w %d4,%d5146 move.w %d2,%d6147 muls.w %d3,%d6148 sub.l %d6,%d5 | cross149 bpl.s cross_positive150 neg.l %d5151cross_positive:152 | A positive dot can be65536 only at the extreme diagonal corner with cross0.153 | That exact on-axis case is accepted before16-bit MULU, avoiding truncation.154 tst.l %d5155 beq.s accept156 mulu.w #4096,%d5157 add.w %d7,%d7158 lea tangents(%pc),%a0159 mulu.w (%a0,%d7.w),%d0160 cmp.l %d0,%d5161 bhi.s reject162accept:163 andi.w #0xFFF0,60(%sp) | preserve X and upper SR; Z=1 means pass native BHI164 ori.w #4,60(%sp)165 bra.s cone_done166reject:167 andi.w #0xFFF0,60(%sp) | Z=0/C=0: native BHI rejects168cone_done:169 movem.l (%sp)+,%d0-%d7/%a0-%a6170 move.w (%sp)+,%sr171 rts172native_cone:173 movem.l (%sp)+,%d0-%d7/%a0-%a6174 move.w (%sp)+,%sr175 bra.w legacy_cone176vectors:177 .word 0,1, 1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1178tangents:179 .word 1097,2364,4096 | floor(4096*tan(15/30/45 degrees)), half-angle180181legacy_cone: | exact r6 predicate for human Default/special callers182 btst #3,0x62(%a3)183 beq.s legacy_cpu184 btst #3,0x62(%a1)185 beq.s legacy_cpu186 cmp.l #0x40000,%d0187 rts188legacy_cpu:189 cmp.l #0x10000,%d0190 rts191192keeper_fallback: | called only by the existing HUMAN-only branch193 move.w %sr,-(%sp)194 move.l %d0,-(%sp)195 bsr.w human_allowed196 bne.s old_keeper_score197 move.w CONE,%d0198 subq.w #1,%d0199 cmpi.w #2,%d0200 bhi.s old_keeper_score201 move.w #-1,0xFFFFBEE0202 move.l (%sp)+,%d0203 move.w (%sp)+,%sr204 jmp 0x2FF1EE | initial scan found none in cone: no blind angle override205old_keeper_score:206 move.l (%sp)+,%d0207 move.w (%sp)+,%sr208 btst #3,0x62(%a1)209 beq.s score_candidate210 lsr.l #8,%d2211score_candidate:212 jmp 0x2FF1E4213214custom_pass: | alternate human-only dopass; standard native outer frame215 movem.l %d0-%d5/%a0-%a1,-(%sp)216 bclr #2,0xFFFFC2EC217 st.b 0xFFFFB7AA218 move.b #0x10,0x5E(%a3)219 move.w 0x52(%a3),0xFFFFBEDA220 bclr #3,0xFFFFC2F6 | eligibility retained the original special path above221 moveq #8,%d0222 tst.w 0x34(%a3)223 beq.s pass_power224 move.b 0x6E(%a3),%d0225pass_power:226 asl.w #2,%d0227 asr.w #1,%d0228 addi.w #0xA0,%d0229 move.w %d0,0xFFFFBEDE230 btst #0,0x6E(%a3)231 beq.s power_ready232 asr.w #4,%d0233 add.w %d0,0xFFFFBEDE234power_ready:235 .if WITH_PASS_CHARGE236 jsr 0x2E8208237 .endif238 move.w #-1,0xFFFFBEE0239 move.w 0xFFFFBEDC,%d0240 andi.w #7,%d0241 asl.w #2,%d0242 lea 0x10E64,%a0243 move.w 2(%a0,%d0.w),%d1244 muls.w 0xFFFFBEDE,%d1245 moveq #10,%d2246 asl.l %d2,%d1247 divs.w #3000,%d1248 move.w %d1,0xFFFFB774249 move.w (%a0,%d0.w),%d1250 muls.w 0xFFFFBEDE,%d1251 asl.l %d2,%d1252 divs.w #3000,%d1253 move.w %d1,0xFFFFB772254 cmpi.w #1,SPEED255 bne.s free_lift256 move.w 0xFFFFB772,%d0257 muls.w #4,%d0258 divs.w #5,%d0259 move.w %d0,0xFFFFB772260 move.w 0xFFFFB774,%d0261 muls.w #4,%d0262 divs.w #5,%d0263 move.w %d0,0xFFFFB774264free_lift:265 move.w #0x600,0xFFFFB776266 cmpi.w #1,HEIGHT267 bne.s free_done268 move.w #0x300,0xFFFFB776269free_done:270 jmp 0xBDD8 | native pose/sound/outer return; pure keeper D-pad too271272record:273 lea 0x203DDD,%a0 | logical1EEE, after slots' complete1EAC..1EED snapshot274 tst.w VIEW275 bne.s record_ready276 lea 0x209A41,%a0 | logical4D20, excluded Light-bank profile gap277record_ready:278 rts279load:280 move.w %sr,-(%sp)281 movem.l %d0-%d2/%a0,-(%sp)282 bsr.s record283 .if WITH_REFINEMENTS284 move.w #1,HEIGHT285 .else286 clr.w HEIGHT287 .endif288 clr.w SPEED289 clr.w MODE290 clr.w CONE291 .if WITH_PENALTY_RATE292 .if WITH_REFINEMENTS293 move.w #1,0xFFFFF006294 .else295 clr.w 0xFFFFF006296 .endif297 .endif298 moveq #0,%d0299 move.b (%a0),%d0300 move.w %d0,%d1301 not.b %d1302 cmp.b 2(%a0),%d1303 bne.s loaded304 move.w %d0,%d1305 andi.w #0xFC,%d1306 cmpi.w #0x50,%d1 | legacyr6 height/speed, new choices default0307 .if WITH_REFINEMENTS308 beq.s tagged_old_values309 .else310 beq.s old_values311 .endif312 move.w %d0,%d1313 .if WITH_PENALTY_RATE314 andi.w #0xE0,%d1315 cmpi.w #0x80,%d1316 bcs.s loaded317 cmpi.w #0xE0,%d1318 beq.s loaded | top bits11 are reserved/corrupt319 move.w %d0,%d1320 lsr.w #5,%d1321 andi.w #3,%d1322 move.w %d1,0xFFFFF006323 .else324 andi.w #0xE0,%d1325 cmpi.w #0x80,%d1326 bne.s loaded327 .endif328 move.w %d0,%d1329 lsr.w #2,%d1330 andi.w #1,%d1331 move.w %d1,MODE332 move.w %d0,%d1333 lsr.w #3,%d1334 andi.w #3,%d1335 move.w %d1,CONE336 .if WITH_REFINEMENTS337 bra.s old_values338tagged_old_values:339 clr.w 0xFFFFF006 | a valid old-format100% selection remains100%340 .endif341old_values:342 move.w %d0,%d1343 andi.w #1,%d1344 move.w %d1,HEIGHT345 lsr.w #1,%d0346 andi.w #1,%d0347 move.w %d0,SPEED348loaded:349 .if WITH_REFINEMENTS350 jsr 0x258000351 .endif352 .if WITH_MOMENTUM353 jsr 0x226000354 .endif355 .if WITH_FACEOFF_DOTS356 jsr 0x224008357 .endif358 .if WITH_AI_SHOT_PLAN359 jsr 0x223010360 .endif361 .if WITH_STRICT_SO362 jsr 0x222010363 .endif364 .if WITH_ALT_GOALIES365 jsr 0x221010366 .endif367 .if WITH_PICKUP_DELAY368 jsr 0x220004369 .endif370 .if WITH_PASS_CHARGE371 jsr 0x2E820C372 .endif373 movem.l (%sp)+,%d0-%d2/%a0374 move.w (%sp)+,%sr375 rts376put: | A0mapped record; retain old put's D0-only scratch contract377 move.l %d1,-(%sp)378 moveq #0,%d0379 cmpi.w #1,HEIGHT380 bne.s put_speed381 addq.w #1,%d0382put_speed:383 cmpi.w #1,SPEED384 bne.s put_mode385 addq.w #2,%d0386put_mode:387 cmpi.w #1,MODE388 bne.s put_cone389 addq.w #4,%d0390put_cone:391 move.w CONE,%d1392 cmpi.w #3,%d1393 bhi.s put_tag394 lsl.w #3,%d1395 or.w %d1,%d0396put_tag:397 .if WITH_PENALTY_RATE398 move.w 0xFFFFF006,%d1399 cmpi.w #2,%d1400 bhi.s put_rate_ready401 lsl.w #5,%d1402 or.w %d1,%d0403put_rate_ready:404 move.w %d0,%d1405 andi.w #0x7C,%d1406 .else407 move.w %d0,%d1408 andi.w #0x1C,%d1409 .endif410 bne.s new_tag411 ori.w #0x50,%d0 | default new choices preserve exact r6 record encoding412 bra.s put_bytes413new_tag:414 ori.w #0x80,%d0415put_bytes:416 move.b %d0,(%a0)417 not.b %d0418 move.b %d0,2(%a0)419 .if WITH_PASS_CHARGE420 jsr 0x2E8210421 .endif422 .if WITH_PICKUP_DELAY423 jsr 0x220008424 .endif425 .if WITH_ALT_GOALIES426 jsr 0x221014427 .endif428 .if WITH_STRICT_SO429 jsr 0x222014430 .endif431 .if WITH_MOMENTUM432 jsr 0x226004433 .endif434 .if WITH_FACEOFF_DOTS435 jsr 0x22400C436 .endif437 .if WITH_AI_SHOT_PLAN438 jsr 0x223014439 .endif440 .if WITH_REFINEMENTS441 jsr 0x258004442 .endif443 move.l (%sp)+,%d1444 rts445writer:446 .if WITH_REFINEMENTS447 cmpi.w #48,%d7448 beq.s refinement_range449 cmpi.w #50,%d7450 bne.s original_range451refinement_range:452 cmpi.w #1,%d3453 bhi.w flags454 bra.w writer_lock455original_range:456 .endif457 .if WITH_MOMENTUM458 cmpi.w #48+TRANSFER_ROW_SHIFT-4*WITH_REFINEMENTS,%d7459 bne.s not_momentum_range460 cmpi.w #1,%d3461 bhi.w flags462 bra.w writer_lock463not_momentum_range:464 .endif465 .if WITH_FACEOFF_DOTS && !WITH_REFINEMENTS466 cmpi.w #46+TRANSFER_ROW_SHIFT,%d7467 bne.s not_dots_range468 cmpi.w #1,%d3469 bhi.w flags470 bra.w writer_lock471not_dots_range:472 .endif473 .if WITH_AI_SHOT_PLAN474 cmpi.w #44+TRANSFER_ROW_SHIFT-2*WITH_REFINEMENTS,%d7475 bne.s not_plan_range476 cmpi.w #1,%d3477 bhi.w flags478 bra.w writer_lock479not_plan_range:480 .endif481 .if WITH_STRICT_SO && !WITH_REFINEMENTS482 cmpi.w #42+TRANSFER_ROW_SHIFT,%d7483 bne.s not_strict_range484 cmpi.w #1,%d3485 bhi.w flags486 bra.s writer_lock487not_strict_range:488 .endif489 .if WITH_ALT_GOALIES490 cmpi.w #40+TRANSFER_ROW_SHIFT,%d7491 bne.s not_alt_range492 cmpi.w #1,%d3493 bhi.w flags494 bra.s writer_lock495not_alt_range:496 .endif497 .if WITH_PICKUP_DELAY498 cmpi.w #38+TRANSFER_ROW_SHIFT,%d7499 bne.s not_pickup_range500 cmpi.w #1,%d3501 bhi.w flags502 bra.s writer_lock503not_pickup_range:504 .endif505 .if WITH_PASS_CHARGE506 cmpi.w #36+TRANSFER_ROW_SHIFT,%d7507 bne.s not_charge_range508 cmpi.w #1,%d3509 bhi.w flags510 bra.s writer_lock511not_charge_range:512 .endif513 cmpi.w #30+TRANSFER_ROW_SHIFT,%d7514 bne.s cone_range515 cmpi.w #1,%d3516 bhi.w flags517 bra.s writer_lock518cone_range:519 .if WITH_PENALTY_RATE520 cmpi.w #34+TRANSFER_ROW_SHIFT,%d7521 bne.s cone_range_old522 cmpi.w #2,%d3523 bhi.w flags524 bra.s writer_lock525cone_range_old:526 .endif527 cmpi.w #3,%d3528 bhi.w flags529writer_lock:530 tst.w VIEW531 beq.s writable532 tst.w 0xFFFFE3E8533 beq.s writable534 cmpi.w #1,0xFFFFE3F0535 beq.w flags536 cmpi.w #3,0xFFFFE3F0537 beq.w flags538 cmpi.w #4,0xFFFFE3F0539 beq.w flags540writable:541 move.w %sr,-(%sp)542 movem.l %d0-%d1/%a0-%a1,-(%sp)543 .if WITH_REFINEMENTS544 lea 0xFFFFF8D8,%a0545 cmpi.w #48,%d7546 beq.w selected_value547 lea 0xFFFFF8DA,%a0548 cmpi.w #50,%d7549 beq.w selected_value550 .endif551 .if WITH_MOMENTUM552 lea 0xFFFFF84A,%a0553 cmpi.w #48+TRANSFER_ROW_SHIFT-4*WITH_REFINEMENTS,%d7554 beq.w selected_value555 .endif556 .if WITH_FACEOFF_DOTS && !WITH_REFINEMENTS557 lea 0xFFFFF848,%a0558 cmpi.w #46+TRANSFER_ROW_SHIFT,%d7559 beq.w selected_value560 .endif561 .if WITH_AI_SHOT_PLAN562 lea 0xFFFFF810,%a0563 cmpi.w #44+TRANSFER_ROW_SHIFT-2*WITH_REFINEMENTS,%d7564 beq.w selected_value565 .endif566 .if WITH_STRICT_SO && !WITH_REFINEMENTS567 lea 0xFFFFF046,%a0568 cmpi.w #42+TRANSFER_ROW_SHIFT,%d7569 beq.s selected_value570 .endif571 .if WITH_ALT_GOALIES572 lea 0xFFFFF012,%a0573 cmpi.w #40+TRANSFER_ROW_SHIFT,%d7574 beq.s selected_value575 .endif576 .if WITH_PICKUP_DELAY577 lea 0xFFFFF010,%a0578 cmpi.w #38+TRANSFER_ROW_SHIFT,%d7579 beq.s selected_value580 .endif581 .if WITH_PASS_CHARGE582 lea 0xFFFFF008,%a0583 cmpi.w #36+TRANSFER_ROW_SHIFT,%d7584 beq.s selected_value585 .endif586 .if WITH_PENALTY_RATE587 lea 0xFFFFF006,%a0588 cmpi.w #34+TRANSFER_ROW_SHIFT,%d7589 beq.s selected_value590 .endif591 lea MODE,%a0592 cmpi.w #30+TRANSFER_ROW_SHIFT,%d7593 beq.s selected_value594 lea CONE,%a0595selected_value:596 cmp.w (%a0),%d3597 beq.s writer_done598 ori.w #0x700,%sr599 move.w %d3,(%a0)600 move.b #1,MAP601 bsr.w record602 bsr.w put603 lea 0x200001,%a0604 tst.w VIEW605 bne.s checksum606 lea 0x208001,%a0607checksum:608 moveq #0,%d0609 move.w #0x1FFE-1,%d1610sum:611 add.b (%a0),%d0612 addq.l #2,%a0613 dbra %d1,sum614 not.b %d0615 move.b %d0,(%a0)616 not.b %d0617 move.b %d0,2(%a0)618 move.b #0,MAP619writer_done:620 movem.l (%sp)+,%d0-%d1/%a0-%a1621 move.w (%sp)+,%sr622flags:623 tst.w %d2624 rts625