← A674 Corner-bounce lookup for a two-axis hit Map A717 → Overlap test between two named objects
A680: Deflect the active ball off a solid pool object it overlaps
Deflects the active ball off the first solid pool object it overlaps. It queues the reflected heading, which the ball update applies later in the same frame.
ball_object_deflect A680 LD C,$01 Start the candidate scan in C at the first pool slot after the bat.
The second-bat skip is one-sided. A scan for ball B still tries ball A. Ball A's sprite pointer sits below the pass-through window, so ball B does deflect off ball A. While the double bat prize is not in effect, ball A and a real ball B deflect off each other here.
ball_object_deflect_0 A682 LD A,(double_bat_active) With the second bat in play, skip the slot that fills with it.
A685 OR A
A686 JR Z,ball_object_deflect_1
A688 LD A,C
A689 CP $02
A68B JR Z,ball_object_deflect_2
ball_object_deflect_1 A68D LD HL,overlap_slot_1 Skip the ball's own slot.
A690 LD A,C
A691 CP (HL)
A692 JR Z,ball_object_deflect_2
A694 LD HL,overlap_slot_2 Set the second overlap operand to the candidate slot.
A697 LD (HL),C
A698 CALL overlap_pair
A69B OR A On an overlap, deflect; otherwise fall through to the next slot.
A69C JR NZ,ball_object_deflect_3
ball_object_deflect_2 A69E INC C Advance to the next slot; stop after the last inhabitant slot with nothing queued.
A69F LD A,C
A6A0 CP $08
A6A2 RET Z
A6A3 JR ball_object_deflect_0
ball_object_deflect_3 A6A5 LD A,(overlap_slot_2) Point HL at the struck object's record in the object pool, 9 bytes per slot.
A6A8 LD B,A
A6A9 LD DE,$0009
A6AC LD HL,object_table
ball_object_deflect_4 A6AF ADD HL,DE
A6B0 DJNZ ball_object_deflect_4
A6B2 LD DE,$0006 Fetch the record's sprite-data pointer.
A6B5 ADD HL,DE
A6B6 LD A,(HL)
A6B7 INC HL
A6B8 LD H,(HL)
A6B9 LD L,A
Solidity is the struck object's sprite-data pointer. A pointer inside the window that starts at the first death-burst frame is pass-through and deflects nothing. One below or above it is solid. The window covers exactly the eight death-burst and four spawn-flash frames. A ball passes through an inhabitant only while it spawns or explodes.
A6BA PUSH HL Solidity test: a sprite-data pointer inside the fixed window is non-solid, so return without a deflection. Below or above the window, the object is solid and deflects.
A6BB LD DE,slot_death_burst_1
A6BE XOR A
A6BF SBC HL,DE
A6C1 POP HL
A6C2 JR C,ball_object_deflect_5
A6C4 LD DE,nonsolid_sprite_end
A6C7 SBC HL,DE
A6C9 RET C
ball_object_deflect_5 A6CA LD HL,bat_heading Read the ball's heading code, indexed by its slot, into B.
A6CD LD D,$00
A6CF PUSH HL
A6D0 LD A,(overlap_slot_1)
A6D3 LD E,A
A6D4 ADD HL,DE
A6D5 LD B,(HL)
A6D6 POP HL Read the struck object's heading code from the same array, into C.
A6D7 LD A,(overlap_slot_2)
A6DA LD E,A
A6DB ADD HL,DE
A6DC LD C,(HL)
The new heading mirrors the struck object's heading about the ball's, then turns it a half-turn. Both heading codes come from the heading array. One full-turn step folds the result back toward the valid range, and an extreme pair can still overshoot it. That is harmless, because the velocity setup resets any heading outside the range to the default before it indexes the velocity table.
A6DD LD A,B Mirror the struck object's heading about the ball's, then add a half-turn; see the routine notes.
A6DE SUB C
A6DF ADD A,B
A6E0 ADD A,$24
A6E2 CP $48 Fold the heading back into its band with one full-turn step either way.
A6E4 JR NC,ball_object_deflect_6
A6E6 ADD A,$48
A6E8 JR ball_object_deflect_7
ball_object_deflect_6 A6EA CP $90 Above the band instead: take a full turn back off.
A6EC JR C,ball_object_deflect_7
A6EE SUB $48
ball_object_deflect_7 A6F0 EX AF,AF' Stash the new heading, then point HL at this ball's pending-heading cell.
A6F1 LD HL,pending_heading_base
A6F4 LD A,(overlap_slot_1)
A6F7 LD D,$00
A6F9 LD E,A
A6FA ADD HL,DE
A6FB EX AF,AF' Store the pending heading.
A6FC LD (HL),A
A6FD LD HL,apply_heading_base Set this ball's apply flag so the ball update turns it onto the heading later in the same frame.
A700 ADD HL,DE
A701 LD (HL),$01
A703 LD A,(active_ball) Select the active ball state record for the bounce count; this arm takes ball A.
A706 OR A
A707 JR NZ,ball_object_deflect_8
A709 LD IY,ball_a_x_accum
A70D JR ball_object_deflect_9
ball_object_deflect_8 A70F LD IY,ball_b_x_accum This arm takes ball B.
ball_object_deflect_9 A713 CALL ball_accelerate Count the bounce against the rally interval.
A716 RET
← A674 Corner-bounce lookup for a two-axis hit Map A717 → Overlap test between two named objects
Fork me on GitHub