Tuesday 2 December 2014

Rocket Raid Under the Hood 7: Hall of Fame (cont.)

This is the seventh part in a series of posts on digging into the code of the Acornsoft side-scrolling arcade game, Rocket Raid.


Hall of Fame: Checking for Qualification



This section of code checks whether the player's score qualifies for entry into the Top Eight in the Hall of Fame, at the end of a game. The player's score qualifies if greater than or equal to the lowest-ranking score stored in the scoreLadder table.

The player's score is stored in 3 bytes at the address labelled "score" and these are compared to the lowest-ranking score which is stored in 3 bytes at the address at scoreLadder+3. The comparison is made byte-wise, starting from the most-significant byte.

Labels for BeebDis:
jumpToHallOfFame $04FF
qualified $0528
Disassembly:

    LDA score+2
    CMP scoreLadder+5     ; Compare MSB of player's score
                          ; to MSB of lowest rank score
    BCC jumpToHallOfFame  ; If less then the player has not qualified;
                          ; skip to display the Hall of Fame
    BNE qualified         ; If more then the player has qualified.
    LDA score+1        
    CMP scoreLadder+4     
; If equal then compare the second byte of 
                          ; the scores
    BCC jumpToHallOfFame
  ; If less then skip to the Hall of Fame
    BNE qualified         
; If more then the player has qualified.
    LDA score          
    CMP scoreLadder+3     
; If this is also equal then compare
                          ; the LSB of the scores
    BCC jumpToHallOfFame  ; If less then skip to the Hall of Fame
.qualified

Hall of Fame: Sorting the Player's Entry


If the player's score has qualified, then the player's score needs to be inserted into the Hall of Fame at the correct position. This is done by first inserting it at rank 9, and then moving it up to the correct rank until it is at the correct place.

The initial insertion at rank 9 is done before the code is called, simply by copying the player's score to rank 9 in the scoreLadder table, and setting a pointer at rank 9 in the nameLookup table to point to the user's name string.

The code in the following sections steps through each rank in the scoreLadder table, starting from the lowest rank. A comparison is made between the player's score and the rank immediately above it (using similar logic to the previous section); if the player's score is greater then the score for that rank, then a swap is made of scores and names.


Swapping Scores & Names


First a check is made to see whether a swap is needed, by comparing the player's score with the score immediately above it in rank (which will be rank 8 on the initial pass).

Labels for BeebDis:
checkNextRank $0580
swapRank $05A1
moveToNextRank $05FB


Disassembly:
    LDX #$03               ; X is the offset to the rank being checked
.checkNextRank             ; Start of loop for checking each ranked score
    TXA
    TAY                  
    DEY
    DEY
    DEY                    ; Y is the offset to the player's score, 3 bytes (one rank) below the offset to the current rank
    LDA scoreLadder+2,Y  
    CMP scoreLadder+2,X    ; Compare MSB of scores
    BCC moveToNextRank     ; If player's score is less, no swap
    BNE swapRank           ; If greater, then swap score & name
    LDA scoreLadder+1,Y
    CMP scoreLadder+1,X    
; If equal, then compare the next significant byte
    BCC moveToNextRank     
; If player's score is less, no swap
    BNE 
swapRank           ; If greater, then swap score & name
    LDA scoreLadder,Y
    CMP scoreLadder,X      ; If this is also equal, then compare LSB
    BCC moveToNextRank     ; If LSB is less, no swap
The scores are swapped byte-by-byte with the help of a third, temporary, memory location ("tempScore").

Next the names are handled, although there is no need to copy actual string data; instead, only the pointers to the strings, stored in the nameLookup table, are swapped.


.swapRank
    LDA scoreLadder,X             ; Swap scores
    STA tempScore
    LDA scoreLadder+1,X
    STA tempScore+1
    LDA scoreLadder+2,X
    STA tempScore+2
    LDA scoreLadder,Y
    STA scoreLadder,X
    LDA scoreLadder+1,Y
    STA scoreLadder+1,X
    LDA scoreLadder+2,Y
    STA scoreLadder+2,X
    LDA tempScore
    STA scoreLadder,Y
    LDA tempScore+1
    STA scoreLadder+1,Y
    LDA tempScore+2
    STA scoreLadder+2,Y
    LDA nameLookup,X              ; Swap names
    STA tempScore
    LDA nameLookup+1,X
    STA tempScore+1
    LDA nameLookup,Y
    STA nameLookup,X
    LDA nameLookup+1,Y
    STA nameLookup+1,X
    LDA tempScore
    STA nameLookup,Y
    LDA tempScore+1
    STA nameLookup+1,Y
Finally, X is increased to point to the next-highest rank, and the code loops back again until all ranks have been traversed.

.moveToNextRank
        INX                             ;
        INX                             ;
        INX                             ; X=X+3 (length of an entry)
        CPX     #$1B                    ; Check if all 9 ranks have been
        BEQ     hallOfFame              ; traversed. If so, then
                                        ; display Hall of Fame table,
        JMP     checkNextRank           ; else loop back to check next rank


No comments:

Post a Comment