Figured out the local and sram high score saving routines
Code; save high score loop
$01/BE9D 20 E4 BE JSR $BEE4 [$00:BEE4] ;
$01/BEA0 A5 36 LDA $36 [$00:0036] ;
$01/BEA2 05 35 ORA $35 [$00:0035] ;
$01/BEA4 29 F0 AND #$F0 ;
$01/BEA6 F0 3B BEQ $3B [$BEE3] ;
$01/BEA8 22 B7 B2 01 JSL $01B2B7[$01:B2B7] ;
$01/BEAC A2 1F LDX #$1F ;
$01/BEAE AD 85 03 LDA $0385 [$00:0385] ;\
$01/BEB1 10 05 BPL $05 [$BEB8] ; |
$01/BEB3 20 38 BF JSR $BF38 [$00:BF38] ; | if bonus, go to bonus game
$01/BEB6 A2 29 LDX #$29 ; |
$01/BEB8 8E 18 01 STX $0118 [$00:0118] ;/
$01/BEBB A9 F1 LDA #$F1 ;
$01/BEBD 85 4D STA $4D [$00:004D] ;
$01/BEBF EE 20 02 INC $0220 [$00:0220] ;
$01/BEC2 AE 1A 02 LDX $021A [$00:021A] ; load level ID
$01/BEC5 AD 0C 03 LDA $030C [$00:030C] ; load current or high score (whichever is higher)
$01/BEC8 DD B8 02 CMP $02B8,x[$00:02B8] ;\ compare to high score
$01/BECB F0 13 BEQ $13 [$BEE0] ; | branch if you didn't get a high score
$01/BECD 90 11 BCC $11 [$BEE0] ;/
$01/BECF 48 PHA ; push high score
$01/BED0 BD 22 02 LDA $0222,x[$00:0222] ;\
$01/BED3 29 7F AND #$7F ; | branch if you have beat the level before
$01/BED5 F0 08 BEQ $08 [$BEDF] ;/
$01/BED7 BD B8 02 LDA $02B8,x[$00:02B8] ;\
$01/BEDA 09 80 ORA #$80 ; | store old score for the overworld score change (when you get a new high score)
$01/BEDC 8D 20 02 STA $0220 [$00:0220] ;/
$01/BEDF 68 PLA ; pull high score
$01/BEE0 9D B8 02 STA $02B8,x[$00:02B8] ; store new high score
$01/BEE3 60 RTS ; return
Code; high score sram save loop
$10/82B3 A0 00 LDY #$00 ;
$10/82B5 B9 22 02 LDA $0222,y[$10:0222] ;\
$10/82B8 29 01 AND #$01 ; | branch if you've beaten the level
$10/82BA F0 07 BEQ $07 [$82C3] ;/
$10/82BC B9 B8 02 LDA $02B8,y[$10:02B8] ;\
$10/82BF 09 80 ORA #$80 ; | sets the high bit of the high score address to indicate the level has been beaten
$10/82C1 87 00 STA [$00] [$50:0342] ;/ store high score for the level in RAM
$10/82C3 C2 20 REP #$20 ;
$10/82C5 E6 00 INC $00 [$00:0000] ;
$10/82C7 E2 20 SEP #$20 ;
$10/82C9 C8 INY ;
$10/82CA C0 48 CPY #$48 ;
$10/82CC 90 E7 BCC $E7 [$82B5] ;
relevant addresses:
$7E021A level ID
$7E0220 old score for the overworld score change (when you get a new high score)
$7E0222,x log of your history in the level, indexed by level ID
format: X------Y (X = unlocked but not beaten; Y = beaten level)
if none of the bits are set, you haven't unlocked the level yet
$7E02B8,x table of high scores, indexed by level ID
$7E030C current or high score (whichever is higher)
Additionally, I found the bonus item sram save routine:
Code; bonus item sram save loop
$10/82CE A0 00 LDY #$00 ;\
$10/82D0 B9 57 03 LDA $0357,y[$10:0357] ; |
$10/82D3 87 00 STA [$00] [$50:0342] ; |
$10/82D5 C2 20 REP #$20 ; |
$10/82D7 E6 00 INC $00 [$00:0000] ; | save all of your bonus items to sram
$10/82D9 E2 20 SEP #$20 ; |
$10/82DB C8 INY ; |
$10/82DC C0 1B CPY #$1B ; |
$10/82DE 90 F0 BCC $F0 [$82D0] ;/
$10/82E0 C2 20 REP #$20 ;
$10/82E2 AD 82 60 LDA $6082 [$10:6082] ;
$10/82E5 87 00 STA [$00] [$50:0342] ;
$10/82E7 E6 00 INC $00 [$00:0000] ;
$10/82E9 AD 72 03 LDA $0372 [$10:0372] ;
$10/82EC 87 00 STA [$00] [$50:0342] ;
$10/82EE E2 20 SEP #$20 ;
$10/82F0 C2 20 REP #$20 ;
Incidentally, when the game saves your high score to sram, it makes a duplicate table and gets the checksum of it before and after a new high score is added. The process is done thusly:
Code$10/82F2 DA PHX ;\
$10/82F3 DA PHX ; |
$10/82F4 BD 12 80 LDA $8012,x[$10:8012] ; |
$10/82F7 8D 14 30 STA $3014 [$10:3014] ; | get high score checksum before a new high score is added
$10/82FA A2 08 LDX #$08 ; |
$10/82FC A9 83 DE LDA #$DE83 ; |
$10/82FF 22 44 DE 7E JSL $7EDE44[$7E:DE44] ;/ GSU init
$10/8303 FA PLX ;
$10/8304 AD 00 30 LDA $3000 [$10:3000] ;\
$10/8307 9F 70 7E 70 STA $707E70,x[$70:7E70] ;/ store high score checksum
$10/830B BD 12 80 LDA $8012,x[$10:8012] ;\
$10/830E 8D 02 30 STA $3002 [$10:3002] ; |
$10/8311 BD 3A 80 LDA $803A,x[$10:803A] ; |
$10/8314 8D 14 30 STA $3014 [$10:3014] ; | store high scores and get new checksum
$10/8317 A2 08 LDX #$08 ; |
$10/8319 A9 73 DE LDA #$DE73 ; |
$10/831C 22 44 DE 7E JSL $7EDE44[$7E:DE44] ;/ GSU init
$10/8320 FA PLX ;
$10/8321 AD 00 30 LDA $3000 [$10:3000] ;\
$10/8324 9F 76 7E 70 STA $707E76,x[$70:7E76] ;/ store new high score checksum
$10/8328 E2 20 SEP #$20 ;
$10/832A AB PLB ;
$10/832B 6B RTL ;
I've documented the GSU routine as well:
Code; r1 = source table (dw $7C00, $7C68, $7CD0)
; r10 = desination table (dw $7D38, $7DA0, $7E08)
; indexed by save file
0008:DE73 2A 12 move r2,r10 ; move desination into r2
0008:DE75 02 cache ;\ table copy loop
0008:DE76 FC 34 00 iwt r12,#0034 ; | load number of high scores to save (number of levels total)
0008:DE79 FD 7C DE iwt r13,#DE7C ; | set loop address
0008:DE7C 41 ldw (r1) ; |\ copy high score from source table to desination table
0008:DE7D 32 stw (r2) ; |/
0008:DE7E D1 inc r1 ; |\
0008:DE7F D1 inc r1 ; | | loop until every high score is saved
0008:DE80 D2 inc r2 ; | |
0008:DE81 3C loop ; |/
0008:DE82 D2 inc r2 ;/
; r10 = destination
0008:DE83 02 cache ;\ checksum loop
0008:DE84 FC 34 00 iwt r12,#0034 ; | load number of high scores
0008:DE87 FD 8C DE iwt r13,#DE8C ; | set loop address
0008:DE8A A1 00 ibt r1,#00 ; |
0008:DE8C 4A ldw (r10) ; | load destination table
0008:DE8D 11 51 add r1 ; | add score to r1
0008:DE8F DA inc r10 ; |\
0008:DE90 3C loop ; | | loop through every index ($34 times)
0008:DE91 DA inc r10 ;/ /
0008:DE92 F0 77 77 iwt r0,#7777 ;\ compute checksum
0008:DE95 61 sub r1 ;/ r0 = final checksum
0008:DE96 00 stop ;\ halt gsu processing
0008:DE97 01 nop ;/
The checksum of the duplicate table before the copy is stored to $707E70,x; the checksum of the table after the copy is stored to $707E76,x. Both are indexed with the save file.
Warning: Opinions expressed by Lexie or others in this post do not necessarily reflect the views, opinions, or position of Lexie himself on the matter(s) being discussed therein.
Yoshi's Island Disassembly C3 Thread
SPASM - LevelASM for Yoshi's Island!
Yoshi's Island Disassembly Data Dump Wiki