| Routines

621E: Control the sniper while active

The address of this interruptible subcommand routine is placed into bytes 0x0E and 0x0F of the sniper's buffer by the routine at 62DB. It controls the sniper from the moment he appears until he hides again.
Input
H | 0xE3 (sniper)
621E | LD L,$02 | A=sniper's y-coordinate
6220 | LD A,(HL)
6221 | LD L,$11 | Point HL at byte 0x11 of the sniper's buffer
6223 | INC (HL) | Is it zero (meaning the sniper has not fired recently)?
6224 | DEC (HL)
6225 | JR Z,$6228 | Jump if so
6227 | DEC (HL) | Otherwise decrement byte 0x11
6228 | DEC L | L=0x10
6229 | CP $32 | The sniper's y-coordinate is 50 when he's inactive
622B | JR NZ,$6250 | Jump if the sniper is currently active
The sniper is currently inactive.
622D | DEC (HL) | Decrement byte 0x10 of the sniper's buffer
622E | JP Z,$F284 | Terminate this subcommand if byte 0x10 is now 0
6231 | CALL $66D8 | Is the sniper on screen at least 8 x-coordinates away from Sam?
6234 | NOP |
6235 | JP NZ,$F284 | Terminate this subcommand if not
6238 | INC L | Point HL at byte 0x02 of the sniper's buffer
6239 | LD (HL),$25 | Set the sniper's y-coordinate to 37 (out of sight, but ready to emerge)
623B | LD A,($E601) | A=Sam's x-coordinate
623E | DEC L | L=0x01
623F | SUB (HL) | Subtract the sniper's x-coordinate
6240 | CCF | Compute the appropriate animatory state for the sniper: 0x36 if he's to the right of Sam, 0xB6 if he's to the left
6241 | LD A,$6C
6243 | RRA
6244 | DEC HL | Set the sniper's animatory state
6245 | LD (HL),A
This entry point is used by the routine at 6FE6.
6246 | LD L,$02 | Collect the sniper's x- and y-coordinates in DE
6248 | LD D,(HL)
6249 | DEC HL
624A | LD E,(HL)
624B | DEC HL | A=sniper's animatory state
624C | LD A,(HL)
624D | JP $6670 | Update the sniper's sprite tile references
The sniper is currently active (his y-coordinate is 34-37).
6250 | LD A,($DEB6) | Collect the sprite tile reference for tile 7 of animatory states 0x36/0xB6; this will be 0xEB if the sniper is firing, or 0x00, 0x6E, 0x6F or 0x71 otherwise
6253 | CP H | Is the sniper firing?
6254 | JP NC,$6FE6 | If so, make the firing sound effect
6257 | LD A,($7FFF) | A=y-coordinate of the topmost row of the play area on screen
625A | CP $14 | Is the sidewalk on screen?
625C | JR NZ,$6269 | If not, deactivate the sniper and terminate this subcommand
625E | DEC (HL) | Decrement byte 0x10 of the sniper's buffer
625F | JR NZ,$627A | Jump unless byte 0x10 is now zero
Byte 0x10 of the sniper's buffer has been decremented to zero. The apparent intention here is to make the sniper duck out of sight and terminate this subcommand; however, if the sniper is not already out of sight, he will duck briefly but remain in view, and byte 0x10 will be decremented to 0xFF on the next pass through this routine. This is a bug.
6261 | CALL $E9C8 | Update the SRB for the sniper's current animatory state and location
6264 | LD A,D | A=sniper's y-coordinate
6265 | CP $25 | Is the sniper currently out of sight?
6267 | JR NZ,$6272 | Jump if not to make him duck
6269 | LD L,$0F | Remove the address of this routine from bytes 0x0E and 0x0F of the sniper's buffer
626B | LD (HL),$00
626D | LD L,$02 | Set the sniper's y-coordinate to 50 (inactive)
626F | LD (HL),$32
6271 | RET |
The sniper is in the process of ducking.
6272 | INC D | D=sniper's next y-coordinate (35-37)
6273 | LD L,$00 | Point HL at byte 0x00 of the sniper's buffer
6275 | LD A,(HL) | A=sniper's animatory state
6276 | AND A | Reset the carry flag to indicate that the sniper is not firing
6277 | JP $6670 | Update the sniper's sprite tile references
Byte 16 of the sniper's buffer is not zero.
627A | CALL $66D8 | Compare the sniper's coordinates with Sam's
627D | JR Z,$628B | Jump if the sniper is on screen and at least 8 x-coordinates away from Sam
627F | JR NC,$6269 | Terminate this subcommand if the sniper if off screen
6281 | CALL $E9C8 | Update the SRB for the sniper's current animatory state and location
6284 | LD A,D | A=sniper's y-coordinate
6285 | CP $25 | Has the sniper already ducked out of sight?
6287 | JR NZ,$6272 | Jump if not to make the sniper continue ducking
6289 | JR $626D | Deactivate the sniper
The sniper is on screen and at least 8 x-coordinates away from Sam. If he's already popped his head out far enough (his y-coordinate is 34 or 35), he can consider shooting; otherwise he'll need to emerge a little further first.
628B | LD L,$02 | Point HL at byte 0x02 of the sniper's buffer
628D | LD A,(HL) | A=sniper's y-coordinate
628E | CP $24 | Is at least half of the sniper visible?
6290 | JR C,$6298 | Jump if so
6292 | CALL $E9C8 | Update the SRB for the sniper's current animatory state and location
6295 | DEC D | D=sniper's next y-coordinate (35 or 36)
6296 | JR $6276 | Jump back to update the sniper's sprite tile references
At least half of the sniper is visible (his y-coordinate is 34 or 35), which means he can shoot.
6298 | LD L,$10 | Collect byte 0x10 of the sniper's buffer
629A | LD A,(HL)
629B | AND $03 | Is bit 0 or bit 1 set?
629D | JR NZ,$62AF | Jump if so
629F | CALL $F17F | Get a random number in A
62A2 | CP $A0 | Should the sniper consider shooting?
62A4 | JR C,$62AF | Jump if so (5 times out of 8)
62A6 | CALL $E9C8 | Update the SRB for the sniper's current animatory state and location
62A9 | LD A,D | A=sniper's y-coordinate (34 or 35)
62AA | XOR $01 | Toggle between 34 and 35
62AC | LD D,A | D=sniper's next y-coordinate (35 or 34)
62AD | JR $6273 | Jump back to update the sniper's sprite tile references
The sniper will consider shooting.
62AF | LD A,($E604) | A=Sam's z-coordinate
62B2 | RRCA | Is Sam indoors?
62B3 | RET C | Return if so
62B4 | LD A,($7FFC) | Collect Sam's status flags from 7FFC
62B7 | AND $81 | Is Sam falling from a building or being carried?
62B9 | RET NZ | Return if so
62BA | LD L,$11 | Collect byte 0x11 of the sniper's buffer
62BC | LD A,(HL)
62BD | AND A | Has the sniper fired recently?
62BE | RET NZ | Return if so
62BF | CALL $F17F | Get a random number in A
62C2 | CP $54 | Should the sniper continue to consider shooting?
62C4 | RET NC | Return if not (21 times out of 64)
62C5 | LD DE,$7FC2 | Point DE at the third byte of bullet buffer 1 (at 7FC0)
62C8 | LD A,(DE) | Pick this up in A
62C9 | AND A | Is bullet buffer 1 in use?
62CA | JR Z,$62D1 | Jump if not
62CC | LD E,$C6 | Point DE at the third byte of bullet buffer 2 (at 7FC4)
62CE | LD A,(DE) | Pick this up in A
62CF | AND A | Is bullet buffer 2 in use?
62D0 | RET NZ | Return if so
The sniper has decided to shoot, and a bullet buffer is available.
62D1 | LD (HL),$0C | Place 0x0C into byte 0x11 of the sniper's buffer (indicating that he's just fired)
62D3 | CALL $E9C8 | Update the SRB for the sniper's current animatory state and location
62D6 | SCF | Set the carry flag to indicate that the sniper is firing
62D7 | JP $6670 | Update the sniper's sprite tile references and initialise a bullet