Skip to navigation

Elite on the BBC Micro and NES

Main loop: Main flight loop (Part 3 of 16)

[NES version, Bank 0]

Name: Main flight loop (Part 3 of 16) [Show more] Type: Subroutine Category: Main loop Summary: Scan for flight keys and process the results Deep dive: Program flow of the main game loop The key logger Splitting the main loop in the NES version
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

The main flight loop covers most of the flight-specific aspects of Elite. This section covers the following: * Scan for flight keys and process the results Flight keys are logged in the key logger at location KY1 onwards, with a non-zero value in the relevant location indicating a key press. See the deep dive on "The key logger" for more details.
.BS2 LDA KY2 ; If both the B and up buttons are being pressed, keep BEQ MA17 ; going, otherwise jump down to MA17 to skip the ; following LDA DELTA ; The "go faster" key is being pressed, so first we CLC ; add 4 to the current speed in DELTA (we also store ADC #4 ; this value in DELTA, though this isn't necessary as STA DELTA ; we are about to do that again) CMP #40 ; If the new speed in A < 40, then this is a valid BCC main8 ; speed, so jump down to main8 to set DELTA to this ; value LDA #40 ; The maximum allowed speed is 40, so set A = 40 .main8 STA DELTA ; Store the updated speed in DELTA .MA17 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA KY1 ; If both the B and down buttons are being pressed, BEQ MA4 ; keep going, otherwise jump down to MA4 to skip the ; following LDA DELTA ; The "slow down" key is being pressed, so subtract 4 SEC ; from the speed in DELTA SBC #4 BEQ main9 ; If the result is zero, jump to main9 to set the speed ; to the minimum value of 1 BCS main10 ; If the subtraction didn't underflow then this is a ; valid speed, so jump down to main10 to set DELTA to ; this value .main9 LDA #1 ; Set A = 1 to use as the minimum speed .main10 STA DELTA ; Store the updated speed in DELTA .MA4 LDA iconBarKeyPress ; Set A to the icon bar key logger entry in ; iconBarKeyPress, which contains the button number of ; the icon bar button (if one has been chosen) CMP #24 ; If the Target Missile button has not been chosen, BNE MA25 ; jump to MA25 to skip the following LDA NOMSL ; If the number of missiles in NOMSL is zero, jump to BEQ MA64S ; MA64 via MA64S to skip the rest of the button checks LDA MSAR ; The "target missile" key is being pressed and we have EOR #$FF ; at least one missile, so flip MSAR between 0 and $FF STA MSAR ; to flip the missile between being disarmed and armed BNE MA20 ; If MSAR is now $FF then the missile is now armed, so ; jump to MA20 to skip the following and process the ; arming of the missile LDY #$6C ; Otherwise we just chose to disarm the missile, so call JSR ABORT ; ABORT to disarm the missile and update the missile ; indicators on the dashboard to the pattern number in ; Y (black indicator = pattern 108) LDY #4 ; Set Y = 4 so the call to NOISE makes a low, long beep ; to indicate the missile is now disarmed .main11 JSR NOISE ; Call the NOISE routine to make the sound in Y (which ; will either be a low, long beep to indicate the ; missile is now disarmed, or a short, high beep to ; indicate that it is looking for a target) JMP MA64 ; Jump to MA64 to skip the rest of the button checks .MA20 LDY #108 ; Set the pattern for the active missile indicator to LDX NOMSL ; 108 (which is a black indicator), so we can flash JSR MSBAR ; it between red and black in the main loop to indicate ; that it is looking for a target LDY #3 ; Set Y = 3 and jump up to main11 to make a short, BNE main11 ; high beep to indicate that it is looking for a target ; (this BNE is effectively a JMP as Y is never zero) .MA25 CMP #25 ; If the Fire Targeted Missile button was chosen on BNE MA24 ; the icon bar, keep going, otherwise jump down to MA24 ; to skip the following LDA MSTG ; If MSTG = $FF then there is no target lock, so jump to BMI MA64S ; MA64 via MA64S to skip the rest of the button checks JSR FRMIS ; The "fire missile" key is being pressed and we have ; a missile lock, so call the FRMIS routine to fire ; the missile JSR UpdateIconBar_b3 ; Update the icon bar to hide the fire button as we have ; just fired a missile .MA64S JMP MA64 ; Jump to MA64 to skip the rest of the button checks .MA24 CMP #26 ; If the Energy Bomb button is being pressed, keep BNE MA76 ; going, otherwise jump down to MA76 to skip the ; following LDA BOMB ; If we already set off our energy bomb, then BOMB is BMI MA64S ; negative, so this jumps to MA64 via MA64S to skip the ; rest of the button checks when our energy bomb is ; already going off ASL BOMB ; The "energy bomb" key is being pressed, so double ; the value in BOMB. If we have an energy bomb fitted, ; BOMB will contain $7F (%01111111) before this shift ; and will contain $FE (%11111110) after the shift; if ; we don't have an energy bomb fitted, BOMB will still ; contain 0. The bomb explosion is dealt with in the ; MAL1 routine below - this just registers the fact that ; we've set the bomb ticking BEQ MA64S ; If BOMB now contains 0, then the bomb is not going off ; any more (or it never was), so jump to MA64 via MA64S ; to skip the rest of the button checks LDA #$28 ; Set hiddenColour to $28, which is green-brown, so this STA hiddenColour ; reveals pixels that use the (no-longer) hidden colour ; in palette 0 LDY #8 ; Call the NOISE routine with Y = 8 to make the sound of JSR NOISE ; the energy bomb going off JMP MA64 ; Jump to MA64 to skip the rest of the button checks .MA76 CMP #27 ; If the Escape Pod button is not being pressed, jump to BNE noescp ; noescp to skip the following LDX ESCP ; If we do not have an escape pod fitted, jump to MA64 BEQ MA64 ; to skip the rest of the button checks LDA MJ ; If we are in witchspace, we can't launch our escape BNE MA64 ; pod, so jump down to MA64 to skip the rest of the ; button checks JMP ESCAPE ; The button is being pressed to launch an escape pod ; and we have an escape pod fitted, so jump to ESCAPE to ; launch it, and exit the main flight loop using a tail ; call .noescp CMP #12 ; If the Fast-forward button is not being pressed, jump BNE main12 ; to main12 to skip the following LDA allowInSystemJump ; If either of bits 6 or 7 of allowInSystemJump are set AND #%11000000 ; then there is something in the vicinity that is BNE MA64 ; preventing in-system jumps, so jump to MA64 to skip ; the rest of the button checks JSR WARP ; Call WARP to process an in-system jump JMP MA64 ; Jump to MA64 to skip the rest of the button checks .main12 CMP #23 ; If the E.C.M. button is not being pressed, jump to BNE MA64 ; to MA64 to skip the following LDA ECM ; If we do not have an E.C.M. fitted, jump to MA64 to BEQ MA64 ; skip the following LDA ECMA ; If ECMA is non-zero, that means an E.C.M. is already BNE MA64 ; operating and is counting down (this can be either ; our E.C.M. or an opponent's), so jump down to MA64 to ; skip the following (as we can't have two E.C.M. ; systems operating at the same time) DEC ECMP ; The E.C.M. button is being pressed and nobody else ; is operating their E.C.M., so decrease the value of ; ECMP to make it non-zero, to denote that our E.C.M. ; is now on JSR ECBLB2 ; Call ECBLB2 to light up the E.C.M. indicator bulb on ; the dashboard, set the E.C.M. countdown timer to 32, ; and start making the E.C.M. sound .MA64 JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 .MA68 LDA #0 ; Set LAS = 0, to switch the laser off while we do the STA LAS ; following logic STA DELT4 ; Take the 16-bit value (DELTA 0) - i.e. a two-byte LDA DELTA ; number with DELTA as the high byte and 0 as the low LSR A ; byte - and divide it by 4, storing the 16-bit result ROR DELT4 ; in DELT4(1 0). This has the effect of storing the LSR A ; current speed * 64 in the 16-bit location DELT4(1 0) ROR DELT4 STA DELT4+1 LDA LASCT ; If LASCT is zero and this is the space view, keep ORA QQ11 ; going, otherwise the laser is a pulse laser that is BNE MA3 ; between pulses, or we aren't showing laser fire, so ; jump down to MA3 to skip the following LDA KY7 ; If the A button is being pressed, keep going, BPL MA3 ; otherwise jump down to MA3 to skip the following LDA GNTMP ; If the laser temperature >= 242 then the laser has CMP #242 ; overheated, so jump down to MA3 to skip the following BCS MA3 LDX VIEW ; If the current space view has a laser fitted (i.e. the LDA LASER,X ; laser power for this view is greater than zero), then BEQ MA3 ; keep going, otherwise jump down to MA3 to skip the ; following BMI main13 ; If the current laser power is 128 or greater, then ; this is a beam or military laser, so jump to main13 ; to skip the following two instructions BIT KY7 ; If bit 6 of KY7 is set, then the A button was being BVS MA3 ; pressed in the previous VBlank and it is still being ; pressed now, so jump down to MA3 to skip the following ; so that lower power lasers only fire every other ; VBlank when the A button is held down .main13 ; If we get here, then the "fire" button is being ; pressed, our laser hasn't overheated and isn't already ; being fired, and we actually have a laser fitted to ; the current space view, so it's time to hit me with ; those laser beams PHA ; Store the current view's laser power on the stack AND #%01111111 ; Set LAS and LAS2 to bits 0-6 of the laser power STA LAS STA LAS2 ; We now set Y to the correct sound to pass to the NOISE ; routine to make the sound of the laser firing LDY #18 ; Set Y = 18 to use as the sound number for a pulse ; laser PLA ; Set A to the current view's laser power, which we PHA ; stored on the stack above (and leave the value on ; the stack BMI main15 ; If A >= 128, jump to main15 to check whether this is ; a beam laser or a military laser CMP #Mlas ; If A is not the power for a mining laser, jump to BNE main14 ; main14 to keep Y = 18 LDY #16 ; This is a mining laser, so set Y = 16 to use as the ; sound number .main14 BNE main17 ; Jump to main17 to make the sound in Y (this BNE is ; effectively a JMP as Y is never zero) .main15 ; If we get here then this is either a beam laser or a ; military laser CMP #Armlas ; If this is a military laser, jump to main16 to set BEQ main16 ; Y = 15 LDY #17 ; This is a beam laser, so set Y = 17 to use as the ; sound number EQUB $2C ; Skip the next instruction by turning it into ; $2C $A0 $0F, or BIT $0FA0, which does nothing apart ; from affect the flags .main16 LDY #15 ; This is a military laser, so set Y = 15 to use as the ; sound number .main17 JSR NOISE ; Call the NOISE routine to make the sound in Y, which ; will be one of 15 (military laser), 16 (mining laser), ; 17 (beam laser) or 18 (pulse laser) JSR LASLI ; Call LASLI to draw the laser lines PLA ; Restore the current view's laser power into A BPL ma1 ; If the laser power has bit 7 set, then it's an "always ; on" laser rather than a pulsing laser, so keep going, ; otherwise jump down to ma1 to skip the following ; instruction LDA #0 ; This is an "always on" laser (i.e. a beam laser or a ; military laser), so set A = 0, which will be stored in ; LASCT to denote that this is not a pulsing laser .ma1 AND #%11101111 ; LASCT will be set to 0 for beam lasers, and to the STA LASCT ; laser power AND %11101111 for pulse lasers, which ; comes to comes to 8 (as pulse lasers have a power ; of 24) .MA3 JSR FlightLoop4To16 ; Display in-flight messages, call parts 4 to 12 of the ; main flight loop for each ship slot, and finish off ; with parts 13 to 16 of the main flight loop ; Fall through into DrawSpaceViewInNMI to tell the NMI ; handler to send the updated space view to the PPU