Prev: B2C5 Up: Map Next: B37F
B2EE: Get Sprite Address
Used by the routines at DrawObject and CalculateSpriteSize.
Makes sure that the sprite of an object faces the way the object does. The sprite data holds its own state in the top two bits of its first byte: bit 7 says that it is upside down and bit 6 that it is mirrored. If either differs from the flags of the object (bits 7 and 6 of its flag byte) the sprite data is flipped to match, in place.
A sprite is held as rows of pairs of bytes, one pair per 08 pixels, with the mask byte first. Its bottom row comes first. Flipping it upside down swaps the rows over; mirroring it reverses the bits of each byte and the order of the bytes in each row.
If the type of the object has no sprite, the routine returns to the caller of its caller.
Input
IX Object record
Output
DE Address of the sprite
Find the address of the sprite.
GetSpriteAddress B2EE LD L,(IX+$00) Fetch the sprite number.
B2F1 LD H,$00 Set H to 00.
B2F3 ADD HL,HL Double HL.
Find the entry for the type in the sprite table, SpriteTable.
B2F4 LD BC,$6DD7 Point BC at SpriteTable.
B2F7 ADD HL,BC Add BC to HL.
B2F8 LD E,(HL) Fetch the address of the sprite.
B2F9 INC HL
B2FA LD D,(HL)
B2FB LD A,(DE) Jump to GetSpriteAddress_Vertical if the sprite exists, which is when its first byte is not zero.
B2FC AND A
B2FD JR NZ,GetSpriteAddress_Vertical
B2FF INC SP Otherwise discard the return address of the caller...
B300 INC SP
B301 RET ...and return to the caller of the caller.
Flip the sprite upside down if its state differs from that of the object.
GetSpriteAddress_Vertical B302 PUSH DE Stash the address of the sprite on the stack.
B303 LD A,(DE) Compare the first byte of the sprite with the flags of the object.
B304 XOR (IX+$07)
B307 AND %10000000 Keep only bit 7.
B309 JR Z,GetSpriteAddress_Horizontal Jump to GetSpriteAddress_Horizontal if they are the same.
B30B LD A,(DE) Toggle bit 7 of the sprite state.
B30C XOR $80
B30E LD (DE),A
B30F RLCA Rotate the width up by one bit, to double it.
B310 AND %00011110 Keep the doubled width, which is the number of bytes in a row.
B312 LD B,A Set B to the row length.
B313 INC DE Move on to the height.
B314 LD A,(DE) Fetch the height of the sprite in C.
B315 LD C,A
B316 INC DE Move on to the first row.
B317 PUSH BC Stash the row length and the height, and the address of the data, on the stack.
B318 PUSH DE
B319 LD E,C Set DE to the height and clear HL.
B31A LD D,$00
B31C LD H,D
B31D LD L,D
GetSpriteAddress_Multiply B31E ADD HL,DE Multiply the height by the row length, to get the size of the data.
B31F DJNZ GetSpriteAddress_Multiply
B321 POP DE Restore the address of the data and the row length from the stack.
B322 POP BC
B323 ADD HL,DE Add the address of the data to get the address of the end of it.
B324 EX DE,HL Put the end of the sprite data against its start.
B325 LD A,B Call AddAToHL to add the row length to HL, which then points to the end of the first row.
B326 CALL AddAToHL
B329 DEC DE Line up the last byte of the last row with that of the first row.
B32A DEC HL
B32B SRL C Halve the height to get the number of pairs of rows to swap.
GetSpriteAddress_SwapRows B32D PUSH BC Stash the counters on the stack.
GetSpriteAddress_SwapByte B32E LD A,(DE) Swap a byte of the lower row with a byte of the upper row.
B32F LD C,(HL)
B330 LD (HL),A
B331 LD A,C
B332 LD (DE),A
B333 DEC HL Move both pointers back to the previous byte.
B334 DEC DE
B335 DJNZ GetSpriteAddress_SwapByte Decrease the byte counter and loop until the rows have been swapped.
B337 POP BC Restore the counters from the stack.
Move on to the next pair of rows: the upper pointer on to the end of the next row, while the lower pointer is already at the end of the row below.
B338 LD A,B Call AddAToHL to add the row length to HL.
B339 CALL AddAToHL
B33C LD A,B Call AddAToHL to add the row length to HL again.
B33D CALL AddAToHL
B340 DEC C Count down the row pairs and jump to GetSpriteAddress_SwapRows until they are swapped.
B341 JR NZ,GetSpriteAddress_SwapRows
Mirror the sprite if its state differs from that of the object.
GetSpriteAddress_Horizontal B343 POP DE Restore the address of the sprite from the stack.
B344 PUSH DE Stash the address of the sprite on the stack again.
B345 LD A,(DE) Compare the first byte of the sprite with the flags of the object.
B346 XOR (IX+$07)
B349 AND %01000000 Keep only bit 6.
B34B JR Z,GetSpriteAddress_Done Jump to GetSpriteAddress_Done if they are the same.
B34D LD A,(DE) Toggle bit 6 of the sprite state.
B34E XOR $40
B350 LD (DE),A
B351 AND %00001111 Keep only the width.
B353 LD B,A Set B and C to the width in byte columns.
B354 LD C,A
B355 INC DE Move on to the height.
B356 LD A,(DE) Fetch the height.
B357 EX AF,AF' Keep the height as the row counter.
B358 INC DE Move on to the first row.
B359 EX DE,HL Start at the first row of the sprite.
B35A PUSH HL Stash the address of the first row on the stack.
B35B EXX Switch to the shadow registers.
B35C POP HL Restore it into HL' from the stack to read the data with.
B35D LD B,$F1 Use the table of reversed bytes, whose page is F1.
B35F EXX Switch back to the main registers.
Read a row, reversing the bits of each byte, and stack each pair of bytes.
GetSpriteAddress_ReadRow B360 EXX Switch to the shadow registers.
B361 LD C,(HL) Look up the mask byte in the table of reversed bytes, and keep the result in the low byte of DE'.
B362 LD A,(BC)
B363 LD E,A
B364 INC HL Move on to the pixel byte.
B365 LD C,(HL) Do the same with the pixel byte, keeping the result in the high byte of DE'.
B366 LD A,(BC)
B367 LD D,A
B368 INC HL Move on to the next pair.
B369 PUSH DE Stash the reversed pair on the stack.
B36A EXX Switch back to the main registers.
B36B DJNZ GetSpriteAddress_ReadRow Decrease the column counter and loop until the row has been read.
B36D LD B,C Restore the column counter.
Write the pairs back in the opposite order.
GetSpriteAddress_WriteRow B36E POP DE Take a pair from the stack.
B36F LD (HL),E Write the mask byte.
B370 INC HL Move on.
B371 LD (HL),D Write the pixel byte.
B372 INC HL Move on.
B373 DJNZ GetSpriteAddress_WriteRow Decrease the column counter and loop until the row has been written.
B375 EX AF,AF' Swap in the row counter.
B376 DEC A Jump to GetSpriteAddress_Done once the last row has been mirrored.
B377 JR Z,GetSpriteAddress_Done
B379 EX AF,AF' Stash the row counter again.
B37A LD B,C Restore the column counter.
B37B JR GetSpriteAddress_ReadRow Jump to GetSpriteAddress_ReadRow to do the next row.
GetSpriteAddress_Done B37D POP DE Restore the address of the sprite from the stack.
B37E RET Return.
View the equivalent code in;
Prev: B2C5 Up: Map Next: B37F