![]() |
Routines |
| Prev: 27886 | Up: Map | Next: 28408 |
|
Used by the routine at Handler_PlayerDeathGameOver.
|
||||||||||||||||||||
| Handler_Shield | 28111 | CALL CheckCollision | Call CheckCollision. | |||||||||||||||||
| 28114 | LD A,(26349) | A=*PlayerAttributeBufferPosition. | ||||||||||||||||||
| 28117 | PUSH AF | Stash the player position on the stack. | ||||||||||||||||||
| 28118 | LD HL,26260 | Jump to Shield_CheckDemoMode if *ShieldTimer isn't active. | ||||||||||||||||||
| 28121 | LD A,(HL) | |||||||||||||||||||
| 28122 | OR A | |||||||||||||||||||
| 28123 | JR Z,Shield_CheckDemoMode | |||||||||||||||||||
|
The players shield is active, so decrease the shield timer.
|
||||||||||||||||||||
| 28125 | DEC (HL) | Decrease *ShieldTimer by one. | ||||||||||||||||||
|
Check if the timer has "wrapped around" to 255 i.e. finished counting down.
|
||||||||||||||||||||
| 28126 | BIT 7,(HL) | Jump to PlayShieldSound if bit 7 of *ShieldTimer is set. | ||||||||||||||||||
| 28128 | JR NZ,PlayShieldSound | |||||||||||||||||||
| 28130 | XOR A | Write 0 ("inactive") to *Flag_Shield. | ||||||||||||||||||
| 28131 | LD (26259),A | |||||||||||||||||||
| 28134 | JR PlayShieldSound | Jump to PlayShieldSound. | ||||||||||||||||||
|
Check for shield activation player inputs.
Start by checking if the game is running in demo mode or not?
|
||||||||||||||||||||
| Shield_CheckDemoMode | 28136 | LD A,(26355) | Jump to Shield_CheckKempston if *Flag_ActiveDemoMode is not active. | |||||||||||||||||
| 28139 | OR A | |||||||||||||||||||
| 28140 | JR Z,Shield_CheckKempston | |||||||||||||||||||
|
Demo mode is active, so use a random number to decide whether to activate the shield or not.
|
||||||||||||||||||||
| 28142 | CALL GenerateRandomNumber | Call GenerateRandomNumber. | ||||||||||||||||||
| 28145 | OR A | Jump to Shield_ActivateShield if the generated random number is zero. | ||||||||||||||||||
| 28146 | JR Z,Shield_ActivateShield | |||||||||||||||||||
| 28148 | JR PlayShieldSound | Jump to PlayShieldSound. | ||||||||||||||||||
|
Check if the control method is the Kempston joystick?
|
||||||||||||||||||||
| Shield_CheckKempston | 28150 | LD A,(26358) | Jump to Shield_CheckAGF if *ControlMethod is not the Kempston joystick. | |||||||||||||||||
| 28153 | CP 2 | |||||||||||||||||||
| 28155 | JR NZ,Shield_CheckAGF | |||||||||||||||||||
|
The control method is Kempston joystick, so test for "down" being pressed.
|
||||||||||||||||||||
| 28157 | IN A,(31) | A=read from the Kempston joystick port. | ||||||||||||||||||
| 28159 | AND %00000100 | Jump to Shield_ActivateShield if "down" (bit 2) is being pressed. | ||||||||||||||||||
| 28161 | JR NZ,Shield_ActivateShield | |||||||||||||||||||
| 28163 | JR PlayShieldSound | Jump to PlayShieldSound. | ||||||||||||||||||
|
Check if the control method is the AGF joystick?
|
||||||||||||||||||||
| Shield_CheckAGF | 28165 | CP 1 | Jump to Shield_CheckKeyboard if *ControlMethod is not the AGF joystick. | |||||||||||||||||
| 28167 | JR NZ,Shield_CheckKeyboard | |||||||||||||||||||
|
The control method is the AGF joystick, so test for "down" being pressed.
|
||||||||||||||||||||
| 28169 | LD A,239 | Read from the keyboard;
|
||||||||||||||||||
| 28171 | IN A,(254) | |||||||||||||||||||
| 28173 | BIT 4,A | Jump to Shield_ActivateShield if "down" ("4") was pressed. | ||||||||||||||||||
| 28175 | JR Z,Shield_ActivateShield | |||||||||||||||||||
| 28177 | JR PlayShieldSound | Jump to PlayShieldSound. | ||||||||||||||||||
|
Else, the only control option left is the keyboard.
|
||||||||||||||||||||
| Shield_CheckKeyboard | 28179 | LD A,191 | Read from the keyboard;
|
|||||||||||||||||
| 28181 | IN A,(254) | |||||||||||||||||||
| 28183 | AND %00000001 | Jump to PlayShieldSound if "ENTER" isn't being pressed. | ||||||||||||||||||
| 28185 | JR NZ,PlayShieldSound | |||||||||||||||||||
|
Activate the shield.
|
||||||||||||||||||||
| Shield_ActivateShield | 28187 | LD (HL),255 | Write 255 to *ShieldTimer. | |||||||||||||||||
| 28189 | DEC HL | Write 1 to *Flag_Shield to activate it. | ||||||||||||||||||
| 28190 | LD (HL),1 | |||||||||||||||||||
|
Play a sound when the shield is active (but not in demo mode).
|
||||||||||||||||||||
| PlayShieldSound | 28192 | LD A,(26259) | Jump to Handler_ShipMovement if *Flag_Shield is not active. | |||||||||||||||||
| 28195 | OR A | |||||||||||||||||||
| 28196 | JP Z,Handler_ShipMovement | |||||||||||||||||||
| 28199 | LD A,(26355) | Jump to DrawShield if *Flag_ActiveDemoMode is active. | ||||||||||||||||||
| 28202 | OR A | |||||||||||||||||||
| 28203 | JR NZ,DrawShield | |||||||||||||||||||
|
Play an iteration of the shield sound effect.
|
||||||||||||||||||||
| 28205 | LD A,(26260) | A=*ShieldTimer. | ||||||||||||||||||
| 28208 | AND %00000111 | Calculate the sound pitch: 0222 + ((*ShieldTimer & 7) × 4). | ||||||||||||||||||
| 28210 | ADD A,A | |||||||||||||||||||
| 28211 | ADD A,A | |||||||||||||||||||
| 28212 | LD HL,222 | |||||||||||||||||||
| 28215 | LD D,H | |||||||||||||||||||
| 28216 | LD E,A | |||||||||||||||||||
| 28217 | ADD HL,DE | |||||||||||||||||||
| 28218 | LD E,4 | Set the duration in E to 4. | ||||||||||||||||||
| 28220 | CALL 949 | Call BEEPER. | ||||||||||||||||||
| 28223 | DI | Disable interrupts. | ||||||||||||||||||
|
Draws the shield graphic around the ship in the attribute buffer and screen buffer. The shield consists of two segments (left and right) that are drawn when the shield is active.
|
||||||||||||||||||||
| DrawShield | 28224 | LD HL,(26349) | Load the player position from PlayerAttributeBufferPosition into HL. | |||||||||||||||||
| 28227 | LD H,82 | Set H to 82 (attribute buffer base address). | ||||||||||||||||||
| 28229 | LD B,2 | Set counter in B for 2 shield segments (left and right). | ||||||||||||||||||
| 28231 | LD A,(26278) | Load the movement animation frame counter from MovementAnimationFrameCounter into A. | ||||||||||||||||||
| 28234 | PUSH AF | Stash the movement animation frame counter on the stack. | ||||||||||||||||||
|
Calculate a value to be used for this shield segment based on the shield state and movement animation frame counter.
|
||||||||||||||||||||
| DrawShield_SegmentLoop | 28235 | OR A | Test if the movement animation frame counter value in A is zero. | |||||||||||||||||
| 28236 | LD DE,0 | Initialise the value to 0000 ("NOP NOP"). |
||||||||||||||||||
| 28239 | JR NZ,DrawShield_SetAttribute | Jump to DrawShield_SetAttribute if the movement animation frame counter is zero (use default value). | ||||||||||||||||||
| 28241 | LD A,(26260) | Jump to DrawShield_SetAttribute if bit 2 of the shield state at *ShieldTimer is not set (shield not active). | ||||||||||||||||||
| 28244 | BIT 2,A | |||||||||||||||||||
| 28246 | JR Z,DrawShield_SetAttribute | |||||||||||||||||||
| 28248 | LD DE,310 | Set the value to 0310 ("LD (HL),1"). |
||||||||||||||||||
| 28251 | LD A,B | Jump to DrawShield_SetAttribute if this is not the second segment (B is not 1). | ||||||||||||||||||
| 28252 | CP 1 | |||||||||||||||||||
| 28254 | JR NZ,DrawShield_SetAttribute | |||||||||||||||||||
| 28256 | LD D,128 | Set the high byte of the value to 128 for the second segment. | ||||||||||||||||||
|
Store the calculated value for both shield segments using self-modifying code.
|
||||||||||||||||||||
| DrawShield_SetAttribute | 28258 | LD (28295),DE | Write the self-modifying code to the address used by the left segment (28295). | |||||||||||||||||
| 28262 | LD (28314),DE | Write the self-modifying code to the address used by the right segment (28314). | ||||||||||||||||||
| 28266 | POP AF | Restore the movement animation frame counter from the stack. | ||||||||||||||||||
| 28267 | INC A | Increment the movement animation frame counter value in A. | ||||||||||||||||||
| 28268 | PUSH BC | Stash BC on the stack. | ||||||||||||||||||
| 28269 | LD B,A | Set the loop counter in B to the movement animation frame counter value. | ||||||||||||||||||
| 28270 | PUSH HL | Stash the attribute buffer address in HL on the stack. | ||||||||||||||||||
| 28271 | LD HL,28294 | Load the address of the left segment code to modify at (28294). | ||||||||||||||||||
|
Calculate an attribute byte value based on the movement animation frame counter.
|
||||||||||||||||||||
| 28274 | LD A,(26260) | Load the shield state from *ShieldTimer. | ||||||||||||||||||
| 28277 | BIT 2,A | Test bit 2 of the shield state to check if the shield is active. | ||||||||||||||||||
| 28279 | LD A,126 | Set the base attribute value to INK:YELLOW, PAPER:WHITE (BRIGHT). | ||||||||||||||||||
| 28281 | JR Z,DrawShield_AttributeLoop | Jump to DrawShield_AttributeLoop if the shield is not active (use base value). | ||||||||||||||||||
| 28283 | ADD A,64 | Add 64 to the base attribute value (set BRIGHT bit). | ||||||||||||||||||
| DrawShield_AttributeLoop | 28285 | ADD A,8 | Add 8 to the attribute value (increment PAPER colour). | |||||||||||||||||
| 28287 | DJNZ DrawShield_AttributeLoop | Decrease counter by one and loop back to DrawShield_AttributeLoop until counter is zero. | ||||||||||||||||||
| 28289 | LD (HL),A | Write the calculated attribute byte to the storage location. | ||||||||||||||||||
| 28290 | POP HL | Restore the attribute buffer address from the stack. | ||||||||||||||||||
|
Draw the left shield segment.
|
||||||||||||||||||||
| 28291 | LD B,6 | Set a counter in B for 6 lines of the left shield segment. | ||||||||||||||||||
| DrawShield_LeftSegment_Loop | 28293 | SET 0,(HL) | Set bit 0 of the attribute byte at *HL (set INK bit 0). | |||||||||||||||||
|
Modified by the code at DrawShield_SetAttribute.
|
||||||||||||||||||||
| 28295 | LD (HL),1 | Write 1 to the attribute buffer at *HL. | ||||||||||||||||||
| 28297 | INC H | Move down one line in the attribute buffer. | ||||||||||||||||||
| 28298 | DJNZ DrawShield_LeftSegment_Loop | Decrease the left segment loop counter by one and loop back to DrawShield_LeftSegment_Loop until all 6 lines are drawn. | ||||||||||||||||||
| 28300 | LD A,(28294) | Load the attribute value from the storage location. | ||||||||||||||||||
| 28303 | LD (28313),A | Store the attribute value at the address used by the right segment. | ||||||||||||||||||
| 28306 | SET 5,L | Move to the right segment position (set bit 5 of L, add 32). | ||||||||||||||||||
| 28308 | LD H,80 | Set H to 80 (screen buffer base address). | ||||||||||||||||||
|
Draw the right shield segment.
|
||||||||||||||||||||
| 28310 | LD B,8 | Set a counter in B for 8 lines of the right shield segment. | ||||||||||||||||||
| DrawShield_RightSegment_Loop | 28312 | SET 0,(HL) | Set bit 0 of the pixel data at *HL (set pixel bit 0). | |||||||||||||||||
|
Modified by the code at 28262.
|
||||||||||||||||||||
| 28314 | LD (HL),1 | Write 1 to the screen buffer at *HL. | ||||||||||||||||||
| 28316 | INC H | Move down one pixel line in the screen buffer. | ||||||||||||||||||
| 28317 | DJNZ DrawShield_RightSegment_Loop | Decrease the right segment loop counter by one and loop back to DrawShield_RightSegment_Loop until all 8 lines are drawn. | ||||||||||||||||||
| 28319 | LD HL,(26349) | Reload the player position from PlayerAttributeBufferPosition. | ||||||||||||||||||
| 28322 | LD H,82 | Set H back to 82 (attribute buffer base address). | ||||||||||||||||||
| 28324 | INC L | Move to the next shield segment position (increment L by two). | ||||||||||||||||||
| 28325 | INC L | |||||||||||||||||||
| 28326 | POP BC | Restore BC from the stack. | ||||||||||||||||||
| 28327 | LD A,(26278) | Reload the movement animation frame counter from MovementAnimationFrameCounter into A. | ||||||||||||||||||
| 28330 | PUSH AF | Stash AF on the stack. | ||||||||||||||||||
| 28331 | SUB 7 | Decrease the movement animation frame counter by 7 to adjust for the next iteration. | ||||||||||||||||||
| 28333 | DJNZ DrawShield_SegmentLoop | Decrease counter by one and loop back to DrawShield_SegmentLoop until both shield segments are drawn. | ||||||||||||||||||
|
Process the shield graphic data: copy the appropriate shield sprite to the work buffer and apply bit manipulation if the shield timer is active.
|
||||||||||||||||||||
| 28335 | POP AF | Restore AF from the stack. | ||||||||||||||||||
| 28336 | LD A,(26260) | Load the shield state from *ShieldTimer. | ||||||||||||||||||
| 28339 | BIT 2,A | Test bit 2 of the shield state to check if the shield is active. | ||||||||||||||||||
|
Select which shield sprite to use based on the shield state.
|
||||||||||||||||||||
| 28341 | LD HL,24596 | Set HL to point to the first shield sprite at Graphics_Shield_01. | ||||||||||||||||||
| 28344 | JR Z,DrawShield_CopySprite | Jump to DrawShield_CopySprite if the shield is not active (use first sprite). | ||||||||||||||||||
| 28346 | LD HL,24605 | Set HL to point to the second shield sprite at Graphics_Shield_02. | ||||||||||||||||||
|
Copy the shield sprite data (9 bytes) to the work buffer at 24955.
|
||||||||||||||||||||
| DrawShield_CopySprite | 28349 | LD DE,24955 | Set DE to point to the work buffer at 24955. | |||||||||||||||||
| 28352 | LD C,9 | Set the shield byte count in C to 9. | ||||||||||||||||||
| 28354 | LDIR | Copy the shield sprite data from HL to the work buffer. | ||||||||||||||||||
| 28356 | LD A,(26278) | Jump to DrawPlayersShip if the movement animation frame counter at *MovementAnimationFrameCounter is zero (skip bit manipulation). | ||||||||||||||||||
| 28359 | OR A | |||||||||||||||||||
| 28360 | JR Z,DrawPlayersShip | |||||||||||||||||||
|
Apply bit manipulation to the shield graphic data based on the movement animation frame counter value.
|
||||||||||||||||||||
| 28362 | LD B,A | Load the movement animation frame counter from *MovementAnimationFrameCounter into B (outer loop counter). | ||||||||||||||||||
| DrawShield_RotateLoop | 28363 | PUSH BC | Stash the outer loop counter on the stack. | |||||||||||||||||
| 28364 | LD HL,24955 | Set HL to point to the work buffer at 24955. | ||||||||||||||||||
| 28367 | LD B,9 | Set counter in B for 9 bytes (one complete pass). | ||||||||||||||||||
| DrawShield_RotateByte | 28369 | SLA (HL) | Shift the byte at *HL left by one bit. | |||||||||||||||||
| 28371 | INC HL | Move to the next byte in the work buffer. | ||||||||||||||||||
| 28372 | BIT 7,(HL) | Test bit 7 of the next byte. | ||||||||||||||||||
| 28374 | DEC HL | Move back to the previous byte. | ||||||||||||||||||
| 28375 | JR Z,DrawShield_RotateNext | Jump to DrawShield_RotateNext if bit 7 was not set (no carry to propagate). | ||||||||||||||||||
| 28377 | SET 0,(HL) | Set bit 0 of the current byte (propagate the carry). | ||||||||||||||||||
| DrawShield_RotateNext | 28379 | INC HL | Move to the next byte in the work buffer. | |||||||||||||||||
| 28380 | DJNZ DrawShield_RotateByte | Decrease counter by one and loop back to DrawShield_RotateByte until all 9 bytes are processed. | ||||||||||||||||||
| 28382 | POP BC | Restore the outer loop counter from the stack. | ||||||||||||||||||
| 28383 | DJNZ DrawShield_RotateLoop | Decrease the outer loop counter by one and loop back to DrawShield_RotateLoop until the shield timer value is reached. | ||||||||||||||||||
|
Draws the player's ship sprite to the screen buffer. The ship graphic is copied from the work buffer at 24955, which may have been modified by the shield bit manipulation routine.
|
||||||||||||||||||||
| DrawPlayersShip | 28385 | LD DE,(26349) | Load the player position from PlayerAttributeBufferPosition. | |||||||||||||||||
| 28389 | LD D,80 | Set D to 80 (screen buffer base address). | ||||||||||||||||||
| 28391 | LD HL,24955 | Set HL to point to the ship graphic data in the work buffer at 24955. | ||||||||||||||||||
| 28394 | LD B,3 | Set counter in B for 3 pixel rows (ship sprite height). | ||||||||||||||||||
|
Draw each row of the ship sprite (3 bytes per row, 3 rows total).
|
||||||||||||||||||||
| DrawPlayersShip_Loop | 28396 | PUSH BC | Stash the row counter and screen position on the stack. | |||||||||||||||||
| 28397 | PUSH DE | |||||||||||||||||||
| 28398 | LD BC,3 | Set a row counter in BC to 0003 bytes. | ||||||||||||||||||
| 28401 | LDIR | Copy the ship graphic row from HL to the screen buffer. | ||||||||||||||||||
| 28403 | POP DE | Restore the screen position from the stack. | ||||||||||||||||||
| 28404 | INC D | Move down one pixel line in the screen buffer. | ||||||||||||||||||
| 28405 | POP BC | Restore the row counter from the stack. | ||||||||||||||||||
| 28406 | DJNZ DrawPlayersShip_Loop | Decrease counter by one and loop back to DrawPlayersShip_Loop until all 3 rows are drawn. | ||||||||||||||||||
|
Continue on to Handler_ShipMovement.
|
||||||||||||||||||||
| Prev: 27886 | Up: Map | Next: 28408 |