Prev: E3D6 Up: Map Next: E49F
E3D9: Draw one object from the draw list
Used by the routine at SORT_AND_DRAW_THINGS.
Called by the depth sort (SORT_AND_DRAW_THINGS) for each object in turn, back to front. The projection (PROJECT_THING) gives the object's place relative to the knight's in DRAW_X and DRAW_Y; adding the drawing offsets (+C, +D) gives the pixel x and y of the sprite's bottom left corner, which are kept in +E and +F. The game's y counts upwards: the play area is 112 lines, from y 72 at the bottom (line 127 of the screen) to 183 (line 16), and its buffer 24 bytes a row from x 16, of which the first two bytes are a margin never shown (COPY_BUFFER).
An object is not drawn at all if its x is below 16 or above 202, or its y is 184 or more, or either high byte from the projection is not 0. If its bottom is below the play area, only its rows from y 72 up are drawn; if its top is above, only those below. The knight's graphics (16 to 47, legs and top) are cut instead at ARRIVING lines above the bottom, which counts up to 112 as he appears at a new life (UPDATE_KNIGHT), so he is shown from the ground up. The entry point DRAW_SPRITE_AT draws at +E and +F as they are, with no projection and no checks at the sides; the ending's pictures use it (ENDING_PIT_FRONT).
The row loop is unrolled for a sprite five bytes wide, twice: a plain run for a sprite whose x is on a byte boundary (SPRITE_ALIGNED_RUN), and a shifted run that reads its bytes through the tables of SHIFT_TABLES and touches one byte more a 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 SPRITE_NEXT_ROW (SPRITE_SHIFTED_FOUR) with the step from the last byte drawn in a row to the first of the row above. Bits 1 and 2 of x choose the shift, 0 (the plain run), 2, 4 or 6 pixels; bit 0 is ignored, so things move across in steps of two pixels. 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.
On the way out SPRITE_WIDTH holds the bytes drawn a row (one more than the sprite's width when shifted), SPRITE_ROWS the rows drawn, and bit 1 of the object's flags (+7) is set. Checked in the simulator, drawing a monster's sprite into an empty buffer at a range of places: the rows land from y less 72 up, the clipping at the bottom, the top and ARRIVING comes out as described, and the patched offsets and steps are the ones worked out here.
Nothing is clipped at the sides beyond the tests on x. A sprite starting in a row's last byte runs on into the first bytes of the row above: the two margin bytes hide two of them, but a four-byte sprite drawn shifted there would put its last two into the visible columns 2 and 3 of the row above (the simulator shows the run-on; whether it is ever seen in play is not known).
Input
IX The object
DRAW_SPRITE E3D9 CALL PROJECT_THING Project the object into DRAW_X and DRAW_Y
E3DC LD HL,(DRAW_X) x = DRAW_X plus the offset +C; not drawn unless DRAW_X's high byte is 0 and x is 16 to 202
E3DF LD A,H
E3E0 AND A
E3E1 RET NZ
E3E2 LD A,L
E3E3 ADD A,(IX+$0C)
E3E6 CP $CB
E3E8 RET NC
E3E9 CP $10
E3EB RET C
E3EC LD (IX+$0E),A Keep x in +E
E3EF LD HL,(DRAW_Y) y = DRAW_Y plus +D; not drawn unless the high byte is 0 and y is below 184
E3F2 LD A,H
E3F3 AND A
E3F4 RET NZ
E3F5 LD A,L
E3F6 ADD A,(IX+$0D)
E3F9 CP $B8
E3FB RET NC
E3FC LD (IX+$0F),A Keep y in +F
This entry point is used by the routine at ENDING_PIT_FRONT.
DRAW_SPRITE_AT E3FF CALL TURN_SPRITE DRAW_SPRITE_AT: find the sprite, turned the right way; DE = its width byte
E402 LD A,(IX+$0E) Bits 1-2 of x: 0 for a sprite on a byte boundary
E405 AND $06
E407 JP Z,DRAW_SPRITE_6
E40A OR $F8 H = the first page of the shift's pair: $FA, $FC or $FE for 2, 4 or 6 pixels
E40C LD H,A
E40D LD A,(DE) B and SPRITE_WIDTH = the width plus one: a shifted row touches one byte more
E40E INC DE
E40F AND $07
E411 INC A
E412 LD B,A
E413 LD (SPRITE_WIDTH),A
E416 DEC A The JR offset into the shifted run: 18 bytes a unit, entered as many units from the end as the sprite is wide
E417 AND $07
E419 ADD A,A
E41A LD C,A
E41B ADD A,A
E41C ADD A,A
E41D ADD A,A
E41E ADD A,C
E41F NEG
E421 ADD A,$5A
DRAW_SPRITE_0 E423 LD ($E4CC),A Patch it into the JR in SPRITE_ROW, for either run
E426 LD A,B The step from the last byte drawn in a row to the first of the next: 25 less the bytes a row; patched into SPRITE_NEXT_ROW
E427 CPL
E428 ADD A,$1A
E42A LD ($E52A),A
E42D EX DE,HL HL = the height byte
E42E LD A,(IX+$00) C = how far up from the bottom may be drawn: the whole 112 lines, but ARRIVING for the knight's legs and top (graphics 16 to 47)
E431 SUB $10
E433 CP $20
E435 LD A,$70
E437 JR NC,DRAW_SPRITE_1
E439 LD A,(ARRIVING)
DRAW_SPRITE_1 E43C LD C,A
E43D LD A,(IX+$0F) y less 72: the lines above the play area's bottom; below it, clip there
E440 SUB $48
E442 JR C,DRAW_SPRITE_4
E444 SUB C Nothing to draw if it starts at or above the limit
E445 RET NC
E446 NEG The rows: the lines up to the limit, or the height if fewer; HL on to the data
E448 CP (HL)
E449 JR C,DRAW_SPRITE_2
E44B LD A,(HL)
DRAW_SPRITE_2 E44C INC HL
E44D LD (SPRITE_ROWS),A
DRAW_SPRITE_3 E450 EX DE,HL BC = the buffer address of the sprite's bottom left byte (BUFFER_ADDRESS), from +E and +F; HL = the table page again
E451 PUSH HL
E452 LD L,(IX+$0E)
E455 LD H,(IX+$0F)
E458 CALL BUFFER_ADDRESS
E45B LD C,L
E45C LD B,H
E45D POP HL
E45E LD (SAVED_SP),SP Keep SP, and point it at the data
E462 EX DE,HL
E463 LD SP,HL
E464 EX DE,HL
E465 SET 1,(IX+$07) Mark the object drawn
E469 LD A,(SPRITE_ROWS) A = the rows; into the row loop
E46C JR SPRITE_ROW
DRAW_SPRITE_4 E46E NEG Below the bottom: C = the lines under it; the rows left above it, if any
E470 LD C,A
E471 LD A,(HL)
E472 SUB C
E473 RET M
E474 RET Z
E475 LD (SPRITE_ROWS),A
E478 LD B,$00 Skip C rows of the data, twice the width a row, and start at the bottom line
E47A DEC HL
E47B LD A,(HL)
E47C AND $3F
E47E INC HL
E47F INC HL
E480 SLA C
E482 RL B
DRAW_SPRITE_5 E484 ADD HL,BC
E485 DEC A
E486 JR NZ,DRAW_SPRITE_5
E488 LD (IX+$0F),$48
E48C JR DRAW_SPRITE_3 Draw
DRAW_SPRITE_6 E48E LD A,(DE) On a byte boundary: B and SPRITE_WIDTH = the width
E48F INC DE
E490 AND $0F
E492 LD (SPRITE_WIDTH),A
E495 LD B,A
E496 ADD A,A The JR offset into the plain run: 8 bytes a unit, entered as many units from the end as the sprite is wide
E497 ADD A,A
E498 ADD A,A
E499 NEG
E49B SUB $06
E49D JR DRAW_SPRITE_0
Prev: E3D6 Up: Map Next: E49F