Prev: 692B Up: Map Next: 6988
692C: Draw Sprite Object
Used by the routines at Handler_PlayerSprite and Handler_GhostRider.
Input
A Sprite frame ID
C Sprite colour
DE Sprite screen position
DrawSpriteObject 692C LD B,A Store the sprite frame ID in B.
692D LD A,C Load the sprite attribute value into A.
692E EXX Switch to the shadow registers.
692F LD HL,($781C) HL'=*SpriteBackgroundBuffer_Pointer.
6932 LD C,A Load the sprite attribute value into C'.
6933 LD A,($781B) Load *ActiveSpriteBlocks into B'.
6936 LD B,A
6937 EXX Switch back to the normal registers.
Calculate the sprite data address from the frame ID.
6938 LD A,B Load L with the frame ID multiplied by 02.
6939 ADD A,A
693A LD L,A
This is quite clever, and very subtle. It's probably easier here to show examples:
Input Value Output in HL
0D BE1A
12 BE24
87 BF0E
C7 BF8E
From a quick glance, the following code looks pretty straight-forward, just a little strange: H=(frame ID * 02) + BE - (frame ID * 02).
The cleverness here is with the carry flag and the ADC instruction.
When the multiplication of the frame ID passes 0100 the carry flag is set and this is included when adding the graphics high byte BE. The SUB L then removes the "frame ID * 02" part, leaving just BE + carry flag.
693B ADC A,$BE Load H with the high byte for the graphics data: BE + the carry flag.
693D SUB L
693E LD H,A
693F LD A,B Load the original frame ID into A.
Fetch the sprite data.
6940 LD C,(HL) Fetch the sprite data address from *HL and store it in BC.
6941 INC L
6942 LD B,(HL)
Check the sprite "type" bit.
6943 BIT 5,A Jump to DrawLargeSprite if bit 5 of the sprite ID is set.
6945 JP NZ,DrawLargeSprite
Process regular sprite animation frames.
6948 LD A,(BC) Fetch the sprite X offset and store it in A.
ProcessNextFrame 6949 INC BC Move to the next data byte.
694A ADD A,E E=base X position + the sprite X offset.
694B LD E,A
694C LD A,(BC) Fetch the sprite Y offset and store it in A.
694D INC BC Move to the next data byte.
CalculatePosition 694E ADD A,D D=base Y position + the sprite Y offset.
694F LD D,A
Check if the sprite frame is within the screen boundaries.
6950 CP $10 Jump to SkipToNextFrame if the sprites "Y" position is higher than 10.
6952 JR NC,SkipToNextFrame
6954 LD A,E Jump to DrawVisibleFrame if the sprites "X" position is lower than 20.
6955 CP $20
6957 JR C,DrawVisibleFrame
Skip the current frame and advance to the next frame data.
SkipToNextFrame 6959 LD HL,$0008 BC=sprite data pointer+0008.
695C ADD HL,BC
695D LD B,H
695E LD C,L
CheckNextFrame 695F LD A,(BC) Load A with the next control byte from *BC.
Check for the terminator (FF+01 will set the zero flag).
6960 INC A Increment the control byte by one.
6961 LD A,$01 Set the sprite "type" flag in A to 01.
6963 JR NZ,CalculatePosition Jump to CalculatePosition if the terminator character wasn't detected (on line 6960).
We reached the terminator.
6965 INC BC Move to the next data byte.
Check for the sequence end marker byte.
6966 LD A,(BC) Read the sequence control byte.
6967 CP $80 Jump to ProcessNextFrame if the sequence control byte is not equal to 80.
6969 JR NZ,ProcessNextFrame
696B JP CompleteSpriteSequence Jump to CompleteSpriteSequence.
Draw the sprite frame to the screen.
DrawVisibleFrame 696E LD A,D Load the sprite Y position.
696F ADD A,$40 Convert it to a screen buffer address.
Extract the bits which relate to the ZX Spectrum screen layout.
6971 AND %01001000 Keep only bits 3 and 6.
6973 LD H,A Store the result in H.
6974 LD A,D Reload the sprite Y position.
6975 RRCA Rotate A right three positions (bits 0 to 2 are now in positions 5 to 7).
6976 RRCA
6977 RRCA
Keep only the row bits.
6978 AND %11100000 Keep only bits 5-7.
697A ADD A,E Add the sprite X position and store the result in L.
697B LD L,A
Draw the sprite to the screen buffer.
697C CALL DrawSprite Call DrawSprite to draw the top of the sprite.
697F INC H Move to the next screen row.
6980 CALL DrawSprite Call DrawSprite to draw the bottom of the sprite.
6983 CALL ScreenBufferToAttributeBuffer Call ScreenBufferToAttributeBuffer.
6986 JR CheckNextFrame Jump to CheckNextFrame.
Prev: 692B Up: Map Next: 6988