Prev: B3B6 Up: Map Next: B44F
B3D3: Draw one object from the draw list
Used by the routine at DRAW_CANDIDATE.
Called by the depth sort (DRAW_CANDIDATE) for each listed object in turn, back to front. Graphic 1 marks an object on its way out of the room's records -- TAKE_OR_LEAVE sets it on what is picked up, END_PUFF at the end of a puff -- and is not drawn: its record is emptied instead, which frees it. Anything else loses its draw flag (bit 4 of +$07), is projected onto the screen by CALC_PIXEL_XY, and is drawn by the entry point below unless its pixel y is 192 or more, wholly above the screen.
The entry point DRAW_SPRITE draws whatever sprite IX's graphic names at the pixel position already in +$1A and +$1B, with no projection: SHOW_CARRIED draws the panel's carried things with it, and DRAW_LIVES the lives icon, both through the spare record at PANEL_RECORD.
A sprite is a width byte (bits 0-3 the width in bytes, bits 6 and 7 how it is currently stored, flipped or not), a height byte, and then a mask byte and an image byte for each byte of each row, the bottom row first. Each buffer byte is cleared where the mask is set and has the image put in, so an object punches its own shape out of whatever was drawn behind it.
The row loop is unrolled for the widest sprite, five bytes, twice: a plain run for a sprite whose pixel x is a multiple of 8 (SPRITE_ALIGNED_RUN), and a shifted run that reads its bytes through the mask tables from SHIFTED7 up and so touches one byte more per row (SPRITE_SHIFTED_RUN). This routine patches the offset of the JR in SPRITE_ROW to enter the right run as many units from its end as the sprite is wide, and the operand of the ADD at the foot of SPRITE_SHIFTED_RUN with the step from the end of one row to the start of the next. The stack pointer reads the sprite: SP is pointed at the data and each POP DE fetches a mask into E and its image into D, the real SP kept in SAVED_SP meanwhile. The game runs with interrupts off (only PAUSE turns them on, and only while paused), so nothing pushes onto the sprite.
On the way out +$18 holds the width in bytes that was drawn (one more than the sprite's own when shifted) and +$19 the height, cut to the rows below the top of the screen; the main loop copies them to +$1C and +$1D before the next turn's update, so RENDER_DYNAMIC_OBJECTS knows what to rub out. Nothing is clipped at the sides or the bottom.
Input
IX the object
DRAW_OBJECT B3D3 LD A,(IX+$00) graphic 1: empty the record instead
B3D6 CP $01
B3D8 JR NZ,DRAW_OBJECT_0
B3DA LD (IX+$00),$00
B3DE RET
DRAW_OBJECT_0 B3DF RES 4,(IX+$07) drawn now: off the draw list's flag
B3E3 CALL CALC_PIXEL_XY pixel position into +$1A and +$1B; above the screen, nothing to draw
B3E6 RET NC
This entry point is used by the routines at SHOW_CARRIED, TRANSFER_SPRITE_AND_PRINT, MULTIPLE_PRINT_SPRITE and DRAW_LIVES.
DRAW_SPRITE B3E7 CALL FIND_SPRITE DE = the sprite's width byte, the sprite turned the way the object faces (FIND_SPRITE); an empty sprite returns from here at once
B3EA LD A,(IX+$1A) the pixel x within its byte; 0 goes to the aligned case, SPRITE_ALIGNED
B3ED AND $07
B3EF JR Z,SPRITE_ALIGNED
B3F1 RLCA H = $F0 + 2 * the shift: the page pair of MAKE_TABLES's tables for that shift
B3F2 AND $0E
B3F4 OR $F0
B3F6 LD H,A
B3F7 LD A,(DE) the width from the header, plus one: the bytes a shifted row touches, into +$18
B3F8 INC DE
B3F9 AND $07
B3FB INC A
B3FC LD B,A
B3FD LD (IX+$18),A
B400 DEC A the JR's offset: 16 bytes of code per byte of width, back from the end of the shifted run at SPRITE_SHIFTED_RUN
B401 AND $07
B403 ADD A,A
B404 ADD A,A
B405 ADD A,A
B406 ADD A,A
B407 NEG
B409 ADD A,$50
PATCH_SPRITE_ROWS B40B LD ($B47C),A the offset, into the JR in SPRITE_ROW
B40E LD A,B the step to the next row, into the ADD at the foot of SPRITE_SHIFTED_RUN: 33 less the bytes touched, since a row moves BC on one fewer than that
B40F CPL
B410 ADD A,$22
B412 LD ($B4D0),A
B415 LD A,(DE) the height, into +$19
B416 INC DE
B417 LD (IX+$19),A
B41A ADD A,(IX+$1B)
B41D SUB $C0 if the sprite would run past the top of the screen, only the rows below it: 192 less the pixel y
B41F JR C,DRAW_SPRITE_ROWS
B421 NEG
B423 ADD A,(IX+$19)
B426 LD (IX+$19),A
DRAW_SPRITE_ROWS B429 LD C,(IX+$1A) BC = the buffer address of the sprite's bottom-left byte (CALC_VIDBUF_ADDR)
B42C LD B,(IX+$1B)
B42F CALL CALC_VIDBUF_ADDR
B432 LD (SAVED_SP),SP SP onto the mask and image bytes, the real one kept in SAVED_SP
B436 EX DE,HL
B437 LD SP,HL
B438 EX DE,HL
B439 LD A,(IX+$19) A = the rows to draw; into the loop
B43C JR SPRITE_ROW
SPRITE_ALIGNED B43E LD A,(DE) the aligned case: the width from the header, into +$18
B43F INC DE
B440 AND $0F
B442 LD (IX+$18),A
B445 LD B,A B = the bytes a row touches, the width itself
B446 ADD A,A the JR's offset: 8 bytes of code per byte of width, back from the end of the aligned run at SPRITE_ALIGNED_RUN
B447 ADD A,A
B448 ADD A,A
B449 NEG
B44B SUB $06
B44D JR PATCH_SPRITE_ROWS
Prev: B3B6 Up: Map Next: B44F