Prev: E32C Up: Map Next: E3D6
E353: Find an object's sprite, and turn its stored data the way the object wants it
Used by the routine at DRAW_SPRITE.
The graphic (+0) indexes GRAPHICS for the sprite. A sprite is a width byte -- bits 0-3 the width in bytes, bit 7 set while its data is stored upside down, bit 6 while it is stored mirrored -- a height byte, and then a mask byte and an image byte for each byte of each row, the bottom row first. Bits 7 and 6 of the object's flags (+7) say how it wants to be drawn. Where they differ from the sprite's, the data is turned in place and the sprite's bit toggled, so an object that keeps facing one way costs nothing after the first time, while two objects sharing a sprite and facing opposite ways turn it back and forth every time each is drawn.
Upside down swaps whole rows end for end, the first with the last, working inwards. Mirroring (MIRROR_SPRITE_DATA, also entered by MIRROR_SPRITE) reverses the order of each row's mask and image pairs and the bits of every byte, through REVERSE_TABLE: a row's pairs are read, reversed, onto the stack and popped back in the opposite order.
Nothing in the game sets bit 7 of a record's flags. Every write to that byte was read: the records are cleared or copied from templates that hold 0 there; the rest set or clear bits 0, 1 and 5, set bit 6 from the view or the facing, take bits 6 and 7 from a table whose four bytes have bit 7 clear (FACING_LOOKS), or copy another record's flags. So the upside-down half, and the multiply it uses (HL_EQUALS_DE_X_A), never run -- which the build's sessions agree with -- and every sprite's bit 7 stays clear. Knight Lore's objects do turn upside down; Pentagram's routine is the same as this one, and Alien 8's nearly so.
Input
IX The object
Output
DE The sprite (its width byte)
TURN_SPRITE E353 LD A,(IX+$00) DE = the sprite, kept on the stack
E356 LD BC,GRAPHICS
E359 CALL TABLE_WORD
E35C EX DE,HL
E35D PUSH DE
E35E LD A,(DE) Stored the way up the object wants?
E35F XOR (IX+$07)
E362 AND $80
E364 JR Z,TURN_SPRITE_2
E366 LD A,(DE) No (it never happens): toggle the sprite's upside-down bit
E367 XOR $80
E369 LD (DE),A
E36A RLCA B = the bytes in a row, twice the width
E36B AND $1E
E36D LD B,A
E36E INC DE C = the height; DE on to the data
E36F LD A,(DE)
E370 LD C,A
E371 INC DE
E372 PUSH DE
E373 LD E,B DE = the end of the data: the height times a row's bytes on from its start
E374 LD D,$00
E376 CALL HL_EQUALS_DE_X_A
E379 POP DE
E37A ADD HL,DE
E37B EX DE,HL
E37C LD A,B HL = the last byte of the first row, DE the last byte of the last; C = half the height, the pairs of rows to swap
E37D CALL ADD_HL_A
E380 DEC DE
E381 DEC HL
E382 SRL C
TURN_SPRITE_0 E384 PUSH BC Swap a row with its partner, byte for byte from their ends
TURN_SPRITE_1 E385 LD A,(DE)
E386 LD C,(HL)
E387 LD (HL),A
E388 LD A,C
E389 LD (DE),A
E38A DEC HL
E38B DEC DE
E38C DJNZ TURN_SPRITE_1
E38E POP BC HL on to the end of the next row up; DE is already at the end of the row below its last
E38F LD A,B
E390 CALL ADD_HL_A
E393 LD A,B
E394 CALL ADD_HL_A
E397 DEC C Until the middle
E398 JR NZ,TURN_SPRITE_0
TURN_SPRITE_2 E39A POP DE Stored mirrored or not as the object wants?
E39B PUSH DE
E39C LD A,(DE)
E39D XOR (IX+$07)
E3A0 AND $40
E3A2 JR Z,TURN_SPRITE_5
This entry point is used by the routine at MIRROR_SPRITE.
MIRROR_SPRITE_DATA E3A4 LD A,(DE) No, or entered here (MIRROR_SPRITE_DATA): toggle the sprite's mirrored bit; B and C = the width
E3A5 XOR $40
E3A7 LD (DE),A
E3A8 AND $0F
E3AA LD B,A
E3AB LD C,A
E3AC INC DE A' = the height; HL at the data, and HL' too, with B' the page of REVERSE_TABLE
E3AD LD A,(DE)
E3AE EX AF,AF'
E3AF INC DE
E3B0 EX DE,HL
E3B1 PUSH HL
E3B2 EXX
E3B3 POP HL
E3B4 LD B,$F9
E3B6 EXX
TURN_SPRITE_3 E3B7 EXX Read a row's pairs onto the stack, each byte's bits reversed
E3B8 LD C,(HL)
E3B9 LD A,(BC)
E3BA LD E,A
E3BB INC HL
E3BC LD C,(HL)
E3BD LD A,(BC)
E3BE LD D,A
E3BF INC HL
E3C0 PUSH DE
E3C1 EXX
E3C2 DJNZ TURN_SPRITE_3
E3C4 LD B,C Pop them back over the same row, the last pair first
TURN_SPRITE_4 E3C5 POP DE
E3C6 LD (HL),E
E3C7 INC HL
E3C8 LD (HL),D
E3C9 INC HL
E3CA DJNZ TURN_SPRITE_4
E3CC EX AF,AF' The next row, until the height is done
E3CD DEC A
E3CE JR Z,TURN_SPRITE_5
E3D0 EX AF,AF'
E3D1 LD B,C
E3D2 JR TURN_SPRITE_3
TURN_SPRITE_5 E3D4 POP DE Return the sprite in DE
E3D5 RET
Prev: E32C Up: Map Next: E3D6