Text_WouldYouLikeToSaveTheGame EQU $5283 Text_SavingDontTurnOffThePower EQU $5288 SaveTheGame_yesorno EQU $4BAF SaveMenu.refused EQU $4A4A Text_WaitBGMap EQU $13B6 SpeechTextBox EQU $103E FarCall EQU $08 FadeOutPalettes EQU $23:$4084 LoadMapPalettes EQU $41:$47EB ClearScreen EQU $0FDB UpdateSprites EQU $1AD2 GetSGBLayout EQU $3340 SetPalettes EQU $32F9 DelayFrame EQU $045A DelayFrames EQU $0468 PrintText EQU $1057 Request1bpp EQU $0F1E DoubleSpeed EQU $2FEF hTransferVirtualOAM EQU $FFEC rSTAT EQU $FF41 CopyBytes EQU $3026 s02_9A12: db ; s02_9A12 SaveGame: ; s02_AD44 push af push bc push de push hl ei call Text_WaitBGMap ld a,[wSavingAllowed] and a jr z,.cantsave ; Ask the player to save or some dumb shit idfk ld hl,$B1E8 ld a,$02 ld [w01_DF34],a call $A2A3 ld bc,$0204 ld hl,$A41A ld de,Start call $AB1F ; Get player input? and a jr z,.declined ; Confirmed save ld a,[wPartyCount] cp a,$04 jr c,.actuallysave ; Too many party members yadda yadda ld hl,$B323 ld a,$02 ld [w01_DF34],a call $A2A3 ld bc,$0204 ld hl,$A41A ld de,Start call $AB1F and a jr z,$ADA7 .actuallysave ; s02_AD8F ld a,BANK(FadeOutPalettes) ld hl,FadeOutPalettes rst FarCall ld a,BANK(LoadMapPalettes) ld hl,LoadMapPalettes rst FarCall jp SavingTheGame .cantsave ; s02_A9DC ld hl,$B1A6 ld a,$02 ld [$DF34],a call $A2A3 .declined ; s02_ADA7 pop hl pop de pop bc pop af jp $0460 sSaveSource: dw ; s02_ADAE sSaveBlockChecksum: db ; s02_ADB0 s02_ADB1: dl ; s02_ADB1 sBufferCarry: ; s02_ADB5 sROPScriptBackup: dw ; s02_ADB6 s02_ADB8: db ; s02_ADB8 s02_ADB9: db ; s02_ADB9 ROPGadget_ldi_a_hl: ; s02_ADBA ld a, [hl+] ret ROPGadget_ldd_a_hl: ; s02_ADBC ld a, [hl-] ret ROPGadget_ld_hl_c: ; s02_ADBE ld [hl], c ret ROPGadget_ld_b_hl: ; s02_ADC0 ld b, [hl] ret ROPGadget_add_b: ; s02_ADC2 add b ret ROPGadget_srl_a: ; s02_ADC4 srl a ret ROPGadget_xor_hl: ; s02_ADC7 xor [hl] ret ROPGadget_call_z: ; s02_ADC9 ret z pop hl ret ROPGadget_variable: ; s02_ADCC add [hl] ret SavingTheGame: ; s02_ADCE ; Cleanup shit because well fuck nobody cares call ClearScreen call UpdateSprites call UninstallVBlankHook ; Only interesting line in this entire blob of fuzz ld b,$08 call GetSGBLayout call SetPalettes ld hl,wMusicFadeID ld [hl],$00 dec hl dec hl ld [hl],$08 ld c,$32 call DelayFrames ld a,$03 ld [wOptions],a ld a,$05 rst $10 ld hl,Text_SavingDontTurnOffThePower call PrintText ld de,$B400 ld hl,$8C00 ; This graphic is probably a picture of a cucumber ld bc,$0104 call Request1bpp call DelayFrame ; Now THAT's more like it ld de,ROPScript_SaveMain di call DoubleSpeed call UpdateSaveSpinner ld sp,SaveROPMain ret ROP_SaveMain: ; s02_AE18 ld a, [de] inc de add a ld bc, 0 ld c, a ld hl, .jmptable add hl, bc ldw hl, [hl] .jmptable ; s02_AE2C jp hl dw ROP_SetAddr ; $01 dw ROP_InitChecksum ; $02 dw ROP_FetchByte ; $03 dw ROP_end ; $04 dw ROP_ApplyCrypto ; $05 dw ROP_RotateBuffer ; $06 dw ROP_InitCrypto ; $07 dw ROP_AddChecksum ; $08 dw ROP_XorChecksum ; $09 dw $0000 ; $0A dw ROP_WriteChecksumByte ; $0B dw ROP_rept ; $0C dw ROP_StoreByte ; $0D dw ROP_LoadByte ; $0E ROP_end: ; s02_AE4A ld bc, $0100 ld de, $CB00 ld hl, $AE58 ld af, $FF00 call CopyBytes ; Here's the destination of the copied code, ; it does some shit to copy the buffer back to the SRAM. ; I don't really care what it does. UpdateSaveSpinner: ; s02_AEDB ld hl,s02_9A12 ld b,$C0 ld a,[s02_ADB9] inc a and a,%11 ld [s02_ADB9],a add b ld b,a ; Wait for HBlank .loop ; s02_AEEB ldh a,[rSTAT] and a,%11 jr nz,.loop ld [hl],b ret ROP_SetAddr: ; s02_AEF3 ; sSaveSource = param ld hl, sSaveSource ld a, [de] ld [hl+], a inc de ld a, [de] ld [hl+], a inc de ld hl, ROP_SaveMain jp hl ROP_InitChecksum: ; s02_AF09 ; sSaveBlockChecksum = param ld hl, sSaveBlockChecksum ld a, [de] inc de ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_FetchByte: ; s02_AF19 ; w00_C800 = *(sSaveSource++) ; Fetch byte from pointer stored at sSaveSource ld hl, sSaveSource ldw hl, [hl] ld a, [hl+] ; Save incremented pointer back into sSaveSource ld b, h ld c, l ld hl, sSaveSource ld [hl], c inc hl ld [hl], b ; Save byte into w00_C800 ld hl, w00_C800 ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_ApplyCrypto: ; s02_AF3B ; w00_C800 ^= func(s02_ADB1) ; s02_ADB2 ^= (s02_ADB1 + 1) ^ s02_ADB4 ld hl, s02_ADB1 inc [hl] ld b, [hl] ; s02_ADB1 ld a, [hl+] ld a, [hl+] ld a, [hl+] ld a, [hl-] ; s02_ADB4 xor b ld b, a ld a, [hl-] ld a, [hl-] ; s02_ADB2 inc hl xor b ld [hl+], a ; s02_ADB2 ; s02_ADB3 += s02_ADB2 ld b, a ld a, [hl-] ; s02_ADB3 inc hl add b ld [hl+], a ; s02_ADB3 ; s02_ADB4 = s02_ADB2 ^ (s02_ADB4 + (s02_ADB3 / 2)) srl a ld b, a ld a, [hl-] ; s02_ADB4 add b ld b, a ld a, [hl-] ld a, [hl+] ; s02_ADB2 xor b inc hl ld [hl+], a ; s02_ADB4 ; w00_C800 ^= s02_ADB4 ld hl, w00_C800 xor [hl] ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_RotateBuffer: ; s02_AF85 ; s02_ADB8 = ((s02_ADB8 + 1) | $C0) ^ $C0 ; s02_ADB8 = (s02_ADB8 + 1) & 0x3F ld hl, s02_ADB8 ld a, [hl-] inc a ld hl, $07FC or [hl] ld bc, $C000 xor b ld hl, s02_ADB8 ld [hl+], a ; Called every 64 times this function is ran and a call z, UpdateSaveSpinner ; Save ROPScript pointer ld hl, sROPScriptBackup ld a, e ld [hl+], a ld [hl], d ; Rotate the entire buffer, using sBufferCarry as carry ld hl, w00_C800 ld a, [hl+] ld hl, sBufferCarry ld [hl+], a ld bc, $01B0 ld de, w00_C800 ld hl, w00_C800 + 1 ld af, $FF00 call CopyBytes ; bc bytes from hl to de ld hl, sBufferCarry ld a, [hl+] ld hl, w00_C9AF ld [hl+], a ; Restore ROPScript pointer ld hl, sROPScriptBackup ld a, [hl+] ld d, [hl] ld e, a ld hl, ROP_SaveMain jp hl ROP_InitCrypto: ; s02_AFE3 ; s02_ADB1 = param ld hl, s02_ADB1 ld a, [de] ld [hl+], a inc de ld a, [de] ld [hl+], a inc de ld a, [de] ld [hl+], a inc de ld a, [de] ld [hl+], a inc de ld hl, ROP_SaveMain jp hl ROP_AddChecksum: ; s02_B005 ; sSaveBlockChecksum += w00_C800 ld hl, ROPGadget_variable ld af, $8600 ; add [hl] ld [hl+], a ld hl, ROP_s02_B01B jp hl ROP_XorChecksum: ; s02_B013 ; sSaveBlockChecksum ^= w00_C800 ld hl, ROPGadget_variable ld af, $AE00 ; xor [hl] ld [hl+], a ; fallthrough ROP_s02_B01B: ; s02_B01B ld hl, sSaveBlockChecksum ld a, [hl+] ld hl, w00_C800 add [hl]/xor [hl] ; Modified by caller ld hl, sSaveBlockChecksum ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_WriteChecksumByte: ; s02_B033 ; w00_C800 = sSaveBlockChecksum ld hl, sSaveBlockChecksum ld a, [hl+] ld hl, w00_C800 ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_StoreByte: ; s02_B045 ; *(sSaveSource++) = sSaveBlockChecksum ; *sSaveSource = sSaveBlockChecksum ld hl, sSaveBlockChecksum ld b, [hl] ld hl, sSaveSource ldw hl, [hl] ld [hl], b inc hl ; sSaveSource = sSaveSource + 1 ld b, h ld c, l ld hl, sSaveSource ld [hl], c inc hl ld [hl], b ld hl, ROP_SaveMain jp hl ROP_LoadByte: ; s02_B069 ; sSaveBlockChecksum = *sSaveSource ld hl, sSaveSource ldw hl, [hl] ld a, [hl+] ld hl, sSaveBlockChecksum ld [hl+], a ld hl, ROP_SaveMain jp hl ROP_rept: ; s02_B07D ; do {} while(param[2]--); ; Fetch jump pointer to bc ld a, [de] ld c, a inc de ld a, [de] ld b, a inc de ; If param == 0, return ld a, [de] inc de ld hl, ROP_SaveMain and a call z, (jp hl) ; Decrement parameter, if 0, return dec a dec de ld [de], a inc de ld hl, ROP_SaveMain call z, (jp hl) ; Jump to the script at bc ld d, b ld a, c ld e, a ld hl, ROP_SaveMain jp hl ROPScript_SaveMain: ; s02_B0B3 ; ========================================================================== ; Start compiling data into save blob, and applying first crypto layer. ; Each "section" of the save blob has its own, fixed crypto seed and checksum. ; ========================================================================== ; sSaveSource = $FCDF dbw $01, $FCDF ; ROP_SetAddr ; sSaveBlockChecksum = $7F dbb $02, $7F ; ROP_InitChecksum ; s02_ADB1 = $8C10E62F dbl $07, $8C10E62F ; ROP_InitCrypto .s02_B0BD ; rept ($48) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B0BD, $48 ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $FA7A dbw $01, $FA7A ; ROP_SetAddr ; sSaveBlockChecksum = $C2 dbb $02, $C2 ; ROP_InitChecksum ; s02_ADB1 = $6AF528C2 dbl $07, $6AF528C2 ; ROP_InitCrypto .s02_B0D5 ; rept ($14) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B0D5, $14 ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $F84E dbw $01, $F84E ; ROP_SetAddr .s02_B0E2 ; rept ($03) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B0E2, $03 ; ROP_rept ; sSaveSource = $F859 dbw $01, $F859 ; ROP_SetAddr ; sSaveBlockChecksum = $06 dbb $02, $06 ; ROP_InitChecksum ; s02_ADB1 = $EF7305A6 dbl $07, $EF7305A6 ; ROP_InitCrypto .s02_B0F2 ; rept ($4C) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B0F2, $4C ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $DE41 dbw $01, $DE41 ; ROP_SetAddr ; s02_ADB1 = $2A7FEC38 dbl $07, $2A7FEC38 ; ROP_InitCrypto ; sSaveBlockChecksum = $3C dbb $02, $3C ; ROP_InitChecksum .s02_B10A ; rept ($21) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B10A, $21 ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $DE99 dbw $01, $DE99 ; ROP_SetAddr ; sSaveBlockChecksum = $E2 dbb $02, $E2 ; ROP_InitChecksum ; s02_ADB1 = $4BFC1115 dbl $07, $4BFC1115 ; ROP_InitCrypto .s02_B11E ; rept ($40) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B11E, $40 ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; s02_ADB1 = $A23F387C dbl $07, $A23F387C ; ROP_InitCrypto ; sSaveBlockChecksum = $16 dbb $02, $16 ; ROP_InitChecksum ; sSaveSource = $A003 dbw $01, $A003 ; ROP_SetAddr .s02_B132 ; rept ($04) { ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B132, $04 ; ROP_rept ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; ========================================================================== ; End compiling data into save blob. ; ========================================================================== ; ========================================================================== ; Apply second layer of crypto onto the save file as a whole. ; The seed for this crypto is based on random bytes, ; which are stored in the final blob as well. ; ========================================================================== ; sSaveBlockChecksum = $00 dbb $02, $00 ; ROP_InitChecksum ; sSaveSource = $FFE1 dbw $01, $FFE1 ; ROP_SetAddr ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; sSaveSource = $B16B dbw $01, $B16B ; ROP_SetAddr ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $FFE2 dbw $01, $FFE2 ; ROP_SetAddr ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; sSaveSource = $B16C dbw $01, $B16C ; ROP_SetAddr ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $FF04 dbw $01, $FF04 ; ROP_SetAddr ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; sSaveSource = $B16D dbw $01, $B16D ; ROP_SetAddr ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $FF05 dbw $01, $FF05 ; ROP_SetAddr ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; w00_C800 = sSaveBlockChecksum db $0B ; ROP_WriteChecksumByte ; sSaveSource = $B16E dbw $01, $B16E ; ROP_SetAddr ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; NOTE: The parameter of this command is modified by the commands above. ; s02_ADB1 = $EFBEADDE dbl $07, $EFBEADDE ; ROP_InitCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveBlockChecksum = $55 dbb $02, $55 ; ROP_InitChecksum ; sSaveSource = $F350 dbw $01, $F350 ; ROP_SetAddr ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte .s02_B178 ; rept ($1AB) { ; sSaveSource = $F350 dbw $01, $F350 ; ROP_SetAddr ; sSaveBlockChecksum = *sSaveSource db $0E ; ROP_LoadByte ; sSaveBlockChecksum += w00_C800 db $08 ; ROP_AddChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; sSaveBlockChecksum = *sSaveSource db $0E ; ROP_LoadByte ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; } dbwb $0C, .s02_B178, $D5 ; ROP_rept dbwb $0C, .s02_B178, $D6 ; ROP_rept ; sSaveBlockChecksum = $CC dbb $02, $CC ; ROP_InitChecksum ; sSaveSource = $ADB1 dbw $01, $ADB1 ; ROP_SetAddr ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveBlockChecksum ^= w00_C800 db $09 ; ROP_XorChecksum ; *(sSaveSource++) = sSaveBlockChecksum db $0D ; ROP_StoreByte ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; sSaveSource = $F350 dbw $01, $F350 ; ROP_SetAddr ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; w00_C800 = *(sSaveSource++) db $03 ; ROP_FetchByte ; w00_C800 ^= func(s02_ADB1) db $05 ; ROP_ApplyCrypto ; rotatebuffer(w00_C800) db $06 ; ROP_RotateBuffer ; Copy save blob from the buffer to final location in SRAM, and end. db $04 ; ROP_end ; Temporary save location for the DelayFrame return pointer sVBlankReturnPointer: dw ; s02_B4E6 VBlankHook_Save: ; s02_B673 ; Saving hook code ; Check if the "P" tile is on the screen (part of "PLAYER") ld a,[$C4CD] ; wTileMap + ??? cp a,"P" ; $8F ret nz ; Check that we're trying to make a textbox for saving the game ld hl,[sp+$12] ldi a,[hl] cp a,LOW(Text_WouldYouLikeToSaveTheGame) ret nz ldd a,[hl] cp a,HIGH(Text_WouldYouLikeToSaveTheGame) ret nz ; Change that text pointer to an empty text box (only include the TX_END command) ld [hl],LOW($0134) inc hl ld [hl],HIGH($0134) ; Change the MapTextbox return address to skip to the end of SaveTheGame_yesorno ld hl,sp+$16 ld [hl],LOW(SaveTheGame_yesorno + 27) ; $4BCA ; Change the SaveTheGame_yesorno return address to skip to SaveMenu.refused inc hl inc hl ld [hl],LOW(SaveMenu.refused) inc hl ld [hl],HIGH(SaveMenu.refused) ; Overwrite return pointer for the vblank hook ld hl,SaveGame ld a,l ld [sVBlankReturnPointer],a ld a,h ld [sVBlankReturnPointer + 1],a ld a,BANK(SaveGame) ld [wVBlankReturnBank],a ; Overwrite return bank? ret UninstallVBlankHook: ; s02_B711 ld hl, hTransferVirtualOAM ld [hl], $3E ; ld a, n8 inc hl ld [hl], $C4 ret w00_C800: ds $1b0 ; w00_C800 w00_C9AF: ; w00_C9AF wOptions: db ; w01_CFCC wPartyCount: db ; w01_DCD7 w01_DF34: db wVBlankReturnBank: db ; w01_DF35 wSavingAllowed: db ; w01_DF3A