Prev: 45765 Up: Map Next: 45951
45806: 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 8 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 45806 LD L,(IX+0) Fetch the sprite number.
45809 LD H,0 Set H to 0.
45811 ADD HL,HL Double HL.
Find the entry for the type in the sprite table, SpriteTable.
45812 LD BC,28119 Point BC at SpriteTable.
45815 ADD HL,BC Add BC to HL.
45816 LD E,(HL) Fetch the address of the sprite.
45817 INC HL
45818 LD D,(HL)
45819 LD A,(DE) Jump to GetSpriteAddress_Vertical if the sprite exists, which is when its first byte is not zero.
45820 AND A
45821 JR NZ,GetSpriteAddress_Vertical
45823 INC SP Otherwise discard the return address of the caller...
45824 INC SP
45825 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 45826 PUSH DE Stash the address of the sprite on the stack.
45827 LD A,(DE) Compare the first byte of the sprite with the flags of the object.
45828 XOR (IX+7)
45831 AND %10000000 Keep only bit 7.
45833 JR Z,GetSpriteAddress_Horizontal Jump to GetSpriteAddress_Horizontal if they are the same.
45835 LD A,(DE) Toggle bit 7 of the sprite state.
45836 XOR 128
45838 LD (DE),A
45839 RLCA Rotate the width up by one bit, to double it.
45840 AND %00011110 Keep the doubled width, which is the number of bytes in a row.
45842 LD B,A Set B to the row length.
45843 INC DE Move on to the height.
45844 LD A,(DE) Fetch the height of the sprite in C.
45845 LD C,A
45846 INC DE Move on to the first row.
45847 PUSH BC Stash the row length and the height, and the address of the data, on the stack.
45848 PUSH DE
45849 LD E,C Set DE to the height and clear HL.
45850 LD D,0
45852 LD H,D
45853 LD L,D
GetSpriteAddress_Multiply 45854 ADD HL,DE Multiply the height by the row length, to get the size of the data.
45855 DJNZ GetSpriteAddress_Multiply
45857 POP DE Restore the address of the data and the row length from the stack.
45858 POP BC
45859 ADD HL,DE Add the address of the data to get the address of the end of it.
45860 EX DE,HL Put the end of the sprite data against its start.
45861 LD A,B Call AddAToHL to add the row length to HL, which then points to the end of the first row.
45862 CALL AddAToHL
45865 DEC DE Line up the last byte of the last row with that of the first row.
45866 DEC HL
45867 SRL C Halve the height to get the number of pairs of rows to swap.
GetSpriteAddress_SwapRows 45869 PUSH BC Stash the counters on the stack.
GetSpriteAddress_SwapByte 45870 LD A,(DE) Swap a byte of the lower row with a byte of the upper row.
45871 LD C,(HL)
45872 LD (HL),A
45873 LD A,C
45874 LD (DE),A
45875 DEC HL Move both pointers back to the previous byte.
45876 DEC DE
45877 DJNZ GetSpriteAddress_SwapByte Decrease the byte counter and loop until the rows have been swapped.
45879 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.
45880 LD A,B Call AddAToHL to add the row length to HL.
45881 CALL AddAToHL
45884 LD A,B Call AddAToHL to add the row length to HL again.
45885 CALL AddAToHL
45888 DEC C Count down the row pairs and jump to GetSpriteAddress_SwapRows until they are swapped.
45889 JR NZ,GetSpriteAddress_SwapRows
Mirror the sprite if its state differs from that of the object.
GetSpriteAddress_Horizontal 45891 POP DE Restore the address of the sprite from the stack.
45892 PUSH DE Stash the address of the sprite on the stack again.
45893 LD A,(DE) Compare the first byte of the sprite with the flags of the object.
45894 XOR (IX+7)
45897 AND %01000000 Keep only bit 6.
45899 JR Z,GetSpriteAddress_Done Jump to GetSpriteAddress_Done if they are the same.
45901 LD A,(DE) Toggle bit 6 of the sprite state.
45902 XOR 64
45904 LD (DE),A
45905 AND %00001111 Keep only the width.
45907 LD B,A Set B and C to the width in byte columns.
45908 LD C,A
45909 INC DE Move on to the height.
45910 LD A,(DE) Fetch the height.
45911 EX AF,AF' Keep the height as the row counter.
45912 INC DE Move on to the first row.
45913 EX DE,HL Start at the first row of the sprite.
45914 PUSH HL Stash the address of the first row on the stack.
45915 EXX Switch to the shadow registers.
45916 POP HL Restore it into HL' from the stack to read the data with.
45917 LD B,241 Use the table of reversed bytes, whose page is 241.
45919 EXX Switch back to the main registers.
Read a row, reversing the bits of each byte, and stack each pair of bytes.
GetSpriteAddress_ReadRow 45920 EXX Switch to the shadow registers.
45921 LD C,(HL) Look up the mask byte in the table of reversed bytes, and keep the result in the low byte of DE'.
45922 LD A,(BC)
45923 LD E,A
45924 INC HL Move on to the pixel byte.
45925 LD C,(HL) Do the same with the pixel byte, keeping the result in the high byte of DE'.
45926 LD A,(BC)
45927 LD D,A
45928 INC HL Move on to the next pair.
45929 PUSH DE Stash the reversed pair on the stack.
45930 EXX Switch back to the main registers.
45931 DJNZ GetSpriteAddress_ReadRow Decrease the column counter and loop until the row has been read.
45933 LD B,C Restore the column counter.
Write the pairs back in the opposite order.
GetSpriteAddress_WriteRow 45934 POP DE Take a pair from the stack.
45935 LD (HL),E Write the mask byte.
45936 INC HL Move on.
45937 LD (HL),D Write the pixel byte.
45938 INC HL Move on.
45939 DJNZ GetSpriteAddress_WriteRow Decrease the column counter and loop until the row has been written.
45941 EX AF,AF' Swap in the row counter.
45942 DEC A Jump to GetSpriteAddress_Done once the last row has been mirrored.
45943 JR Z,GetSpriteAddress_Done
45945 EX AF,AF' Stash the row counter again.
45946 LD B,C Restore the column counter.
45947 JR GetSpriteAddress_ReadRow Jump to GetSpriteAddress_ReadRow to do the next row.
GetSpriteAddress_Done 45949 POP DE Restore the address of the sprite from the stack.
45950 RET Return.
View the equivalent code in;
Prev: 45765 Up: Map Next: 45951