| Routines

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

Used by the routines at 25420, 25789, 26224, 29149, 30989, 31204, 31476, 31670, 31713, 60347, 60506, 62264, 62325, 63281, 63558, 63954, 64131 and 64227. 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 (215-230)
59861 | LD L,2 | Point HL at byte 2 of the character's buffer
59863 | LD (HL),D | Fill in the new y-coordinate
59864 | DEC L | L=1
59865 | LD (HL),E | Fill in the new x-coordinate
59866 | DEC L | L=0
59867 | LD (HL),A | Fill in the new animatory state
This entry point is used by the routine at 59848.
59868 | LD BC,514 | B=2, C=2
59871 | LD A,(HL) | A=character's animatory state
59872 | AND 127 | Clear the 'direction' bit (bit 7)
59874 | ADD A,136 | Is the animatory state >= 120?
59876 | JR C,59889 | Jump if so
59878 | LD BC,1283 | B=5, C=3
59881 | INC A | Is the animatory state equal to 7 mod 8?
59882 | AND 7
59884 | JR NZ,59889 | Jump if not
59886 | LD BC,773 | B=3, C=5
Now B holds the height of the sprite in tiles, and C holds the width.
59889 | LD A,(32767) | A=Y, the y-coordinate of the topmost row of the play area on screen (2-20)
59892 | SUB B | A=Y-B
59893 | JR C,59897 | Jump if B>Y
59895 | CP D | Is the character entirely above the portion of the play area currently on screen?
59896 | RET NC | Return if so
59897 | ADD A,B | A=Y
59898 | ADD A,19 | A=y-coordinate of the bottom row of the play area on screen (21-39)
59900 | SUB D | Is the character entirely below the portion of the play area currently on screen?
59901 | RET C | Return if so
59902 | CPL | A=4*(D-Y+4)
59903 | ADD A,24
59905 | ADD A,A
59906 | ADD A,A
59907 | LD D,A | Copy this value (0, 4, 8, 12,...92) to D
59908 | LD A,(32766) | A=X, the x-coordinate of the leftmost column of the play area on screen
59911 | SUB C | A=X-C
59912 | JR C,59916 | Jump if C>X
59914 | CP E | Is the character entirely off-screen to the left?
59915 | RET NC | Return if so
59916 | ADD A,C | A=X
59917 | ADD A,31 | A=x-coordinate of the rightmost column of the play area on screen
59919 | SUB E | Is the character entirely off-screen to the right?
59920 | RET C | Return if so
If we get here, then the character's sprite (or at least a portion of it) is on-screen.
59921 | CPL | A=E-X: the character's screen x-coordinate (-4 to 31)
59922 | ADD A,32
59924 | PUSH AF | Save this temporarily
59925 | LD A,(HL) | A=character's animatory state
59926 | AND 7 | Set the zero flag if the animatory state is 0 mod 8
59928 | LD A,(HL) | A=character's animatory state
59929 | JR NZ,59933 | Jump unless the animatory state is 0 mod 8
59931 | ADD A,2 | Add 2 if the animatory state is congruent to 0 mod 8
59933 | PUSH BC | Push the sprite dimensions onto the stack
59934 | EXX |
59935 | POP BC | Retrieve the sprite dimensions in BC'
59936 | LD H,215 | Page 215 holds sprite tile references for the top-left tile (tile 0) in the left-facing sprites
59938 | LD D,B | D'=sprite height (2, 3 or 5)
59939 | RLCA | Set bit 7 of A, and set the carry flag if the character is facing right
59940 | SCF
59941 | RRA
59942 | LD L,A | L'=character's animatory state (with bit 7 set)
59943 | JR NC,59956 | Jump if the character is facing left
59945 | XOR A | D'=-B' (negative sprite height)
59946 | SUB B
59947 | LD D,A
59948 | LD E,C | E'=C'-1 (sprite width minus 1)
59949 | DEC E
59950 | LD A,H | A=215 (page containing references for sprite tile 0)
59951 | ADD A,B | A=215+B'*(C'-1)
59952 | DEC E
59953 | JR NZ,59951
59955 | 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.
59956 | POP AF | Restore the character's screen x-coordinate to A
59957 | LD E,A | Copy it to E'
59958 | JR C,59967 | Jump if E'>=0 (meaning that the leftmost tiles in the character's sprite are on-screen)
59960 | LD A,H | A=H'-D'*E' (sprite tile reference page number); C'=C'+E'
59961 | ADD A,D
59962 | DEC C
59963 | INC E
59964 | JR NZ,59961
59966 | 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.
59967 | LD A,E | A=leftmost column of the screen occupied by the sprite (0-31)
59968 | EXX |
59969 | LD E,A | E=leftmost column of the screen occupied by the sprite
59970 | AND 7 | Point BC at byte 21 of page 160+(E%8)
59972 | ADD A,160
59974 | LD B,A
59975 | LD C,21
59977 | LD A,(BC) | Pick up the contents in A
59978 | LD C,A | Copy them to C
Now C holds 1, 2, 4, 8, 16, 32, 64 or 128. The bit set in C corresponds to the bit that needs to be set in the relevant byte of the screen refresh buffer (SRB).
59979 | LD A,E | A=leftmost column of the screen occupied by the sprite (0-31)
59980 | RRCA | Set A to the LSB of the first byte of the SRB that needs to be modified: D+INT(E/8)
59981 | RRCA
59982 | RRCA
59983 | AND 3
59985 | ADD A,D
59986 | LD B,A | Copy this LSB to B
59987 | LD D,127 | The SRB is in page 127
59989 | 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.
59990 | PUSH BC | Save the tile row and column counters temporarily
59991 | LD E,0 | Start at sprite tile row 0 (top row)
59993 | LD A,(HL) | Pick up the sprite tile reference in A
59994 | AND A | Is this the 'null' tile (blank square)?
59995 | JR Z,60007 | Jump if so (no need to set a bit in the SRB)
59997 | LD A,E | A=sprite tile row number (0-4)
59998 | EXX |
59999 | ADD A,A | Multiply by 4 (the number of bytes of the SRB that correspond to one row of the screen)
60000 | ADD A,A
60001 | ADD A,B | Point DE at the relevant byte of the SRB
60002 | LD E,A
60003 | LD A,(DE) | Pick up the SRB byte in A
60004 | OR C | Make sure the appropriate bit is set
60005 | LD (DE),A | Restore the SRB byte with the appropriate bit set
60006 | EXX |
60007 | INC H | Point HL' at the reference for the next tile in the sprite (one row down)
60008 | INC E | Next row down in this column of the sprite
60009 | DJNZ 59993 | Jump back until we've set all the SRB bits for this tile column of the sprite
60011 | LD A,H | Point HL' at the reference for the tile in the top row of the next column of the sprite
60012 | ADD A,D
60013 | POP BC
60014 | SUB B
60015 | LD H,A
60016 | EXX |
60017 | RRC C | Move the SRB marker bit in C one place to the right (possibly wrapping round to bit 7)
60019 | JR NC,60026 | Jump if there are still bits to be set in the current SRB byte
60021 | INC B | Otherwise move along to the next byte in the SRB
60022 | LD A,B | A=LSB of the next SRB byte
60023 | AND 3 | 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)?
60025 | RET Z | Return if so (any remaining sprite tile columns are off-screen to the right)
60026 | EXX |
60027 | DEC C | Next sprite tile column
60028 | JR NZ,59990 | Jump back until the relevant SRB bits for every sprite tile column have been set
60030 | EXX |
60031 | RET |