.NWSHP STA T ; Store the ship type in location T LDX #0 ; Before we can add a new ship, we need to check ; whether we have an empty slot we can put it in. To do ; this, we need to loop through all the slots to look ; for an empty one, so set a counter in X that starts ; from the first slot at 0. When ships are killed, then ; the slots are shuffled down by the KILLSHP routine, so ; the first empty slot will always come after the last ; filled slot. This allows us to tack the new ship's ; data block and ship line heap onto the end of the ; existing ship data and heap, as shown in the memory ; map below .NWL1 LDA FRIN,X ; Load the ship type for the X-th slot BEQ NW1 ; If it is zero, then this slot is empty and we can use ; it for our new ship, so jump down to NW1 INX ; Otherwise increment X to point to the next slot CPX #NOSH ; If we haven't reached the last slot yet, loop back up BCC NWL1 ; to NWL1 to check the next slot (note that this means ; only slots from 0 to #NOSH - 1 are populated by this ; routine, but there is one more slot reserved in FRIN, ; which is used to identify the end of the slot list ; when shuffling the slots down in the KILLSHP routine) .NW3 CLC ; Otherwise we don't have an empty slot, so we can't RTS ; add a new ship, so clear the C flag to indicate that ; we have not managed to create the new ship, and return ; from the subroutine .NW1 ; If we get here, then we have found an empty slot at ; index X, so we can go ahead and create our new ship. ; We do that by creating a ship data block at INWK and, ; when we are done, copying the block from INWK into ; the K% workspace (specifically, to INF) JSR GINF ; Get the address of the data block for ship slot X ; (which is in workspace K%) and store it in INF LDA T ; If the type of ship that we want to create is BMI NW2 ; negative, then this indicates a planet or sun, so ; jump down to NW2, as the next section sets up a ship ; data block, which doesn't apply to planets and suns, ; as they don't have things like shields, missiles, ; vertices and edges ; This is a ship, so first we need to set up various ; pointers to the ship blueprint we will need. The ; blueprints for each ship type in Elite are stored ; in a table at location XX21, so refer to the comments ; on that variable for more details on the data we're ; about to access ASL A ; Set Y = ship type * 2 TAY LDA XX21-1,Y ; The ship blueprints at XX21 start with a lookup ; table that points to the individual ship blueprints, ; so this fetches the high byte of this particular ship ; type's blueprint BEQ NW3 ; If the high byte is 0 then this is not a valid ship ; type, so jump to NW3 to clear the C flag and return ; from the subroutine STA XX0+1 ; This is a valid ship type, so store the high byte in ; XX0+1 LDA XX21-2,Y ; Fetch the low byte of this particular ship type's STA XX0 ; blueprint and store it in XX0, so XX0(1 0) now ; contains the address of this ship's blueprint CPY #2*SST ; If the ship type is a space station (SST), then jump BEQ NW6 ; to NW6, skipping the heap space steps below, as the ; space station has its own line heap at LSO (which it ; shares with the sun) ; We now want to allocate space for a heap that we can ; use to store the lines we draw for our new ship (so it ; can easily be erased from the screen again). SLSP ; points to the start of the current heap space, and we ; can extend it downwards with the heap for our new ship ; (as the heap space always ends just before the WP ; workspace) LDY #5 ; Fetch ship blueprint byte #5, which contains the LDA (XX0),Y ; maximum heap size required for plotting the new ship, STA T1 ; and store it in T1 LDA SLSP ; Take the 16-bit address in SLSP and subtract T1, SEC ; storing the 16-bit result in INWK(34 33), so this now SBC T1 ; points to the start of the line heap for our new ship STA INWK+33 LDA SLSP+1 SBC #0 STA INWK+34 ; We now need to check that there is enough free space ; for both this new line heap and the new data block ; for our ship. In memory, this is the layout of the ; ship data blocks and ship line heaps: ; ; +-----------------------------------+ $FFC0 = LS% ; | | ; | Current ship line heap | ; | | ; +-----------------------------------+ SLSP ; | | ; | Proposed heap for new ship | ; | | ; +-----------------------------------+ INWK(34 33) ; | | ; . . ; . . ; . . ; . . ; . . ; | | ; +-----------------------------------+ INF + NI% ; | | ; | Proposed data block for new ship | ; | | ; +-----------------------------------+ INF ; | | ; | Existing ship data blocks | ; | | ; +-----------------------------------+ $F900 = K% ; ; So, to work out if we have enough space, we have to ; make sure there is room between the end of our new ; ship data block at INF + NI%, and the start of the ; proposed heap for our new ship at the address we ; stored in INWK(34 33). Or, to put it another way, we ; and to make sure that: ; ; INWK(34 33) > INF + NI% ; ; which is the same as saying: ; ; INWK+33 - INF > NI% ; ; because INWK is in zero page, so INWK+34 = 0 LDA INWK+33 ; Calculate INWK+33 - INF, again using 16-bit ;SEC ; arithmetic, and put the result in (A Y), so the high SBC INF ; byte is in A and the low byte in Y. The SEC TAY ; instruction is commented out in the original source; LDA INWK+34 ; as the previous subtraction will never underflow, it SBC INF+1 ; is superfluous BCC NW3+1 ; If we have an underflow from the subtraction, then ; INF > INWK+33 and we definitely don't have enough ; room for this ship, so jump to NW3+1, which returns ; from the subroutine (with the C flag already cleared) BNE NW4 ; If the subtraction of the high bytes in A is not ; zero, and we don't have underflow, then we definitely ; have enough space, so jump to NW4 to continue setting ; up the new ship CPY #NI% ; Otherwise the high bytes are the same in our BCC NW3+1 ; subtraction, so now we compare the low byte of the ; result (which is in Y) with NI%. This is the same as ; doing INWK+33 - INF > NI% (see above). If this isn't ; true, the C flag will be clear and we don't have ; enough space, so we jump to NW3+1, which returns ; from the subroutine (with the C flag already cleared) .NW4 LDA INWK+33 ; If we get here then we do have enough space for our STA SLSP ; new ship, so store the new bottom of the ship line LDA INWK+34 ; heap (i.e. INWK+33) in SLSP, doing both the high and STA SLSP+1 ; low bytes .NW6 LDY #14 ; Fetch ship blueprint byte #14, which contains the LDA (XX0),Y ; ship's energy, and store it in byte #35 STA INWK+35 LDY #19 ; Fetch ship blueprint byte #19, which contains the LDA (XX0),Y ; number of missiles and laser power, and AND with %111 AND #%00000111 ; to extract the number of missiles before storing in STA INWK+31 ; byte #31 LDA T ; Restore the ship type we stored above .NW2 STA FRIN,X ; Store the ship type in the X-th byte of FRIN, so the ; this slot is now shown as occupied in the index table TAX ; Copy the ship type into X BMI NW8 ; If the ship type is negative (planet or sun), then ; jump to NW8 to skip the following instructions CPX #HER ; If the ship type is a rock hermit, jump to gangbang BEQ gangbang ; to increase the junk count CPX #JL ; If JL <= X < JH, i.e. the type of ship we killed in X BCC NW7 ; is junk (escape pod, alloy plate, cargo canister, CPX #JH ; asteroid, splinter, Shuttle or Transporter), then keep BCS NW7 ; going, otherwise jump to NW7 .gangbang INC JUNK ; We're adding junk, so increase the junk counter .NW7 INC MANY,X ; Increment the total number of ships of type X .NW8 LDY T ; Restore the ship type we stored above LDA E%-1,Y ; Fetch the E% byte for this ship to get the default ; settings for the ship's NEWB flags AND #%01101111 ; Zero bits 4 and 7 (so the new ship is not docking, has ; not been scooped, and has not just docked) ORA NEWB ; Apply the result to the ship's NEWB flags, which sets STA NEWB ; bits 0-3 and 5-6 in NEWB if they are set in the E% ; byte LDY #NI%-1 ; The final step is to copy the new ship's data block ; from INWK to INF, so set up a counter for NI% bytes ; in Y .NWL3 LDA INWK,Y ; Load the Y-th byte of INWK and store in the Y-th byte STA (INF),Y ; of the workspace pointed to by INF DEY ; Decrement the loop counter BPL NWL3 ; Loop back for the next byte until we have copied them ; all over SEC ; We have successfully created our new ship, so set the ; C flag to indicate success RTS ; Return from the subroutineName: NWSHP [Show more] Type: Subroutine Category: Universe Summary: Add a new ship to our local bubble of universeContext: See this subroutine in context in the source code References: This subroutine is called as follows: * BRIEF calls NWSHP * FRS1 calls NWSHP * GTHG calls NWSHP * KS4 calls NWSHP * Main game loop (Part 1 of 6) calls NWSHP * Main game loop (Part 2 of 6) calls NWSHP * Main game loop (Part 3 of 6) calls NWSHP * Main game loop (Part 4 of 6) calls NWSHP * SFS1 calls NWSHP * SOLAR calls NWSHP * SOS1 calls NWSHP * TITLE calls NWSHP
This creates a new block of ship data in the K% workspace, allocates a new block in the ship line heap at WP, adds the new ship's type into the first empty slot in FRIN, and adds a pointer to the ship data into UNIV. If there isn't enough free memory for the new ship, it isn't added.
Arguments: A The type of the ship to add (see variable XX21 for a list of ship types)
Returns: C flag Set if the ship was successfully added, clear if it wasn't (as there wasn't enough free memory) INF Points to the new ship's data block in K%
[X]
Configuration variable E% = $D042
The address of the default NEWB ship bytes, as set in elite-data.asm
[X]
Subroutine GINF (category: Universe)
Fetch the address of a ship's data block into INF
[X]
Configuration variable HER = 15
Ship type for a rock hermit (asteroid)
[X]
Configuration variable JH = SHU+2
Junk is defined as ending before the Cobra Mk III
[X]
Configuration variable JL = ESC
Junk is defined as starting from the escape pod
[X]
Configuration variable NI% = 37
The number of bytes in each ship's data block (as stored in INWK and K%)
[X]
Configuration variable NOSH = 10
The maximum number of ships in our local bubble of universe
[X]
Label NW1 is local to this routine
[X]
Label NW2 is local to this routine
[X]
Label NW3 is local to this routine
[X]
[X]
Label NW4 is local to this routine
[X]
Label NW6 is local to this routine
[X]
Label NW7 is local to this routine
[X]
Label NW8 is local to this routine
[X]
Label NWL1 is local to this routine
[X]
Label NWL3 is local to this routine
[X]
Configuration variable SST = 2
Ship type for a Coriolis space station
[X]
Temporary storage, used to store the address of a ship blueprint. For example, it is used when we add a new ship to the local bubble in routine NWSHP, and it contains the address of the current ship's blueprint as we loop through all the nearby ships in the main flight loop
[X]
Configuration variable XX21 = $D000
The address of the ship blueprints lookup table, as set in elite-data.asm
[X]
Label gangbang is local to this routine