Prev: CFFE Up: Map Next: D08F
D013: 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 -- a thing picked up (TAKE_OR_LEAVE), or at the end of SPARKLE_END_PLACE -- and is not drawn: its record is emptied instead, which frees it. Anything else loses its draw flag (bit 4 of +7), is projected onto the screen by CALC_PIXEL_XY, and is drawn by the entry point PRINT_SPRITE unless its pixel y is 192 or more, wholly above the screen.
PRINT_SPRITE draws whatever sprite IX's graphic names at the pixel position already in +1A and +1B, with no projection: the panel and the border (TRANSFER_SPRITE_AND_PRINT, MULTIPLE_PRINT_SPRITE) and the carried things (SHOW_CARRIED) are drawn with it, 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 stored now, turned 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 tables above MIRROR_TABLE 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 never enables interrupts, 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 and the pixel position to +1C to +1F before the next turn's update, so RENDER_DYNAMIC_OBJECTS knows what to rub out. Nothing is clipped at the sides or the bottom. As Knight Lore's calc_pixel_XY_and_render and print_sprite.
Input
IX the object
CALC_PIXEL_XY_AND_RENDER D013 LD A,(IX+$00) Graphic 1: empty the record instead
D016 CP $01
D018 JR NZ,PROJECT_AND_DRAW
D01A LD (IX+$00),$00
D01E RET
PROJECT_AND_DRAW D01F RES 4,(IX+$07) Drawn now: off the draw list's flag
D023 CALL CALC_PIXEL_XY Pixel position into +1A and +1B; above the screen, nothing to draw
D026 RET NC
This entry point is used by the routines at MULTIPLE_PRINT_SPRITE, SHOW_CARRIED and TRANSFER_SPRITE_AND_PRINT.
PRINT_SPRITE D027 CALL FLIP_SPRITE DE = the sprite's width byte, the sprite turned the way the object faces; an empty sprite returns from here at once
D02A LD A,(IX+$1A) The pixel x within its byte; 0 goes to the aligned case, SPRITE_ALIGNED
D02D AND $07
D02F JR Z,SPRITE_ALIGNED
D031 RLCA H = $F0 + 2 * the shift: the page pair of BUILD_LOOKUP_TBLS's tables for that shift
D032 AND $0E
D034 OR $F0
D036 LD H,A
D037 LD A,(DE) The width from the width byte (bits 0-2 here), plus one: the bytes a shifted row touches, into +18
D038 INC DE
D039 AND $07
D03B INC A
D03C LD B,A
D03D LD (IX+$18),A
D040 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
D041 AND $07
D043 ADD A,A
D044 ADD A,A
D045 ADD A,A
D046 ADD A,A
D047 NEG
D049 ADD A,$50
PATCH_SPRITE_ROWS D04B LD ($D0BC),A The offset, into the JR in SPRITE_ROW
D04E 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
D04F CPL
D050 ADD A,$22
D052 LD ($D110),A
D055 LD A,(DE) The height, into +19
D056 INC DE
D057 LD (IX+$19),A
D05A ADD A,(IX+$1B) If the sprite would run past the top of the screen, only the rows below it: 192 less the pixel y
D05D SUB $C0
D05F JR C,DRAW_SPRITE_ROWS
D061 NEG
D063 ADD A,(IX+$19)
D066 LD (IX+$19),A
DRAW_SPRITE_ROWS D069 LD C,(IX+$1A) BC = the buffer address of the sprite's bottom-left byte (CALC_VIDBUF_ADDR)
D06C LD B,(IX+$1B)
D06F CALL CALC_VIDBUF_ADDR
D072 LD (SAVED_SP),SP SP onto the mask and image bytes, the real one kept in SAVED_SP
D076 EX DE,HL
D077 LD SP,HL
D078 EX DE,HL
D079 LD A,(IX+$19) A = the rows to draw; into the loop
D07C JR SPRITE_ROW
SPRITE_ALIGNED D07E LD A,(DE) The aligned case: the width (bits 0-3), into +18; B = the bytes a row touches
D07F INC DE
D080 AND $0F
D082 LD (IX+$18),A
D085 LD B,A
D086 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
D087 ADD A,A
D088 ADD A,A
D089 NEG
D08B SUB $06
D08D JR PATCH_SPRITE_ROWS
Prev: CFFE Up: Map Next: D08F