| Routines

E9D5: Update a character's animatory state and location and update the SRB

Used by the routines at 634C, 64BD, 6670, 71DD, 790D, 79E4, 7AF4, 7BB6, 7BE1, EBBB, EC5A, F338, F375, F731, F846, F9D2, FA83 and FAE3. Sets the new animatory state and location of a character, and updates the screen refresh buffer (SRB) accordingly.
Input
A | New animatory state
D | New y-coordinate
E | New x-coordinate
H | Character number (0xD7-0xE6)
E9D5 | LD L,$02 | Point HL at byte 0x02 of the character's buffer
E9D7 | LD (HL),D | Fill in the new y-coordinate
E9D8 | DEC L | L=0x01
E9D9 | LD (HL),E | Fill in the new x-coordinate
E9DA | DEC L | L=0x00
E9DB | LD (HL),A | Fill in the new animatory state
This entry point is used by the routine at E9C8.
E9DC | LD BC,$0202 | B=2, C=2
E9DF | LD A,(HL) | A=character's animatory state
E9E0 | AND $7F | Clear the 'direction' bit (bit 7)
E9E2 | ADD A,$88 | Is the animatory state >= 0x78?
E9E4 | JR C,$E9F1 | Jump if so
E9E6 | LD BC,$0503 | B=5, C=3
E9E9 | INC A | Is the animatory state equal to 7 mod 8?
E9EA | AND $07
E9EC | JR NZ,$E9F1 | Jump if not
E9EE | LD BC,$0305 | B=3, C=5
Now B holds the height of the sprite in tiles, and C holds the width.
E9F1 | LD A,($7FFF) | A=Y, the y-coordinate of the topmost row of the play area on screen (2-20)
E9F4 | SUB B | A=Y-B
E9F5 | JR C,$E9F9 | Jump if B>Y
E9F7 | CP D | Is the character entirely above the portion of the play area currently on screen?
E9F8 | RET NC | Return if so
E9F9 | ADD A,B | A=Y
E9FA | ADD A,$13 | A=y-coordinate of the bottom row of the play area on screen (21-39)
E9FC | SUB D | Is the character entirely below the portion of the play area currently on screen?
E9FD | RET C | Return if so
E9FE | CPL | A=4*(D-Y+4)
E9FF | ADD A,$18
EA01 | ADD A,A
EA02 | ADD A,A
EA03 | LD D,A | Copy this value (0, 4, 8, 12,...92) to D
EA04 | LD A,($7FFE) | A=X, the x-coordinate of the leftmost column of the play area on screen
EA07 | SUB C | A=X-C
EA08 | JR C,$EA0C | Jump if C>X
EA0A | CP E | Is the character entirely off-screen to the left?
EA0B | RET NC | Return if so
EA0C | ADD A,C | A=X
EA0D | ADD A,$1F | A=x-coordinate of the rightmost column of the play area on screen
EA0F | SUB E | Is the character entirely off-screen to the right?
EA10 | RET C | Return if so
If we get here, then the character's sprite (or at least a portion of it) is on-screen.
EA11 | CPL | A=E-X: the character's screen x-coordinate (-4 to 31)
EA12 | ADD A,$20
EA14 | PUSH AF | Save this temporarily
EA15 | LD A,(HL) | A=character's animatory state
EA16 | AND $07 | Set the zero flag if the animatory state is 0 mod 8
EA18 | LD A,(HL) | A=character's animatory state
EA19 | JR NZ,$EA1D | Jump unless the animatory state is 0 mod 8
EA1B | ADD A,$02 | Add 2 if the animatory state is congruent to 0 mod 8
EA1D | PUSH BC | Push the sprite dimensions onto the stack
EA1E | EXX |
EA1F | POP BC | Retrieve the sprite dimensions in BC'
EA20 | LD H,$D7 | Page 0xD7 holds sprite tile references for the top-left tile (tile 0) in the left-facing sprites
EA22 | LD D,B | D'=sprite height (2, 3 or 5)
EA23 | RLCA | Set bit 7 of A, and set the carry flag if the character is facing right
EA24 | SCF
EA25 | RRA
EA26 | LD L,A | L'=character's animatory state (with bit 7 set)
EA27 | JR NC,$EA34 | Jump if the character is facing left
EA29 | XOR A | D'=-B' (negative sprite height)
EA2A | SUB B
EA2B | LD D,A
EA2C | LD E,C | E'=C'-1 (sprite width minus 1)
EA2D | DEC E
EA2E | LD A,H | A=0xD7 (page containing references for sprite tile 0)
EA2F | ADD A,B | A=0xD7+B'*(C'-1)
EA30 | DEC E
EA31 | JR NZ,$EA2F
EA33 | LD H,A | Copy this value to H'
Now HL' points at the sprite tile reference for the top-left tile in the character's sprite.
EA34 | POP AF | Restore the character's screen x-coordinate to A
EA35 | LD E,A | Copy it to E'
EA36 | JR C,$EA3F | Jump if E'>=0 (meaning that the leftmost tiles in the character's sprite are on-screen)
EA38 | LD A,H | A=H'-D'*E' (sprite tile reference page number); C'=C'+E'
EA39 | ADD A,D
EA3A | DEC C
EA3B | INC E
EA3C | JR NZ,$EA39
EA3E | LD H,A | Copy the sprite tile reference page number to H'
Now HL' points at the sprite tile reference for the tile in the top row and the leftmost column of the character's sprite that is on-screen. C' holds the number of tile columns of the character's sprite that are to the right of the left edge of the screen.
EA3F | LD A,E | A=leftmost column of the screen occupied by the sprite (0-31)
EA40 | EXX |
EA41 | LD E,A | E=leftmost column of the screen occupied by the sprite
EA42 | AND $07 | Point BC at byte 0x15 of page 0xA0+(E%8)
EA44 | ADD A,$A0
EA46 | LD B,A
EA47 | LD C,$15
EA49 | LD A,(BC) | Pick up the contents in A
EA4A | LD C,A | Copy them to C
Now C holds 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 or 0x80. The bit set in C corresponds to the bit that needs to be set in the relevant byte of the screen refresh buffer (SRB).
EA4B | LD A,E | A=leftmost column of the screen occupied by the sprite (0-31)
EA4C | RRCA | Set A to the LSB of the first byte of the SRB that needs to be modified: D+INT(E/8)
EA4D | RRCA
EA4E | RRCA
EA4F | AND $03
EA51 | ADD A,D
EA52 | LD B,A | Copy this LSB to B
EA53 | LD D,$7F | The SRB is in page 0x7F
EA55 | EXX |
Here we enter a loop to set the appropriate bits in the SRB. At this point B' holds the number of tile rows in the sprite (2, 3, or 5) and C' holds the number of tile columns of the sprite that are to the right of the left edge of the screen.
EA56 | PUSH BC | Save the tile row and column counters temporarily
EA57 | LD E,$00 | Start at sprite tile row 0 (top row)
EA59 | LD A,(HL) | Pick up the sprite tile reference in A
EA5A | AND A | Is this the 'null' tile (blank square)?
EA5B | JR Z,$EA67 | Jump if so (no need to set a bit in the SRB)
EA5D | LD A,E | A=sprite tile row number (0-4)
EA5E | EXX |
EA5F | ADD A,A | Multiply by 4 (the number of bytes of the SRB that correspond to one row of the screen)
EA60 | ADD A,A
EA61 | ADD A,B | Point DE at the relevant byte of the SRB
EA62 | LD E,A
EA63 | LD A,(DE) | Pick up the SRB byte in A
EA64 | OR C | Make sure the appropriate bit is set
EA65 | LD (DE),A | Restore the SRB byte with the appropriate bit set
EA66 | EXX |
EA67 | INC H | Point HL' at the reference for the next tile in the sprite (one row down)
EA68 | INC E | Next row down in this column of the sprite
EA69 | DJNZ $EA59 | Jump back until we've set all the SRB bits for this tile column of the sprite
EA6B | LD A,H | Point HL' at the reference for the tile in the top row of the next column of the sprite
EA6C | ADD A,D
EA6D | POP BC
EA6E | SUB B
EA6F | LD H,A
EA70 | EXX |
EA71 | RRC C | Move the SRB marker bit in C one place to the right (possibly wrapping round to bit 7)
EA73 | JR NC,$EA7A | Jump if there are still bits to be set in the current SRB byte
EA75 | INC B | Otherwise move along to the next byte in the SRB
EA76 | LD A,B | A=LSB of the next SRB byte
EA77 | AND $03 | Does the next SRB byte correspond to a segment in the leftmost 8 columns of the screen (i.e. have we wrapped around from right to left)?
EA79 | RET Z | Return if so (any remaining sprite tile columns are off-screen to the right)
EA7A | EXX |
EA7B | DEC C | Next sprite tile column
EA7C | JR NZ,$EA56 | Jump back until the relevant SRB bits for every sprite tile column have been set
EA7E | EXX |
EA7F | RET |