Skip to navigation

Revs on the BBC Micro

Drivers: SortDrivers

Name: SortDrivers [Show more] Type: Subroutine Category: Drivers Summary: Create a sorted list of driver numbers, ordered as specified
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainLoop (Part 3 of 6) calls SortDrivers * MainLoop (Part 4 of 6) calls SortDrivers * MainLoop (Part 6 of 6) calls SortDrivers

This routine sorts the driver list in driversInOrder according to the value specified by argument A. It also populates carStatus with the position numbers for the sorted driver list, which will typically run from 0 to 19, but may also contain repeated numbers in the case of a tie. The routine uses a basic bubble sort algorithm, swapping neighbouring drivers repeatedly until the whole list is sorted. This is not very efficient, but as this is only done when showing the driver table between races, that doesn't matter.
Arguments: A Determines the order of the sorted list to create: * 0 = best lap times * Bit 6 set = accumulated points * Bit 7 set = total race times
Returns: positionNumber A list of position numbers, from 0 to 19, ready to print in the first column of the driver table (with 1 added), with drivers who are tied in the same position sharing the same number driversInOrder A list of driver numbers, sorted according to the value specified by argument A
.SortDrivers STA G \ Store A in G SED \ Set the D flag to switch arithmetic to Binary Coded \ Decimal (BCD) .sort1 LDX #0 \ Set V = 0, which we will use to indicate whether the STX V \ driversInOrder list is sorted \ \ We start at 0 to indicate it is sorted, and change it \ if we have to reorder the list STX positionNumber \ Set the first entry in positionNumber to 0, as the \ winning driver will always be in position 0 INX \ Set X = 1 as a position counter, counting through 1 to \ 19, which denotes the position number that we are \ processing in this iteration of the loop (we skip the \ first position as we already set it) .sort2 STX W \ Store the position counter in W LDY driversInOrder,X \ Set Y to the number of the driver at position X in the \ driversInOrder list ("this driver") TXA \ Set the X-th entry in positionNumber to the position STA positionNumber,X \ counter (as the X-th driver is in position X) LDA driversInOrder-1,X \ Set X to the number of the driver at position X - 1 in TAX \ the driversInOrder list ("the driver ahead") SEC \ Set the C flag for the subtractions below BIT G \ If bit 6 of G is set, jump to sort5 to compare total BVS sort5 \ points BMI sort6 \ If bit 7 of G is set, jump to sort6 to compare best \ lap times \ If we get here then bit 6 and 7 of G are clear, so we \ compare most recent lap times LDA bestLapTenths,Y \ Set (A H U) = this driver's best lap time SBC bestLapTenths,X \ - best lap time of the driver ahead STA U \ \ starting with the tenths of a second LDA bestLapSeconds,Y \ Then the seconds SBC bestLapSeconds,X STA H LDA bestLapMinutes,Y \ And then the minutes SBC bestLapMinutes,X BCC sort7 \ If the subtraction underflowed, then this driver's \ lap time is quicker than the lap time of the driver \ ahead, which is the wrong way round if we are trying \ to create a list where the winner has the fastest lap \ time, so jump to sort7 to swap them around in the \ driversInOrder list .sort3 ORA U \ At this point (A H U) contains the difference between ORA H \ the two drivers' times/points, so this jumps to sort4 BNE sort4 \ if any of the bytes in (A U H) are non-zero, i.e. if \ the two drivers have different times/points LDX W \ The two drivers have identical times/points, so set DEX \ we need to set the current driver's position number to LDA positionNumber,X \ be the same as the position number of the driver ahead STA positionNumber+1,X \ as there is a tie .sort4 \ If we get here then we move on to the next position LDX W \ Fetch the position counter that we stored in W above INX \ Increment the position counter to the next position CPX #20 \ Loop back until we have gone through the whole table BCC sort2 \ of 20 positions LDA V \ If V <> 0 then we had to alter the order of the BNE sort1 \ driversInOrder list, as it wasn't fully sorted, so \ we jump back to sort1 to repeat the whole process as \ we don't yet know that the list is fully sorted CLD \ Otherwise the driversInOrder list is sorted, so clear \ the D flag to switch arithmetic to normal JSR SetPlayerPositions \ Set the current player's position, plus the position \ ahead and the position behind RTS \ Return from the subroutine .sort5 LDA totalPointsLo,X \ Set (A H U) = total points of the driver ahead SBC totalPointsLo,Y \ - this driver's total points STA U \ \ starting with the low bytes LDA totalPointsHi,X \ Then the high bytes SBC totalPointsHi,Y STA H LDA totalPointsTop,X \ And then the top bytes SBC totalPointsTop,Y BCC sort7 \ If the subtraction underflowed, then this driver has \ more points than the driver ahead, which is the wrong \ way round if we are trying to create a list where the \ winner has the most points, so jump to sort7 to swap \ them around in the driversInOrder list BCS sort3 \ Jump to sort3 to check for a tie and move on to the \ next position (this BCS is effectively a JMP as we \ just passed through a BCC) .sort6 LDA totalRaceTenths,Y \ Set (A H U) = this driver's total race time SBC totalRaceTenths,X \ - total race time of the driver ahead STA U \ \ starting with the tenths of a second LDA totalRaceSeconds,Y \ Then the seconds SBC totalRaceSeconds,X STA H LDA totalRaceMinutes,Y \ And then the minutes SBC totalRaceMinutes,X BCS sort4 \ If the subtraction didn't underflow then the drivers \ are in the correct order, so jump to sort4 to move on \ to the next position \ Otherwise the subtraction underflowed, so this \ driver's total race time is quicker than the total \ race time of the driver ahead, which is the wrong way \ round if we are trying to create a list where the \ winner has the fastest time, so fall through into \ sort7 to swap them around in the driversInOrder list .sort7 \ If we get here then the two drivers we are comparing \ are in the wrong order in the driversInOrder list, so \ we need to swap them round \ \ At this point X contains the number of the driver \ ahead and Y contains the number of this driver STX T \ Store the number of the driver ahead in T LDX W \ Set X to the position counter TYA \ Set A to the number of this driver STA driversInOrder-1,X \ Set the number of the driver ahead (i.e. the position \ before the one we are processing) to A (i.e. the \ number of this driver) LDA T \ Set the number of this driver (i.e. the current STA driversInOrder,X \ position) to T (i.e. the number of the driver ahead) DEC V \ Decrement V so that is it non-zero, to indicate that \ we had to swap an entry in the driversInOrder list JMP sort4 \ Jump to sort4 to move on to the next position