| ← 997A | Map | 9AF3 → |
9988: Move the player's bat
|
Moves the player's bat up and down once per frame, from the sampled controls.
The chosen control style, direct or inertia, decides the step. Whatever is attached comes with it, both the bat extension and any ball caught on the bat.
Three gates can suppress the move, and the double bat tail runs even then.
|
|||||||||||||||
|
Both control styles test the same three travel bounds before they move the bat.
|
|||||||||||||||
| move_bat | 9988 | LD IX,object_table | Only the bat's Y moves here. The side the player chose fixes its column. | ||||||||||||
| 998C | LD A,(bat_sting_freeze) | Gate 1: the sting freeze. The bee sets it on its overlap with the bat itself, never on a sweep hit. While it is set, jump straight to the double bat tail. That skips all bat movement, so the player cannot steer the bat. Cleared when the last ball is lost (lose_ball_last) or by the level setup (clear_state_buffers). | |||||||||||||
| 998F | OR A | ||||||||||||||
| 9990 | JP NZ,track_double_bat | ||||||||||||||
| 9993 | LD A,(bat_freeze) | Gate 2: the bat freeze. If clear, go on to the third gate. If set, run the release timer below and hold position. | |||||||||||||
| 9996 | OR A | ||||||||||||||
| 9997 | JR Z,pick_bat_control | ||||||||||||||
| 9999 | LD HL,bat_freeze_timer | Frozen: count the freeze timer up by one this frame. | |||||||||||||
| 999C | INC (HL) | ||||||||||||||
| 999D | LD A,(HL) | ||||||||||||||
| 999E | CP $0F | Release the bat freeze once the hold runs out; either way jump to the double bat tail, and leave the bat where it is. | |||||||||||||
| 99A0 | JP NZ,track_double_bat | ||||||||||||||
| 99A3 | XOR A | ||||||||||||||
| 99A4 | LD (HL),A | ||||||||||||||
| 99A5 | LD (bat_freeze),A | ||||||||||||||
| 99A8 | JP track_double_bat | ||||||||||||||
| pick_bat_control | 99AB | LD A,(death_pause_timer) | Gate 3: the death-pause timer is set – skip all movement, but still run the double bat tail. | ||||||||||||
| 99AE | OR A | ||||||||||||||
| 99AF | JP NZ,track_double_bat | ||||||||||||||
| 99B2 | LD A,(bat_control_type) | Pick the control style: inertia runs inertia control, and either dual-speed style runs direct control below. | |||||||||||||
| 99B5 | OR A | ||||||||||||||
| 99B6 | JR NZ,apply_direct_control | ||||||||||||||
| 99B8 | CALL apply_inertia_control | ||||||||||||||
| 99BB | JP track_double_bat | ||||||||||||||
|
The direct control style. The step follows the control bits of the current frame, with nothing carried over from the frames before it.
The step is the slow speed, or the fast speed while fire is also held. The options screen sets both, on the rows it prints as DUAL SPEED SLOW and DUAL SPEED FAST. Up decreases the bat Y, down increases it. The edge test uses the position before the step, so a large step can carry the bat past the limit.
|
|||||||||||||||
| apply_direct_control | 99BE | LD HL,controls | Read the live control bits into HL. | ||||||||||||
| 99C1 | BIT 3,(HL) | Up held? | |||||||||||||
| 99C3 | JR Z,direct_down | ||||||||||||||
| 99C5 | LD A,(bat_speed_slow) | Take the slow speed as the step. | |||||||||||||
| 99C8 | LD B,A | ||||||||||||||
| 99C9 | LD A,(IX+$01) | Current bat Y | |||||||||||||
| 99CC | CP $26 | Blocked at the top edge – the bat cannot move further up. | |||||||||||||
| 99CE | JP C,track_double_bat | ||||||||||||||
| 99D1 | SUB B | Move the bat up by the slow speed. | |||||||||||||
| 99D2 | LD (IX+$01),A | ||||||||||||||
| 99D5 | CALL drag_attached_up | Drag the bat extension up with it. | |||||||||||||
| 99D8 | LD A,(bat_speed_slow) | ||||||||||||||
| 99DB | CALL drag_caught_up | Drag any caught ball up with it. | |||||||||||||
| 99DE | BIT 4,(HL) | Fire also held? Apply the fast-speed bonus. | |||||||||||||
| 99E0 | JP Z,track_double_bat | ||||||||||||||
| 99E3 | LD A,(bat_speed_slow) | Take the difference between the fast and slow speeds as the extra step. | |||||||||||||
| 99E6 | LD C,A | ||||||||||||||
| 99E7 | LD A,(bat_speed_fast) | ||||||||||||||
| 99EA | SUB C | ||||||||||||||
| 99EB | LD B,A | ||||||||||||||
| 99EC | LD A,(IX+$01) | ||||||||||||||
| 99EF | SUB B | Move up by the extra amount, for a total step of the fast speed this frame. | |||||||||||||
| 99F0 | LD (IX+$01),A | ||||||||||||||
| 99F3 | CALL drag_attached_up | ||||||||||||||
| 99F6 | LD A,B | ||||||||||||||
| 99F7 | CALL drag_caught_up | ||||||||||||||
| 99FA | JR track_double_bat | ||||||||||||||
| direct_down | 99FC | BIT 2,(HL) | Down held? | ||||||||||||
| 99FE | JR Z,track_double_bat | ||||||||||||||
| 9A00 | LD A,(expand_active) | An attached extension raises the bottom travel limit. | |||||||||||||
| 9A03 | OR A | ||||||||||||||
| 9A04 | JR Z,direct_down_clamp | ||||||||||||||
| 9A06 | LD A,(IX+$01) | ||||||||||||||
| 9A09 | CP $8A | Extension attached: the raised bottom limit applies. | |||||||||||||
| 9A0B | JR NC,track_double_bat | ||||||||||||||
| 9A0D | JR direct_down_apply | ||||||||||||||
| direct_down_clamp | 9A0F | LD A,(IX+$01) | No extension: take the bat's Y on its own. | ||||||||||||
| 9A12 | CP $9A | Otherwise the plain bottom limit applies. | |||||||||||||
| 9A14 | JR NC,track_double_bat | ||||||||||||||
| direct_down_apply | 9A16 | LD A,(bat_speed_slow) | Move the bat down by the slow speed and drag the extension and caught ball with it. | ||||||||||||
| 9A19 | LD B,A | ||||||||||||||
| 9A1A | LD A,(IX+$01) | ||||||||||||||
| 9A1D | ADD A,B | ||||||||||||||
| 9A1E | LD (IX+$01),A | ||||||||||||||
| 9A21 | CALL drag_attached_down | ||||||||||||||
| 9A24 | LD A,(bat_speed_slow) | ||||||||||||||
| 9A27 | CALL drag_caught_down | ||||||||||||||
| 9A2A | BIT 4,(HL) | Fire also held? Apply the fast-speed bonus downward too. | |||||||||||||
| 9A2C | JR Z,track_double_bat | ||||||||||||||
| 9A2E | LD A,(bat_speed_slow) | ||||||||||||||
| 9A31 | LD B,A | ||||||||||||||
| 9A32 | LD A,(bat_speed_fast) | ||||||||||||||
| 9A35 | SUB B | ||||||||||||||
| 9A36 | LD B,A | ||||||||||||||
| 9A37 | LD A,(IX+$01) | ||||||||||||||
| 9A3A | ADD A,B | Move down by the extra amount, for a total step of the fast speed. | |||||||||||||
| 9A3B | LD (IX+$01),A | ||||||||||||||
| 9A3E | CALL drag_attached_down | ||||||||||||||
| 9A41 | LD A,B | ||||||||||||||
| 9A42 | CALL drag_caught_down | ||||||||||||||
|
Double bat tail, run every frame. It acts only while the double bat flag is set, with no missile shot in flight and no retract or bomb effect armed. It then parks the secondary object at the bat's current Y on the bat's side and activates it. Drawn with the bat sprite, it is the second bat, which follows the bat's Y.
|
|||||||||||||||
| track_double_bat | 9A45 | LD A,(double_bat_active) | Skip unless the double bat flag is set. | ||||||||||||
| 9A48 | OR A | ||||||||||||||
| 9A49 | JR Z,launch_missile | ||||||||||||||
| 9A4B | LD A,(missile_shot) | Skip while the missile shot is in flight, or while the retract or bomb effect is armed. | |||||||||||||
| 9A4E | OR A | ||||||||||||||
| 9A4F | JR NZ,launch_missile | ||||||||||||||
| 9A51 | LD A,(fx_retract_arm) | ||||||||||||||
| 9A54 | OR A | ||||||||||||||
| 9A55 | JR NZ,launch_missile | ||||||||||||||
| 9A57 | LD A,(fx_bomb_arm) | ||||||||||||||
| 9A5A | OR A | ||||||||||||||
| 9A5B | JR NZ,launch_missile | ||||||||||||||
| 9A5D | LD B,(IX+$01) | Take the bat's current Y. | |||||||||||||
| 9A60 | PUSH IX | ||||||||||||||
| 9A62 | LD IX,obj2_object | Target the secondary object and pick its X column from the bat side: the right bat parks it at x 188. | |||||||||||||
| 9A66 | LD A,(bat_side) | ||||||||||||||
| 9A69 | OR A | ||||||||||||||
| 9A6A | JR NZ,track_double_bat_left | ||||||||||||||
| 9A6C | LD (IX+$00),$BC | ||||||||||||||
| 9A70 | JR track_double_bat_set | ||||||||||||||
| track_double_bat_left | 9A72 | LD (IX+$00),$34 | The left bat parks it at the mirrored column. | ||||||||||||
| track_double_bat_set | 9A76 | LD (IX+$01),B | Set the second bat's Y to the bat's, point it at the bat sprite, and set its active flag. | ||||||||||||
| 9A79 | LD DE,slot_bat_normal | ||||||||||||||
| 9A7C | LD (IX+$06),E | ||||||||||||||
| 9A7F | LD (IX+$07),D | ||||||||||||||
| 9A82 | SET 0,(IX+$08) | ||||||||||||||
| 9A86 | POP IX | ||||||||||||||
|
Launch the missile shot on fire. When the missile bat is armed and fire is held in the controls, it spawns the secondary object at the bat's Y. It also seeds ball B's motion state. The shot moves outward from the bat's side. Returns immediately when nothing is armed or fire is not held.
|
|||||||||||||||
| launch_missile | 9A88 | LD A,(missile_active) | No missile bat armed? Return. | ||||||||||||
| 9A8B | OR A | ||||||||||||||
| 9A8C | RET Z | ||||||||||||||
| 9A8D | BIT 4,(HL) | Fire not held? Return. HL points at the control bitfield only under direct control, or under inertia while the bat stands still. On every other path, this tests a byte that is not the controls – see Defects. | |||||||||||||
| 9A8F | RET Z | ||||||||||||||
| 9A90 | XOR A | Disarm the missile bat and clear ball B's combo. Cancel the swap to the missile-bat sprite and arm the swap back to the normal bat. | |||||||||||||
| 9A91 | LD (missile_active),A | ||||||||||||||
| 9A94 | LD (combo_b),A | ||||||||||||||
| 9A97 | LD (fx_bat_missile_arm),A | ||||||||||||||
| 9A9A | INC A | ||||||||||||||
| 9A9B | LD (fx_bat_normal_arm),A | ||||||||||||||
| 9A9E | LD B,(IX+$01) | Spawn the secondary object at the bat's Y. The side the bat plays from picks the X column (x 204 right / x 36 left) and the launch heading for that side. | |||||||||||||
| 9AA1 | LD IX,obj2_object | ||||||||||||||
| 9AA5 | LD A,(bat_side) | ||||||||||||||
| 9AA8 | OR A | ||||||||||||||
| 9AA9 | JR NZ,launch_missile_left | ||||||||||||||
| 9AAB | LD (IX+$00),$CC | ||||||||||||||
| 9AAF | LD C,$63 | ||||||||||||||
| 9AB1 | JR launch_missile_set | ||||||||||||||
| launch_missile_left | 9AB3 | LD (IX+$00),$24 | The left bat mirrors the column and takes the opposite heading code. | ||||||||||||
| 9AB7 | LD C,$87 | ||||||||||||||
| launch_missile_set | 9AB9 | LD (IX+$01),B | Store the position, point at the missile-shot sprite and activate the object. Seed ball B's motion with the launch heading, its speed and counters, and set the two-ball and missile-shot flags. The shot then travels as the secondary object and clears every brick it passes through, the golden one included. A missile run thus cuts a lane the ball cannot. | ||||||||||||
| 9ABC | LD DE,slot_missile_shot | ||||||||||||||
| 9ABF | LD (IX+$06),E | ||||||||||||||
| 9AC2 | LD (IX+$07),D | ||||||||||||||
| 9AC5 | SET 0,(IX+$08) | ||||||||||||||
| 9AC9 | LD A,C | ||||||||||||||
| 9ACA | LD (ball_b_heading),A | ||||||||||||||
| 9ACD | LD A,$05 | ||||||||||||||
| 9ACF | LD (ball_b_speed),A | ||||||||||||||
| 9AD2 | LD (ball_b_x_threshold),A | ||||||||||||||
| 9AD5 | XOR A | ||||||||||||||
| 9AD6 | LD (ball_b_on_bat),A | ||||||||||||||
| 9AD9 | LD (ball_b_y_threshold),A | ||||||||||||||
| 9ADC | LD (ball_b_y_dir),A | ||||||||||||||
| 9ADF | LD (ball_b_x_accum),A | ||||||||||||||
| 9AE2 | LD (ball_b_y_accum),A | ||||||||||||||
| 9AE5 | INC A | ||||||||||||||
| 9AE6 | LD (ball_b_in_play),A | ||||||||||||||
| 9AE9 | LD (missile_shot),A | ||||||||||||||
| 9AEC | LD A,(bat_side) | ||||||||||||||
| 9AEF | LD (ball_b_x_dir),A | ||||||||||||||
| 9AF2 | RET | ||||||||||||||
| ← 997A | Map | 9AF3 → |
