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