![]() |
Routines |
| Prev: CFFE | Up: Map | Next: D08F |
|
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.
|
||||||||
| 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 |