| Routines

65DB: Move and draw the bullets

Used by the routine at F080. For each bullet currently in flight, calculates the bullet's next location and draws it there (unless it has hit Sam).
65DB | LD HL,$7FE7 | 7FE7 holds the bullet timer
65DE | DEC (HL) | Is it time to move and redraw the bullets?
65DF | RET NZ | Return if not
65E0 | LD A,($7F9F) | Collect the MSB of Sam's cash supply
65E3 | LD C,$03 | Keep only bits 0 and 1 of the MSB
65E5 | AND C
65E6 | XOR C | A=6-A
65E7 | ADD A,C
65E8 | LD (HL),A | Reinitialise the bullet timer at 7FE7 to 3, 4, 5 or 6
65E9 | LD L,$C0 | HL=7FC0 (first byte of bullet buffer 1)
The following loop checks each bullet to see whether it is in flight or has flown off the screen.
65EB | LD DE,($7FFE) | Collect the x- and y-coordinates of the top-left tile of the play area on screen in E and D
65EF | LD A,(HL) | A=x-coordinate of the leftmost column of the play area that was on screen the last time the bullet was drawn
65F0 | LD (HL),E | Replace that x-coordinate with the current value
65F1 | SUB E | A=bullet's current screen x-coordinate
65F2 | INC HL
65F3 | ADD A,(HL)
65F4 | LD E,A | Copy this to E
65F5 | LD (HL),A | Also store it in the bullet buffer
65F6 | INC HL | Point HL at the third byte of the bullet buffer
65F7 | CP $20 | Has the bullet flown off screen to the right?
65F9 | JR NC,$65FF | Jump if so
65FB | LD A,(HL) | A=bullet's current screen y-coordinate (or 0 if the bullet is not in flight)
65FC | AND A | Is the bullet in flight at the moment?
65FD | JR NZ,$6608 | Jump if so
65FF | LD (HL),$00 | Set the third byte of the bullet's buffer to 0, indicating that it is not in flight
6601 | INC L | Point HL at the last byte of the bullet buffer
6602 | INC L | Point HL at the first byte of the next bullet buffer
6603 | BIT 3,L | Have we dealt with both bullets yet?
6605 | JR Z,$65EB | Jump back if not
6607 | RET |
This bullet is currently in flight.
6608 | LD A,D | A=y-coordinate of the topmost row of the play area on screen
6609 | CP $14 | Is the sidewalk on screen at the moment?
660B | JR NZ,$65FF | Terminate the bullet if not
660D | LD D,(HL) | D=bullet's current screen y-coordinate
660E | PUSH HL | Save the pointer to the bullet buffer
660F | EX DE,HL | Transfer the bullet's screen x- and y-coordinates to L and H
6610 | CALL $E70C | Print the play area tile at these coordinates, thus erasing the bullet
6613 | POP HL | Restore the bullet buffer pointer to HL
6614 | INC HL | Point HL at the fourth byte of the bullet buffer
6615 | LD A,$20 | Flip bit 5 of this byte
6617 | XOR (HL)
6618 | LD (HL),A
6619 | DEC HL | Point HL at the second byte of the bullet buffer (which holds the bullet's screen x-coordinate)
661A | DEC HL
661B | DEC (HL) | Decrement the bullet's screen x-coordinate
661C | ADD A,A | Is the bullet flying leftwards?
661D | JR NC,$6621 | Jump if so
661F | INC (HL) | Otherwise increment the bullet's x-coordinate
6620 | INC (HL)
6621 | LD E,(HL) | E=bullet's next screen x-coordinate
6622 | INC HL | Point HL at the third byte of the bullet buffer
6623 | BIT 5,E | Would the bullet now be off-screen to the left or right?
6625 | JR NZ,$65FF | Terminate the bullet if so
6627 | ADD A,A | Is the bullet flying perfectly horizontally?
6628 | JR NC,$664C | Jump if so
The bullet is flying at an angle towards the ground or the sky.
662A | ADD A,A | Push what was bit 5 of the fourth byte of the bullet buffer into the carry flag (and ignore it)
662B | NOP |
662C | NOP |
662D | ADD A,A | Set the carry flag if the bullet is flying towards the sky
662E | INC HL | Point HL at the fourth byte of the bullet buffer
662F | JR C,$6642 | Jump if the bullet is flying towards the sky
The bullet is flying at an angle towards the ground.
6631 | RES 3,(HL) | Reset bit 3 to prevent overflow (which would affect bits 4-7)
6633 | INC (HL) | Increment the pixel row counter in bits 0-2
6634 | LD A,(HL) | Pick up the fourth byte of the bullet buffer
6635 | AND $07 | Keep only bits 0-2 (the pixel row counter)
6637 | DEC HL | Point HL at the third byte of the bullet buffer
6638 | JR NZ,$664C | Jump unless the pixel row counter rolled over from 7 to 0
663A | INC (HL) | Increment the bullet's screen y-coordinate
663B | LD A,(HL) | A=bullet's next screen y-coordinate
663C | CP $14 | Has the bullet flown off the bottom of the screen?
663E | JR Z,$65FF | Terminate it if so
6640 | JR $664C |
The bullet is flying at an angle towards the sky.
6642 | SET 3,(HL) | Set bit 3 to prevent underflow (which would affect bits 4-7)
6644 | LD A,(HL) | Pick up the fourth byte of the bullet buffer
6645 | DEC (HL) | Decrement the pixel row counter in bits 0-2
6646 | AND $07 | A=previous value of the pixel row counter (0-7)
6648 | DEC HL | Point HL at the third byte of the bullet buffer
6649 | JR NZ,$664C | Jump unless the pixel row counter rolled over from 0 to 7
664B | DEC (HL) | Decrement the bullet's screen y-coordinate
664C | LD D,(HL) | D=bullet's next screen y-coordinate
Having calculated where the bullet is going next, we check whether it would hit Sam.
664D | CALL $6592 | Would the bullet hit Sam?
6650 | JR C,$65FF | Terminate the bullet if so
The bullet has not flown off the screen or hit Sam, so now we draw it.
6652 | LD A,D | A=bullet's next screen y-coordinate
6653 | AND $07 | Point DE at the top pixel row of the screen cell in which the bullet will be drawn
6655 | RRCA
6656 | RRCA
6657 | RRCA
6658 | ADD A,E
6659 | LD E,A
665A | LD A,D
665B | AND $18
665D | ADD A,$40
665F | LD D,A
6660 | INC HL | Point HL at the fourth byte of the bullet buffer
6661 | LD A,(HL) | Point DE at the exact pixel row of the screen cell in which the bullet will be drawn
6662 | AND $07
6664 | ADD A,D
6665 | LD D,A
6666 | LD A,(DE) | Pick up the current pixel row from the display file
6667 | OR $3C | Set bits 2-5
6669 | AND $BD | Reset bits 6 and 1
666B | LD (DE),A | Draw the bullet
666C | JR $6602 | Jump back to deal with the next bullet