![]() |
Routines |
| Prev: 51536 | Up: Map | Next: 52353 |
|
Used by the routine at Stage_Next_Wave.
Wave-active game loop entry, called from Stage_Next_Wave once the entity list and playfield are ready. Initialises the player's starting screen position and frame counters, copies the sprite template via Initialise_Wave_Start_Sprites, then falls into the per-frame control poll at Main_Loop_Poll. Each frame: reads the controller via Read_Control_Input, moves and redraws the player sprite, spawns one new entity every three frames adjacent to the player, dispatches all active entity handlers via DispatchWordFromHL, updates the colour bar and protection checks, then loops back to Main_Loop_Poll.
|
||||
|
Initialise the player's screen position and frame counters for the start of the wave.
|
||||
| Main_Game_Loop | 52047 | LD HL,50388 | Point HL at Player_Y_Position and set the starting screen row to 92. | |
| 52050 | LD (HL),92 | |||
| 52052 | INC HL | |||
| 52053 | LD (HL),125 | Set the starting screen column to 125 and reset the wave-start delay counter at Wave_Start_Delay to 26. | ||
| 52055 | LD A,26 | |||
| 52057 | LD (50483),A | |||
| 52060 | LD A,15 | Set the animation frame counters at Animation_Frame_Counter_One and Animation_Frame_Counter_Two to 15 and copy the sprite template via Initialise_Wave_Start_Sprites. | ||
| 52062 | LD (50484),A | |||
| 52065 | LD (50486),A | |||
| 52068 | CALL Initialise_Wave_Start_Sprites | |||
|
This entry point is used by the routine at Dispatch_Narrow_Entity_Approach.
Per-frame start: check whether the wave is still active before processing input.
|
||||
| Main_Loop_Poll | 52071 | LD A,(50483) | If the wave-start delay counter at Wave_Start_Delay is non-zero, jump to Dispatch_Narrow_Entity_Approach (wave-end / game-over handling). | |
| 52074 | AND A | |||
| 52075 | JP NZ,Dispatch_Narrow_Entity_Approach | |||
|
This entry point is used by the routine at Animate_Wave_Start_Sequence.
Read the controller and map the input to player movement directions.
|
||||
| Main_Loop_Frame | 52078 | CALL Read_Control_Input | Read the controller state via Read_Control_Input. | |
| 52081 | LD A,C | Apply vertical input processing via Compute_Entity_Approach_Position_Short and store the result in C. | ||
| 52082 | CALL Compute_Entity_Approach_Position_Short | |||
| 52085 | LD C,A | |||
| 52086 | LD A,B | Apply horizontal input processing via Compute_Entity_Approach_Position and store the result in B. | ||
| 52087 | CALL Compute_Entity_Approach_Position | |||
| 52090 | LD B,A | |||
| 52091 | CP 15 | If the direction is neutral (15), skip to Main_Loop_Update_Y. | ||
| 52093 | JR Z,Main_Loop_Update_Y | |||
| 52095 | LD (50456),A | Store the updated X direction at Player_X_Direction. | ||
| Main_Loop_Update_Y | 52098 | LD A,C | If the vertical direction changed, store it at Player_Y_Direction. | |
| 52099 | CP 15 | |||
| 52101 | JR Z,Main_Loop_Move_Player | |||
| 52103 | LD (50455),A | |||
|
Move the player sprite if a direction was input. Neutral direction (15) means no movement — skip directly to entity spawning.
|
||||
| Main_Loop_Move_Player | 52106 | LD A,B | If no horizontal direction, skip to Main_Loop_Entity_Spawn. | |
| 52107 | CP 15 | |||
| 52109 | JR Z,Main_Loop_Entity_Spawn | |||
| 52111 | LD E,A | Build the sprite frame word offset from the X direction and stash it; point HL at Intro_Closing_Sprite and erase the current player sprite via Erase_Entity_Sprite. | ||
| 52112 | SLA E | |||
| 52114 | LD D,0 | |||
| 52116 | PUSH DE | |||
| 52117 | LD HL,50387 | |||
| 52120 | CALL Erase_Entity_Sprite | Erase the current player sprite via Erase_Entity_Sprite. | ||
| 52123 | POP DE | Look up the movement delta for the current direction in the table at Movement_Delta_Table; add the Y delta to Player_Y_Position. | ||
| 52124 | LD HL,50862 | |||
| 52127 | ADD HL,DE | |||
| 52128 | EX DE,HL | |||
| 52129 | LD HL,50388 | |||
| 52132 | LD A,(DE) | |||
| 52133 | ADD A,(HL) | |||
| 52134 | CP 16 | |||
| 52136 | JR C,Main_Loop_Clamp_X | |||
| 52138 | CP 173 | Reject the Y move if the new position is above the playfield top or below the bottom edge. | ||
| 52140 | JR NC,Main_Loop_Clamp_X | |||
| 52142 | LD (HL),A | Write the updated Y position. | ||
| Main_Loop_Clamp_X | 52143 | INC HL | Add the X delta to Player_X_Position. | |
| 52144 | INC DE | |||
| 52145 | LD A,(DE) | |||
| 52146 | ADD A,(HL) | |||
| 52147 | CP 8 | |||
| 52149 | JR C,Main_Loop_Update_Sprite | Reject the X move if the new position is past the left edge. | ||
| 52151 | CP 242 | |||
| 52153 | JR NC,Main_Loop_Update_Sprite | Reject the X move if past the right edge. | ||
| 52155 | LD (HL),A | Write the updated X position. | ||
|
Select the sprite frame for the new direction and redraw the player.
|
||||
| Main_Loop_Update_Sprite | 52156 | LD A,(50456) | Look up the sprite frame index for the current X direction in Sprite_Frame_Table; write it to Intro_Closing_Sprite. | |
| 52159 | LD E,A | |||
| 52160 | LD D,0 | |||
| 52162 | LD HL,54816 | |||
| 52165 | ADD HL,DE | |||
| 52166 | EX DE,HL | |||
| 52167 | LD A,(DE) | |||
| 52168 | LD HL,50387 | |||
| 52171 | LD (HL),A | |||
| 52172 | EXX | Set the player colour to INK: WHITE, PAPER: BLACK (BRIGHT) in B' and redraw the player sprite via Draw_Entity_Sprite. | ||
| 52173 | LD B,71 | |||
| 52175 | EXX | |||
| 52176 | CALL Draw_Entity_Sprite | |||
|
Every three frames spawn one new entity adjacent to the player.
|
||||
| Main_Loop_Entity_Spawn | 52179 | LD HL,50383 | Decrement the entity spawn timer at Entity_Spawn_Timer. | |
| 52182 | DEC (HL) | |||
| 52183 | JP NZ,Main_Loop_Entity_Update | If the timer has not reached zero, skip to Main_Loop_Entity_Update. | ||
| 52186 | LD (HL),3 | Reset the spawn timer to 3. | ||
| 52188 | LD HL,(50385) | Load the entity list end pointer from Playfield_Entity_List_Pointer and write the movement handler address Move_And_Redraw_Entity to the entity list. | ||
| 52191 | LD DE,54749 | |||
| 52194 | LD (HL),E | Advance past the handler address word in the entity list. | ||
| 52195 | INC HL | |||
| 52196 | LD (HL),D | |||
| 52197 | INC HL | |||
| 52198 | LD (50394),HL | Save the entity record write pointer to Entity_Record_Pointer. | ||
| 52201 | LD A,(50455) | Load the Y direction index from Player_Y_Direction. | ||
| 52204 | EX DE,HL | Index the entity type table at Entity_Type_By_Direction_Table by Y direction and write the entity type to the entity record. | ||
| 52205 | LD C,A | |||
| 52206 | LD B,0 | |||
| 52208 | LD HL,54513 | |||
| 52211 | ADD HL,BC | |||
| 52212 | EX DE,HL | |||
| 52213 | LD A,(DE) | |||
| 52214 | LD (HL),A | |||
| 52215 | INC HL | Advance to the next entity record field. | ||
| 52216 | LD A,(50455) | Load the Y direction again, scale it to a byte offset (×8), and look up the sprite pixel offsets in Narrow_Entity_Sprite_Data. | ||
| 52219 | LD C,A | |||
| 52220 | SLA C | |||
| 52222 | SLA C | |||
| 52224 | SLA C | |||
| 52226 | LD B,0 | Clear the high byte of the offset and index into Narrow_Entity_Sprite_Data. | ||
| 52228 | EX DE,HL | |||
| 52229 | LD HL,51151 | |||
| 52232 | ADD HL,BC | Add the direction offset to the sprite data base address. | ||
| 52233 | LD A,(50388) | Compute the entity's initial Y position from Player_Y_Position plus the sprite Y offset; write both bytes to the entity record. | ||
| 52236 | ADD A,(HL) | |||
| 52237 | LD (DE),A | |||
| 52238 | INC HL | |||
| 52239 | INC DE | |||
| 52240 | LD A,(50389) | |||
| 52243 | ADD A,(HL) | Write the X position bytes derived from Player_X_Position. | ||
| 52244 | LD (DE),A | |||
| 52245 | INC HL | |||
| 52246 | INC DE | |||
| 52247 | LD A,(50388) | Add the sprite Y check offset to the player Y position and reject the spawn if the result is above the playfield top edge. | ||
| 52250 | ADD A,(HL) | |||
| 52251 | CP 16 | |||
| 52253 | JR C,Main_Loop_Abort_Spawn | Reject the spawn if the Y position is below the playfield bottom edge (184). | ||
| 52255 | CP 184 | |||
| 52257 | JR NC,Main_Loop_Abort_Spawn | Reject if below the bottom edge. | ||
| 52259 | LD (DE),A | Write the validated Y position field to the entity record. | ||
| 52260 | INC HL | |||
| 52261 | INC DE | |||
| 52262 | LD A,(50389) | Check the X position is within the playfield horizontal bounds (8–247). | ||
| 52265 | ADD A,(HL) | |||
| 52266 | CP 8 | |||
| 52268 | JR C,Main_Loop_Abort_Spawn | Reject the spawn if the X position is past the left edge. | ||
| 52270 | CP 248 | |||
| 52272 | JR NC,Main_Loop_Abort_Spawn | Reject if past the right edge. | ||
| 52274 | LD (DE),A | Write the validated X position field to the entity record. | ||
| 52275 | INC HL | |||
| 52276 | INC DE | |||
| 52277 | LD BC,4 | Copy the remaining four entity record bytes via LDIR. | ||
| 52280 | LDIR | |||
| 52282 | EX DE,HL | Mark the end of the entity record and update the entity list end pointer at Playfield_Entity_List_Pointer. | ||
| 52283 | LD (HL),255 | |||
| 52285 | INC HL | |||
| 52286 | LD (50385),HL | |||
| 52289 | LD E,1 | Initialise the entity via Initialise_Entity_State. | ||
| 52291 | CALL Initialise_Entity_State | |||
| 52294 | LD HL,(50394) | Reload the entity record pointer from Entity_Record_Pointer and set the entity colour to INK: WHITE, PAPER: BLACK (BRIGHT) in B'. | ||
| 52297 | EXX | |||
| 52298 | LD B,71 | |||
| 52300 | EXX | |||
| 52301 | CALL Draw_Narrow_Entity_Sprite | Draw the spawned entity sprite via Draw_Narrow_Entity_Sprite. | ||
| 52304 | LD HL,(50385) | Reload the entity list end pointer from Playfield_Entity_List_Pointer. | ||
| Main_Loop_Write_Terminator | 52307 | LD DE,52834 | Write the playfield entity handler 52834 and the 255 sentinel as the entity list terminator. | |
| 52310 | LD (HL),E | |||
| 52311 | INC HL | |||
| 52312 | LD (HL),D | |||
| 52313 | INC HL | |||
| 52314 | LD (HL),255 | |||
|
Dispatch all active entity handlers, update animation and colour bar.
|
||||
| Main_Loop_Entity_Update | 52316 | LD HL,24832 | Set HL to the start of the entity list at Entity_List_Base. | |
| 52319 | CALL DispatchWordFromHL | Dispatch all entity handlers in the list via DispatchWordFromHL. | ||
| 52322 | LD HL,(50459) | Decrement the animation counter at Animation_Frame_Pair if it is non-zero. | ||
| 52325 | LD A,H | |||
| 52326 | OR L | |||
| 52327 | JR Z,Main_Loop_Colour_Bar_Update | |||
| 52329 | DEC HL | |||
| 52330 | LD (50459),HL | |||
| Main_Loop_Colour_Bar_Update | 52333 | CALL UpdateAttributeBar | Update the colour bar via UpdateAttributeBar, run the protection check via CheckScoreAwardLife, and call the game state update via Dispatch_Entity_State_Handler. | |
| 52336 | CALL CheckScoreAwardLife | |||
| 52339 | CALL Dispatch_Entity_State_Handler | |||
| 52342 | CALL CheckScoreAwardLife_SessionGate | Run the copy protection gate via CheckScoreAwardLife_SessionGate and loop back to Main_Loop_Poll. | ||
| 52345 | JP Main_Loop_Poll | |||
|
Out-of-bounds abort: the new entity would fall outside the playfield. Skip the spawn but still write the entity list terminator.
|
||||
| Main_Loop_Abort_Spawn | 52348 | LD HL,(50385) | Reload the entity list end pointer from Playfield_Entity_List_Pointer and jump to Main_Loop_Write_Terminator. | |
| 52351 | JR Main_Loop_Write_Terminator | |||
| Prev: 51536 | Up: Map | Next: 52353 |