Skip to navigation

Elite on the BBC Micro and NES

Flight: DOCKIT

[NES version, Bank 0]

Name: DOCKIT [Show more] Type: Subroutine Category: Flight Summary: Apply docking manoeuvres to the ship in INWK Deep dive: The docking computer
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DOKEY calls DOCKIT * TACTICS (Part 3 of 7) calls DOCKIT
.DOCKIT LDA #6 ; Set RAT2 = 6, which is the threshold below which we STA RAT2 ; don't apply pitch and roll to the ship (so a lower ; value means we apply pitch and roll more often, and a ; value of 0 means we always apply them). The value is ; compared with double the high byte of sidev . XX15, ; where XX15 is the vector from the ship to the station LSR A ; Set RAT = 2, which is the magnitude we set the pitch STA RAT ; or roll counter to in part 7 when turning a ship ; towards a vector (a higher value giving a longer ; turn) LDA #29 ; Set CNT2 = 29, which is the maximum angle beyond which STA CNT2 ; a ship will slow down to start turning towards its ; prey (a lower value means a ship will start to slow ; down even if its angle with the enemy ship is large, ; which gives a tighter turn) LDA SSPR ; If we are inside the space station safe zone, skip the BNE P%+5 ; next instruction .GOPLS JMP GOPL ; Jump to GOPL to make the ship head towards the planet JSR VCSU1 ; If we get here then we are in the space station safe ; zone, so call VCSU1 to calculate the following, where ; the station is at coordinates (station_x, station_y, ; station_z): ; ; K3(2 1 0) = (x_sign x_hi x_lo) - station_x ; ; K3(5 4 3) = (y_sign y_hi z_lo) - station_y ; ; K3(8 7 6) = (z_sign z_hi z_lo) - station_z ; ; so K3 contains the vector from the station to the ship LDA K3+2 ; If any of the top bytes of the K3 results above are ORA K3+5 ; non-zero (after removing the sign bits), jump to GOPL ORA K3+8 ; via GOPLS to make the ship head towards the planet, as AND #%01111111 ; this will aim the ship in the general direction of the BNE GOPLS ; station (it's too far away for anything more accurate) JSR TA2 ; Call TA2 to calculate the length of the vector in K3 ; (ignoring the low coordinates), returning it in Q LDA Q ; Store the value of Q in K, so K now contains the STA K ; distance between station and the ship JSR TAS2 ; Call TAS2 to normalise the vector in K3, returning the ; normalised version in XX15, so XX15 contains the unit ; vector pointing from the station to the ship LDY #10 ; Call TAS4 to calculate: JSR TAS4 ; ; (A X) = nosev . XX15 ; ; where nosev is the nose vector of the space station, ; so this is the dot product of the station to ship ; vector with the station's nosev (which points straight ; out into space, out of the docking slot), and because ; both vectors are unit vectors, the following is also ; true: ; ; (A X) = cos(t) ; ; where t is the angle between the two vectors ; ; If the dot product is positive, that means the vector ; from the station to the ship and the nosev sticking ; out of the docking slot are facing in a broadly ; similar direction (so the ship is essentially heading ; for the slot, which is facing towards the ship), and ; if it's negative they are facing in broadly opposite ; directions (so the station slot is on the opposite ; side of the station as the ship approaches) BMI PH1 ; If the dot product is negative, i.e. the station slot ; is on the opposite side, jump to PH1 to fly towards ; the ideal docking position, some way in front of the ; slot CMP #35 ; If the dot product < 35, jump to PH1 to fly towards BCC PH1 ; the ideal docking position, some way in front of the ; slot, as there is a large angle between the vector ; from the station to the ship and the station's nosev, ; so the angle of approach is not very optimal ; ; Specifically, as the unit vector length is 96 in our ; vector system, ; ; (A X) = cos(t) < 35 / 96 ; ; so: ; ; t > arccos(35 / 96) = 68.6 degrees ; ; so the ship is coming in from the side of the station ; at an angle between 68.6 and 90 degrees off the ; optimal entry angle ; If we get here, the slot is on the same side as the ; ship and the angle of approach is less than 68.6 ; degrees, so we're heading in pretty much the correct ; direction for a good approach to the docking slot LDY #10 ; Call TAS3 to calculate: JSR TAS3 ; ; (A X) = nosev . XX15 ; ; where nosev is the nose vector of the ship, so this is ; the dot product of the station to ship vector with the ; ship's nosev, and is a measure of how close to the ; station the ship is pointing, with negative meaning it ; is pointing at the station, and positive meaning it is ; pointing away from the station CMP #$A2 ; If the dot product is in the range 0 to -34, jump to BCS PH3 ; PH3 to refine our approach, as we are pointing towards ; the station ; If we get here, then we are not pointing straight at ; the station, so check how close we are LDA K ; Fetch the distance to the station into A CMP #157 ; If A < 157, jump to PH2 to turn away from the station, BCC PH2 ; as we are too close LDA TYPE ; Fetch the ship type into A BMI PH3 ; If bit 7 is set, then that means the ship type was set ; to -96 in the DOKEY routine when we switched on our ; docking computer, so this is us auto-docking our ; Cobra, so jump to PH3 to refine our approach ; ; Otherwise this is an NPC trying to dock, so keep going ; to turn away from the station .PH2 ; If we get here then we turn away from the station and ; slow right down, effectively aborting this approach ; attempt JSR TAS6 ; Call TAS6 to negate the vector in XX15 so it points in ; the opposite direction, away from the station and ; towards the ship JSR TA151 ; Call TA151 to make the ship head in the direction of ; XX15, which makes the ship turn away from the station .PH22 ; If we get here then we slam on the brakes and slow ; right down LDX #0 ; Set the acceleration in byte #28 to 0 STX INWK+28 INX ; Set the speed in byte #28 to 1 STX INWK+27 RTS ; Return from the subroutine .PH1 ; If we get here then the slot is on the opposite side ; of the station to the ship, or it's on the same side ; and the approach angle is not optimal, so we just fly ; towards the station, aiming for the ideal docking ; position some distance in front of the slot JSR VCSU1 ; Call VCSU1 to set K3 to the vector from the station to ; the ship JSR DCS1 ; Call DCS1 twice to calculate the vector from the ideal JSR DCS1 ; docking position to the ship, where the ideal docking ; position is straight out of the docking slot at a ; distance of 8 unit vectors from the centre of the ; station JSR TAS2 ; Call TAS2 to normalise the vector in K3, returning the ; normalised version in XX15 JSR TAS6 ; Call TAS6 to negate the vector in XX15 so it points in ; the opposite direction JMP TA151 ; Call TA151 to make the ship head in the direction of ; XX15, which makes the ship turn towards the ideal ; docking position, and return from the subroutine using ; a tail call .TN11 ; If we get here, we accelerate and apply a full ; clockwise roll (which matches the space station's ; roll) INC INWK+28 ; Increment the acceleration in byte #28 LDA #%01111111 ; Set the roll counter to a positive (clockwise) roll STA INWK+29 ; with no damping, to match the space station's roll BNE TN13 ; Jump down to TN13 (this BNE is effectively a JMP as ; A will never be zero) .PH3 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 ; If we get here, we refine our approach using pitch and ; roll to aim for the station LDX #0 ; Set RAT2 = 0 STX RAT2 STX INWK+30 ; Set the pitch counter to 0 to stop any pitching LDA TYPE ; If this is not our ship's docking computer, but is an BPL PH32 ; NPC ship trying to dock, jump to PH32 ; In the following, ship_x and ship_y are the x and ; y-coordinates of XX15, the vector from the station to ; the ship EOR XX15 ; A is negative, so this sets the sign of A to the same EOR XX15+1 ; as -XX15 * XX15+1, or -ship_x * ship_y ASL A ; Shift the sign bit into the C flag, so the C flag has ; the following sign: ; ; * Positive if ship_x and ship_y have different signs ; * Negative if ship_x and ship_y have the same sign LDA #2 ; Set A = +2 or -2, giving it the sign in the C flag, ROR A ; and store it in byte #29, the roll counter, so that STA INWK+29 ; the ship rolls towards the station LDA XX15 ; If |ship_x * 2| >= 12, i.e. |ship_x| >= 6, then jump ASL A ; to PH22 to slow right down and return from the CMP #12 ; subroutine, as the station is not in our sights BCS PH22 LDA XX15+1 ; Set A = +2 or -2, giving it the same sign as ship_y, ASL A ; and store it in byte #30, the pitch counter, so that LDA #2 ; the ship pitches towards the station ROR A STA INWK+30 LDA XX15+1 ; If |ship_y * 2| >= 12, i.e. |ship_y| >= 6, then jump ASL A ; to PH22 to slow right down and return from the CMP #12 ; subroutine, as the station is not in our sights BCS PH22 .PH32 ; If we get here, we try to match the station roll STX INWK+29 ; Set the roll counter to 0 to stop any pitching LDA INWK+22 ; Set XX15 = sidev_x_hi STA XX15 LDA INWK+24 ; Set XX15+1 = sidev_y_hi STA XX15+1 LDA INWK+26 ; Set XX15+2 = sidev_z_hi STA XX15+2 ; ; so XX15 contains the sidev vector of the ship LDY #16 ; Call TAS4 to calculate: JSR TAS4 ; ; (A X) = roofv . XX15 ; ; where roofv is the roof vector of the space station. ; To dock with the slot horizontal, we want roofv to be ; pointing off to the side, i.e. parallel to the ship's ; sidev vector, which means we want the dot product to ; be large (it can be positive or negative, as roofv can ; point left or right - it just needs to be parallel to ; the ship's sidev) ASL A ; If |A * 2| >= 66, i.e. |A| >= 33, then the ship is CMP #66 ; lined up with the slot, so jump to TN11 to accelerate BCS TN11 ; and roll clockwise (a positive roll) before jumping ; down to TN13 to check if we're docked yet JSR PH22 ; Call PH22 to slow right down, as we haven't yet ; matched the station's roll .TN13 ; If we get here, we check to see if we have docked LDA K3+10 ; If K3+10 is non-zero, skip to TNRTS, to return from BNE TNRTS ; the subroutine ; ; I have to say I have no idea what K3+10 contains, as ; it isn't mentioned anywhere in the whole codebase ; apart from here, but it does share a location with ; XX2+10, so it will sometimes be non-zero (specifically ; when face #10 in the ship we're drawing is visible, ; which probably happens quite a lot). This would seem ; to affect whether an NPC ship can dock, as that's the ; code that gets skipped if K3+10 is non-zero, but as ; to what this means... that's not yet clear ASL NEWB ; Set bit 7 of the ship's NEWB flags to indicate that SEC ; the ship has now docked, which only has meaning if ROR NEWB ; this is an NPC trying to dock .TNRTS RTS ; Return from the subroutine