| ← A674 | Map | A717 → |
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 | Map | A717 → |
