Prev: EE73 Up: Map Next: EF4E
EE8D: Draw an object's sprite into one of the region's buffers
Used by the routines at REDRAW_OBJECT, CULL_OBJECT and SORT_AND_DRAW_BEHIND.
The one routine that draws objects, and it never touches the screen: it draws the object at IX into a buffer the shape of the region being rebuilt -- a row one byte wider than the region's width in bytes (IY+$73), as many rows as the region is high, wrapping within its 256-byte page -- clipped to the region and shifted to the pixel. The compositor (COMPOSITE_TO_SCREEN) then makes the screen's bytes from the buffers. Krumlinde's name for it is RTN_Draw_Sprite.
The mode in A says what is drawn where. Mode $80, for the object being redrawn (REDRAW_OBJECT): its mask, into page $D9, with three rows of $FF (nothing covered) above and below it. Mode 0, for an object in front of it (CULL_OBJECT): its cover -- the mask inverted, a bit set where the object shows -- ORed into page $D8. Modes 4 and 8, for the objects behind (SORT_AND_DRAW_BEHIND): the cover ORed into page $DA and cleared out of page $DB, and then the image ORed into page $DB. A sprite is its image and then its mask, each width/8 bytes by height rows (+2 and +3), so every mode but 8 starts one plane in.
The setting up works out, in turn: which rows to draw -- skipping the sprite's rows above the region, or the buffer's rows above the sprite -- into IY+$75; the shift, x mod 8, written into the JR in DRAW_SPRITE_ROWS that jumps into its run of RRCAs, and the masks for the two parts of a shifted byte written into the three ANDs there; and which columns: a sprite starting left of the region is handled by DRAW_SPRITE_CLIP_LEFT, one starting inside it by moving the buffer pointer along (DRAW_SPRITE_SKIP_COLUMNS). Then DRAW_SPRITE_ROWS draws.
The bits of C, besides the mode's: bit 4, the sprite starts left of the region; bit 5, the first column only primes the spill and is not written; bit 6, no spill column after the last, because the sprite is on a byte boundary or is cut by the region's right edge.
Input
A The mode: $80, 0, 4 or 8
IX The object's record
DRAW_SPRITE EE8D PUSH BC The sprite's width in bytes, kept at IY+$78
EE8E PUSH DE
EE8F LD C,A
EE90 LD A,(IX+OBJ_WIDTH)
EE93 SRL A
EE95 SRL A
EE97 SRL A
EE99 LD B,A
EE9A LD (FOUND_RECORD),A
EE9D XOR A One plane's size: width times height
DRAW_SPRITE_0 EE9E ADD A,(IX+OBJ_ROWS)
EEA1 DJNZ DRAW_SPRITE_0
EEA3 LD H,(IX+OBJ_SPRITE+$01) The sprite; every mode but 8 draws the second plane, the mask
EEA6 LD L,(IX+OBJ_SPRITE)
EEA9 BIT 3,C
EEAB JR NZ,DRAW_SPRITE_1
EEAD LD E,A
EEAE LD D,$00
EEB0 ADD HL,DE
DRAW_SPRITE_1 EEB1 EX DE,HL DE: where to read from
EEB2 LD A,(POINT_ROW) Does the sprite start above the region's top row?
EEB5 SUB (IX+OBJ_SCREEN_Y)
EEB8 JR C,DRAW_SPRITE_3
EEBA LD B,A No: skip the buffer's rows above it (a count of 0 goes round 256 times and comes back to no rows)
EEBB XOR A
DRAW_SPRITE_2 EEBC ADD A,(IY+DRAW_WIDTH-V)
EEBF INC A
EEC0 DJNZ DRAW_SPRITE_2
EEC2 LD L,A
EEC3 LD H,$D9
EEC5 LD A,(POINT_ROW) And draw down to the region's bottom, or the sprite's height if that is less
EEC8 SUB (IY+SECOND_POINT_ROW-V)
EECB LD B,A
EECC LD A,(IX+OBJ_SCREEN_Y)
EECF SUB B
EED0 CP (IX+OBJ_ROWS)
EED3 JR C,DRAW_SPRITE_5
EED5 LD A,(IX+OBJ_ROWS)
EED8 JR DRAW_SPRITE_5
DRAW_SPRITE_3 EEDA CPL Yes: skip the sprite's rows above the region
EEDB LD H,A
EEDC LD B,(IY+FOUND_RECORD-V)
EEDF INC H
EEE0 XOR A
DRAW_SPRITE_4 EEE1 ADD A,H
EEE2 DJNZ DRAW_SPRITE_4
EEE4 LD H,$00
EEE6 LD L,A
EEE7 ADD HL,DE
EEE8 EX DE,HL
EEE9 LD HL,BUFFER_D900 And draw from the buffer's top down to the sprite's bottom
EEEC LD A,(IX+OBJ_SCREEN_Y)
EEEF SUB (IX+OBJ_ROWS)
EEF2 LD B,A
EEF3 LD A,(POINT_ROW)
EEF6 SUB B
DRAW_SPRITE_5 EEF7 LD (IY+WORK_ANIMATION-V),A The rows to draw
EEFA LD A,(IX+OBJ_SCREEN_X) 7 minus (x mod 8) into the JR's displacement: that many of the seven RRCAs are jumped over
EEFD CPL
EEFE AND $07
EF00 LD ($EFD1),A
EF03 CP $07 On a byte boundary: nothing spills into a next column
EF05 JR NZ,DRAW_SPRITE_6
EF07 SET 6,C
DRAW_SPRITE_6 EF09 LD B,A A mask of the low 8 minus (x mod 8) bits: the part of a shifted byte that stays in its column
EF0A XOR A
EF0B INC B
DRAW_SPRITE_7 EF0C SCF
EF0D RLA
EF0E DJNZ DRAW_SPRITE_7
EF10 LD ($EFF4),A Into the two ANDs that keep it, and its complement into the one that keeps the spill
EF13 LD ($EFE3),A
EF16 CPL
EF17 LD ($F008),A
EF1A LD A,(POINT) Columns from the region's left byte to the sprite's; bit 4 if the sprite starts left of it
EF1D AND $F8
EF1F LD B,A
EF20 LD A,(IX+OBJ_SCREEN_X)
EF23 AND $F8
EF25 SUB B
EF26 JR NC,DRAW_SPRITE_8
EF28 SET 4,C
EF2A NEG
DRAW_SPRITE_8 EF2C SRL A In bytes; starting left: DRAW_SPRITE_CLIP_LEFT
EF2E SRL A
EF30 SRL A
EF32 LD B,A
EF33 BIT 4,C
EF35 JR NZ,DRAW_SPRITE_CLIP_LEFT
EF37 INC B Starting inside: draw what fits before the region's right edge and its spare column, the spill cut off...
EF38 SET 6,C
EF3A SUB (IY+DRAW_WIDTH-V)
EF3D NEG
EF3F INC A
EF40 CP (IY+FOUND_RECORD-V)
EF43 JR C,DRAW_SPRITE_SKIP_COLUMNS_0
EF45 JR Z,DRAW_SPRITE_SKIP_COLUMNS_0
EF47 LD A,(FOUND_RECORD) ...or the whole width and the spill column after it
EF4A RES 6,C
EF4C JR DRAW_SPRITE_SKIP_COLUMNS_0
Prev: EE73 Up: Map Next: EF4E