.AlienInAcornsville LDY alienToMove \ Set Y to the number of the alien whose turn it is to \ move towards Acornsville in this iteration of the main \ loop, which we set in UpdateAliens BMI acrn1 \ If Y is negative, then there is no alien to move, so \ jump to acrn1 to return from the subroutine LDA alienState,Y \ If the alien's state is 27, then it is heading for the CMP #27 \ town, so jump to acrn7 if this is not the case BNE acrn7 \ The alien is heading towards the town. This happens \ in three stages: first, the alien takes off; then it \ flies towards the town; and finally it descends. When \ the alien's state is 27, it is working through the \ first two stages, so that's what we do now LDA yObjectHi+33 \ If the high byte of the alien's y-coordinate >= 12, CMP #12 \ then the alien is already flying high, so jump to BCS acrn2 \ acrn2 to move it closer to Acornsville LDA yObjectLo+33 \ Otherwise add 10 to the alien's yObject coordinate, ADC #10 \ so that it rises into the air, starting with the low STA yObjectLo+33 \ bytes BCC acrn1 \ If the addition of the low bytes overflowed, increment INC yObjectHi+33 \ the high byte .acrn1 RTS \ Return from the subroutine .acrn2 \ If we get here then the alien's yObjectHi coordinate \ is 12 or more, so it's already flying high LDX #0 \ Set X = 0, to use in the following to check either the \ x-coordinate (X = 0) or the z-coordinate (X = 80) STX T \ Set T = 0, which we use to record whether we move the \ alien along the x-axis or z-axis (or both) .acrn3 \ We either do the following with X = 0 or X = 80, which \ either checks the x-coordinate or the z-coordinate \ (as zObjectHi - xObjectHi is 80) \ \ The comments are for when X = 0, which checks the \ x-coordinate LDA xObjectHi+33,X \ If the high byte of the alien's x-coordinate is zero, BEQ acrn5 \ then we have already reached the right longitude for \ Acornsville, so jump to acrn5 LDA xObjectLo+33,X \ Subtract alienSpeed from the alien's x-coordinate, SEC \ starting with the low bytes, so the alien moves SBC alienSpeed \ towards Acornsville along the x-axis at the correct STA xObjectLo+33,X \ speed (which increases with later waves) BCS acrn4 \ If the subtraction of the low bytes underflowed, DEC xObjectHi+33,X \ decrement the high byte .acrn4 LDA #1 \ Set T = 1, to record the fact that we moved the alien STA T .acrn5 CPX #80 \ If X = 80 then we have checked both axes, so jump to BEQ acrn6 \ acrn6 to check the alien's altitude LDX #80 \ Otherwise jump back to acrn3 with X = 80 to check the BNE acrn3 \ alien's latitude in its z-coordinate (this BNE is \ effectively a JMP as X is never zero) .acrn6 LDA T \ If T <> 0 then we moved the alien along at least one BNE acrn1 \ of the axes, so jump to acrn1 to return from the \ subroutine as the alien is still in the process of \ flying to Acornsville LDA #28 \ Set the alien's state to 28, so the next time we call STA alienState,Y \ this routine, we jump straight to the following .acrn7 CMP #28 \ If the alien's state is not 28, then it isn't BNE acrn1 \ attacking the town, so jump to acrn1 to return from \ the subroutine \ The alien is heading towards the town. This happens \ in three stages: first, the alien takes off; then it \ flies towards the town; and finally it descends. When \ the alien's state is 28, it is on the final stage, so \ that's what we do now LDA hitTimer \ If hitTimer is non-zero, jump to acrn1 to return from BNE acrn1 \ the subroutine, so the alien doesn't move if we \ recently hit one of its comrades LDA yObjectLo+33 \ Subtract 10 from the alien's yObject coordinate, so SEC \ that it descends towards the town, starting with the SBC #10 \ low bytes STA yObjectLo+33 BCS acrn8 \ If the subtraction of the low bytes underflowed, DEC yObjectHi+33 \ decrement the high byte .acrn8 LDA yObjectHi+33 \ If the high byte of the alien's y-coordinate is zero, BNE acrn1 \ then it is still too high to attack, so jump to acrn1 \ to return from the subroutine LDA yObjectLo+33 \ If the low byte of the alien's y-coordinate is 10 or CMP #10 \ more, then it is still too high to attack, so jump to BCS acrn1 \ acrn1 to return from the subroutine JSR PrintTooLate \ Otherwise the alien is close enough to the town to \ wreak havoc... which means it's game over, so print \ the "TOO LATE!" message in the middle of the screen LDA #90 \ Delay for 90^3 loop iterations JSR Delay JSR TerminateGame \ Terminate the game TSX \ Remove the two bytes from the top of the stack that INX \ were put there by the JSR that called this routine, so INX \ we can jump to NewGame without leaving any trace on TXS \ the stack JMP NewGame \ Jump to NewGame to start a new gameName: AlienInAcornsville [Show more] Type: Subroutine Category: The Theme Summary: Move an alien towards Acornsville and check whether it has reached it yet (and if so, end the game) Deep dive: Aliens attack Acornsville!Context: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 4 of 15) calls AlienInAcornsville.GetRadarVector CPX #0 \ If X = 0, jump to rvec1 to calculate the line vector BEQ rvec1 \ for the runway \ Otherwise we return the deltas for a dot, T = U = 1, \ and don't worry about setting the direction in V as \ it gets ignored when drawing dots LDY #1 \ Set Y = 1 to return as the y-delta in U BNE rvec2 \ Jump down to rvec2 to set X = 1 and return from the \ subroutine (this BNE is effectively a JMP as Y is \ never zero) .rvec1 \ We now want to calculate the vector for the runway \ line on the radar \ \ The runway runs north-south, so our compass direction \ in A lets us work out the direction of the runway line \ on the radar. The value of our compass in A is: \ \ * 0 = north \ * 64 = east \ * 128 = south \ * 192 = west STA previousCompass \ Store A in previousCompass, so we can pass it to this \ routine again when we want to erase the line we are \ about to draw CLC \ Set A = A + 16 ADC #16 \ \ This rotates the compass needle clockwise by 16, or \ 22.5 degrees, so if the needle is just anticlockwise \ of a cardinal compass point (e.g. NNW, ENE) it will be \ bumped along to the quadrant and will inherit the \ correct direction bit in bit 7. At the cardinal \ points, A now contains the following: \ \ * 16 = north -> bit 7 clear \ * 80 = east -> bit 7 clear \ * 144 = south -> bit 7 set \ * 208 = west -> bit 7 set \ \ So bit 7 contains the direction of the needle along \ the x-axis, with 0 to the right and 1 to the left ASL A \ Shift bit 7 of the result into the C flag, which we \ will use below as the direction of the line's x-delta STA P \ Store the result in P, so: \ \ P = (A + 16) << 1 \ \ which looks like this: \ \ * %00100000 = north \ * %10100000 = east \ * %00100000 = south \ * %10100000 = west \ \ We use this below to work out the line's vector PHP \ Store the flags on the stack, in particular the C \ flag from the above operation, which gives us the \ direction of the line's x-delta ROR A \ Shift the C flag back into bit 7 of A, so bit 7 once \ again contains the direction of the x-delta SEC \ Set A = A - 64 SBC #64 \ \ This rotates the compass needle anticlockwise by 64, \ or 90 degrees, which will change bit 7 from being the \ direction of the x-delta to the being the direction of \ the y-delta PLP \ Retrieve the C flag from above, which contains the \ direction of the x-delta ROR A \ Shift the direction of the x-delta into bit 7 of A, \ and at the same time shift the y-delta from bit 7 to \ bit 6 EOR #%11000000 \ Reverse both deltas by flipping bits 6 and 7 of A \ (I am not sure why this is done) STA V \ Store the result in V to set the direction of the line \ vector \ Above, we stored a value in P like this: \ \ * %00100000 = north \ * %10100000 = east \ * %00100000 = south \ * %10100000 = west \ \ We can use this below to work out the vector of the \ line to show, as follows: \ \ * A set bit 6 means the line is between the cardinal \ points, e.g. northeast, southwest and so on, so \ the line is diagonal \ \ * A set bit 7 means the line is generally east-west, \ which is horizontal \ \ * A clear bit 7 means the line is generally north- \ south, which is vertical \ \ We use this to set the vector in T and U to the \ following: \ \ * Diagonal: x-delta = 2, y-delta = 4 \ \ * Horizontal: x-delta = 2, y-delta = 1 \ \ * Vertical: x-delta = 1, y-delta = 4 \ \ The y-delta is twice the x-delta because the pixels \ in mode 5 are twice as wide as they are tall LDX #2 \ Set X = 2 to return as the x-delta in T for a diagonal LDY #4 \ Set Y = 4 to return as the y-delta in U for a diagonal BIT P \ If bit 6 of P is set, jump to rvec3 to return these BVS rvec3 \ values as the deltas (i.e. 2 and 4), as the runway \ line is diagonal BPL rvec2 \ If bit 7 of P is clear, jump to rvec2 to return an \ x-delta of 1 and a y-delta of 4, as the runway line is \ vertical LDY #1 \ Otherwise set Y = 1 and jump to rvec3 to return an BNE rvec3 \ x-delta of 2 and a y-delta of 1, as the runway line is \ horizontal .rvec2 LDX #1 \ Set X = 1 to return as the x-delta in T .rvec3 STX T \ Return X as the x-delta in T STY U \ Return Y as the y-delta in U RTS \ Return from the subroutineName: GetRadarVector [Show more] Type: Subroutine Category: Dashboard Summary: Calculate the radar line vector for a line (the runway) or a dot (an alien)Context: See this subroutine on its own page References: This subroutine is called as follows: * DrawRadarBlip calls GetRadarVector

Arguments: A For the runway line only, this is either the current compass direction from yRotationHi (if we are drawing the radar line), or a previous compass direction (if we are erasing the existing radar line) X The type of radar line to calculate: * 0 = runway line * Non-zero = alien (shown as a dot) Returns: T Magnitude of x-coordinate of line's vector |x-delta| U Magnitude of y-coordinate of line's vector |y-delta| V The direction of the line (runway), or an arbitrary direction for the dot, because it doesn't matter (alien) * Bit 7 is the direction of the x-delta * Bit 6 is the direction of the y-delta Direction is like a clock, so positive (clear) is up and right.colour1L2R EQUB %00001000 \ Colour 1, drawing a line left to right EQUB %00001100 EQUB %00001110 EQUB %00001111 EQUB %00000100 EQUB %00000110 EQUB %00000111 EQUB %00000010 EQUB %00000011 EQUB %00000001Name: colour1L2R [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for drawing canopy lines left to right in colour 1Context: See this variable on its own page References: This variable is used as follows: * DrawCanopyLine (Part 2 of 9) calls colour1L2R * DrawCanopyLine (Part 4 of 9) calls colour1L2R * DrawCanopyLine (Part 6 of 9) calls colour1L2R * ModifyDrawRoutine calls colour1L2R.colour1R2L EQUB %00000001 \ Colour 1, drawing a line right to left EQUB %00000011 EQUB %00000111 EQUB %00001111 EQUB %00000010 EQUB %00000110 EQUB %00001110 EQUB %00000100 EQUB %00001100 EQUB %00001000Name: colour1R2L [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for drawing canopy lines right to left in colour 1Context: See this variable on its own page References: This variable is used as follows: * DrawCanopyLine (Part 2 of 9) calls colour1R2L * DrawCanopyLine (Part 5 of 9) calls colour1R2L * ModifyDrawRoutine calls colour1R2L.colour2L2R EQUB %10000000 \ Colour 2, drawing a line left to right EQUB %11000000 EQUB %11100000 EQUB %11110000 EQUB %01000000 EQUB %01100000 EQUB %01110000 EQUB %00100000 EQUB %00110000 EQUB %00010000Name: colour2L2R [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for drawing canopy lines left to right in colour 2Context: See this variable on its own page References: This variable is used as follows: * ModifyDrawRoutine calls colour2L2R.colour2R2L EQUB %00010000 \ Colour 2, drawing a line right to left EQUB %00110000 EQUB %01110000 EQUB %11110000 EQUB %00100000 EQUB %01100000 EQUB %11100000 EQUB %01000000 EQUB %11000000 EQUB %10000000Name: colour2R2L [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for drawing canopy lines right to left in colour 2Context: See this variable on its own page References: This variable is used as follows: * ModifyDrawRoutine calls colour2R2L.colour1Row EQUB %00001111 \ Solid colour 1 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111 EQUB %00001111Name: colour1Row [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for erasing canopy lines in colour 1Context: See this variable on its own page References: This variable is used as follows: * ModifyDrawRoutine calls colour1Row.colour2Row EQUB %11110000 \ Solid colour 2 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000 EQUB %11110000Name: colour2Row [Show more] Type: Variable Category: Drawing lines Summary: Pixel bytes for erasing canopy lines in colour 2Context: See this variable on its own page References: This variable is used as follows: * ModifyDrawRoutine calls colour2Row.previousCompass EQUB &20Name: previousCompass [Show more] Type: Variable Category: Dashboard Summary: Stores the value of the compass heading when we draw the runway on the radar, so we can erase the line laterContext: See this variable on its own page References: This variable is used as follows: * DrawRadarBlip calls previousCompass * GetRadarVector calls previousCompass.previousTime EQUB &20 EQUB &20, &20 \ These bytes appear to be unusedName: previousTime [Show more] Type: Variable Category: Main loop Summary: Stores the current time (low byte only), so we can process lines in a timely fashion during the main loopContext: See this variable on its own page References: This variable is used as follows: * CheckTimePassed calls previousTime.ClearCanopy LDX #0 \ Set X = 0 so we clear the canopy to black \ Fall through into FillCanopy to fill the canopy with \ black, leaving the top and side edges aloneName: ClearCanopy [Show more] Type: Subroutine Category: Graphics Summary: Clear the canopy to black, leaving the canopy edges aloneContext: See this subroutine on its own page References: This subroutine is called as follows: * Crash calls ClearCanopy * NewGame calls ClearCanopy.FillCanopy TXA \ Copy the colour into X LDX #19 \ Set R = 19, so we clear 19 character rows (the whole STX R \ canopy view except for the top row containing the \ canopy edge) LDY #HI(row1_block1_0) \ Set (Y X) to the screen address for row 1, block 1 LDX #LO(row1_block1_0) \ Fall through into FillCanopyRows to fill the canopy \ view, from the top row to the bottom, avoiding the top \ and side edgesName: FillCanopy [Show more] Type: Subroutine Category: Graphics Summary: Fill the canopy with a specified colour, leaving the canopy edges aloneContext: See this subroutine on its own page References: This subroutine is called as follows: * Crash calls FillCanopy

Arguments: X The colour to fill the canopy with.FillCanopyRows STY Q \ Set (Q P) = (Y X), so (Q P) is now the screen address STX P \ we want to start filling from STA S \ Store the value we want to store into S .fill1 LDY #0 \ Set a byte counter in Y LDA S \ Fetch the value of A that we stored in S above .fill2 STA (P),Y \ Set the Y-th byte of (Q P) to A, which sets 4 pixels \ to the pixel pattern in S DEY \ Decrement the byte counter BNE fill2 \ Loop back until we have set 256 bytes, starting at \ (Q P), to the value in A LDY #47 \ Set a byte counter in Y for 47 bytes INC Q \ Set (Q P) = (Q P) + 256 \ \ so it points to the next byte to fill after the 256 \ bytes we just did .fill3 STA (P),Y \ Set the Y-th byte of (Q P) to A, which sets 4 pixels \ to the pixel pattern in S DEY \ Decrement the byte counter BPL fill3 \ Loop back until we have set 47 bytes, starting at \ (Q P), to the value in A LDA P \ Set (Q P) = (Q P) + 64 CLC \ ADC #64 \ starting with the low bytes STA P BCC fill4 \ If the above addition didn't overflow, skip the next \ instruction INC Q \ The above addition overflowed, so increment the high \ byte of (Q P) to point to the next page in memory \ So now (Q P) is 320 greater than at the start, so it \ points to the next character row in screen memory .fill4 DEC R \ Decrement the row counter in R BNE fill1 \ Loop back until we have updated R rows RTS \ Return from the subroutineName: FillCanopyRows [Show more] Type: Subroutine Category: Graphics Summary: Fill multiple screen rows with a particular colour, avoiding the canopy edgesContext: See this subroutine on its own page References: This subroutine is called as follows: * DrawGunSights calls FillCanopyRows * RemoveScore calls FillCanopyRows

Arguments: A The colour to fill the canopy with (Y X) The screen address to start filling from R The number of character rows to fill.Delay STA T \ Set T as the counter for the outer loop .dely1 STA U \ Set U as the counter for the middle loop .dely2 STA V \ Set V as the counter for the inner loop .dely3 DEC V \ Loop around for A iterations in the inner loop BNE dely3 DEC U \ Loop around for A iterations in the middle loop BNE dely2 DEC T \ Loop around for A iterations in the outer loop BNE dely1 RTS \ Return from the subroutineName: Delay [Show more] Type: Subroutine Category: Utility routines Summary: Delay for a specified number of loopsContext: See this subroutine on its own page References: This subroutine is called as follows: * AlienInAcornsville calls Delay * Crash calls Delay

This routine performs A^3 loop iterations, to create a delay. Fragments of the original source for this routine appear in the game code, as follows: .dlp2 STA&76 .dl ... ... :BNE dlp2 DEC&74:BNE dlp1 rts.UpdateBullets LDY #15 \ The bullets are made up of objects 12 to 15, so set a STY objectId \ counter in objectId to count through all four LDA #98 \ Objects 12 to 15 are made up of points 95 to 98, so STA GG \ set a counter in GG to count through all four .ubul1 TYA \ Set X = Y + 216 CLC \ ADC #216 \ so X will be 228 to 231 for objects 12 to 15, which is TAX \ the ID of each bullet object's velocity vector, as set \ up in the FireGuns routine JSR AddPointToObject \ Add the vector in point X to the object coordinates \ for object Y (in other words, add the velocity vector \ to object Y's coordinates, which moves the bullet in \ space by the correct amount) LDA #0 \ Set showLine = 0 as a starting point for the line's STA showLine \ visibility (so we start out by assuming the line is \ visible, and change this in the following call to \ SetObjectCoords if we find that it isn't) JSR SetObjectCoords \ Calculate the object's coordinates and visibilty, \ updating the object's status byte with the results BPL ubul2 \ If bit 7 of the object's updated status byte is clear, \ then the bullets have hit the ground, so jump to ubul2 \ to remove the bullets LDY GG \ Set Y to the point ID that we're checking LDX #60 \ Set X to line ID 60 for the call to CheckLineDistance JSR CheckLineDistance \ Check whether point GG on line 60 is within the \ visible distance for the line BEQ ubul3 \ If the result is 0, then the point is visible, so \ jump to ubul3 to move onto the next bullet point .ubul2 \ If we get here then this bullet point has either hit \ the ground, or it is too far away to be seen any more, \ so it's time to remove the bullets LDA #0 \ Set firingStatus = 0 to indicate that there are no STA firingStatus \ bullets are in the air .ubul3 DEC GG \ Decrement the point counter to move on to the next \ point from 98 down to 95 DEC objectId \ Decrement the object counter to move on to the next \ object from 15 down to 12 LDY objectId \ Loop back until we have processed all four objects CPY #12 \ and points BCS ubul1 RTS \ Return from the subroutineName: UpdateBullets [Show more] Type: Subroutine Category: The Theme Summary: Move the bullets through the airContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 3 of 15) calls UpdateBullets

This is called UBUL in the original source code..SpawnAlien LDX themeStatus \ If bit 7 of themeStatus is set, then the Theme is not BMI spaw3 \ enabled, so jump to spaw3 to return from the \ subroutine BEQ spaw3 \ If themeStatus is zero, then we have already spawned \ all eight aliens in this wave, so return from the \ subroutine LDA onGround \ If onGround is non-zero, then we are on the ground, so BNE spaw3 \ jump to spaw3 to return from the subroutine \ If we get here, themeStatus is in the range 1 to 8 and \ we are not on the ground, so the Theme has started but \ we haven't yet spawned all eight aliens in the current \ wave, so we need to spawn another alien (specifically \ the alien whose ID is in themeStatus) STA alienState-1,X \ We know A is 0, as we just passed through a BNE above, \ so this zeroes the state of the alien whose number is \ in themeStatus, so it starts its feeding routine from \ scratch \ We now need to allocate an object ID to this alien, \ from the range 16 to 29, making sure we don't reuse \ any objects that are currently in use by other aliens \ in the wave LDA VIA+&64 \ Read the 6522 User VIA T1C-L timer 1 low-order \ counter (SHEILA &44) which increments 1000 times a \ second so this will be pretty random AND #15 \ Reduce the random number to the range 0 to 15 CMP #14 \ If the random number is >= 14 (12.5% chance), jump to BCS spaw3 \ spaw3 to return from the subroutine ORA #16 \ Increase the random number to the range 16 to 29, to \ give us a potential object ID DEC themeStatus \ We are spawning a new alien, so decrement the counter \ in themeStatus so it reflects the number of aliens \ that still have to spawn to complete this wave LDX #8 \ We now need to confirm that this object ID isn't being \ used by any other aliens that we've already spawned in \ this wave, so set X to act as a loop counter, going \ from 8 down to themeStatus (so this works through the \ IDs of the aliens that we have already spawned in this \ wave, as we start spawning at ID 8 and work our way \ down to 1) .spaw1 DEX \ Decrement the loop counter CPX themeStatus \ If X <> themeStatus, jump to spaw2 to check this BNE spaw2 \ alien's object ID STA alienObjectId,X \ Otherwise we have run through all the other aliens in \ this wave and none of them are using this object ID, \ so set this as the object ID for this alien RTS \ Return from the subroutine .spaw2 CMP alienObjectId,X \ If the object ID for the X-th alien does not match our BNE spaw1 \ random number, then jump back to spaw1 to move on to \ the next alien INC themeStatus \ Otherwise we've found an alien that is already using \ the object ID we generated above, so we give up on \ spawning this alien, incrementing the alien counter \ in themeStatus so that it's back to the original value \ (so we can have another go at spawning an alien on the \ next call to SpawnAlien) .spaw3 RTS \ Return from the subroutineName: SpawnAlien [Show more] Type: Subroutine Category: The Theme Summary: If the Theme is enabled and the current wave does not yet have eight aliens in it, spawn a new alien Deep dive: Alien feeding and growth patternsContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 1 of 15) calls SpawnAlien

This routine tries to add a new alien to the current wave. It sets the alien's state to 0, and chooses a random object ID from the range 16 to 29 for the alien. If this object ID is already in use by an alien that we've already spawned for this wave, then it aborts the spawning, otherwise it allocates the object ID to the new alien's alienObjectId entry and our new alien is spawned. This means that aliens only ever spawn in the fixed locations for objects 16 to 29, which can be seen in the xObjectLo table. This is called SUTR in the original source code..UpdateAliens LDA mainLoopCounter \ If the mainLoopCounter is a multiple of 128, jump to AND #127 \ upal3 to move on to part 2 (so we only do this part BNE upal3 \ on 2 out of every 256 iterations round the main loop) LDX #7 \ We now progress the state of each alien, from alien 7 \ down to alien 0, so set a loop counter in X .upal1 LDA alienState,X \ If the state of alien X is zero, jump to upal2 BEQ upal2 \ to move on to the next alien CMP #22 \ If the state of alien X is 22, jump to upal2 BEQ upal2 \ to move on to the next alien CMP #27 \ If the state of alien X is 27 or higher, jump BCS upal2 \ to upal2 to move on to the next alien INC alienState,X \ If we get here then the state of alien X is not 0, 22 \ or >= 27, i.e. it's 1-21 or 23-26, so increment the \ state to progress through the feeding and take-off \ stages .upal2 DEX \ Decrement the alien number BPL upal1 \ Loop back until we have progressed all eight aliens \ to the next stateName: UpdateAliens (Part 1 of 5) [Show more] Type: Subroutine Category: The Theme Summary: Update the aliens so they progress through their feeding or attack cycles Deep dive: Scheduling tasks in the main loop Alien feeding and growth patternsContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 6 of 15) calls UpdateAliens

We start by incrementing the state of any non-dormant aliens, so they slowly move through their feeding or take-off cycles..upal3 LDY #31 \ We run the following outer loop twice, once for alien \ slot 31 and again for alien slot 32, so set a counter \ in Y to iterate through 31 and 32 .upal4 LDX alienSlot-30,Y \ If alien slot Y contains a negative number, then the BMI upal6 \ slot is already empty, so jump to upal6 LDA alienState,X \ If the state of the alien in slot Y is 24, then skip CMP #24 \ the following two instructions BEQ upal5 LDA alienObjectId,X \ If the object ID of the alien in slot Y is positive, BPL upal11 \ jump to upal11 to move on to the next alien .upal5 \ If we get here then alien slot Y contains an alien \ (with ID 0 to 7), and either the alien's state is 24, \ or the alien's object ID is negative (which means it \ has been destroyed) LDA #254 \ Clear out slot Y by setting it to a negative number STA alienSlot-30,Y .upal6 \ We now run through aliens 7 to 0, until we find one \ with a positive object ID and a state of 0, and which \ is not already in the other slot. When we find it, \ we insert it into the slot, bump its state up to 1 \ and stop looking LDX #7 \ Set a loop counter in X to contain the alien's number .upal7 LDA alienObjectId,X \ If the alien's object ID is negative, jump to upal10 BMI upal10 \ to move on to the next alien, as this alien has been \ destroyed LDA alienState,X \ If the alien's state is non-zero, jump to upal10 to BNE upal10 \ move on to the next alien CPY #31 \ If we are processing alien slot 31 in the outer loop, BEQ upal8 \ skip the following two instructions CPX alienSlot+1 \ Compare the alien number with the contents of alien JMP upal9 \ slot 31 and skip the following instruction .upal8 CPX alienSlot+2 \ Compare the alien number with the contents of alien \ slot 32 .upal9 BEQ upal10 \ If the current alien number matches the contents of \ slot Y, jump to upal10 to move on to the next alien TXA \ Insert this alien number into alien slot Y STA alienSlot-30,Y STX U \ Store the alien number in U LDA #%10000000 \ Set bit 7 of A so the call to ResizeFeedingAlien sets \ the size of the alien to the first feeding stage JSR ResizeFeedingAlien \ Resize the alien to the first feeding stage LDX U \ Retrieve the alien number from U LDA #1 \ Set the alien's state to 1 STA alienState,X BNE upal11 \ Jump to upal11 to terminate the inner loop (this BNE \ is effectively a JMP as A is never zero) .upal10 DEX \ Decrement the inner loop alien counter BPL upal7 \ Loop back until we have worked our way through aliens \ 0 to 7 .upal11 INY \ Increment the alien counter CPY #33 \ Loop back until we have processed both alien slots 31 BNE upal4 \ and 32Name: UpdateAliens (Part 2 of 5) [Show more] Type: Subroutine Category: The Theme Summary: Manage alien slots 31 and 32, and if there's a vacancy, wake up a dormant alien, move it into the slot and start its feeding cycle Deep dive: Alien feeding and growth patternsContext: See this subroutine on its own page References: No direct references to this subroutine in this source file

Look at alien slots 31 and 32, and for each one: * If the alien in the slot is in state 24, remove it from the slot * Otherwise check to see if the alien in the slot has been destroyed, and if so, empty the slot * If the slot is not empty, search the aliens for one is dormant (i.e. in state 0), isn't already in the other slot, and hasn't been destroyed, and put that into the slot, bumping its state up to 1 and setting the size of the alien to the correct size for the first feeding stage\ At this point Y = 33, so we now process alien slot 33 LDX alienSlot-30,Y \ If alien slot 33 contains a negative number, then the BMI upal12 \ slot is already empty, so jump to upal12 to move on to \ skip the following LDA alienObjectId,X \ If the object ID of the alien in slot 33 is positive, BPL upal15 \ then we already have an alien moving towards the town, \ so jump to upal15 to skip the STA alienSlot-30,Y \ Clear out slot 33 by setting it to a negative number \ (we know A is negative because we just passed through \ a BPL instruction) .upal12 LDY #31 \ We now work our way through alien slots 31 and 32, \ so set a counter in Y for the slot number .upal13 LDX alienSlot-30,Y \ If alien slot Y contains a negative number, then the BMI upal14 \ slot is empty, so jump to upal14 to skip the following LDA alienState,X \ If the alien's state is not 22, jump to upal14 to skip CMP #22 \ the following BNE upal14 STX alienToMove \ Set this alien as the one to move towards Acornsville \ in this iteration of the main loop by setting \ alienToMove to the alien number in X LDA #23 \ Set the alien's state to 23 STA alienState,X BNE upal15 \ Jump to upal15 to exit the loop (this BNE is \ effectively a JMP as A is never zero) .upal14 INY \ Increment the counter to point to the next alien slot CPY #33 \ Loop back until we have done alien slots 31 and 32 BNE upal13Name: UpdateAliens (Part 3 of 5) [Show more] Type: Subroutine Category: The Theme Summary: If alien slot 33 is free and there's an alien waiting to take off, promote it into slot 33 Deep dive: Alien feeding and growth patternsContext: See this subroutine on its own page References: No direct references to this subroutine in this source file

Look at alien slot 33, and: * If the alien in slot 33 has been destroyed, clear the slot * If slot 33 is clear, then check slots 31 and 32 to see if either of then contains an alien in state 22 (i.e. an alien that has finished feeding and is ready to take off), and if so, move that alien into slot 33, promoting it to state 23 in the process.upal15 LDA mainLoopCounter \ If the mainLoopCounter is a multiple of 128, jump to AND #127 \ upal19 to skip the following (so we only do this part BNE upal19 \ on 2 out of every 256 iterations round the main loop, \ just like part 1) LDY #31 \ We now work our way through alien slots 31 and 32, \ so set a counter in Y for the slot number .upal16 LDX alienSlot-30,Y \ If alien slot Y contains a negative number, then the BMI upal17 \ slot is empty, so jump to upal17 to move on to the \ next slot LDA alienState,X \ If the alien's state is < 5, jump to upal17 to move on CMP #5 \ to the next slot, as the alien is still in feeding BCC upal17 \ stage 1 and doesn't need resizing CMP #20 \ If the alien's state is >= 20, jump to upal17 to move BCS upal17 \ on to the next slot, as the alien has already reached \ the last feeding stage and can't get any bigger AND #%00000011 \ Check whether the feeding state is in the form BNE upal17 \ %xxxxxx00, and if not, jump to upal17 to move on to \ the next slot \ If we get here, then the alien's state is between 6 \ and 19, and matches %xxxxxx00, so it's one of these: \ \ * 8 = %00001000 \ * 12 = %00001100 \ * 16 = %00010000 \ \ These are the points in the feeding stage when the \ size of the alien doubles JSR ResizeFeedingAlien \ Double the size of the feeding alien to move it onto \ the next feeding stage .upal17 INY \ Increment the counter to point to the next alien slot CPY #33 \ Loop back until we have done alien slots 31 and 32 BNE upal16Name: UpdateAliens (Part 4 of 5) [Show more] Type: Subroutine Category: The Theme Summary: When an alien reaches the next feeding stage, double its size Deep dive: Scheduling tasks in the main loop Alien feeding and growth patternsContext: See this subroutine on its own page References: No direct references to this subroutine in this source fileLDX #7 \ We now work through all the aliens, from alien 7 down \ to alien 0, to check whether they have all been \ destroyed (i.e. whether they all have a negative \ object ID), so set a loop counter in X .upal18 LDA alienObjectId,X \ If the X-th alien object ID is positive, then that BPL upal19 \ alien is still at large, so jump to upal19 to return \ from the subroutine, as we haven't destroyed all eight \ aliens in this wave DEX \ Decrement the loop counter to point to the next alien BPL upal18 \ Loop back until we have checked all eight aliens \ If we get here then all eight aliens have negative \ object IDs, so they have all been destroyed LDA #8 \ Set themeStatus = 8 to initiate a brand new wave of STA themeStatus \ aliens LDX #&00 \ Add 500 points to the score and make a beep by calling LDA #&50 \ ScorePoints with (X A) = &0050 JSR ScorePoints \ \ This is the score for completing a wave in the Theme LDA alienSpeed \ Set A = alienSpeed + 4 CLC ADC #4 CMP #19 \ If A >= 19, skip the following instruction, so BCS upal19 \ alienSpeed has a maximum value of 22 (as alienSpeed \ starts with a value of 10, and increases by 4 with \ each wave until it is >= 19, which happens when it \ reaches 22) STA alienSpeed \ Update alienSpeed with the faster speed so the next \ wave has faster-moving aliens .upal19 RTS \ Return from the subroutineName: UpdateAliens (Part 5 of 5) [Show more] Type: Subroutine Category: The Theme Summary: Check whether the whole wave has been destroyed, and award points accordingly Deep dive: Alien feeding and growth patterns.ResizeFeedingAlien STA K \ Store the A argument in K so we can retrieve it below STY T \ Store Y in T so we can ensure it is unchanged by the \ routine LDX #3 \ We do the following loop four times, to update the \ alien's four object ID z-coordinates, so set a loop \ counter in X LDA #186 \ Set A to the object point ID to update for slot 31, so \ we update points 183 to 186 in the loop CPY #31 \ If this is alien slot 31, skip the following BEQ size1 \ instruction LDA #191 \ Set A to the object point ID to update for slot 32, so \ we update points 188 to 191 in the loop .size1 TAY \ Copy the object point ID we just set in A into Y, so \ we can use it as an index .size2 LDA zObjectPoint,Y \ Set A to the z-coordinate of the object point CLC \ Add 16 to the z-coordinate, which doubles the scale ADC #16 \ factor in bits 4 to 7 BIT K \ If bit 7 of K is clear, skip the following two BPL size3 \ instructions, as we are done AND #15 \ Otherwise bit 7 of S is set, so we need to reset the ORA #32 \ scale to the first feeding stage, which we can do like \ this: \ \ z = 32 + (z + 16) MOD 16 \ \ This gives us a result iwith 32 in bits 4 to 7 (i.e. a \ scale factor of 2^2) while retaining the value in bits \ 0 to 3 .size3 STA zObjectPoint,Y \ Store the updated z-coordinate DEY \ Decrement the object point ID DEX \ Decrement the loop counter BPL size2 \ Loop back until we have updated three slots LDY T \ Restore Y from T, so it doesn't get changed by the \ routine RTS \ Return from the subroutineName: ResizeFeedingAlien [Show more] Type: Subroutine Category: The Theme Summary: Change the size of an alien so it grows bigger as it feeds Deep dive: Alien feeding and growth patternsContext: See this subroutine on its own page References: This subroutine is called as follows: * UpdateAliens (Part 2 of 5) calls ResizeFeedingAlien * UpdateAliens (Part 4 of 5) calls ResizeFeedingAlien

This routine grows the alien in slot 31 or 32 by scaling the z-coordinates for the alien's four object points. Because object points are stored with the scale factor in bits 4 to 7, we can double the size of the alien by adding 16 to each z-coordinate, thus doubling the scale factor. If bit 7 of A is set, then this routine resets the size to the smallest feeding stage, which has a scale factor of 32 (i.e. 2^2). Arguments: A Determines how the alien is resized: * If bit 7 is clear, double the size of the alien * If bit 7 is set, reset the alien to stage 1 Y The number of the alien slot to process (31 or 32), which determines which object points have their z-coordinates updated in the zObjectPoint table: * Resize object points 183 to 186 for alien slot 31 * Resize object points 188 to 191 for alien slot 32 Returns: zObjectPoint Updated z-coordinates for the relevant object points, scaled as required Y Y is unchanged.CheckIfAlienIsHit LDA #%01111101 \ Set QQ = %01111101, to hold the y-axis dimension of STA QQ \ the alien's weak spot (let's call this y-size), which \ we will scale down to match the alien's current size LDA #%01000000 \ Set Q = %01000000, to hold the low byte of the offset STA Q \ of the alien's weak spot from the alien's anchor point \ (the high byte is always 5), which we will scale down \ to match the alien's current size LDA #%10100000 \ Set RR = %10100000, to hold the x-axis dimension of STA RR \ the alien's weak spot (let's call this x-size), which \ we will scale down to match the alien's current size STA PP \ Set PP = %10100000, to hold the z-axis dimension of \ the alien's weak spot (let's call this z-size), which \ we will scale down to match the alien's current size CPY #31 \ If Y >= 31, jump to ahit1 BCS ahit1 \ If we get here then Y = 30, so this is a dormant alien LDA #4 \ Set A = 4, to set as the feeding stage in ahit5 (stage \ 4 is the dormant phase) LDX #3 \ Set X = 3, so ahit4 shifts right by 3 places BNE ahit4 \ Jump to ahit4 (this BNE is effectively a JMP as X is \ never zero) .ahit1 LDA #0 \ Set A = 0, so if this is the flying alien (Y = 33), we \ set the feeding stage to 0 in ahit5 (stage 0 is for \ fully fed aliens, and only fully fed aliens can fly) CPY #32 \ If Y >= 32, jump to ahit2 BCS ahit2 \ If we get here then Y = 31, so this is a feeding alien LDX #183 \ Set X = 183, to use as the object point ID BNE ahit3 \ Jump to ahit3 (this BNE is effectively a JMP as X is \ never zero) .ahit2 BNE ahit5 \ If Y <> 32, then Y = 33 and this is the flying alien, \ so jump to ahit5 to store the feeding stage and move \ on to the next part \ If we get here then Y = 32, so this is a feeding alien LDX #188 \ Set X = 188, to use as the object point ID .ahit3 \ If we get here then Y = 31 or 32 and X is the ID of \ the first object point for this alien, so now we \ extract the alien's current feeding stage from the \ scale of the object point' z-coordinate, which gets \ updated in ResizeFeedingAlien as the alien grows \ \ Note that the feeding stage goes from 4 (dormant) down \ to 0 (fully fed) as the alien feeds and grows bigger, \ so we need to invert the scale of the z-coordinate \ to get the correct value for the feeding stage LDA zObjectPoint,X \ Set A to the object point's z-coordinate EOR #%01110000 \ The z-coordinate contains scale information in bits 4 \ to 7, with the smallest feeding alien having a scale \ factor of 2^2, and the largest having a scale factor \ of 2^5 (there are four different sizes of feeding \ alien) \ \ This means that even at the largest scale, bit 7 of \ the scale will still be zero, so to invert the scale \ we only need to flip bits 4 to 6, as then: \ \ * If scale is %0010 (2^2), result is %0101 (5) \ * If scale is %0011 (2^3), result is %0100 (4) \ * If scale is %0100 (2^4), result is %0011 (3) \ * If scale is %0101 (2^5), result is %0010 (2) \ \ so this EOR inverts the alien's scale factor to the \ range 2 to 5, if we only consider the top nibble LSR A \ We now shift the top nibble down, so A contains the LSR A \ inverted scale factor (i.e. A is in the range 2 to 5) LSR A LSR A TAX \ Finally, we subtract 2 from the inverted scale factor, DEX \ so A is now in the range 0 to 3 and reflects the four DEX \ feeding stages: \ \ * 0 = large feeding alien (fully fed) \ * 1 = medium feeding alien \ * 2 = small feeding alien \ * 3 = smallest feeding alien TXA \ Copy the feeding stage into X BEQ ahit5 \ If X = 0, the alien is at its largest size, so jump to \ ahit5 to store the feeding stage and move on to the \ next part \ Otherwise we scale QQ, RR, PP and QQ right by the \ number of places given in X .ahit4 \ This loop shifts the following to the right by X \ places, where X > 0 LSR QQ \ Shift QQ, RR, PP and QQ right by one place LSR RR LSR PP LSR Q DEX \ Decrement the shift counter in X BNE ahit4 \ Loop back until we have shifted right by X places \ By the time we get here, the variables are set as \ follows: \ \ * Fully fed (stage 0) or flying alien: \ \ Q = %01000000, so (5 Q) = &540 = 1360 \ RR = %10100000, so x-size = 160 \ QQ = %01111101, so y-size = 125 \ PP = %10100000, so z-size = 160 \ \ * Medium feeding alien (stage 1): \ \ Q = %00100000, so (5 Q) = &520 = 1312 \ RR = %01010000, so x-size = 80 \ QQ = %00111110, so y-size = 62 \ PP = %01010000, so z-size = 80 \ \ * Small feeding alien (stage 2): \ \ Q = %00010000, so (5 Q) = &510 = 1296 \ RR = %00101000, so x-size = 40 \ QQ = %00011111, so y-size = 31 \ PP = %00101000, so z-size = 40 \ \ * Smallest feeding alien (stage 3) or dormant alien: \ \ Q = %00001000, so (5 Q) = &508 = 1288 \ RR = %00010100, so x-size = 20 \ QQ = %00001111, so y-size = 15 \ PP = %00010100, so z-size = 20 .ahit5 STA feedingStage \ Store the alien's feeding stage in feedingStageName: CheckIfAlienIsHit (Part 1 of 2) [Show more] Type: Subroutine Category: The Theme Summary: Extract the alien's feeding stage, ready for the hit calculations in part 2 Deep dive: Detecting alien hitsContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 6 of 15) calls CheckIfAlienIsHit

Arguments: Y The object ID of the alien to check (30 to 33) objectId The object ID of the alien to check (30 to 33)LDA #0 \ Set hitTimer = 0 so the default result is a miss STA hitTimer LDY objectId \ Set Y to the object ID of the alien JSR GetAlienWeakSpot \ Calculate the coordinate of the alien's weak spot as \ follows: \ \ (I+2 W+2) = xObject + (5 Q) \ \ (I+1 W+1) = yObject \ \ (I W) = zObject + (5 Q) \ \ So for the alien object, the weak spot is at a point \ coordinate of ((5 Q), 0, (5 Q)) within the object LDX #228 \ Set VV to iterate through the following in the outer STX VV \ loop below (i.e. from ahit6 to the end): \ \ * 228 = the trailing end of the left bullet trail \ \ * 230 = the trailing end of the right bullet trail .ahit6 LDX VV \ Set X to denote the trailing end of the bullet trail \ that we are analysing (228 or 230) LDA #31 \ Set WW to act as a loop counter for when we check STA WW \ along the length of the bullet trail for a hit, moving \ 1/32 of the way for each of the 32 iterations LDY #0 \ Set Y to loop through the three axes .ahit7 STY Q \ Store the axis counter in Q so we can retrieve it \ below JSR GetTrailVectorStep \ Set (A V R) to 1/32 of the vector for the specified \ bullet trail LDY Q \ Restore the axis counter into Y STA xTemp2Hi,Y \ Set (xTemp2Hi xTemp2Lo xTemp1Lo) = (A V R) LDA V STA xTemp2Lo,Y LDA R STA xTemp1Lo,Y INY \ Increment the loop counter to move on to the next axis CPY #3 \ Loop back until we have calculated the bullet trail BNE ahit7 \ vector LDX #LO(xTemp2Lo) \ Set X so the call to CopyWorkToPoint copies the \ coordinates from (xTemp2, yTemp2, zTemp2) LDY #0 \ Set Y so the call to CopyWorkToPoint copies the \ coordinates to point 0 JSR CopyWorkToPoint \ Copy the coordinates from (xTemp2, yTemp2, zTemp2) \ to point 0 \ Point 0 now contains the vector of the bullet trail \ for the bullet specified in VV, with the lowest byte \ dropped, so each axis contains (A V) from the above LDY VV \ Set Y to the bullet that we are analysing (228 or 230) JSR CheckAlienWeakSpot \ Check whether this end of the bullet trail has hit the \ alien's weak spot, and if it has, set up the explosion \ and return from the subroutine LDY VV \ Set Y to the bullet that we are analysing (228 or 230) LDX #216 \ Set X to iterate through the coordinate offsets for \ object 0 .ahit8 TYA \ Point Y to the next axis (xObject, yObject, zObject) CLC \ ADC #nextAxis \ The first iteration of this loop has Y = 228 or 230, TAY \ so this bumps Y onto 268 or 260, which gets truncated \ in the 8-bit register to 12 or 14, so this moves Y \ through the xObject, yObject and zObject values for \ object 12 (when the initial value of Y = 228) or \ object 14 (when the initial value of Y = 230) TXA \ Point X to the next axis (xObject, yObject, zObject) CLC \ ADC #nextAxis \ The first iteration of this loop has X = 216, so this TAX \ bumps X onto 256, which gets truncated in the 8-bit \ register to 0, so this moves X through the xObject, \ yObject and zObject values for object 0 LDA xObjectLo,Y \ Copy the coordinate from the bullet object to object 0 STA xObjectLo,X CPX #200 \ Loop back until we have copied all six coordinates BNE ahit8 \ By this point, object 0 is at the same coordinate as \ the bullet we are checking, and we now work our way \ along the trail vector, adding the 1/32 vector that \ we calculated above for each of the 32 iterations of \ the following loop .ahit9 LDY #2 \ Set a counter in Y to iterate through the three axes \ (the comments below are for the x-axis calculation) LDX #nextAxis*2 \ Set the index in X to point to the z-coordinate for \ object 0, which we decrement by nextAxis over each \ iteration to work through the three axes .ahit10 \ Above we set (xTemp2Hi xTemp2Lo xTemp1Lo) to the 1/32 \ vector, but we only copied (xTemp2Hi xTemp2Lo) into \ point 0, and ignored the fractional part, so we add \ that part to the object 0 coordinate first LDA xTemp1Lo,Y \ Set xTemp2Hi = xTemp2Hi + xTemp1Lo CLC \ ADC xTemp2Hi,Y \ to work out when the fractional part cumulatively STA xTemp2Hi,Y \ adds up to an integer (in other words, we store the \ cumulative sum of the fractional part from xTemp1Lo in \ xTemp2Hi) BCC ahit11 \ If the addition didn't overflow, jump to ahit11 to \ skip incrementing the object coordinate \ Otherwise the cumulative sum of the fractional part \ just reached an integer, so we need to add an extra \ integer (1) to the object 0 coordinate INC xObjectLo,X \ Increment the object coordinate for object 0 in BNE ahit11 \ (xObjectHi xObjectLo), starting with the low byte INC xObjectHi,X \ and incrementing the high byte if the low byte \ overflows .ahit11 TXA \ Point X to the next axis (zObject, yObject, xObject) SEC SBC #nextAxis TAX DEY \ Decrement the axis counter BPL ahit10 \ Loop back until we have processed all three axes \ We have now moved object 0 along the trail by adding \ the fractional part of the 1/32 vector xTemp1Lo, so \ now we can add the rest of the vector which we stored \ in point 0 above, to move along the trail by exactly \ 1/32 of the trail vector LDX #0 \ Move object 0 by the vector in point 0, which we set LDY #0 \ to the vector of the bullet trail above JSR AddPointToObject \ We now check whether this point along the bullet trail \ is in the alien's weak spot LDY #216 \ Check whether object 0 has hit the alien's weak JSR CheckAlienWeakSpot \ spot, and if it has, set up the explosion and return \ from the subroutine DEC WW \ Decrement the counter we set in WW so we repeat this \ process 32 times BPL ahit9 \ Loop back until we have stepped all the way along the \ trail vector, from the back end of the trail all the \ way to the bullet at the front, in steps of 1/32, \ checking at each point whether it is in the weak spot \ If we get here then we have now checked the entire \ trail of the left bullet for a hit, so we repeat the \ whole thing for the right bullet trail LDA VV \ Set VV = VV + 2 CLC \ ADC #2 \ so VV now points to the next bullet trail (i.e. 230) STA VV CMP #232 \ If VV = 232 then we have now processed both bullet BEQ ahit12 \ trails, so jump to ahit12 to return from the \ subroutine JMP ahit6 \ Otherwise loop back to ahit6 to process the next \ bullet trail .ahit12 RTS \ Return from the subroutineName: CheckIfAlienIsHit (Part 2 of 2) [Show more] Type: Subroutine Category: The Theme Summary: Check to see whether the alien has been hit, and if so, initiate the explosion Deep dive: Detecting alien hits.GetAlienWeakSpot LDX #2 \ Set a counter in X to iterate through 2, 1, 0, which \ has the following effect: \ \ When X = 2: \ \ * (I+2 W+2) = (xObjectHi xObjectLo) + (5 Q) \ \ When X = 1: \ \ * (I+1 W+1) = (yObjectHi yObjectLo) \ \ When X = 0: \ \ * (I W) = (zObjectHi zObjectLo) + (5 Q) \ \ note that .weak1 LDA xObjectLo,Y \ Set (I+X W+X) = (xObjectHi xObjectLo) + (5 Q) CLC \ ADC Q \ starting with the low bytes STA W,X LDA xObjectHi,Y \ And then the high bytes ADC #5 STA I,X .weak2 TYA \ Point Y to the next axis (xObject, yObject, zObject) CLC ADC #nextAxis TAY DEX \ Decrement the loop counter BPL weak3 \ If we haven't yet done all three calculations, jump \ to weak3 RTS \ Return from the subroutine .weak3 BEQ weak1 \ If X = 0, jump up to weak1 to add (5 Q) LDA xObjectLo,Y \ If we get here then X = 1, so do the calculation STA W,X \ without adding (5 Q) LDA xObjectHi,Y STA I,X JMP weak2 \ Jump back to weak2 to move on to X = 0Name: GetAlienWeakSpot [Show more] Type: Subroutine Category: The Theme Summary: Calculate the coordinates of an alien's weak spot Deep dive: Detecting alien hitsContext: See this subroutine on its own page References: This subroutine is called as follows: * CheckIfAlienIsHit (Part 2 of 2) calls GetAlienWeakSpot

The alien's weak spot is calculated as follows: * x-coordinate = (xObjectHi xObjectLo) + (5 Q) * y-coordinate = (yObjectHi yObjectLo) * z-coordinate = (zObjectHi zObjectLo) + (5 Q) where Q is This is called STIP in the original source code. Arguments: Y The object ID of the alien (30 to 33) Q The low byte of the amount to add Returns: (I+2 W+2) The x-coordinate of the alien's weak spot (I+1 W+1) The y-coordinate of the alien's weak spot (I W) The z-coordinate of the alien's weak spot.CheckAlienWeakSpot LDX #2 \ Set a counter in X to iterate through the three axes .spot1 TYA \ Point Y to the next axis (xObject, yObject, zObject) CLC \ ADC #nextAxis \ The routine is called is with Y = 216, 228 or 230, so TAY \ this bumps X onto 256, 268 or 260, which gets \ truncated in the 8-bit register to 0, 12 or 14, so \ this moves X through the xObject, yObject and zObject \ values for object 0 (when called with X = 216), object \ 12 (when called with X = 228) or object 14 (when \ called with X = 230) \ \ Objects 12 and 14 are the trailing ends of the two \ bullet trails, so the following checks whether the \ trailing end is within the weak spot, rather than the \ bullets themselves LDA xObjectLo,Y \ Set (A T) = (xObjectHi xObjectLo) - (I+X W+X) SEC \ SBC W,X \ starting with the low bytes STA T LDA xObjectHi,Y \ And then the high bytes SBC I,X \ So we now have: \ \ (A T) = xObject - (I W) \ \ where xObject is the coordinate of the bullet, and \ (I W) is the coordinate of the alien's weak spot \ \ In other words, (A T) is the distance between the \ bullet and the alien's weak spot BNE spot2 \ If the high byte in A is non-zero, then the bullet is \ too far from the weak spot to do any damage, so jump \ to spot2 to return from the subroutine LDA T \ If the low byte in T is >= the corresponding value in CMP PP,X \ PP, QQ or RR (for the z, y and x-axes respectively), BCS spot2 \ then the bullet is too far away from the weak spot to \ to do any damage, so jump to spot2 to return from the \ subroutine DEX \ Otherwise the bullet is close enough to the weak spot \ to cause damage in this axis, so decrement X to point \ to the next axis BPL spot1 \ Loop back until we have checked all three axes \ If we get here then the bullet is close enough to the \ weak spot in all three axes, so we have a hit LDA objectId \ Store the object ID of the hit alien in hitObjectId STA hitObjectId TSX \ Remove two bytes from the top of the stack, so the INX \ RTS below returns us to the JSR CheckIfAlienIsHit in INX \ part 6 of the main loop TXS LDA #27 \ Set the hitTimer to 27 to start the explosion counter STA hitTimer .spot2 RTS \ Return from the subroutineName: CheckAlienWeakSpot [Show more] Type: Subroutine Category: The Theme Summary: Check whether an object is close enough to an alien's weak spot to be hitting it Deep dive: Detecting alien hitsContext: See this subroutine on its own page References: This subroutine is called as follows: * CheckIfAlienIsHit (Part 2 of 2) calls CheckAlienWeakSpot

If the object is hitting the alien's weak spot, the routine returns to the caller of the caller - in other words, it returns from the original call to the CheckIfAlienIsHit routine, in part 6 of the main loop. This is called HITS in the original source code. Arguments: Y The bullet trail to be calculated: * 216 = object 0, which we set to points along the bullet trail at 1/32 intervals * 228 = the trailing end of the left bullet trail * 230 = the trailing end of the right bullet trail.GetTrailVectorStep LDA #0 \ Set P = 0, to feed bits into the top bit of (A V R) in STA P \ the final stage below STA R \ Set R = 0, for use in constructing (A V R) TXA \ Point X to the next axis (xObject, yObject, zObject) CLC \ ADC #nextAxis \ The first time that the routine is called is with TAX \ X = 228 or 230, so this bumps X onto 268 or 260, which \ gets truncated in the 8-bit register to 12 or 14, so \ this moves X through the xObject, yObject and zObject \ values for object 12 (when first called with X = 228) \ or object 14 (when first called with X = 230) \ We now subtract the following object coordinates: \ \ * If first called with X = 228, we calculate object \ 13 - object 12 (i.e. the left bullet minus the \ back end of the left bullet trail) \ \ * If first called with X = 230, we calculate object \ 15 - object 13 (i.e. the right bullet minus the \ back end of the right bullet trail) \ \ In each case we end up with the vector of the relevant \ bullet trail for axis Y in (A V) LDA xObjectLo+1,X \ Set (A V) = xObject+1 - xObject SEC \ SBC xObjectLo,X \ starting with the low bytes STA V LDA xObjectHi+1,X \ And then the high bytes SBC xObjectHi,X BPL bulv1 \ If (A V) is negative, decrement P to &FF, so it is DEC P \ full of bits of the correct polarity to shift into bit \ 7 of A in (A V R) .bulv1 \ We now have the number (A V 0) in (A V R), plus a byte \ P made up of the correct sign bits, so the final stage \ is to divide this by 32 by shifting right LDY #4 \ We want to shift the result right by five places to \ divide the result by 32, so set a shift counter in Y .bulv2 LSR P \ Shift (A V R) right by one place, shifting one of the ROR A \ sign bits from P into bit 7 of of A ROR V ROR R DEY \ Decrement the shift counter BPL bulv2 \ Loop back until we have done all five shifts, so we \ now have: \ \ (A V R) = (A V R) / 32 RTS \ Return from the subroutineName: GetTrailVectorStep [Show more] Type: Subroutine Category: The Theme Summary: Calculate 1/32 of the vector for a bullet trail Deep dive: Detecting alien hitsContext: See this subroutine on its own page References: This subroutine is called as follows: * CheckIfAlienIsHit (Part 2 of 2) calls GetTrailVectorStep

Calculates one axis of the vector for the 1/32 of the specified bullet trail and returns it in (A V R). This is called ADIF in the original source code. Arguments: X The bullet trail to be calculated: * 228 = left bullet trail * 230 = right bullet trail Returns: X Updated to point to the next axis, so the first call will return the x-axis of the vector, the second the y-axis, and the third the z-axis (A V R) One axis of the vector for the specified bullet trail, as a signed 24-bit number and divided by 32.ShowUpsideDownBar LDA zRotationHi \ If bit 7 of zRotationHi is clear, skip the following BPL upsi1 \ instruction EOR #%11000000 \ Flip bits 6 and 7 of A, making bit 7 clear and bit 6 \ flipped .upsi1 \ When we get here, we know bit 7 of A is clear AND #%11000000 \ Extract bits 6 and 7 of A BEQ upsi2 \ If bit 6 of A is clear (we already know bit 7 is \ clear), then the plane is the correct way up, so skip \ the following instruction \ We get here if one of the following is true: \ \ * Bit 7 of zRotationHi is clear and bit 6 is set \ * Bit 7 of zRotationHi is set and bit 6 is clear \ \ either of which means the plane is upside down LDA #%00001110 \ Bit 6 is set, so set A to a three-pixel horizontal \ line to show in the indicator .upsi2 STA row25_block13_1 \ Set the line at the bottom of the artificial horizon \ indicator to the pixel pattern in A (0 if the plane is \ the right way up, %00001110 if it is upside down) RTS \ Return from the subroutineName: ShowUpsideDownBar [Show more] Type: Subroutine Category: Dashboard Summary: Show or hide the upside down bar in the artificial horizon indicatorContext: See this subroutine on its own page References: This subroutine is called as follows: * ApplyFlightModel (Part 6 of 7) calls ShowUpsideDownBar

This routine shows the upside down bar in the artificial horizon if bit 6 and bit 7 of zRotationHi are different. This is how it works. The value of zRotationHi contains the following: * 0 to 63 (bit 6 clear, bit 7 clear) * 64 to 127 (bit 6 set, bit 7 clear) * 128 to 191 (bit 6 clear, bit 7 set) * 192 to 255 (bit 6 set, bit 7 set) The zRotation angle determines how the plane is rotated around the z-axis. The z-axis points into the screen, so rotating the plane around this axis is the same as rolling the plane. A zRotation of 0 is a horizontal plane, and as the angle increases, the plane rolls to the right. If we consider the plane doing a full 360-degree roll, then for the first quarter the plane is still upright, for the second and third quarters it is upside down, and then for the final quarter it is upright again. You will notice that bits 6 and 7 differ in the second and third quarters in the list above, so if bits 6 and 7 of zRotationHi are different, then the plane is upside down, and we should show a bar at the bottom of the artificial horizon indicator..ProcessRunwayLine LDA objectStatus+1 \ Fetch the status byte for object 1, the runway object BEQ prun3 \ If object 1's status byte is zero, then we have not \ yet calculated the runway object's coordinates and \ visibility, so jump to prun3 to do this BMI prun1 \ If bit 7 of object 1's status byte is set, then we \ have already decided that the runway object is \ visible, so jump to prun1 to set the line's visibility \ accordingly JMP prun9 \ If we get here then we have already decided that the \ runway object is hidden, so jump to prun9 to set the \ line's visibility as hidden .prun1 LDA lineId \ If lineId < 5, then the line ID is in the range 1 to CMP #5 \ 4, so it's part of the runway outline, so jump to BCC prun2 \ prun2 to return from the subroutine as we always show \ the outline when the runway is visible LDA showRunwayDashes \ The line we are checking is one of the dashes down the STA showLine \ middle of the runway, so set the line's visibility to \ the value of showRunwayDashes, which contains the \ visibility of the runway dashes .prun2 RTS \ Return from the subroutineName: ProcessRunwayLine (Part 1 of 5) [Show more] Type: Subroutine Category: Visibility Summary: Calculate coordinates and visibility for a runway line Deep dive: Visibility checksContext: See this subroutine on its own page References: This subroutine is called as follows: * ProcessLine (Part 2 of 7) calls ProcessRunwayLine

Arguments: lineId The line ID to process (1 to 11): * 1 to 4 are the runway outline * 5 to 11 are the dashes down the middle of the runway Returns: showLine Whether this line is visible: * 0 = line is visible * Non-zero = line is not visible.prun3 LDA #0 \ Set the matrix number so the call to SetPointCoords STA matrixNumber \ and SetObjPointCoords use matrix 1 in the calculation, \ which will rotate the point by the plane's pitch, roll \ and yaw angles, transforming it from the outside \ world's frame of reference to the plane's frame of \ reference LDA #1 \ Set objectId = 1 to denote the runway object STA objectId JSR SetObjectCoords \ Calculate the runway object's coordinates and \ visibility, updating the object's status byte with the \ results and setting point 217 to the object's anchor \ point BPL prun9 \ If bit 7 of the runway object's updated status byte is \ clear, then the runway object is not visible, so jump \ to prun9 to set the line's visibility accordingly \ The runway object is visible, so now we work out the \ coordinates of the runway outline, which is a \ rectangle whose corners are points 1 to 4 LDA #0 \ We start by zeroing the (xTemp1 yTemp1 zTemp1) vector, \ which is stored in six bytes to give us three 16-bit \ coordinate values (from xTemp1Lo to zTemp1Hi), so \ first we set A = 0 to use as our zero LDX #5 \ Set a counter in X to count the six bytes .prun4 STA xTemp1Lo,X \ Zero the X-th byte of the six-byte coordinate block \ between xTemp1Lo and zTemp1Hi DEX \ Decrement the loop counter BPL prun4 \ Loop back until we have zeroed all six bytes \ We now calculate the coordinates for points 1 to 4, \ starting with point 1 LDY #217 \ Set Y so the call to AddTempToPoint adds point 217 to \ the xTemp1 vector STY objectAnchorPoint \ The anchor point of the runway is point 217, so set \ objectAnchorPoint to this point for the call to \ SetObjPointCoords LDX #1 \ Set X so the call to AddTempToPoint stores the result \ in point ID 1 JSR AddTempToPoint \ Add point 217 to the (xTemp1 yTemp1 zTemp1) point and \ store the result in (xPoint, yPoint, zPoint) for \ point 1 \ \ This simply sets point ID 1 to the object's anchor \ point, as we just zeroed (xTemp1 yTemp1 zTemp1), so \ point1 of the runway outline is now calculated LDA #2 \ Calculate the coordinates for object point 2 with STA GG \ anchor point 217, so point 2 is now calculated JSR SetObjPointCoords \ \ This also sets (xTemp1 yTemp1 zTemp1) to the vector \ from the anchor point to point 2, which we now copy \ into xTemp2 by copying the following values: \ \ xTemp1Lo, yTemp1Lo, zTemp1Lo \ xTemp1Hi, yTemp1Hi, zTemp1Hi \ \ into the following locations: \ \ xTemp2Hi, yTemp2Hi, zTemp2Hi \ xTemp2Top, yTemp2Top, zTemp2Top \ \ so (xTemp2Top xTemp2Hi) etc. contain the vector from \ the anchor point to the point 2 LDX #5 \ Set a counter for six bytes .prun5 LDA xTemp1Lo,X \ Copy the X-th byte of xTemp1Lo to the X-th byte of STA xTemp2Hi,X \ xTemp2Hi DEX \ Decrement the loop counter BPL prun5 \ Loop back until we have copied all six bytes \ By now we have coordinates for points 1 and 2, plus \ the vector from the anchor point to point 2 (which \ is the same as the vector from point 1 to point 2, \ as point 1 is the runway's anchor point) LDA #4 \ Calculate the coordinates for object point 4 with STA GG \ anchor point 217, so point 4 is now calculated JSR SetObjPointCoords \ \ This also sets (xTemp1 yTemp1 zTemp1) to the vector \ from the anchor point (point 1) to point 4 \ By now we have coordinates for points 1, 2 and 4, and \ we could just call SetObjPointCoords for point 3, but \ we can save a bit of time as the runway outline is a \ rectangle, so we already have all the data we need to \ calculate the coordinates for point 3 \ \ The runway outline looks like this: \ \ 2 3 \ +-------+ \ | : | \ | : | \ | : | \ | : | \ | : | \ +-------+ \ 1 4 \ \ We know the vector from point 1 to point 4 - it's in \ the (xTemp1 yTemp1 zTemp1) vector - and we know the \ coordinates of point 2, so we can calculate the \ coordinates of point 3 by simply adding the vector to \ the coordinates of point 2, which is what we do next LDY #2 \ Set point 3's coordinates to point 2's coordinates + LDX #3 \ (xTemp1 yTemp1 zTemp1), so point 3 is now calculated JSR AddTempToPoint LDA showLine \ If showLine is zero, then all four coordinates fit BEQ prun6 \ within the boundaries of the world, so jump to prun6 \ to keep going LDA #%01000000 \ At least one of the calculations above overflowed, so STA objectStatus+1 \ at leat one coordinate is outside the boundaries of \ the world, so set bit 6 of the status byte for the \ runway object to indicate that we have now calculated \ the runway object's coordinates and visibility, and \ clear bit 7 to indicate that the runway is not visible RTS \ Return from the subroutine .prun6 LDX #4 \ Set the status byte for points 1 to 4 to indicate JSR SetPointVisibility \ that their coordinates and visibility have been \ calculatedName: ProcessRunwayLine (Part 2 of 5) [Show more] Type: Subroutine Category: Visibility Summary: Calculate coordinates and visibility for the runway outlineLDY #1 \ Set Y = 1 so we check point ID 1 in the call to \ CheckLineDistance (point ID 1 is the anchor point of \ the runway) LDX #10 \ Set X = 10 so we check the distance against that for \ line ID 10, which is one of the dashes in the middle \ of the runway .prun7 JSR CheckLineDistance \ Check whether point Y on line X is within the visible STA showLine \ distance for the line and store the result in showLine BNE prun8 \ If the point is too far away to be visible, then all \ the dashes are too far away to be seen, so jump to \ prun8 to return the relevant result CPY #3 \ If Y = 3, then we have checked both point 1 and 3 and BEQ prun12 \ both are close enough to be visible, so jump to prun12 \ to finish off the processing LDY #3 \ Otherwise set Y = 3 and jump back prun7 to check point BNE prun7 \ 3 as well (point 3 is the corner of the runway outline \ opposite the anchor point) .prun8 LDA #%10000000 \ Set showRunwayDashes to indicate that the dashes down STA showRunwayDashes \ the middle of the runway are not visible LDA lineId \ If lineId < 5, then the line ID is in the range 1 to CMP #5 \ 4, so it's part of the runway outline, so jump to BCC prun10 \ prun10 to return the result that the line is visible, \ as we always show the outline when the runway is \ visible, even when the runway dashes are hidden .prun9 LDA #%10000000 \ Set A to indicate the line is not visible, and jump to BNE prun11 \ prun11 to return this as the value of showLine (this \ BNE is effectively a JMP as A is never zero) .prun10 LDA #0 \ Set A to indicate the line is visible, so we can \ return this as the value of showLine .prun11 STA showLine \ Set the line's visibility to the value in A, to return \ as our result RTS \ Return from the subroutineName: ProcessRunwayLine (Part 3 of 5) [Show more] Type: Subroutine Category: Visibility Summary: Calculate visibility for the runway dashes.prun12 \ By the time we get here, (xTemp1 yTemp1 zTemp1) \ contains the vector from the anchor point (point 1) to \ point 4, which is the vector from one side of the \ runway to the other \ \ We now want to halve the (xTemp1 yTemp1 zTemp1) \ vector, to give the vector from one side of the runway \ to the line of dashes down the middle \ \ As a reminder, the runway outline looks like this: \ \ 2 3 \ +-------+ \ | : | \ | : | \ | : | \ | : | \ | : | \ +-------+ \ 1 4 \ \ so we now calculate (xTemp1 yTemp1 zTemp1) to be the \ vector from the left edge of the runway to the dashes \ in the middle LDX #2 \ Set a counter in X to work through the three axes of \ the (xTemp1 yTemp1 zTemp1) vector (the comments below \ cover the iteration for the x-axis) .prun13 CLC \ Clear the C flag, to use when (xTemp1Hi xTemp1Lo) is \ positive LDA xTemp1Hi,X \ If xTemp1Hi is positive, skip the next instruction BPL prun14 SEC \ Set the C flag, to use when (xTemp1Hi xTemp1Lo) is \ negative .prun14 ROR A \ Shift (xTemp1Hi xTemp1Lo) to the right by one place, STA xTemp1Hi,X \ inserting the C flag into the top bit of xTemp1Hi, LDA xTemp1Lo,X \ which ensures that we retain the same sign ROR A STA xTemp1Lo,X DEX \ Decrement the loop counter to move to the next axis BPL prun13 \ Loop back until we have halved xTemp1, yTemp1 and \ zTemp1 \ (xTemp1 yTemp1 zTemp1) now contains the vector from \ one side of the runway to the line of dashes down the \ middle LDY #2 \ Set point 21's coordinates to point 2's coordinates + LDX #21 \ (xTemp1 yTemp1 zTemp1) JSR AddTempToPoint LDY #1 \ Set point 5's coordinates to point 1's coordinates + LDX #5 \ (xTemp1 yTemp1 zTemp1) JSR AddTempToPoint \ So we've now calculated points 5 and 21 as follows: \ \ 2 21 3 \ +-------+ \ | : | \ | : | \ | : | \ | : | \ | : | \ +-------+ \ 1 5 4 \ \ Next, we make a backup of the (xTemp1 yTemp1 zTemp1) \ vector in (xDashesVector yDashesVector zDashesVector) LDX #5 \ Set a counter for six bytes .prun15 LDA xTemp1Lo,X \ Copy the X-th byte of xTemp1Lo to the X-th byte of STA xDashesVectorLo,X \ xDashesVectorLo DEX \ Decrement the loop counter BPL prun15 \ Loop back until we have copied all six bytes \ So (xDashesVector yDashesVector zDashesVector) now \ contains the vector from one side of the runway to the \ line of dashes down the middle \ We now zero variables T, U, V, W, G and H LDX #5 \ Set a counter for six bytes LDA #0 \ Set A = 0 so we can zero the variables .prun16 STA T,X \ Zero the X-th byte from T DEX \ Decrement the loop counter BPL prun16 \ Loop back until we have zeroed all six bytes \ In part 2 above, we set (xTemp2Top xTemp2Hi) etc. to \ the vector from the anchor point (i.e. point 1) to \ point 2 LDX #2 \ Set a counter in X to work through the three axes (the \ comments below cover the iteration for the x-axis) \ For each axis in turn, we .prun17 LDA #0 \ Set R = 0 STA R LDA xTemp2Top,X \ Set A = xTemp2Top BPL prun18 \ If xTemp2Top is positive, skip the following \ instruction DEC R \ Decrement R to %11111111 \ So by this point, R contains the correct bits to \ rotate into bit 7 of A to retain the sign of A .prun18 \ Set (xTemp1Hi A T) = (xTemp2Top xTemp2Hi 0) / 2 \ \ keeping the sign intact by feeding in bits from R LSR R \ We start with the top byte ROR A STA xTemp1Hi,X LDA xTemp2Hi,X \ Then the high byte ROR A ROR T,X \ And then the low byte LDY #2 \ We now shift right by three places, so set a counter \ in Y .prun19 LSR R \ Set (xTemp1Hi A T) = (xTemp1Hi A T) / 2 ROR xTemp1Hi,X \ ROR A \ keeping the sign intact by feeding in bits from R ROR T,X DEY \ Decrement the loop counter BPL prun19 \ Loop back until we have shifted right by three places \ In all, the above does the following: \ \ (xTemp1Hi A T) = (xTemp2Top xTemp2Hi 0) / 16 \ \ while retaining the sign STA xTemp1Lo,X \ Set (xTemp1Hi xTemp1Lo T) = (xTemp1Hi A T) \ = (xTemp2Top xTemp2Hi 0) / 16 DEX \ Decrement the loop counter to move to the next axis BPL prun17 \ Loop back until we have processed all three axes \ So we have now calculated the vector from point 1 to \ point 2, divided by 16, with the result stored in the \ xTemp1 vector and the variables T, U and V used for \ the lowest bytes, like this: \ \ x-coordinate = (xTemp1Hi xTemp1Lo T) \ y-coordinate = (yTemp1Hi yTemp1Lo U) \ z-coordinate = (zTemp1Hi zTemp1Lo V) \ \ In other words, the xTemp1/T/U/V vector contains 1/16 \ of the full vector between points 5 and 21 LDX #LO(xTemp2Lo) \ Set X so the call to CopyPointToWork copies the \ coordinates to (xTemp2, yTemp2, zTemp2) LDY #5 \ Set Y so the call to CopyPointToWork copies the \ coordinates from point 5 JSR CopyPointToWork \ Copy the coordinates from point 5 to \ (xTemp2, yTemp2, zTemp2) \ So (xTemp2, yTemp2, zTemp2) now contains the \ coordinates of point 5 \ We now calculate the start and end points for the \ dashes in the middle of the runway by starting at \ point 5, and moving up the middle line in steps of \ 1/16 of the distance between points 5 and 21 .prun20 LDX #2 \ Set a counter in X to work through the three axes (the \ comments below cover the iteration for the x-axis) .prun21 CLC \ Set (xTemp2Hi xTemp2Lo W) += (xTemp1Hi xTemp1Lo T) LDA W,X \ ADC T,X \ starting with the lowest bytes STA W,X LDA xTemp2Lo,X \ Then the middle bytes ADC xTemp1Lo,X STA xTemp2Lo,X LDA xTemp2Hi,X \ And then the highest bytes ADC xTemp1Hi,X STA xTemp2Hi,X DEX \ Decrement the loop counter to move to the next axis BPL prun21 \ Loop back until we have added all three axes \ On the first iteration through this code, the full \ (xTemp2Hi xTemp2Lo W) vector contains a point 1/16 \ of the way from point 5 to point 21 LDX #LO(xTemp2Lo) \ Set X so the call to CopyWorkToPoint copies the \ coordinates from (xTemp2, yTemp2, zTemp2) INY \ Increment Y so the call to CopyPointToWork copies the \ coordinates from the next point along the dash line \ (which will be point 6 on the first iteration through \ this code, then point 7, and so on) JSR CopyWorkToPoint \ Copy the coordinates from (xTemp2, yTemp2, zTemp2) \ to point Y, the next point along the dash line CPY #19 \ Loop back to prun20 to move another 1/16 along the BNE prun20 \ dash line, until we have done point 19, meaning we \ have set the coordinates for points 6 through 19 \ (i.e. we have added 14 points, two for each of the \ seven dashes in the middle of the runway) LDX #19 \ Set the status byte for points 1 to 19 to indicate JSR SetPointVisibility \ that their coordinates and visibility have been \ calculatedName: ProcessRunwayLine (Part 4 of 5) [Show more] Type: Subroutine Category: Visibility Summary: Construct the dashes down the middle of the runway\ The final step is to check whether the runway appears \ both in front of us and behind us (which will happen \ when we are sitting on the runway, for example, or \ during the final approach when trying to land) \ \ If it is, then we want to clip the part of the runway \ outline that's behind us, as close to the screen as \ possible (though we still want the runway to go behind \ us a bit, so clipping to the nearest coordinate behind \ the screen is the best approach) \ \ We start by restoring the vector that we stored in \ (xDashesVector yDashesVector zDashesVector) back to \ (xTemp1 yTemp1 zTemp1), which is the vector from one \ side of the runway to the line of dashes down the \ middle LDX #5 \ Set a counter for six bytes .prun22 LDA xDashesVectorLo,X \ Copy the X-th byte of xDashesVectorLo to the X-th byte STA xTemp1Lo,X \ of xTemp1Lo DEX \ Decrement the loop counter BPL prun22 \ Loop back until we have copied all six bytes \ So (xTemp1 yTemp1 zTemp1) is once again the vector \ from one side of the runway to the line of dashes down \ the middle \ We now work our way along the dash line, checking the \ coordinates of the points we just added to see if the \ sign of the z-coordinate changes between any of the \ points (which will indicate that the runway is both in \ front of us and behind us) LDA zPointHi+6 \ Set P to the high byte of the z-coordinate for point 6 STA P \ (which contains the sign of the coordinate) LDY #6 \ We now loop through the points we just calculated for \ the dashes, so we set a counter in Y to loop from 6 to \ 19 .prun23 LDA zPointHi,Y \ Set A = z-coordinate for point Y EOR P EOR P BMI prun24 \ If A has a set bit 7, then the z-coordinate for point \ Y has a different sign to the z-coordinate for point \ 6, so jump to prun24 as the runway is both behind us \ and in front of us INY \ Increment Y to point to the next point in the dash \ line CPY #20 \ Loop back until we have worked our way through all the BCC prun23 \ points that we just calculated BCS prun28 \ If we get here then all the points have the same sign \ z-coordinate as point 6, so jump to prun28 to return \ from the subroutine (this BCS is effectively a JMP as \ we just passed through the BCC above) .prun24 \ If we get here, then point Y has a different sign in \ its z-coordinate to point 6, so the runway is both \ behind us and in front of us \ \ We now want to find out which part is in front of us \ and which is behind \ \ We do this by working out which part of the dash line \ is in front of us and which is behind, using the \ following: \ \ 2 21 3 \ +-------+ \ | : | <- Dashes end at point 19 \ | : | \ | : | \ | : | \ | : | <- Dashes start at point 6 \ +-------+ \ 1 5 4 \ \ If the start of the dash line is behind us (i.e. the \ point 6 end), then that means we need to clip points 1 \ and 4 as close as possible to the screen, while if the \ end of the dash line is behind us (i.e. the point 19 \ end), then we need to clip points 2 and 3 as close as \ possible to the screen LDA P \ If point 6 has a positive z-coordinate, jump to prun25 BPL prun25 \ If we get here then point 6 has a negative \ z-coordinate, so point Y must have a positive \ z-coordinate, and the point before Y must have a \ negative z-coordinate \ \ In other words, the dashes start behind us, and pass \ in front of us at point Y, which is in front of us, so \ the point before Y is the last point behind us \ \ To clip the runway, we therefore need to move points 1 \ and 4 DEY \ Decrement Y to point to the last point in the sequence \ we added that has a negative z-coordinate LDA #1 \ Set Q so the second call to AddTempToPoint moves point STA Q \ 1 LDX #4 \ Set X so the first call to AddTempToPoint moves point \ 4 BNE prun26 \ Jump to prun26 to call AddTempToPoint (this BNE is \ effectively a JMP as X is never zero) .prun25 \ If we get here then point 6 has a positive \ z-coordinate, so point Y must have a negative \ z-coordinate, and the point before Y must have a \ positive z-coordinate \ \ In other words, the dashes start in front of us, and \ go behind us at point Y, which is the first point \ behind us \ \ To clip the runway, we therefore need to move points 2 \ and 3 LDA #2 \ Set Q so the second call to AddTempToPoint moves point STA Q \ 2 LDX #3 \ Set X so the first call to AddTempToPoint moves point \ 3 .prun26 \ By the time we get here, Y is the point with the \ negative z-coordinate that's nearest to the screen \ (i.e. nearest to a z-coordinate of 0) \ \ We now work out the new corner coordinates for the \ end of the runway that's behind us, by taking point Y \ and: \ \ * Adding (xTemp1 yTemp1 zTemp1) to point Y to get \ one corner (i.e. corner 3 or 4) \ \ * Subtracting (xTemp1 yTemp1 zTemp1) from point Y to \ get the other corner (i.e. corner 1 or 2) \ \ We start with the addition JSR AddTempToPoint \ Add point Y to the (xTemp1 yTemp1 zTemp1) vector and \ store the result in (xPoint, yPoint, zPoint) for \ point X \ We now negate the (xTemp1 yTemp1 zTemp1) vector so we \ can do the subtraction LDX #2 \ Set a counter in X to work through the three axes of \ the (xTemp1 yTemp1 zTemp1) vector (the comments below \ cover the iteration for the x-axis) .prun27 LDA #0 \ Negate (xTemp1Hi xTemp1Lo), starting with the low SEC \ bytes SBC xTemp1Lo,X STA xTemp1Lo,X LDA #0 \ And then the high bytes SBC xTemp1Hi,X STA xTemp1Hi,X DEX \ Decrement the loop counter to move to the next axis BPL prun27 \ Loop back until we have negated xTemp1, yTemp1 and \ zTemp1 \ The xTemp1 yTemp1 zTemp1) vector is now negated, so we \ can add it with AddTempToPoint to do the subtraction \ we want LDX Q \ Set X so the call to AddTempToPoint stores the result \ in point Q JSR AddTempToPoint \ Add point Y to the (xTemp1 yTemp1 zTemp1) vector and \ store the result in (xPoint, yPoint, zPoint) for \ point Q .prun28 RTS \ Return from the subroutineName: ProcessRunwayLine (Part 5 of 5) [Show more] Type: Subroutine Category: Visibility Summary: Clip any portion of the runway outline that's behind us.SetPointVisibility LDA #%10000000 \ Set bit 7 of point X's status byte, to indicate that ORA pointStatus,X \ the point's coordinates and visibility have been STA pointStatus,X \ calculated DEX \ Decrement X to point to the previous point BNE SetPointVisibility \ Loop back until we have set the status byte for points \ X down to 1, i.e. points 1 to X RTS \ Return from the subroutineName: SetPointVisibility [Show more] Type: Subroutine Category: 3D geometry Summary: Set the status byte for multiple points to indicate that their coordinates and visibility have been calculatedContext: See this subroutine on its own page References: This subroutine is called as follows: * ProcessRunwayLine (Part 2 of 5) calls SetPointVisibility * ProcessRunwayLine (Part 4 of 5) calls SetPointVisibility

Arguments: X The ID of the point to update.DrawHalfHorizon LDX #30 \ Set X = 30, to use as the point ID for point 30, which \ is the start of the horizon line LDY #32 \ Set Y = 32, to use as the point ID for point 32 LDA xPointHi,X \ Set (T A) = x_30 STA T LDA xPointLo,X ASL A \ Set (T A) = (T A) * 2 ROL T \ = x_30 * 2 SEC \ Set x_32 = (T A) - x_31 SBC xPointLo+31 \ = (x_30 * 2) - x_31 STA xPointLo,Y LDA T SBC xPointHi+31 STA xPointHi,Y LDA yPointHi,X \ Set (T A) = y_30 STA T LDA yPointLo,X ASL A \ Set (T A) = (T A) * 2 ROL T \ = y_30 * 2 SEC \ Set y_32 = (T A) - y_31 SBC yPointLo+31 \ = (y_30 * 2) - y_31 STA yPointLo,Y LDA T SBC yPointHi+31 STA yPointHi,Y \ So now we have: \ \ x_32 = (x_30 * 2) - x_31 \ y_32 = (y_30 * 2) - y_31 \ \ which is what we want STX L \ Set L to point 30, so we draw the line from this start \ point STY M \ Set L to point 32, so we draw the line to this end \ point JSR DrawClippedHorizon \ Draw the line from point 30 to 32, which is the first \ half of the horizon line RTS \ Return from the subroutineName: DrawHalfHorizon [Show more] Type: Subroutine Category: Drawing lines Summary: Draw half of the horizon lineContext: See this subroutine on its own page References: This subroutine is called as follows: * DrawCanopyView calls DrawHalfHorizon

The horizon line is line ID 0, which is the line from point 31 to point 30. This line is only half the actual horizon, so this routine calculates the other half of the horizon into point 30, and draws the line from point 30 to point 32. Point 30 is therefore the mid-point of the two-segment horizon line, which goes point 31 to point 30 to point 32. The calculation looks like this: + (x_32, y_32) .Â´ | .Â´ | h .Â´ | (x_30, y_30) .Â´_______| .Â´| w .Â´ | .Â´ | h .Â´ | (x_31, y_31) Â´--------+ w We already know the coordinates of points 30 and 31, and we want to calculate point 32. It's easy to calculate w and h in the bottom triangle: w = x_30 - x_31 h = y_30 - y_31 so to extend the line to point 32, we simply add w and h to the coordinates for point 30, like this: x_32 = x_30 + w = x_30 + x_30 - x_31 = (x_30 * 2) - x_31 y_32 = y_30 + h = y_30 + y_30 - y_31 = (y_30 * 2) - y_31 This routine draws the horizon from point 30 to point 32, while the other half from point 31 to 30 is drawn along with all the other lines in DrawCanopyView..FillUpFuelTank LDA mainLoopCounter \ If the mainLoopCounter is a multiple of 4, jump to AND #3 \ fuel1 to add some fuel to the tank (so we do this BEQ fuel1 \ every four iterations of the main loop) RTS \ Return from the subroutine .fuel1 TAX \ We got here because A = 0, so this sets X = 0 LDA fuelLevel \ If fuelLevel >= 65, then the tank is already full, so CMP #65 \ jump to fuel2 to skip filling it up any more BCS fuel2 INC fuelLevel \ fuelLevel < 65, so increment the fuel level by 1, to \ fill up the fuel tank by 1/65th of a full tank JMP DrawFuelPixel \ Draw an extra pixel at the top of the fuel level, so \ the fuel gauge goes up by one pixel, returning from \ the subroutine using a tail call .fuel2 \ If we get here then the fuel tank is full STX landingStatus \ Set landingStatus = 0 to disable all the landing tasks \ in the main loop, including filling up with fuel RTS \ Return from the subroutineName: FillUpFuelTank [Show more] Type: Subroutine Category: Flight model Summary: Fill up the fuel tank by 1/65th of a full tank every four iterations of the main loop Deep dive: Scheduling tasks in the main loopContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 9 of 15) calls FillUpFuelTank.UpdateFuelGauge LDA mainLoopCounter \ If the mainLoopCounter is a multiple of 16, jump to AND #15 \ upfu1 to update the fuel gauge BEQ upfu1 RTS \ Return from the subroutine .upfu1 LDX #128 \ Set X = 128, so we erase a pixel from the top of the \ fuel gauge in DrawFuelPixel below, if there is one LDA fuelLevel \ Set A = fuelLevel \ Fall through into DrawFuelPixel to erase a pixel from \ the fuel gauge at the top of the gauge if there is \ one, which will set the amount shown on the fuel gauge \ to fuelLevelName: UpdateFuelGauge [Show more] Type: Subroutine Category: Dashboard Summary: Update the fuel gauge every 16 iterations of the main loop Deep dive: Scheduling tasks in the main loopContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 11 of 15) calls UpdateFuelGauge * ResetVariables calls UpdateFuelGauge.DrawFuelPixel STX N \ Store the drawing mode in N CLC \ Set J = A + 184 ADC #184 \ STA J \ so the line's start y-coordinate is between: \ \ * 184, or -72, for A = 0 (empty tank) \ * 249, or -7, for A = 65 (full tank) \ \ As y-coordinates that we send to DrawVectorLine are \ relative to the top of the dashboard, this means we \ draw a pixel on the vertical line from 72 pixels below \ the top of the dashboard (i.e. the bottom of the fuel \ gauge at screen y-coordinate 231), up to 7 pixels \ below the top of the dashboard (i.e. the top of the \ fuel gauge at screen y-coordinate 166) LDA #2 \ Set I = 2, the x-coordinate of the fuel gauge line STA I LDA #1 \ Set T = 1, so line is 1 pixel wide STA T STA U \ Set U = 1, so the line is 1 pixel high LDA #0 \ Set V = 0 so the line is drawn in a positive direction STA V \ for both axes JSR DrawVectorLine \ Draw/erase a pixel at (2, A + 184) RTS \ Return from the subroutineName: DrawFuelPixel [Show more] Type: Subroutine Category: Dashboard Summary: Draw or erase a pixel on the fuel gauge on the dashboardContext: See this subroutine on its own page References: This subroutine is called as follows: * FillUpFuelTank calls DrawFuelPixel

Arguments: A The fuel gauge pixel to draw or erase (0 to 65) X Drawing mode: * Bit 7 clear = draw (using OR logic) * Bit 7 set = erase (using EOR logic).ProcessVolumeKeys LDX #&DB \ Scan the keyboard to see if "7" is being pressed JSR ScanKeyboard BEQ volk1 \ If "7" is being pressed, jump to volk1 LDX #&EA \ Scan the keyboard to see if "8" is being pressed JSR ScanKeyboard BNE volk4 \ If "8" is not being pressed, jump to volk4 to return \ from the subroutine LDA #255 \ "8" is being pressed, which is the increase volume BNE volk2 \ key, so set A = 255 = -1 and jump to volk2 .volk1 LDA #1 \ If we get here then "7" is being pressed, which is the \ decrease volume key, so set A = 1 .volk2 \ By this point, A contains 1 if we want to decrease the \ volume, or -1 if we want to increase it, which we can \ now add to the SOUND command's amplitude parameter to \ adjust the volume, as -15 is the loudest volume and 0 \ is the quietest CLC \ Add A to byte #3 of sound #1 (low byte of amplitude) ADC soundData+10 BMI volk3 \ If the result is negative, then jump to volk3 to \ update the volume BNE volk4 \ If the result is non-zero, then we have just reduced \ the volume beyond the quietest setting of 0, so jump \ to volk4 to return from the subroutine without \ changing the volume, as it is already at the quietest \ setting .volk3 CMP #241 \ If A < 241, i.e. A < -15, then we have just increased BCC volk4 \ the volume past the loudest setting of -15, so jump \ to volk4 to return from the subroutine without \ changing the volume, as it is already at the loudest \ setting STA soundData+10 \ The new volume is valid, so update byte #3 of sound #1 \ (low byte of amplitude) with the new volume INC soundData+60 \ Increment byte #5 of sound #7 (low byte of engine \ pitch) to make the engine pitch jump up a bit, so we \ can hear the engine noise changing while adjusting the \ volume (the MakeEngineSound routine will bring it back \ down to the correct pitch) .volk4 RTS \ Return from the subroutineName: ProcessVolumeKeys [Show more] Type: Subroutine Category: Sound Summary: Adjust the volume when the volume keys are pressedContext: See this subroutine on its own page References: This subroutine is called as follows: * MainLoop (Part 9 of 15) calls ProcessVolumeKeys.RetractFlapsIfFast CMP #14 \ First we check the high byte of the current airspeed BCC flap1 \ in A to see if it is less than 14, at which point the \ airspeed is: \ \ (14 0) * 100 / 2368 = 3584 * 100 / 2368 = 151 \ \ So if the airspeed is less than 151mph, we jump to \ flap1 to return from the subroutine without changing \ the flaps LDA flapsStatus \ If the flaps are already retracted, jump to flap1 to BEQ flap1 \ return from the subroutine without changing anything LDA #0 \ The speed is at least 151 mph and the flaps are on, STA flapsStatus \ so we retract them by setting flapsStatus to 0 JSR IndicatorF \ Update the flaps indicator .flap1 RTS \ Return from the subroutineName: RetractFlapsIfFast [Show more] Type: Subroutine Category: Flight model Summary: Retract the flaps if we are going faster than 150 mphContext: See this subroutine on its own page References: This subroutine is called as follows: * ApplyTurnAndThrust (Part 2 of 2) calls RetractFlapsIfFast

Arguments: A The high byte of the current airspeed.xObjectPoint EQUB 13 \ Point ID 0 is (13, 61, 13) with scale factor 2^0 EQUB 0 \ Point ID 1 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 2 is ( 0, 0, 12) with scale factor 2^9 EQUB 0 \ Point ID 3 is ( 0, 0, 0) with scale factor 2^0 EQUB 8 \ Point ID 4 is ( 8, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 5 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 6 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 7 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 8 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 9 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 10 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 11 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 12 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 13 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 14 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 15 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 16 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 17 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 18 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 19 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 20 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 21 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 22 is ( 0, 0, 8) with scale factor 2^4 EQUB 0 \ Point ID 23 is ( 0, 0, 8) with scale factor 2^4 EQUB 10 \ Point ID 24 is (10, 0, 0) with scale factor 2^6 EQUB 0 \ Point ID 25 is ( 0, 1, 0) with scale factor 2^8 EQUB 0 \ Point ID 26 is ( 0, 1, 0) with scale factor 2^8 EQUB 0 \ Point ID 27 is ( 0, 1, 0) with scale factor 2^8 EQUB 0 \ Point ID 28 is ( 0, 1, 0) with scale factor 2^8 EQUB 4 \ Point ID 29 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 30 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 31 is ( 0, 0, 0) with scale factor 2^0 EQUB 4 \ Point ID 32 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 33 is ( 0, 0, 10) with scale factor 2^5 EQUB 0 \ Point ID 34 is ( 0, 0, 12) with scale factor 2^4 EQUB 0 \ Point ID 35 is ( 0, 0, 0) with scale factor 2^0 EQUB 4 \ Point ID 36 is ( 4, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 37 is ( 0, 0, 2) with scale factor 2^8 EQUB 12 \ Point ID 38 is (12, 0, 0) with scale factor 2^4 EQUB 5 \ Point ID 39 is ( 5, 0, 10) with scale factor 2^5 EQUB 8 \ Point ID 40 is ( 8, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 41 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 42 is ( 0, 10, 0) with scale factor 2^3 EQUB 0 \ Point ID 43 is ( 0, 10, 0) with scale factor 2^3 EQUB 0 \ Point ID 44 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 45 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 46 is ( 0, 10, 0) with scale factor 2^3 EQUB 0 \ Point ID 47 is ( 0, 10, 0) with scale factor 2^3 EQUB 12 \ Point ID 48 is (12, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 49 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 50 is ( 0, 0, 8) with scale factor 2^3 EQUB 12 \ Point ID 51 is (12, 0, 0) with scale factor 2^5 EQUB 11 \ Point ID 52 is (11, 0, 0) with scale factor 2^6 EQUB 0 \ Point ID 53 is ( 0, 10, 0) with scale factor 2^4 EQUB 0 \ Point ID 54 is ( 0, 10, 0) with scale factor 2^4 EQUB 0 \ Point ID 55 is ( 0, 10, 0) with scale factor 2^4 EQUB 0 \ Point ID 56 is ( 0, 10, 0) with scale factor 2^4 EQUB 2 \ Point ID 57 is ( 2, 0, 14) with scale factor 2^8 EQUB 1 \ Point ID 58 is ( 1, 0, 11) with scale factor 2^8 EQUB 3 \ Point ID 59 is ( 3, 0, 9) with scale factor 2^9 EQUB 6 \ Point ID 60 is ( 6, 0, 12) with scale factor 2^8 EQUB 10 \ Point ID 61 is (10, 0, 1) with scale factor 2^8 EQUB 3 \ Point ID 62 is ( 3, 0, 9) with scale factor 2^7 EQUB 9 \ Point ID 63 is ( 9, 0, 15) with scale factor 2^6 EQUB 6 \ Point ID 64 is ( 6, 0, 13) with scale factor 2^8 EQUB 13 \ Point ID 65 is (13, 0, 3) with scale factor 2^4 EQUB 0 \ Point ID 66 is ( 0, 0, 14) with scale factor 2^9 EQUB 1 \ Point ID 67 is ( 1, 0, 0) with scale factor 2^8 EQUB 5 \ Point ID 68 is ( 5, 0, 12) with scale factor 2^9 EQUB 1 \ Point ID 69 is ( 1, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 70 is ( 0, 0, 0) with scale factor 2^0 EQUB 9 \ Point ID 71 is ( 9, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 72 is ( 0, 0, 9) with scale factor 2^5 EQUB 8 \ Point ID 73 is ( 8, 0, 6) with scale factor 2^9 EQUB 0 \ Point ID 74 is ( 0, 0, 1) with scale factor 2^8 EQUB 14 \ Point ID 75 is (14, 0, 7) with scale factor 2^9 EQUB 0 \ Point ID 76 is ( 0, 0, 1) with scale factor 2^8 EQUB 13 \ Point ID 77 is (13, 0, 2) with scale factor 2^9 EQUB 5 \ Point ID 78 is ( 5, 0, 13) with scale factor 2^4 EQUB 12 \ Point ID 79 is (12, 0, 0) with scale factor 2^8 EQUB 15 \ Point ID 80 is (15, 0, 15) with scale factor 2^1 EQUB 0 \ Point ID 81 is ( 0, 12, 0) with scale factor 2^2 EQUB 7 \ Point ID 82 is ( 7, 12, 7) with scale factor 2^1 EQUB 6 \ Point ID 83 is ( 6, 7, 11) with scale factor 2^2 EQUB 12 \ Point ID 84 is (12, 8, 5) with scale factor 2^2 EQUB 0 \ Point ID 85 is ( 0, 10, 0) with scale factor 2^0 EQUB 0 \ Point ID 86 is ( 0, 0, 1) with scale factor 2^8 EQUB 8 \ Point ID 87 is ( 8, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 88 is ( 0, 2, 0) with scale factor 2^8 EQUB 15 \ Point ID 89 is (15, 0, 15) with scale factor 2^1 EQUB 0 \ Point ID 90 is ( 0, 10, 0) with scale factor 2^2 EQUB 4 \ Point ID 91 is ( 4, 12, 4) with scale factor 2^1 EQUB 3 \ Point ID 92 is ( 3, 5, 12) with scale factor 2^2 EQUB 10 \ Point ID 93 is (10, 7, 8) with scale factor 2^2 EQUB 0 \ Point ID 94 is ( 0, 10, 0) with scale factor 2^0 EQUB 0 \ Point ID 95 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 96 is ( 0, 0, 1) with scale factor 2^8 EQUB 10 \ Point ID 97 is (10, 0, 0) with scale factor 2^1 EQUB 0 \ Point ID 98 is ( 0, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 99 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 100 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 101 is ( 0, 0, 11) with scale factor 2^4 EQUB 0 \ Point ID 102 is ( 0, 0, 10) with scale factor 2^4 EQUB 11 \ Point ID 103 is (11, 0, 7) with scale factor 2^8 EQUB 11 \ Point ID 104 is (11, 0, 4) with scale factor 2^9 EQUB 13 \ Point ID 105 is (13, 0, 13) with scale factor 2^3 EQUB 14 \ Point ID 106 is (14, 0, 0) with scale factor 2^9 EQUB 4 \ Point ID 107 is ( 4, 0, 10) with scale factor 2^3 EQUB 4 \ Point ID 108 is ( 4, 0, 0) with scale factor 2^8 EQUB 13 \ Point ID 109 is (13, 0, 3) with scale factor 2^8 EQUB 12 \ Point ID 110 is (12, 0, 0) with scale factor 2^8 EQUB 13 \ Point ID 111 is (13, 0, 10) with scale factor 2^9 EQUB 4 \ Point ID 112 is ( 4, 0, 12) with scale factor 2^8 EQUB 14 \ Point ID 113 is (14, 0, 1) with scale factor 2^9 EQUB 0 \ Point ID 114 is ( 0, 0, 12) with scale factor 2^8 EQUB 3 \ Point ID 115 is ( 3, 0, 5) with scale factor 2^8 EQUB 15 \ Point ID 116 is (15, 0, 0) with scale factor 2^8 EQUB 10 \ Point ID 117 is (10, 0, 5) with scale factor 2^8 EQUB 11 \ Point ID 118 is (11, 0, 4) with scale factor 2^8 EQUB 2 \ Point ID 119 is ( 2, 0, 14) with scale factor 2^8 EQUB 14 \ Point ID 120 is (14, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 121 is ( 0, 0, 9) with scale factor 2^8 EQUB 11 \ Point ID 122 is (11, 0, 7) with scale factor 2^9 EQUB 10 \ Point ID 123 is (10, 0, 3) with scale factor 2^9 EQUB 10 \ Point ID 124 is (10, 0, 3) with scale factor 2^9 EQUB 5 \ Point ID 125 is ( 5, 0, 9) with scale factor 2^9 EQUB 14 \ Point ID 126 is (14, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 127 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 128 is ( 0, 0, 7) with scale factor 2^8 EQUB 11 \ Point ID 129 is (11, 0, 14) with scale factor 2^8 EQUB 14 \ Point ID 130 is (14, 0, 10) with scale factor 2^8 EQUB 5 \ Point ID 131 is ( 5, 0, 0) with scale factor 2^8 EQUB 4 \ Point ID 132 is ( 4, 0, 14) with scale factor 2^8 EQUB 9 \ Point ID 133 is ( 9, 0, 4) with scale factor 2^9 EQUB 10 \ Point ID 134 is (10, 0, 2) with scale factor 2^9 EQUB 0 \ Point ID 135 is ( 0, 0, 0) with scale factor 2^0 EQUB 1 \ Point ID 136 is ( 1, 0, 15) with scale factor 2^8 EQUB 5 \ Point ID 137 is ( 5, 0, 10) with scale factor 2^9 EQUB 13 \ Point ID 138 is (13, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 139 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 140 is ( 0, 0, 11) with scale factor 2^8 EQUB 13 \ Point ID 141 is (13, 0, 9) with scale factor 2^8 EQUB 15 \ Point ID 142 is (15, 0, 0) with scale factor 2^7 EQUB 2 \ Point ID 143 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 144 is ( 0, 0, 13) with scale factor 2^8 EQUB 9 \ Point ID 145 is ( 9, 0, 9) with scale factor 2^9 EQUB 13 \ Point ID 146 is (13, 0, 11) with scale factor 2^8 EQUB 15 \ Point ID 147 is (15, 0, 5) with scale factor 2^8 EQUB 11 \ Point ID 148 is (11, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 149 is ( 0, 0, 11) with scale factor 2^8 EQUB 11 \ Point ID 150 is (11, 0, 13) with scale factor 2^8 EQUB 13 \ Point ID 151 is (13, 0, 2) with scale factor 2^8 EQUB 2 \ Point ID 152 is ( 2, 0, 0) with scale factor 2^8 EQUB 3 \ Point ID 153 is ( 3, 0, 8) with scale factor 2^8 EQUB 10 \ Point ID 154 is (10, 0, 7) with scale factor 2^8 EQUB 8 \ Point ID 155 is ( 8, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 156 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 157 is ( 0, 0, 6) with scale factor 2^8 EQUB 4 \ Point ID 158 is ( 4, 0, 8) with scale factor 2^8 EQUB 12 \ Point ID 159 is (12, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 160 is ( 0, 0, 6) with scale factor 2^8 EQUB 6 \ Point ID 161 is ( 6, 0, 9) with scale factor 2^9 EQUB 14 \ Point ID 162 is (14, 0, 12) with scale factor 2^8 EQUB 11 \ Point ID 163 is (11, 0, 0) with scale factor 2^7 EQUB 0 \ Point ID 164 is ( 0, 0, 3) with scale factor 2^8 EQUB 5 \ Point ID 165 is ( 5, 0, 12) with scale factor 2^9 EQUB 10 \ Point ID 166 is (10, 0, 9) with scale factor 2^9 EQUB 14 \ Point ID 167 is (14, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 168 is ( 0, 0, 12) with scale factor 2^8 EQUB 5 \ Point ID 169 is ( 5, 0, 11) with scale factor 2^9 EQUB 11 \ Point ID 170 is (11, 0, 7) with scale factor 2^8 EQUB 5 \ Point ID 171 is ( 5, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 172 is ( 0, 0, 9) with scale factor 2^8 EQUB 5 \ Point ID 173 is ( 5, 0, 8) with scale factor 2^9 EQUB 13 \ Point ID 174 is (13, 0, 13) with scale factor 2^8 EQUB 2 \ Point ID 175 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 176 is ( 0, 0, 8) with scale factor 2^8 EQUB 2 \ Point ID 177 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 178 is ( 0, 0, 12) with scale factor 2^0 EQUB 12 \ Point ID 179 is (12, 0, 0) with scale factor 2^0 EQUB 14 \ Point ID 180 is (14, 0, 14) with scale factor 2^2 EQUB 5 \ Point ID 181 is ( 5, 0, 5) with scale factor 2^8 EQUB 5 \ Point ID 182 is ( 5, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 183 is ( 0, 0, 3) with scale factor 2^2 EQUB 3 \ Point ID 184 is ( 3, 0, 0) with scale factor 2^2 EQUB 14 \ Point ID 185 is (14, 0, 14) with scale factor 2^2 EQUB 3 \ Point ID 186 is ( 3, 4, 3) with scale factor 2^2 EQUB 5 \ Point ID 187 is ( 5, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 188 is ( 0, 0, 3) with scale factor 2^2 EQUB 3 \ Point ID 189 is ( 3, 0, 0) with scale factor 2^2 EQUB 14 \ Point ID 190 is (14, 0, 14) with scale factor 2^2 EQUB 3 \ Point ID 191 is ( 3, 4, 3) with scale factor 2^2 EQUB 9 \ Point ID 192 is ( 9, 0, 9) with scale factor 2^7 EQUB 4 \ Point ID 193 is ( 4, 0, 5) with scale factor 2^5 EQUB 5 \ Point ID 194 is ( 5, 0, 4) with scale factor 2^5 EQUB 9 \ Point ID 195 is ( 9, 0, 8) with scale factor 2^6 EQUB 7 \ Point ID 196 is ( 7, 4, 5) with scale factor 2^5 EQUB 4 \ Point ID 197 is ( 4, 0, 0) with scale factor 2^4 EQUB 4 \ Point ID 198 is ( 4, 3, 2) with scale factor 2^5 EQUB 0 \ Point ID 199 is ( 0, 0, 4) with scale factor 2^4 EQUB 2 \ Point ID 200 is ( 2, 3, 4) with scale factor 2^5 EQUB 0 \ Point ID 201 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 202 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 203 is ( 0, 0, 12) with scale factor 2^4 EQUB 11 \ Point ID 204 is (11, 0, 0) with scale factor 2^5 EQUB 12 \ Point ID 205 is (12, 0, 0) with scale factor 2^4 EQUB 11 \ Point ID 206 is (11, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 207 is ( 0, 8, 0) with scale factor 2^4 EQUB 0 \ Point ID 208 is ( 0, 8, 0) with scale factor 2^4 EQUB 0 \ Point ID 209 is ( 0, 8, 0) with scale factor 2^4 EQUB 0 \ Point ID 210 is ( 0, 8, 0) with scale factor 2^4 EQUB 4 \ Point ID 211 is ( 4, 1, 4) with scale factor 2^7 EQUB 1 \ Point ID 212 is ( 1, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 213 is ( 0, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 214 is ( 0, 0, 5) with scale factor 2^8 EQUB 4 \ Point ID 215 is ( 4, 2, 5) with scale factor 2^7Name: xObjectPoint [Show more] Type: Variable Category: 3D geometry Summary: Scaled x-coordinates of the points that make up objects, relative to the object's anchor point Deep dive: 3D objects Rotating and translating points in 3D spaceContext: See this variable on its own page References: This variable is used as follows: * SetObjPointCoords (Part 1 of 2) calls xObjectPoint

For a point within an object, (xObjectPoint, yObjectPoint, zObjectPoint) are the coordinates of this point relative to the object's anchor. This is the same as saying (xObjectPoint, yObjectPoint, zObjectPoint) is the vector from the object's anchor to the point. This table effectively defines the shape of each object. Each vector is stored as three coordinates, with each coordinate being in the range 0 to 15, plus a scale factor, which is stored in bits 4 to 7 of the z-coordinate in zObjectPoint. The scale is given as a power of 2, so a scale factor of n means we scale the coordinates by 2^n (where n = 0 to 9). All vectors are positive in all three axes, so the anchor point for an object is therefore the closest point to the origin..yObjectPoint EQUB 61 \ Point ID 0 is (13, 61, 13) with scale factor 2^0 EQUB 0 \ Point ID 1 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 2 is ( 0, 0, 12) with scale factor 2^9 EQUB 0 \ Point ID 3 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 4 is ( 8, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 5 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 6 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 7 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 8 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 9 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 10 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 11 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 12 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 13 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 14 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 15 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 16 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 17 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 18 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 19 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 20 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 21 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 22 is ( 0, 0, 8) with scale factor 2^4 EQUB 0 \ Point ID 23 is ( 0, 0, 8) with scale factor 2^4 EQUB 0 \ Point ID 24 is (10, 0, 0) with scale factor 2^6 EQUB 1 \ Point ID 25 is ( 0, 1, 0) with scale factor 2^8 EQUB 1 \ Point ID 26 is ( 0, 1, 0) with scale factor 2^8 EQUB 1 \ Point ID 27 is ( 0, 1, 0) with scale factor 2^8 EQUB 1 \ Point ID 28 is ( 0, 1, 0) with scale factor 2^8 EQUB 0 \ Point ID 29 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 30 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 31 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 32 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 33 is ( 0, 0, 10) with scale factor 2^5 EQUB 0 \ Point ID 34 is ( 0, 0, 12) with scale factor 2^4 EQUB 0 \ Point ID 35 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 36 is ( 4, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 37 is ( 0, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 38 is (12, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 39 is ( 5, 0, 10) with scale factor 2^5 EQUB 0 \ Point ID 40 is ( 8, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 41 is ( 0, 0, 8) with scale factor 2^3 EQUB 10 \ Point ID 42 is ( 0, 10, 0) with scale factor 2^3 EQUB 10 \ Point ID 43 is ( 0, 10, 0) with scale factor 2^3 EQUB 0 \ Point ID 44 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 45 is ( 0, 0, 0) with scale factor 2^0 EQUB 10 \ Point ID 46 is ( 0, 10, 0) with scale factor 2^3 EQUB 10 \ Point ID 47 is ( 0, 10, 0) with scale factor 2^3 EQUB 0 \ Point ID 48 is (12, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 49 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 50 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 51 is (12, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 52 is (11, 0, 0) with scale factor 2^6 EQUB 10 \ Point ID 53 is ( 0, 10, 0) with scale factor 2^4 EQUB 10 \ Point ID 54 is ( 0, 10, 0) with scale factor 2^4 EQUB 10 \ Point ID 55 is ( 0, 10, 0) with scale factor 2^4 EQUB 10 \ Point ID 56 is ( 0, 10, 0) with scale factor 2^4 EQUB 0 \ Point ID 57 is ( 2, 0, 14) with scale factor 2^8 EQUB 0 \ Point ID 58 is ( 1, 0, 11) with scale factor 2^8 EQUB 0 \ Point ID 59 is ( 3, 0, 9) with scale factor 2^9 EQUB 0 \ Point ID 60 is ( 6, 0, 12) with scale factor 2^8 EQUB 0 \ Point ID 61 is (10, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 62 is ( 3, 0, 9) with scale factor 2^7 EQUB 0 \ Point ID 63 is ( 9, 0, 15) with scale factor 2^6 EQUB 0 \ Point ID 64 is ( 6, 0, 13) with scale factor 2^8 EQUB 0 \ Point ID 65 is (13, 0, 3) with scale factor 2^4 EQUB 0 \ Point ID 66 is ( 0, 0, 14) with scale factor 2^9 EQUB 0 \ Point ID 67 is ( 1, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 68 is ( 5, 0, 12) with scale factor 2^9 EQUB 0 \ Point ID 69 is ( 1, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 70 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 71 is ( 9, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 72 is ( 0, 0, 9) with scale factor 2^5 EQUB 0 \ Point ID 73 is ( 8, 0, 6) with scale factor 2^9 EQUB 0 \ Point ID 74 is ( 0, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 75 is (14, 0, 7) with scale factor 2^9 EQUB 0 \ Point ID 76 is ( 0, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 77 is (13, 0, 2) with scale factor 2^9 EQUB 0 \ Point ID 78 is ( 5, 0, 13) with scale factor 2^4 EQUB 0 \ Point ID 79 is (12, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 80 is (15, 0, 15) with scale factor 2^1 EQUB 12 \ Point ID 81 is ( 0, 12, 0) with scale factor 2^2 EQUB 12 \ Point ID 82 is ( 7, 12, 7) with scale factor 2^1 EQUB 7 \ Point ID 83 is ( 6, 7, 11) with scale factor 2^2 EQUB 8 \ Point ID 84 is (12, 8, 5) with scale factor 2^2 EQUB 10 \ Point ID 85 is ( 0, 10, 0) with scale factor 2^0 EQUB 0 \ Point ID 86 is ( 0, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 87 is ( 8, 0, 0) with scale factor 2^4 EQUB 2 \ Point ID 88 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 89 is (15, 0, 15) with scale factor 2^1 EQUB 10 \ Point ID 90 is ( 0, 10, 0) with scale factor 2^2 EQUB 12 \ Point ID 91 is ( 4, 12, 4) with scale factor 2^1 EQUB 5 \ Point ID 92 is ( 3, 5, 12) with scale factor 2^2 EQUB 7 \ Point ID 93 is (10, 7, 8) with scale factor 2^2 EQUB 10 \ Point ID 94 is ( 0, 10, 0) with scale factor 2^0 EQUB 0 \ Point ID 95 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 96 is ( 0, 0, 1) with scale factor 2^8 EQUB 0 \ Point ID 97 is (10, 0, 0) with scale factor 2^1 EQUB 0 \ Point ID 98 is ( 0, 0, 1) with scale factor 2^8 EQUB 2 \ Point ID 99 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 100 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 101 is ( 0, 0, 11) with scale factor 2^4 EQUB 0 \ Point ID 102 is ( 0, 0, 10) with scale factor 2^4 EQUB 0 \ Point ID 103 is (11, 0, 7) with scale factor 2^8 EQUB 0 \ Point ID 104 is (11, 0, 4) with scale factor 2^9 EQUB 0 \ Point ID 105 is (13, 0, 13) with scale factor 2^3 EQUB 0 \ Point ID 106 is (14, 0, 0) with scale factor 2^9 EQUB 0 \ Point ID 107 is ( 4, 0, 10) with scale factor 2^3 EQUB 0 \ Point ID 108 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 109 is (13, 0, 3) with scale factor 2^8 EQUB 0 \ Point ID 110 is (12, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 111 is (13, 0, 10) with scale factor 2^9 EQUB 0 \ Point ID 112 is ( 4, 0, 12) with scale factor 2^8 EQUB 0 \ Point ID 113 is (14, 0, 1) with scale factor 2^9 EQUB 0 \ Point ID 114 is ( 0, 0, 12) with scale factor 2^8 EQUB 0 \ Point ID 115 is ( 3, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 116 is (15, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 117 is (10, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 118 is (11, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 119 is ( 2, 0, 14) with scale factor 2^8 EQUB 0 \ Point ID 120 is (14, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 121 is ( 0, 0, 9) with scale factor 2^8 EQUB 0 \ Point ID 122 is (11, 0, 7) with scale factor 2^9 EQUB 0 \ Point ID 123 is (10, 0, 3) with scale factor 2^9 EQUB 0 \ Point ID 124 is (10, 0, 3) with scale factor 2^9 EQUB 0 \ Point ID 125 is ( 5, 0, 9) with scale factor 2^9 EQUB 0 \ Point ID 126 is (14, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 127 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 128 is ( 0, 0, 7) with scale factor 2^8 EQUB 0 \ Point ID 129 is (11, 0, 14) with scale factor 2^8 EQUB 0 \ Point ID 130 is (14, 0, 10) with scale factor 2^8 EQUB 0 \ Point ID 131 is ( 5, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 132 is ( 4, 0, 14) with scale factor 2^8 EQUB 0 \ Point ID 133 is ( 9, 0, 4) with scale factor 2^9 EQUB 0 \ Point ID 134 is (10, 0, 2) with scale factor 2^9 EQUB 0 \ Point ID 135 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 136 is ( 1, 0, 15) with scale factor 2^8 EQUB 0 \ Point ID 137 is ( 5, 0, 10) with scale factor 2^9 EQUB 0 \ Point ID 138 is (13, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 139 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 140 is ( 0, 0, 11) with scale factor 2^8 EQUB 0 \ Point ID 141 is (13, 0, 9) with scale factor 2^8 EQUB 0 \ Point ID 142 is (15, 0, 0) with scale factor 2^7 EQUB 0 \ Point ID 143 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 144 is ( 0, 0, 13) with scale factor 2^8 EQUB 0 \ Point ID 145 is ( 9, 0, 9) with scale factor 2^9 EQUB 0 \ Point ID 146 is (13, 0, 11) with scale factor 2^8 EQUB 0 \ Point ID 147 is (15, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 148 is (11, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 149 is ( 0, 0, 11) with scale factor 2^8 EQUB 0 \ Point ID 150 is (11, 0, 13) with scale factor 2^8 EQUB 0 \ Point ID 151 is (13, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 152 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 153 is ( 3, 0, 8) with scale factor 2^8 EQUB 0 \ Point ID 154 is (10, 0, 7) with scale factor 2^8 EQUB 0 \ Point ID 155 is ( 8, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 156 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 157 is ( 0, 0, 6) with scale factor 2^8 EQUB 0 \ Point ID 158 is ( 4, 0, 8) with scale factor 2^8 EQUB 0 \ Point ID 159 is (12, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 160 is ( 0, 0, 6) with scale factor 2^8 EQUB 0 \ Point ID 161 is ( 6, 0, 9) with scale factor 2^9 EQUB 0 \ Point ID 162 is (14, 0, 12) with scale factor 2^8 EQUB 0 \ Point ID 163 is (11, 0, 0) with scale factor 2^7 EQUB 0 \ Point ID 164 is ( 0, 0, 3) with scale factor 2^8 EQUB 0 \ Point ID 165 is ( 5, 0, 12) with scale factor 2^9 EQUB 0 \ Point ID 166 is (10, 0, 9) with scale factor 2^9 EQUB 0 \ Point ID 167 is (14, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 168 is ( 0, 0, 12) with scale factor 2^8 EQUB 0 \ Point ID 169 is ( 5, 0, 11) with scale factor 2^9 EQUB 0 \ Point ID 170 is (11, 0, 7) with scale factor 2^8 EQUB 0 \ Point ID 171 is ( 5, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 172 is ( 0, 0, 9) with scale factor 2^8 EQUB 0 \ Point ID 173 is ( 5, 0, 8) with scale factor 2^9 EQUB 0 \ Point ID 174 is (13, 0, 13) with scale factor 2^8 EQUB 0 \ Point ID 175 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 176 is ( 0, 0, 8) with scale factor 2^8 EQUB 0 \ Point ID 177 is ( 2, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 178 is ( 0, 0, 12) with scale factor 2^0 EQUB 0 \ Point ID 179 is (12, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 180 is (14, 0, 14) with scale factor 2^2 EQUB 0 \ Point ID 181 is ( 5, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 182 is ( 5, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 183 is ( 0, 0, 3) with scale factor 2^2 EQUB 0 \ Point ID 184 is ( 3, 0, 0) with scale factor 2^2 EQUB 0 \ Point ID 185 is (14, 0, 14) with scale factor 2^2 EQUB 4 \ Point ID 186 is ( 3, 4, 3) with scale factor 2^2 EQUB 0 \ Point ID 187 is ( 5, 0, 5) with scale factor 2^8 EQUB 0 \ Point ID 188 is ( 0, 0, 3) with scale factor 2^2 EQUB 0 \ Point ID 189 is ( 3, 0, 0) with scale factor 2^2 EQUB 0 \ Point ID 190 is (14, 0, 14) with scale factor 2^2 EQUB 4 \ Point ID 191 is ( 3, 4, 3) with scale factor 2^2 EQUB 0 \ Point ID 192 is ( 9, 0, 9) with scale factor 2^7 EQUB 0 \ Point ID 193 is ( 4, 0, 5) with scale factor 2^5 EQUB 0 \ Point ID 194 is ( 5, 0, 4) with scale factor 2^5 EQUB 0 \ Point ID 195 is ( 9, 0, 8) with scale factor 2^6 EQUB 4 \ Point ID 196 is ( 7, 4, 5) with scale factor 2^5 EQUB 0 \ Point ID 197 is ( 4, 0, 0) with scale factor 2^4 EQUB 3 \ Point ID 198 is ( 4, 3, 2) with scale factor 2^5 EQUB 0 \ Point ID 199 is ( 0, 0, 4) with scale factor 2^4 EQUB 3 \ Point ID 200 is ( 2, 3, 4) with scale factor 2^5 EQUB 2 \ Point ID 201 is ( 0, 2, 0) with scale factor 2^8 EQUB 2 \ Point ID 202 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 203 is ( 0, 0, 12) with scale factor 2^4 EQUB 0 \ Point ID 204 is (11, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 205 is (12, 0, 0) with scale factor 2^4 EQUB 0 \ Point ID 206 is (11, 0, 0) with scale factor 2^5 EQUB 8 \ Point ID 207 is ( 0, 8, 0) with scale factor 2^4 EQUB 8 \ Point ID 208 is ( 0, 8, 0) with scale factor 2^4 EQUB 8 \ Point ID 209 is ( 0, 8, 0) with scale factor 2^4 EQUB 8 \ Point ID 210 is ( 0, 8, 0) with scale factor 2^4 EQUB 1 \ Point ID 211 is ( 4, 1, 4) with scale factor 2^7 EQUB 0 \ Point ID 212 is ( 1, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 213 is ( 0, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 214 is ( 0, 0, 5) with scale factor 2^8 EQUB 2 \ Point ID 215 is ( 4, 2, 5) with scale factor 2^7Name: yObjectPoint [Show more] Type: Variable Category: 3D geometry Summary: Scaled y-coordinates of the points that make up objects, relative to the object's anchor point Deep dive: 3D objects Rotating and translating points in 3D spaceContext: See this variable on its own page References: This variable is used as follows: * SetObjPointCoords (Part 1 of 2) calls yObjectPoint

See xObjectPoint for an explanation of object points..zObjectPoint EQUB 13 \ Point ID 0 is (13, 61, 13) with scale factor 2^0 EQUB 0 \ Point ID 1 is ( 0, 0, 0) with scale factor 2^0 EQUB 156 \ Point ID 2 is ( 0, 0, 12) with scale factor 2^9 EQUB 0 \ Point ID 3 is ( 0, 0, 0) with scale factor 2^0 EQUB 80 \ Point ID 4 is ( 8, 0, 0) with scale factor 2^5 EQUB 0 \ Point ID 5 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 6 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 7 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 8 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 9 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 10 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 11 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 12 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 13 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 14 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 15 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 16 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 17 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 18 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 19 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 20 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 21 is ( 0, 0, 0) with scale factor 2^0 EQUB 72 \ Point ID 22 is ( 0, 0, 8) with scale factor 2^4 EQUB 72 \ Point ID 23 is ( 0, 0, 8) with scale factor 2^4 EQUB 96 \ Point ID 24 is (10, 0, 0) with scale factor 2^6 EQUB 128 \ Point ID 25 is ( 0, 1, 0) with scale factor 2^8 EQUB 128 \ Point ID 26 is ( 0, 1, 0) with scale factor 2^8 EQUB 128 \ Point ID 27 is ( 0, 1, 0) with scale factor 2^8 EQUB 128 \ Point ID 28 is ( 0, 1, 0) with scale factor 2^8 EQUB 128 \ Point ID 29 is ( 4, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 30 is ( 0, 0, 0) with scale factor 2^0 EQUB 0 \ Point ID 31 is ( 0, 0, 0) with scale factor 2^0 EQUB 128 \ Point ID 32 is ( 4, 0, 0) with scale factor 2^8 EQUB 90 \ Point ID 33 is ( 0, 0, 10) with scale factor 2^5 EQUB 76 \ Point ID 34 is ( 0, 0, 12) with scale factor 2^4 EQUB 0 \ Point ID 35 is ( 0, 0, 0) with scale factor 2^0 EQUB 130 \ Point ID 36 is ( 4, 0, 2) with scale factor 2^8 EQUB 130 \ Point ID 37 is ( 0, 0, 2) with scale factor 2^8 EQUB 64 \ Point ID 38 is (12, 0, 0) with scale factor 2^4 EQUB 90 \ Point ID 39 is ( 5, 0, 10) with scale factor 2^5 EQUB 64 \ Point ID 40 is ( 8, 0, 0) with scale factor 2^4 EQUB 56 \ Point ID 41 is ( 0, 0, 8) with scale factor 2^3 EQUB 48 \ Point ID 42 is ( 0, 10, 0) with scale factor 2^3 EQUB 48 \ Point ID 43 is ( 0, 10, 0) with scale factor 2^3 EQUB 56 \ Point ID 44 is ( 0, 0, 8) with scale factor 2^3 EQUB 0 \ Point ID 45 is ( 0, 0, 0) with scale factor 2^0 EQUB 48 \ Point ID 46 is ( 0, 10, 0) with scale factor 2^3 EQUB 48 \ Point ID 47 is ( 0, 10, 0) with scale factor 2^3 EQUB 80 \ Point ID 48 is (12, 0, 0) with scale factor 2^5 EQUB 56 \ Point ID 49 is ( 0, 0, 8) with scale factor 2^3 EQUB 56 \ Point ID 50 is ( 0, 0, 8) with scale factor 2^3 EQUB 80 \ Point ID 51 is (12, 0, 0) with scale factor 2^5 EQUB 96 \ Point ID 52 is (11, 0, 0) with scale factor 2^6 EQUB 64 \ Point ID 53 is ( 0, 10, 0) with scale factor 2^4 EQUB 64 \ Point ID 54 is ( 0, 10, 0) with scale factor 2^4 EQUB 64 \ Point ID 55 is ( 0, 10, 0) with scale factor 2^4 EQUB 64 \ Point ID 56 is ( 0, 10, 0) with scale factor 2^4 EQUB 142 \ Point ID 57 is ( 2, 0, 14) with scale factor 2^8 EQUB 139 \ Point ID 58 is ( 1, 0, 11) with scale factor 2^8 EQUB 153 \ Point ID 59 is ( 3, 0, 9) with scale factor 2^9 EQUB 140 \ Point ID 60 is ( 6, 0, 12) with scale factor 2^8 EQUB 129 \ Point ID 61 is (10, 0, 1) with scale factor 2^8 EQUB 121 \ Point ID 62 is ( 3, 0, 9) with scale factor 2^7 EQUB 111 \ Point ID 63 is ( 9, 0, 15) with scale factor 2^6 EQUB 141 \ Point ID 64 is ( 6, 0, 13) with scale factor 2^8 EQUB 67 \ Point ID 65 is (13, 0, 3) with scale factor 2^4 EQUB 158 \ Point ID 66 is ( 0, 0, 14) with scale factor 2^9 EQUB 128 \ Point ID 67 is ( 1, 0, 0) with scale factor 2^8 EQUB 156 \ Point ID 68 is ( 5, 0, 12) with scale factor 2^9 EQUB 128 \ Point ID 69 is ( 1, 0, 0) with scale factor 2^8 EQUB 0 \ Point ID 70 is ( 0, 0, 0) with scale factor 2^0 EQUB 80 \ Point ID 71 is ( 9, 0, 0) with scale factor 2^5 EQUB 89 \ Point ID 72 is ( 0, 0, 9) with scale factor 2^5 EQUB 150 \ Point ID 73 is ( 8, 0, 6) with scale factor 2^9 EQUB 129 \ Point ID 74 is ( 0, 0, 1) with scale factor 2^8 EQUB 151 \ Point ID 75 is (14, 0, 7) with scale factor 2^9 EQUB 129 \ Point ID 76 is ( 0, 0, 1) with scale factor 2^8 EQUB 146 \ Point ID 77 is (13, 0, 2) with scale factor 2^9 EQUB 77 \ Point ID 78 is ( 5, 0, 13) with scale factor 2^4 EQUB 128 \ Point ID 79 is (12, 0, 0) with scale factor 2^8 EQUB 31 \ Point ID 80 is (15, 0, 15) with scale factor 2^1 EQUB 32 \ Point ID 81 is ( 0, 12, 0) with scale factor 2^2 EQUB 23 \ Point ID 82 is ( 7, 12, 7) with scale factor 2^1 EQUB 43 \ Point ID 83 is ( 6, 7, 11) with scale factor 2^2 EQUB 37 \ Point ID 84 is (12, 8, 5) with scale factor 2^2 EQUB 0 \ Point ID 85 is ( 0, 10, 0) with scale factor 2^0 EQUB 129 \ Point ID 86 is ( 0, 0, 1) with scale factor 2^8 EQUB 64 \ Point ID 87 is ( 8, 0, 0) with scale factor 2^4 EQUB 128 \ Point ID 88 is ( 0, 2, 0) with scale factor 2^8 EQUB 31 \ Point ID 89 is (15, 0, 15) with scale factor 2^1 EQUB 32 \ Point ID 90 is ( 0, 10, 0) with scale factor 2^2 EQUB 20 \ Point ID 91 is ( 4, 12, 4) with scale factor 2^1 EQUB 44 \ Point ID 92 is ( 3, 5, 12) with scale factor 2^2 EQUB 40 \ Point ID 93 is (10, 7, 8) with scale factor 2^2 EQUB 0 \ Point ID 94 is ( 0, 10, 0) with scale factor 2^0 EQUB 0 \ Point ID 95 is ( 0, 0, 0) with scale factor 2^0 EQUB 129 \ Point ID 96 is ( 0, 0, 1) with scale factor 2^8 EQUB 16 \ Point ID 97 is (10, 0, 0) with scale factor 2^1 EQUB 129 \ Point ID 98 is ( 0, 0, 1) with scale factor 2^8 EQUB 128 \ Point ID 99 is ( 0, 2, 0) with scale factor 2^8 EQUB 0 \ Point ID 100 is ( 0, 0, 0) with scale factor 2^0 EQUB 75 \ Point ID 101 is ( 0, 0, 11) with scale factor 2^4 EQUB 74 \ Point ID 102 is ( 0, 0, 10) with scale factor 2^4 EQUB 135 \ Point ID 103 is (11, 0, 7) with scale factor 2^8 EQUB 148 \ Point ID 104 is (11, 0, 4) with scale factor 2^9 EQUB 61 \ Point ID 105 is (13, 0, 13) with scale factor 2^3 EQUB 144 \ Point ID 106 is (14, 0, 0) with scale factor 2^9 EQUB 58 \ Point ID 107 is ( 4, 0, 10) with scale factor 2^3 EQUB 128 \ Point ID 108 is ( 4, 0, 0) with scale factor 2^8 EQUB 131 \ Point ID 109 is (13, 0, 3) with scale factor 2^8 EQUB 128 \ Point ID 110 is (12, 0, 0) with scale factor 2^8 EQUB 154 \ Point ID 111 is (13, 0, 10) with scale factor 2^9 EQUB 140 \ Point ID 112 is ( 4, 0, 12) with scale factor 2^8 EQUB 145 \ Point ID 113 is (14, 0, 1) with scale factor 2^9 EQUB 140 \ Point ID 114 is ( 0, 0, 12) with scale factor 2^8 EQUB 133 \ Point ID 115 is ( 3, 0, 5) with scale factor 2^8 EQUB 128 \ Point ID 116 is (15, 0, 0) with scale factor 2^8 EQUB 133 \ Point ID 117 is (10, 0, 5) with scale factor 2^8 EQUB 132 \ Point ID 118 is (11, 0, 4) with scale factor 2^8 EQUB 142 \ Point ID 119 is ( 2, 0, 14) with scale factor 2^8 EQUB 64 \ Point ID 120 is (14, 0, 0) with scale factor 2^4 EQUB 137 \ Point ID 121 is ( 0, 0, 9) with scale factor 2^8 EQUB 151 \ Point ID 122 is (11, 0, 7) with scale factor 2^9 EQUB 147 \ Point ID 123 is (10, 0, 3) with scale factor 2^9 EQUB 147 \ Point ID 124 is (10, 0, 3) with scale factor 2^9 EQUB 153 \ Point ID 125 is ( 5, 0, 9) with scale factor 2^9 EQUB 130 \ Point ID 126 is (14, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 127 is ( 0, 0, 0) with scale factor 2^0 EQUB 135 \ Point ID 128 is ( 0, 0, 7) with scale factor 2^8 EQUB 142 \ Point ID 129 is (11, 0, 14) with scale factor 2^8 EQUB 138 \ Point ID 130 is (14, 0, 10) with scale factor 2^8 EQUB 128 \ Point ID 131 is ( 5, 0, 0) with scale factor 2^8 EQUB 142 \ Point ID 132 is ( 4, 0, 14) with scale factor 2^8 EQUB 148 \ Point ID 133 is ( 9, 0, 4) with scale factor 2^9 EQUB 146 \ Point ID 134 is (10, 0, 2) with scale factor 2^9 EQUB 0 \ Point ID 135 is ( 0, 0, 0) with scale factor 2^0 EQUB 143 \ Point ID 136 is ( 1, 0, 15) with scale factor 2^8 EQUB 154 \ Point ID 137 is ( 5, 0, 10) with scale factor 2^9 EQUB 132 \ Point ID 138 is (13, 0, 4) with scale factor 2^8 EQUB 0 \ Point ID 139 is ( 0, 0, 0) with scale factor 2^0 EQUB 139 \ Point ID 140 is ( 0, 0, 11) with scale factor 2^8 EQUB 137 \ Point ID 141 is (13, 0, 9) with scale factor 2^8 EQUB 112 \ Point ID 142 is (15, 0, 0) with scale factor 2^7 EQUB 128 \ Point ID 143 is ( 2, 0, 0) with scale factor 2^8 EQUB 141 \ Point ID 144 is ( 0, 0, 13) with scale factor 2^8 EQUB 153 \ Point ID 145 is ( 9, 0, 9) with scale factor 2^9 EQUB 139 \ Point ID 146 is (13, 0, 11) with scale factor 2^8 EQUB 133 \ Point ID 147 is (15, 0, 5) with scale factor 2^8 EQUB 128 \ Point ID 148 is (11, 0, 0) with scale factor 2^8 EQUB 139 \ Point ID 149 is ( 0, 0, 11) with scale factor 2^8 EQUB 141 \ Point ID 150 is (11, 0, 13) with scale factor 2^8 EQUB 130 \ Point ID 151 is (13, 0, 2) with scale factor 2^8 EQUB 128 \ Point ID 152 is ( 2, 0, 0) with scale factor 2^8 EQUB 136 \ Point ID 153 is ( 3, 0, 8) with scale factor 2^8 EQUB 135 \ Point ID 154 is (10, 0, 7) with scale factor 2^8 EQUB 130 \ Point ID 155 is ( 8, 0, 2) with scale factor 2^8 EQUB 0 \ Point ID 156 is ( 0, 0, 0) with scale factor 2^0 EQUB 134 \ Point ID 157 is ( 0, 0, 6) with scale factor 2^8 EQUB 136 \ Point ID 158 is ( 4, 0, 8) with scale factor 2^8 EQUB 128 \ Point ID 159 is (12, 0, 0) with scale factor 2^8 EQUB 134 \ Point ID 160 is ( 0, 0, 6) with scale factor 2^8 EQUB 153 \ Point ID 161 is ( 6, 0, 9) with scale factor 2^9 EQUB 140 \ Point ID 162 is (14, 0, 12) with scale factor 2^8 EQUB 112 \ Point ID 163 is (11, 0, 0) with scale factor 2^7 EQUB 131 \ Point ID 164 is ( 0, 0, 3) with scale factor 2^8 EQUB 156 \ Point ID 165 is ( 5, 0, 12) with scale factor 2^9 EQUB 153 \ Point ID 166 is (10, 0, 9) with scale factor 2^9 EQUB 128 \ Point ID 167 is (14, 0, 0) with scale factor 2^8 EQUB 140 \ Point ID 168 is ( 0, 0, 12) with scale factor 2^8 EQUB 155 \ Point ID 169 is ( 5, 0, 11) with scale factor 2^9 EQUB 135 \ Point ID 170 is (11, 0, 7) with scale factor 2^8 EQUB 128 \ Point ID 171 is ( 5, 0, 0) with scale factor 2^8 EQUB 137 \ Point ID 172 is ( 0, 0, 9) with scale factor 2^8 EQUB 152 \ Point ID 173 is ( 5, 0, 8) with scale factor 2^9 EQUB 141 \ Point ID 174 is (13, 0, 13) with scale factor 2^8 EQUB 128 \ Point ID 175 is ( 2, 0, 0) with scale factor 2^8 EQUB 136 \ Point ID 176 is ( 0, 0, 8) with scale factor 2^8 EQUB 128 \ Point ID 177 is ( 2, 0, 0) with scale factor 2^8 EQUB 12 \ Point ID 178 is ( 0, 0, 12) with scale factor 2^0 EQUB 0 \ Point ID 179 is (12, 0, 0) with scale factor 2^0 EQUB 46 \ Point ID 180 is (14, 0, 14) with scale factor 2^2 EQUB 133 \ Point ID 181 is ( 5, 0, 5) with scale factor 2^8 EQUB 133 \ Point ID 182 is ( 5, 0, 5) with scale factor 2^8 EQUB 35 \ Point ID 183 is ( 0, 0, 3) with scale factor 2^2 EQUB 32 \ Point ID 184 is ( 3, 0, 0) with scale factor 2^2 EQUB 46 \ Point ID 185 is (14, 0, 14) with scale factor 2^2 EQUB 35 \ Point ID 186 is ( 3, 4, 3) with scale factor 2^2 EQUB 133 \ Point ID 187 is ( 5, 0, 5) with scale factor 2^8 EQUB 35 \ Point ID 188 is ( 0, 0, 3) with scale factor 2^2 EQUB 32 \ Point ID 189 is ( 3, 0, 0) with scale factor 2^2 EQUB 46 \ Point ID 190 is (14, 0, 14) with scale factor 2^2 EQUB 35 \ Point ID 191 is ( 3, 4, 3) with scale factor 2^2 EQUB 121 \ Point ID 192 is ( 9, 0, 9) with scale factor 2^7 EQUB 85 \ Point ID 193 is ( 4, 0, 5) with scale factor 2^5 EQUB 84 \ Point ID 194 is ( 5, 0, 4) with scale factor 2^5 EQUB 104 \ Point ID 195 is ( 9, 0, 8) with scale factor 2^6 EQUB 85 \ Point ID 196 is ( 7, 4, 5) with scale factor 2^5 EQUB 64 \ Point ID 197 is ( 4, 0, 0) with scale factor 2^4 EQUB 82 \ Point ID 198 is ( 4, 3, 2) with scale factor 2^5 EQUB 68 \ Point ID 199 is ( 0, 0, 4) with scale factor 2^4 EQUB 84 \ Point ID 200 is ( 2, 3, 4) with scale factor 2^5 EQUB 128 \ Point ID 201 is ( 0, 2, 0) with scale factor 2^8 EQUB 128 \ Point ID 202 is ( 0, 2, 0) with scale factor 2^8 EQUB 76 \ Point ID 203 is ( 0, 0, 12) with scale factor 2^4 EQUB 80 \ Point ID 204 is (11, 0, 0) with scale factor 2^5 EQUB 64 \ Point ID 205 is (12, 0, 0) with scale factor 2^4 EQUB 80 \ Point ID 206 is (11, 0, 0) with scale factor 2^5 EQUB 64 \ Point ID 207 is ( 0, 8, 0) with scale factor 2^4 EQUB 64 \ Point ID 208 is ( 0, 8, 0) with scale factor 2^4 EQUB 64 \ Point ID 209 is ( 0, 8, 0) with scale factor 2^4 EQUB 64 \ Point ID 210 is ( 0, 8, 0) with scale factor 2^4 EQUB 116 \ Point ID 211 is ( 4, 1, 4) with scale factor 2^7 EQUB 132 \ Point ID 212 is ( 1, 0, 4) with scale factor 2^8 EQUB 130 \ Point ID 213 is ( 0, 0, 2) with scale factor 2^8 EQUB 133 \ Point ID 214 is ( 0, 0, 5) with scale factor 2^8 EQUB 117 \ Point ID 215 is ( 4, 2, 5) with scale factor 2^7Name: zObjectPoint [Show more] Type: Variable Category: 3D geometry Summary: Scaled z-coordinates of the points that make up objects, relative to the object's anchor point Deep dive: 3D objects Rotating and translating points in 3D spaceContext: See this variable on its own page References: This variable is used as follows: * CheckIfAlienIsHit (Part 1 of 2) calls zObjectPoint * ResizeFeedingAlien calls zObjectPoint * SetObjPointCoords (Part 1 of 2) calls zObjectPoint

See xObjectPoint for an explanation of object points..xRadarBuffer EQUB &8A \ The x-coordinate of the runway on the radar, stored so \ we can erase it again EQUB &8A \ The x-coordinate of the alien on the radar, stored so \ we can erase it againName: xRadarBuffer [Show more] Type: Variable Category: Dashboard Summary: The x-coordinates of the runway and alien on the radar Deep dive: Line buffersContext: See this variable on its own page References: This variable is used as follows: * DrawRadarBlip calls xRadarBuffer.yRadarBuffer EQUB &D0 \ The y-coordinate of the runway on the radar, stored so \ we can erase it again EQUB &D0 \ The y-coordinate of the alien on the radar, stored so \ we can erase it againName: yRadarBuffer [Show more] Type: Variable Category: Dashboard Summary: The y-coordinates of the runway and alien on the radar Deep dive: Line buffersContext: See this variable on its own page References: This variable is used as follows: * DrawRadarBlip calls yRadarBuffer.distanceFromHit EQUB &48Name: distanceFromHit [Show more] Type: Variable Category: The Theme Summary: The distance from the alien we just hit, so we can work out whether we get hit by turbulence Deep dive: Explosions and turbulenceContext: See this variable on its own page References: This variable is used as follows: * ApplyFlightModel (Part 3 of 7) calls distanceFromHit * ExplodeAlien calls distanceFromHit * MainLoop (Part 6 of 15) calls distanceFromHit.feedingStage EQUB &49 \ The alien's feeding stage \ \ * 0 = large feeding alien (full up) or flying \ * 1 = medium feeding alien \ * 2 = small feeding alien \ * 3 = smallest feeding alien \ * 4 = dormant (not feeding)Name: feedingStage [Show more] Type: Variable Category: The Theme Summary: The feeding stage of the alien we are currently processingContext: See this variable on its own page References: This variable is used as follows: * CheckIfAlienIsHit (Part 1 of 2) calls feedingStage * ExplodeAlien calls feedingStage * ScoreHitPoints calls feedingStage.hitObjectId EQUB &3DName: hitObjectId [Show more] Type: Variable Category: The Theme Summary: The object ID of the alien we just hit (30 to 33)Context: See this variable on its own page References: This variable is used as follows: * CheckAlienWeakSpot calls hitObjectId * ExplodeAlien calls hitObjectId * ScoreHitPoints calls hitObjectId

This is called EPTR in the original source..hitTimer EQUB &26 \ Zeroed in ResetVariablesName: hitTimer [Show more] Type: Variable Category: The Theme Summary: The time since we hit an alien, so we can time its explosion Deep dive: Explosions and turbulenceContext: See this variable on its own page References: This variable is used as follows: * AlienInAcornsville calls hitTimer * ApplyFlightModel (Part 3 of 7) calls hitTimer * CheckAlienWeakSpot calls hitTimer * CheckIfAlienIsHit (Part 2 of 2) calls hitTimer * ExplodeAlien calls hitTimer * FireGuns calls hitTimer * MainLoop (Part 6 of 15) calls hitTimer * ResetVariables calls hitTimer

The hit timer starts at 27 when we make a hit. While it is non-zero, the gun can't be fired and any attacking aliens stop moving until the timer runs down. This is called EPLO in the original source..fuelUsedLo EQUB &34Name: fuelUsedLo [Show more] Type: Variable Category: Flight model Summary: The low byte of the current batch of fuel usedContext: See this variable on its own page References: This variable is used as follows: * ApplyFlightModel (Part 7 of 7) calls fuelUsedLo.fuelUsedHi EQUB &34Name: fuelUsedHi [Show more] Type: Variable Category: Flight model Summary: The high byte of the current batch of fuel usedContext: See this variable on its own page References: This variable is used as follows: * ApplyFlightModel (Part 7 of 7) calls fuelUsedHi.fuelLevel EQUB &41 \ Current fuel level \ \ * 0 = empty \ \ * 65 = fullName: fuelLevel [Show more] Type: Variable Category: Flight model Summary: The current fuel levelContext: See this variable on its own page References: This variable is used as follows: * ApplyFlightModel (Part 7 of 7) calls fuelLevel * FillUpFuelTank calls fuelLevel * ResetVariables calls fuelLevel * UpdateFuelGauge calls fuelLevel.explodeTo EQUB 178 \ Alien slot 30 moves points 180 to 178 when it explodes EQUB 183 \ Alien slot 31 moves points 186 to 183 when it explodes EQUB 188 \ Alien slot 32 moves points 191 to 188 when it explodes EQUB 193 \ Alien slot 33 moves points 200 to 193 when it explodes EQUB 15 \ This byte appears to be unusedName: explodeTo [Show more] Type: Variable Category: The Theme Summary: The end point ID for exploding each of the four alien slotsContext: See this variable on its own page References: This variable is used as follows: * ExplodeAlien calls explodeTo.explodeFrom EQUB 180 \ Alien slot 30 moves points 180 to 178 when it explodes EQUB 186 \ Alien slot 31 moves points 186 to 183 when it explodes EQUB 191 \ Alien slot 32 moves points 191 to 188 when it explodes EQUB 200 \ Alien slot 33 moves points 200 to 193 when it explodesName: explodeFrom [Show more] Type: Variable Category: The Theme Summary: The starting point ID for exploding each of the four alien slotsContext: See this variable on its own page References: This variable is used as follows: * ExplodeAlien calls explodeFrom.scoreLo EQUB &49 \ Score (low byte of a BCD number) \ \ The score is displayed with an extra "0" added to the \ end, so this contains the score divided by 10Name: scoreLo [Show more] Type: Variable Category: Scoring Summary: Score (low byte)Context: See this variable on its own page References: This variable is used as follows: * DisplayScore calls scoreLo * ResetVariables calls scoreLo * UpdateHighScore calls scoreLo * UpdateScore calls scoreLo.scoreHi EQUB &3D \ Score (high byte of a BCD number) \ \ The score is displayed with an extra "0" added to the \ end, so this contains the score divided by 10Name: scoreHi [Show more] Type: Variable Category: Scoring Summary: Score (high byte)Context: See this variable on its own page References: This variable is used as follows: * DisplayScore calls scoreHi * ResetVariables calls scoreHi * UpdateHighScore calls scoreHi * UpdateScore calls scoreHi.highScoreLo EQUB &26 \ High score (high byte of a BCD number) \ \ The high score is displayed with an extra "0" added to \ the end, so this contains the high score divided by 10Name: highScoreLo [Show more] Type: Variable Category: Scoring Summary: High score (high byte)Context: See this variable on its own page References: This variable is used as follows: * DisplayScore calls highScoreLo * StartGame calls highScoreLo * UpdateHighScore calls highScoreLo.highScoreHi EQUB &34 \ High score (low byte of a BCD number) \ \ The high score is displayed with an extra "0" added to \ the end, so this contains the high score divided by 10Name: highScoreHi [Show more] Type: Variable Category: Scoring Summary: High score (low byte)Context: See this variable on its own page References: This variable is used as follows: * DisplayScore calls highScoreHi * StartGame calls highScoreHi * UpdateHighScore calls highScoreHi.SetEngine CMP engineStatus \ If the value of engineStatus is already the same as A, BEQ seng3 \ jump to seng3 to return from the subroutine STA engineStatus \ Update the value of engineStatus to the new status in \ A TAX \ Either turn the engine sound off (if A = 0) or turn it JSR ToggleEngineSound \ on (if A is non-zero) LDA forceFactor+5 \ Set A to the force factor for zLiftDrag LDX engineStatus \ If the engine is now on, jump to seng1 BNE seng1 CLC \ Set A = A + 20 ADC #20 \ \ so having the engine off increases drag BNE seng2 \ Jump to seng2 (this BNE is effectively a JMP as A is \ never zero) .seng1 SEC \ Set A = A - 20 SBC #20 \ \ so having the engine on decreases drag .seng2 STA forceFactor+5 \ Update the force factor for zLiftDrag, so it is \ incremented by 20 when the engine is off, and reduced \ by 20 when the engine is on, i.e. having the engine \ off increases drag .seng3 RTS \ Return from the subroutineName: SetEngine [Show more] Type: Subroutine Category: Flight model Summary: Set the engine statusContext: See this subroutine on its own page References: This subroutine is called as follows: * ApplyFlightModel (Part 7 of 7) calls SetEngine * MainLoop (Part 11 of 15) calls SetEngine * ProcessLanding (Part 6 of 7) calls SetEngine

Arguments: A The new status of the engine: * 0 = engine off * 1 = engine on.skillZoneLo EQUB &A8, &00, &56 \ Bridge skill zone 0 coordinate = (&4CA8, &0000, &8656) EQUB &A8, &60, &56 \ Bridge skill zone 3 coordinate = (&4CA8, &0060, &8656) EQUB &88, &00, &56 \ Bridge skill zone 6 coordinate = (&4C88, &0000, &8656) EQUB &30, &00, &30 \ Town skill zone 9 coordinate = (&0430, &0000, &0330) EQUB &D0, &00, &70 \ Town skill zone 12 coordinate = (&04D0, &0000, &0470) EQUB &10, &00, &70 \ Town skill zone 15 coordinate = (&0610, &0000, &0470) EQUB &E0, &00, &C0 \ Town skill zone 18 coordinate = (&04E0, &0000, &03C0)Name: skillZoneLo [Show more] Type: Variable Category: Scoring Summary: Low byte of the skill zone coordinates for testing flying skills Deep dive: Flying skillsContext: See this variable on its own page References: This variable is used as follows: * CheckBridgeAndTown calls skillZoneLo.skillZoneHi EQUB &4C, &00, &86 \ Bridge skill zone 0 coordinate = (&4CA8, &0000, &8656) EQUB &4C, &00, &86 \ Bridge skill zone 3 coordinate = (&4CA8, &0060, &8656) EQUB &4C, &00, &86 \ Bridge skill zone 6 coordinate = (&4C88, &0000, &8656) EQUB &04, &00, &03 \ Town skill zone 9 coordinate = (&0430, &0000, &0330) EQUB &04, &00, &04 \ Town skill zone 12 coordinate = (&04D0, &0000, &0470) EQUB &06, &00, &04 \ Town skill zone 15 coordinate = (&0610, &0000, &0470) EQUB &04, &00, &03 \ Town skill zone 18 coordinate = (&04E0, &0000, &03C0)Name: skillZoneHi [Show more] Type: Variable Category: Scoring Summary: High byte of the skill zone coordinates for testing flying skills Deep dive: Flying skillsContext: See this variable on its own page References: This variable is used as follows: * CheckBridgeAndTown calls skillZoneHi.skillZoneSize EQUB &A8, &10, &18 \ Bridge skill zone 0 size = (&A8, &10, &18) EQUB &A8, &16, &18 \ Bridge skill zone 3 size = (&A8, &16, &18) EQUB &B8, &2C, &18 \ Bridge skill zone 6 size = (&B8, &2C, &18) EQUB &A8, &44, &28 \ Town skill zone 9 size = (&A8, &44, &28) EQUB &28, &84, &48 \ Town skill zone 12 size = (&28, &84, &48) EQUB &60, &24, &38 \ Town skill zone 15 size = (&60, &24, &38) EQUB &78, &20, &60 \ Town skill zone 18 size = (&78, &20, &60) EQUB &20 \ This byte appears to be unusedName: skillZoneSize [Show more] Type: Variable Category: Scoring Summary: Sizes of the skill zones for testing flying skills Deep dive: Flying skillsContext: See this variable on its own page References: This variable is used as follows: * CheckBridgeAndTown calls skillZoneSize.shift4Right FOR I%, 0, 255 EQUB HI(I% * 16) NEXTName: shift4Right [Show more] Type: Variable Category: Maths Summary: Lookup table for shifting a byte four places to the right, to extract the high nibble Deep dive: Times tables and nibble arithmeticContext: See this variable on its own page References: This variable is used as follows: * DivideScaled calls shift4Right * Multiply4x16 calls shift4Right * Multiply8x8 calls shift4Right * ScaleUp calls shift4Right * SetObjPointCoords (Part 1 of 2) calls shift4Right

In the table below, shift4Right,X contains the high byte of X * 16. So if X is %XXXXxxxx, shift4Right,X contains %0000XXXX..shift4Left FOR I%, 0, 255 EQUB LO(I% * 16) NEXTName: shift4Left [Show more] Type: Variable Category: Maths Summary: Lookup table for shifting a byte four places to the left, to extract the low nibble Deep dive: Times tables and nibble arithmeticContext: See this variable on its own page References: This variable is used as follows: * DivideScaled calls shift4Left * Multiply4x16 calls shift4Left * Multiply8x8 calls shift4Left * ScaleUp calls shift4Left

In the table below, shift4Left,X contains the low byte of X * 16. So if X is %XXXXxxxx, shift4Left,X contains %xxxx0000..divisionHi EQUB &FF, &FE, &FD, &FC, &FB, &FA, &F9, &F8 EQUB &F7, &F6, &F5, &F4, &F3, &F2, &F1, &F0 EQUB &EF, &EF, &EE, &ED, &EC, &EB, &EA, &E9 EQUB &E9, &E8, &E7, &E6, &E5, &E4, &E4, &E3 EQUB &E2, &E1, &E1, &E0, &DF, &DE, &DD, &DD EQUB &DC, &DB, &DA, &DA, &D9, &D8, &D8, &D7 EQUB &D6, &D5, &D5, &D4, &D3, &D3, &D2, &D1 EQUB &D1, &D0, &CF, &CF, &CE, &CD, &CD, &CC EQUB &CB, &CB, &CA, &C9, &C9, &C8, &C8, &C7 EQUB &C6, &C6, &C5, &C5, &C4, &C3, &C3, &C2 EQUB &C2, &C1, &C0, &C0, &BF, &BF, &BE, &BE EQUB &BD, &BC, &BC, &BB, &BB, &BA, &BA, &B9 EQUB &B9, &B8, &B8, &B7, &B7, &B6, &B6, &B5 EQUB &B5, &B4, &B4, &B3, &B3, &B2, &B2, &B1 EQUB &B1, &B0, &B0, &AF, &AF, &AE, &AE, &AD EQUB &AD, &AC, &AC, &AB, &AB, &AB, &AA, &AA EQUB &A9, &A9, &A8, &A8, &A7, &A7, &A7, &A6 EQUB &A6, &A5, &A5, &A4, &A4, &A4, &A3, &A3 EQUB &A2, &A2, &A2, &A1, &A1, &A0, &A0, &A0 EQUB &9F, &9F, &9E, &9E, &9E, &9D, &9D, &9C EQUB &9C, &9C, &9B, &9B, &9B, &9A, &9A, &99 EQUB &99, &99, &98, &98, &98, &97, &97, &97 EQUB &96, &96, &96, &95, &95, &94, &94, &94 EQUB &93, &93, &93, &92, &92, &92, &91, &91 EQUB &91, &90, &90, &90, &90, &8F, &8F, &8F EQUB &8E, &8E, &8E, &8D, &8D, &8D, &8C, &8C EQUB &8C, &8B, &8B, &8B, &8B, &8A, &8A, &8A EQUB &89, &89, &89, &88, &88, &88, &88, &87 EQUB &87, &87, &86, &86, &86, &86, &85, &85 EQUB &85, &85, &84, &84, &84, &83, &83, &83 EQUB &83, &82, &82, &82, &82, &81, &81, &81 EQUB &81, &80, &80, &80, &80, &7F, &7F, &7FName: divisionHi [Show more] Type: Variable Category: Maths Summary: Division lookup tableContext: See this variable on its own page References: This variable is used as follows: * ProjectPoint (Part 2 of 3) calls divisionHi

This table contains the high byte of the division lookup table, while bits 3 to 7 of divisionLo contain the low byte..timesTable FOR I%, 0, 15 FOR J%, 0, 15 EQUB I% * J% NEXT NEXTName: timesTable [Show more] Type: Variable Category: Maths Summary: Lookup table for multiplication times tables Deep dive: Times tables and nibble arithmeticContext: See this variable on its own page References: This variable is used as follows: * DivideScaled calls timesTable * Multiply4x16 calls timesTable * Multiply8x8 calls timesTable

In the table below, timesTable+X*16,Y contains X * Y. To put it another way, X and Y are both in the range 0 to 15, so they are 4-bit values. If, in binary, they are X = %xxxx and Y = %yyyy, then: timesTable,%xxxxyyyy contains X * Y. This table is used in conjunction with the highNibble and lowNibble tables to look up multiplication results..maxLineDistance EQUB 16 \ Line ID 0 EQUB 125 \ Line ID 1 EQUB 125 \ Line ID 2 EQUB 125 \ Line ID 3 EQUB 125 \ Line ID 4 EQUB 16 \ Line ID 5 EQUB 16 \ Line ID 6 EQUB 16 \ Line ID 7 EQUB 16 \ Line ID 8 EQUB 16 \ Line ID 9 EQUB 40 \ Line ID 10 EQUB 16 \ Line ID 11 EQUB 80 \ Line ID 12 EQUB 80 \ Line ID 13 EQUB 50 \ Line ID 14 EQUB 50 \ Line ID 15 EQUB 50 \ Line ID 16 EQUB 40 \ Line ID 17 EQUB 40 \ Line ID 18 EQUB 40 \ Line ID 19 EQUB 80 \ Line ID 20 EQUB 80 \ Line ID 21 EQUB 40 \ Line ID 22 EQUB 40 \ Line ID 23 EQUB 80 \ Line ID 24 EQUB 80 \ Line ID 25 EQUB 80 \ Line ID 26 EQUB 80 \ Line ID 27 EQUB 80 \ Line ID 28 EQUB 80 \ Line ID 29 EQUB 80 \ Line ID 30 EQUB 80 \ Line ID 31 EQUB 80 \ Line ID 32 EQUB 80 \ Line ID 33 EQUB 80 \ Line ID 34 EQUB 80 \ Line ID 35 EQUB 80 \ Line ID 36 EQUB 80 \ Line ID 37 EQUB 80 \ Line ID 38 EQUB 60 \ Line ID 39 EQUB 70 \ Line ID 40 EQUB 60 \ Line ID 41 EQUB 70 \ Line ID 42 EQUB 60 \ Line ID 43 EQUB 70 \ Line ID 44 EQUB 60 \ Line ID 45 EQUB 70 \ Line ID 46 EQUB 63 \ Line ID 47 EQUB 63 \ Line ID 48 EQUB 63 \ Line ID 49 EQUB 63 \ Line ID 50 EQUB 60 \ Line ID 51 EQUB 70 \ Line ID 52 EQUB 60 \ Line ID 53 EQUB 70 \ Line ID 54 EQUB 60 \ Line ID 55 EQUB 63 \ Line ID 56 EQUB 63 \ Line ID 57 EQUB 63 \ Line ID 58 EQUB 63 \ Line ID 59 EQUB 30 \ Line ID 60 EQUB 30 \ Line ID 61 EQUB 70 \ Line ID 62 EQUB 60 \ Line ID 63 EQUB 70 \ Line ID 64 EQUB 60 \ Line ID 65 EQUB 70 \ Line ID 66 EQUB 60 \ Line ID 67 EQUB 70 \ Line ID 68 EQUB 60 \ Line ID 69 EQUB 70 \ Line ID 70 EQUB 60 \ Line ID 71 EQUB 70 \ Line ID 72 EQUB 60 \ Line ID 73 EQUB 70 \ Line ID 74 EQUB 60 \ Line ID 75 EQUB 120 \ Line ID 76 EQUB 70 \ Line ID 77 EQUB 125 \ Line ID 78 EQUB 125 \ Line ID 79 EQUB 125 \ Line ID 80 EQUB 125 \ Line ID 81 EQUB 125 \ Line ID 82 EQUB 125 \ Line ID 83 EQUB 125 \ Line ID 84 EQUB 125 \ Line ID 85 EQUB 125 \ Line ID 86 EQUB 125 \ Line ID 87 EQUB 125 \ Line ID 88 EQUB 125 \ Line ID 89 EQUB 125 \ Line ID 90 EQUB 125 \ Line ID 91 EQUB 125 \ Line ID 92 EQUB 125 \ Line ID 93 EQUB 125 \ Line ID 94 EQUB 125 \ Line ID 95 EQUB 125 \ Line ID 96 EQUB 125 \ Line ID 97 EQUB 125 \ Line ID 98 EQUB 125 \ Line ID 99 EQUB 125 \ Line ID 100 EQUB 125 \ Line ID 101 EQUB 125 \ Line ID 102 EQUB 125 \ Line ID 103 EQUB 125 \ Line ID 104 EQUB 125 \ Line ID 105 EQUB 125 \ Line ID 106 EQUB 125 \ Line ID 107 EQUB 125 \ Line ID 108 EQUB 125 \ Line ID 109 EQUB 125 \ Line ID 110 EQUB 125 \ Line ID 111 EQUB 125 \ Line ID 112 EQUB 125 \ Line ID 113 EQUB 125 \ Line ID 114 EQUB 125 \ Line ID 115 EQUB 125 \ Line ID 116 EQUB 125 \ Line ID 117 EQUB 125 \ Line ID 118 EQUB 125 \ Line ID 119 EQUB 125 \ Line ID 120 EQUB 125 \ Line ID 121 EQUB 125 \ Line ID 122 EQUB 120 \ Line ID 123 EQUB 125 \ Line ID 124 EQUB 125 \ Line ID 125 EQUB 125 \ Line ID 126 EQUB 125 \ Line ID 127 EQUB 125 \ Line ID 128 EQUB 125 \ Line ID 129 EQUB 125 \ Line ID 130 EQUB 125 \ Line ID 131 EQUB 125 \ Line ID 132 EQUB 125 \ Line ID 133 EQUB 125 \ Line ID 134 EQUB 25 \ Line ID 135 EQUB 25 \ Line ID 136 EQUB 25 \ Line ID 137 EQUB 100 \ Line ID 138 EQUB 100 \ Line ID 139 EQUB 100 \ Line ID 140 EQUB 100 \ Line ID 141 EQUB 100 \ Line ID 142 EQUB 100 \ Line ID 143 EQUB 100 \ Line ID 144 EQUB 100 \ Line ID 145 EQUB 100 \ Line ID 146 EQUB 100 \ Line ID 147 EQUB 100 \ Line ID 148 EQUB 100 \ Line ID 149 EQUB 120 \ Line ID 150 EQUB 100 \ Line ID 151 EQUB 100 \ Line ID 152 EQUB 100 \ Line ID 153 EQUB 100 \ Line ID 154 EQUB 100 \ Line ID 155 EQUB 100 \ Line ID 156 EQUB 100 \ Line ID 157 EQUB 100 \ Line ID 158 EQUB 100 \ Line ID 159 EQUB 100 \ Line ID 160 EQUB 120 \ Line ID 161 EQUB 120 \ Line ID 162 EQUB 120 \ Line ID 163 EQUB 120 \ Line ID 164 EQUB 120 \ Line ID 165 EQUB 120 \ Line ID 166 EQUB 120 \ Line ID 167 EQUB 120 \ Line ID 168 EQUB 60 \ Line ID 169 EQUB 60 \ Line ID 170 EQUB 60 \ Line ID 171 EQUB 60 \ Line ID 172 EQUB 60 \ Line ID 173 EQUB 60 \ Line ID 174 EQUB 60 \ Line ID 175 EQUB 60 \ Line ID 176 EQUB 60 \ Line ID 177 EQUB 60 \ Line ID 178 EQUB 60 \ Line ID 179 EQUB 60 \ Line ID 180 EQUB 60 \ Line ID 181 EQUB 60 \ Line ID 182 EQUB 60 \ Line ID 183 EQUB 60 \ Line ID 184 EQUB 60 \ Line ID 185 EQUB 120 \ Line ID 186 EQUB 120 \ Line ID 187 EQUB 120 \ Line ID 188 EQUB 120 \ Line ID 189 EQUB 120 \ Line ID 190 EQUB 120 \ Line ID 191 EQUB 120 \ Line ID 192 EQUB &3F, &0D \ These bytes appear to be unused EQUB &03, &B1 EQUB &10, &2E EQUB &64, &6C EQUB &70, &32 EQUB &20, &53 EQUB &54, &41 EQUB &26, &37 EQUB &36, &0D EQUB &03, &B2 EQUB &19, &2E EQUB &64Name: maxLineDistance [Show more] Type: Variable Category: Visibility Summary: The furthest distance at which each line is visible Deep dive: Lines and pointsContext: See this variable on its own page References: This variable is used as follows: * CheckLineDistance calls maxLineDistance

Lines are only shown if they are closer than the distance in this table, so this table contains the maximum visible distance for each line. The table is indexed by line ID, so for line ID X, maxLineDistance,X contains the maximum distance at which that line is visible, in any of the individual axes..maxObjDistance EQUB 108 \ Object 0 EQUB 125 \ Object 1 EQUB 125 \ Object 2 EQUB 125 \ Object 3 EQUB 125 \ Object 4 EQUB 125 \ Object 5 EQUB 40 \ Object 6 EQUB 40 \ Object 7 EQUB 110 \ Object 8 EQUB 110 \ Object 9 EQUB 58 \ Object 10 EQUB 66 \ Object 11 EQUB 30 \ Object 12 EQUB 30 \ Object 13 EQUB 30 \ Object 14 EQUB 30 \ Object 15 EQUB 125 \ Object 16 EQUB 125 \ Object 17 EQUB 125 \ Object 18 EQUB 125 \ Object 19 EQUB 125 \ Object 20 EQUB 125 \ Object 21 EQUB 125 \ Object 22 EQUB 125 \ Object 23 EQUB 125 \ Object 24 EQUB 125 \ Object 25 EQUB 125 \ Object 26 EQUB 125 \ Object 27 EQUB 125 \ Object 28 EQUB 125 \ Object 29 EQUB 25 \ Object 30 EQUB 90 \ Object 31 EQUB 90 \ Object 32 EQUB 90 \ Object 33 EQUB 125 \ Object 34 EQUB 58 \ Object 35 EQUB 66 \ Object 36 EQUB 78 \ Object 37 EQUB 69 \ Object 38 EQUB 32 \ Object 39Name: maxObjDistance [Show more] Type: Variable Category: Visibility Summary: The furthest distance at which each object is visibleContext: See this variable on its own page References: This variable is used as follows: * CheckObjDistance calls maxObjDistance

Objects are only shown if they are closer than the distance in this table, so this table contains the maximum visible distance for each object. The table is indexed by object ID, so for object ID X, maxObjDistance,X contains the maximum distance at which that object is visible, in any of the individual axes. The initial contents of the last five bytes of this table contains workspace noise and is ignored. It actually contains snippets of the original source code.

[X]

Subroutine AddPointToObject (category: 3D geometry)

Add a point vector to an object's coordinates

[X]

Subroutine AddTempToPoint (Part 1 of 2) (category: 3D geometry)

Add the xTemp1 vector to a point, store the result in another point, and set the result to hidden if it overflows

[X]

Subroutine CheckAlienWeakSpot (category: The Theme)

Check whether an object is close enough to an alien's weak spot to be hitting it

[X]

Subroutine CheckLineDistance (category: Visibility)

Check whether a point on a line is within the visible distance for the line

[X]

Subroutine CopyPointToWork (category: Utility routines)

Copy a point from the point tables to the variable workspace

[X]

Subroutine CopyWorkToPoint (category: Utility routines)

Copy a point from the variable workspace to the point tables

[X]

Subroutine Delay (category: Utility routines)

Delay for a specified number of loops

[X]

Entry point DrawClippedHorizon in subroutine DrawClippedLine (Part 1 of 6) (category: Drawing lines)

Set bit 1 of the line direction in V (for the horizon)

[X]

Subroutine DrawFuelPixel (category: Dashboard)

Draw or erase a pixel on the fuel gauge on the dashboard

[X]

Subroutine DrawVectorLine (Part 1 of 3) (category: Drawing lines)

Draw a line: set up pixel bytes and slope variables

[X]

Subroutine GetAlienWeakSpot (category: The Theme)

Calculate the coordinates of an alien's weak spot

[X]

Subroutine GetTrailVectorStep (category: The Theme)

Calculate 1/32 of the vector for a bullet trail

[X]

Subroutine IndicatorF (category: Dashboard)

Update the flaps indicator ("F") and and related variables

[X]

[X]

Subroutine NewGame (category: Setup)

Start a new game

[X]

Subroutine PrintTooLate (category: The Theme)

Print the "TOO LATE!" message at column 6, row 7 on-screen

[X]

Subroutine ResizeFeedingAlien (category: The Theme)

Change the size of an alien so it grows bigger as it feeds

[X]

Subroutine ScanKeyboard (category: Keyboard)

Scan the keyboard for a specific key

[X]

Subroutine ScorePoints (category: Scoring)

Increase the score and make a beep

[X]

Subroutine SetObjPointCoords (Part 1 of 2) (category: 3D geometry)

Calculate the coordinate for a point within an object

[X]

Subroutine SetObjectCoords (Part 1 of 11) (category: 3D geometry)

Calculate the coordinates for an object's location

[X]

Subroutine SetPointVisibility (category: 3D geometry)

Set the status byte for multiple points to indicate that their coordinates and visibility have been calculated

[X]

Subroutine TerminateGame (category: Setup)

Terminate the current game

[X]

Subroutine ToggleEngineSound (category: Sound)

Turn the engine sound on or off

[X]

Configuration variable: VIA = &FE00

Memory-mapped space for accessing internal hardware, such as the video ULA, 6845 CRTC and 6522 VIAs (also known as SHEILA)

[X]

Label acrn1 in subroutine AlienInAcornsville

[X]

Label acrn2 in subroutine AlienInAcornsville

[X]

Label acrn3 in subroutine AlienInAcornsville

[X]

Label acrn4 in subroutine AlienInAcornsville

[X]

Label acrn5 in subroutine AlienInAcornsville

[X]

Label acrn6 in subroutine AlienInAcornsville

[X]

Label acrn7 in subroutine AlienInAcornsville

[X]

Label acrn8 in subroutine AlienInAcornsville

[X]

Label ahit1 in subroutine CheckIfAlienIsHit (Part 1 of 2)

[X]

Label ahit10 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit11 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit12 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit2 in subroutine CheckIfAlienIsHit (Part 1 of 2)

[X]

Label ahit3 in subroutine CheckIfAlienIsHit (Part 1 of 2)

[X]

Label ahit4 in subroutine CheckIfAlienIsHit (Part 1 of 2)

[X]

Label ahit5 in subroutine CheckIfAlienIsHit (Part 1 of 2)

[X]

Label ahit6 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit7 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit8 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Label ahit9 in subroutine CheckIfAlienIsHit (Part 2 of 2)

[X]

Variable alienObjectId (category: The Theme)

Object IDs for each of the eight aliens

[X]

Variable alienSlot (category: The Theme)

Slots for up to three aliens that are ready to start moving towards the town

[X]

Variable alienSpeed in workspace Main variable workspace

The speed at which the aliens move, which starts at 10 for the first wave, then 14 for the second, 18 for the third, and 22 for all subsequent waves

[X]

Variable alienState (category: The Theme)

The state of each of the eight aliens

[X]

Variable alienToMove (category: The Theme)

The number of the alien to move towards Acornsville in this iteration of the main loop

[X]

Label bulv1 in subroutine GetTrailVectorStep

[X]

Label bulv2 in subroutine GetTrailVectorStep

[X]

Variable engineStatus in workspace Main variable workspace

Engine status

[X]

Variable feedingStage (category: The Theme)

The feeding stage of the alien we are currently processing

[X]

Label fill1 in subroutine FillCanopyRows

[X]

Label fill2 in subroutine FillCanopyRows

[X]

Label fill3 in subroutine FillCanopyRows

[X]

Label fill4 in subroutine FillCanopyRows

[X]

Variable firingStatus in workspace Main variable workspace

Firing status

[X]

Label flap1 in subroutine RetractFlapsIfFast

[X]

Variable flapsStatus in workspace Main variable workspace

Flaps status

[X]

Variable forceFactor (category: Flight model)

The factors by which the flight forces are multiplied as part of the scaling process

[X]

Label fuel1 in subroutine FillUpFuelTank

[X]

Label fuel2 in subroutine FillUpFuelTank

[X]

Variable fuelLevel (category: Flight model)

The current fuel level

[X]

Variable hitObjectId (category: The Theme)

The object ID of the alien we just hit (30 to 33)

[X]

Variable hitTimer (category: The Theme)

The time since we hit an alien, so we can time its explosion

[X]

Variable landingStatus in workspace Main variable workspace

The current landing status

[X]

Variable mainLoopCounter (category: Main loop)

The main loop counter

[X]

Variable matrixNumber in workspace Main variable workspace

The matrix used in matrix operations

[X]

Configuration variable: nextAxis = 40

The xObject, yObject and zObject tables each contain 40 bytes, and they are positioned one after the other in memory, so if we access, say, the x-coordinate for object Y at xObjectHi+Y, then adding #nextAxis to Y will point xObjectHi+Y to the y-coordinate, and adding it again will point it to the z-coordinate

[X]

Variable objectAnchorPoint in workspace Main variable workspace

Used to store the anchor point of the current object

[X]

Variable objectId in workspace Main variable workspace

Temporary storage for an object ID (0 to 39)

[X]

Variable objectStatus in workspace Main variable workspace

Each object's status byte

[X]

Variable onGround in workspace Main variable workspace

"On the ground" status

[X]

Variable pointStatus in workspace Main variable workspace

Each point's status byte

[X]

Variable previousCompass (category: Dashboard)

Stores the value of the compass heading when we draw the runway on the radar, so we can erase the line later

[X]

Label prun1 in subroutine ProcessRunwayLine (Part 1 of 5)

[X]

Label prun10 in subroutine ProcessRunwayLine (Part 3 of 5)

[X]

Label prun11 in subroutine ProcessRunwayLine (Part 3 of 5)

[X]

Label prun12 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun13 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun14 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun15 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun16 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun17 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun18 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun19 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun2 in subroutine ProcessRunwayLine (Part 1 of 5)

[X]

Label prun20 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun21 in subroutine ProcessRunwayLine (Part 4 of 5)

[X]

Label prun22 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun23 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun24 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun25 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun26 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun27 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun28 in subroutine ProcessRunwayLine (Part 5 of 5)

[X]

Label prun3 in subroutine ProcessRunwayLine (Part 2 of 5)

[X]

Label prun4 in subroutine ProcessRunwayLine (Part 2 of 5)

[X]

Label prun5 in subroutine ProcessRunwayLine (Part 2 of 5)

[X]

Label prun6 in subroutine ProcessRunwayLine (Part 2 of 5)

[X]

Label prun7 in subroutine ProcessRunwayLine (Part 3 of 5)

[X]

Label prun8 in subroutine ProcessRunwayLine (Part 3 of 5)

[X]

Label prun9 in subroutine ProcessRunwayLine (Part 3 of 5)

[X]

Configuration variable: row1_block1_0 = &5948

Second block on second row

[X]

Configuration variable: row25_block13_1 = &77A9

Bottom middle block of artificial horizon

[X]

Label rvec1 in subroutine GetRadarVector

[X]

Label rvec2 in subroutine GetRadarVector

[X]

Label rvec3 in subroutine GetRadarVector

[X]

Variable showLine in workspace Main variable workspace

Determines whether a line is visible

[X]

Variable showRunwayDashes in workspace Main variable workspace

Determines whether the dashes down the middle of the runway are close enough to be visible

[X]

Label size1 in subroutine ResizeFeedingAlien

[X]

Label size2 in subroutine ResizeFeedingAlien

[X]

Label size3 in subroutine ResizeFeedingAlien

[X]

Variable soundData (category: Sound)

OSWORD blocks for making the various game sounds

[X]

Label spaw1 in subroutine SpawnAlien

[X]

Label spaw2 in subroutine SpawnAlien

[X]

Label spaw3 in subroutine SpawnAlien

[X]

Label spot1 in subroutine CheckAlienWeakSpot

[X]

Label spot2 in subroutine CheckAlienWeakSpot

[X]

Variable themeStatus in workspace Main variable workspace

Theme status

[X]

Label ubul1 in subroutine UpdateBullets

[X]

Label ubul2 in subroutine UpdateBullets

[X]

Label ubul3 in subroutine UpdateBullets

[X]

Label upal1 in subroutine UpdateAliens (Part 1 of 5)

[X]

Label upal10 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal11 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal12 in subroutine UpdateAliens (Part 3 of 5)

[X]

Label upal13 in subroutine UpdateAliens (Part 3 of 5)

[X]

Label upal14 in subroutine UpdateAliens (Part 3 of 5)

[X]

Label upal15 in subroutine UpdateAliens (Part 4 of 5)

[X]

Label upal16 in subroutine UpdateAliens (Part 4 of 5)

[X]

Label upal17 in subroutine UpdateAliens (Part 4 of 5)

[X]

Label upal18 in subroutine UpdateAliens (Part 5 of 5)

[X]

Label upal19 in subroutine UpdateAliens (Part 5 of 5)

[X]

Label upal2 in subroutine UpdateAliens (Part 1 of 5)

[X]

Label upal3 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal4 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal5 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal6 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal7 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal8 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upal9 in subroutine UpdateAliens (Part 2 of 5)

[X]

Label upfu1 in subroutine UpdateFuelGauge

[X]

Label upsi1 in subroutine ShowUpsideDownBar

[X]

Label upsi2 in subroutine ShowUpsideDownBar

[X]

Label volk1 in subroutine ProcessVolumeKeys

[X]

Label volk2 in subroutine ProcessVolumeKeys

[X]

Label volk3 in subroutine ProcessVolumeKeys

[X]

Label volk4 in subroutine ProcessVolumeKeys

[X]

Label weak1 in subroutine GetAlienWeakSpot

[X]

Label weak2 in subroutine GetAlienWeakSpot

[X]

Label weak3 in subroutine GetAlienWeakSpot

[X]

Variable xDashesVectorLo in workspace Main variable workspace

The low byte of the xDashesVector temporary variable

[X]

Variable xObjectHi (category: 3D geometry)

High byte of the x-coordinate for an object

[X]

Variable xObjectLo (category: 3D geometry)

Low byte of the x-coordinate for an object

[X]

Variable xPointHi (category: 3D geometry)

High byte of the x-coordinate for a point

[X]

Variable xPointLo in workspace Main variable workspace

The low byte of the x-coordinate for the point with ID X is at xPointLo,X

[X]

Variable xTemp1Hi in workspace Main variable workspace

The high byte of the xTemp1 temporary variable

[X]

Variable xTemp1Lo in workspace Main variable workspace

The low byte of the xTemp1 temporary variable

[X]

Variable xTemp2Hi in workspace Main variable workspace

The high byte of the xTemp2 temporary variable

[X]

Variable xTemp2Lo in workspace Main variable workspace

The low byte of the xTemp2 temporary variable

[X]

Variable xTemp2Top in workspace Main variable workspace

The top byte of the xTemp2 temporary variable

[X]

Variable yObjectHi (category: 3D geometry)

High byte of the y-coordinate for an object

[X]

Variable yObjectLo (category: 3D geometry)

Low byte of the y-coordinate for an object

[X]

Variable yPointHi in workspace Main variable workspace

The high byte of the y-coordinate for the point with ID X is at yPointHi,X

[X]

Variable yPointLo in workspace Main variable workspace

The low byte of the y-coordinate for the point with ID X is at yPointLo,X

[X]

Variable zObjectPoint (category: 3D geometry)

Scaled z-coordinates of the points that make up objects, relative to the object's anchor point

[X]

Variable zPointHi (category: 3D geometry)

High byte of the z-coordinate for a point

[X]

Variable zRotationHi in workspace Main variable workspace

Plane rotation angle around the z-axis (high byte)