summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiegoisawesome <diego@domoreaweso.me>2016-11-01 14:15:48 -0500
committerDiegoisawesome <diego@domoreaweso.me>2016-11-01 14:15:48 -0500
commit7dad2846f83f892cdb4ffd7a757d0858b02fc96e (patch)
treee80d324f47b6ddb8a6405e48d9576d25efb9986e
parentb4a39100c0e052bdab3cfa2da707072c2ee18115 (diff)
Port agb_flash from pokeruby
-rw-r--r--asm/libagbbackup.s1079
-rw-r--r--asm/save.s4
-rw-r--r--ld_script.txt9
-rw-r--r--src/agb_flash.c295
-rw-r--r--src/agb_flash_1m.c86
-rw-r--r--src/agb_flash_le.c31
-rw-r--r--src/agb_flash_mx.c193
7 files changed, 614 insertions, 1083 deletions
diff --git a/asm/libagbbackup.s b/asm/libagbbackup.s
deleted file mode 100644
index 35180530c..000000000
--- a/asm/libagbbackup.s
+++ /dev/null
@@ -1,1079 +0,0 @@
- .include "asm/macros.inc"
-
- .syntax unified
-
- .text
-
- thumb_func_start SwitchFlashBank
-SwitchFlashBank: @ 82E185C
- lsls r0, 24
- lsrs r0, 24
- ldr r3, =0x0e005555
- movs r1, 0xAA
- strb r1, [r3]
- ldr r2, =0x0e002aaa
- movs r1, 0x55
- strb r1, [r2]
- movs r1, 0xB0
- strb r1, [r3]
- movs r1, 0xE0
- lsls r1, 20
- strb r0, [r1]
- bx lr
- .pool
- thumb_func_end SwitchFlashBank
-
- thumb_func_start ReadFlashID
-@ u16 ReadFlashID()
-ReadFlashID: @ 82E1880
- push {r4,r5,lr}
- sub sp, 0x44
- mov r0, sp
- bl SetReadFlash1
- mov r5, sp
- adds r5, 0x1
- ldr r2, =0x0e005555
- movs r0, 0xAA
- strb r0, [r2]
- ldr r1, =0x0e002aaa
- movs r0, 0x55
- strb r0, [r1]
- movs r0, 0x90
- strb r0, [r2]
- add r1, sp, 0x40
- ldr r2, =0x00004e20
- adds r0, r2, 0
- b _082E18B8
- .pool
-_082E18B4:
- ldrh r0, [r1]
- subs r0, 0x1
-_082E18B8:
- strh r0, [r1]
- ldrh r0, [r1]
- cmp r0, 0
- bne _082E18B4
- ldr r0, =0x0e000001
- bl _call_via_r5
- lsls r0, 24
- lsrs r4, r0, 16
- movs r0, 0xE0
- lsls r0, 20
- bl _call_via_r5
- lsls r0, 24
- lsrs r0, 24
- orrs r4, r0
- ldr r1, =0x0e005555
- movs r0, 0xAA
- strb r0, [r1]
- ldr r2, =0x0e002aaa
- movs r0, 0x55
- strb r0, [r2]
- movs r0, 0xF0
- strb r0, [r1]
- strb r0, [r1]
- add r1, sp, 0x40
- ldr r2, =0x00004e20
- adds r0, r2, 0
- b _082E1908
- .pool
-_082E1904:
- ldrh r0, [r1]
- subs r0, 0x1
-_082E1908:
- strh r0, [r1]
- ldrh r0, [r1]
- cmp r0, 0
- bne _082E1904
- adds r0, r4, 0
- add sp, 0x44
- pop {r4,r5}
- pop {r1}
- bx r1
- thumb_func_end ReadFlashID
-
- thumb_func_start FlashTimerIntr
-@ void FlashTimerIntr()
-FlashTimerIntr: @ 82E191C
- push {lr}
- ldr r1, =0x03001a72
- ldrh r0, [r1]
- cmp r0, 0
- beq _082E1938
- ldrh r0, [r1]
- subs r0, 0x1
- strh r0, [r1]
- lsls r0, 16
- cmp r0, 0
- bne _082E1938
- ldr r1, =0x03007840
- movs r0, 0x1
- strb r0, [r1]
-_082E1938:
- pop {r0}
- bx r0
- .pool
- thumb_func_end FlashTimerIntr
-
- thumb_func_start SetFlashTimerIntr
-@ void SetFlashTimerIntr(u8 timer_id, void ( **irq_timer_func)())
-SetFlashTimerIntr: @ 82E1944
- push {lr}
- adds r2, r1, 0
- lsls r0, 24
- lsrs r1, r0, 24
- cmp r1, 0x3
- bhi _082E1978
- ldr r0, =0x03001a70
- strb r1, [r0]
- ldr r1, =0x03001a74
- ldrb r0, [r0]
- lsls r0, 2
- ldr r3, =0x04000100
- adds r0, r3
- str r0, [r1]
- ldr r0, =FlashTimerIntr
- str r0, [r2]
- movs r0, 0
- b _082E197A
- .pool
-_082E1978:
- movs r0, 0x1
-_082E197A:
- pop {r1}
- bx r1
- thumb_func_end SetFlashTimerIntr
-
- thumb_func_start StartFlashTimer
-StartFlashTimer: @ 82E1980
- push {r4-r6,lr}
- mov r6, r10
- mov r5, r9
- mov r4, r8
- push {r4-r6}
- lsls r0, 24
- lsrs r0, 24
- ldr r1, =0x03007864
- lsls r2, r0, 1
- adds r2, r0
- lsls r2, 1
- ldr r0, [r1]
- adds r2, r0
- ldr r1, =0x03001a78
- ldr r0, =0x04000208
- mov r9, r0
- ldrh r0, [r0]
- strh r0, [r1]
- movs r3, 0
- mov r1, r9
- strh r3, [r1]
- ldr r0, =0x03001a74
- mov r8, r0
- ldr r4, [r0]
- strh r3, [r4, 0x2]
- ldr r6, =0x04000200
- ldr r1, =0x03001a70
- mov r10, r1
- ldrb r1, [r1]
- movs r5, 0x8
- adds r0, r5, 0
- lsls r0, r1
- adds r1, r0, 0
- ldrh r0, [r6]
- orrs r0, r1
- strh r0, [r6]
- ldr r0, =0x03007840
- strb r3, [r0]
- ldr r1, =0x03001a72
- ldrh r0, [r2]
- strh r0, [r1]
- adds r2, 0x2
- ldrh r0, [r2]
- strh r0, [r4]
- adds r0, r4, 0x2
- mov r1, r8
- str r0, [r1]
- ldrh r0, [r2, 0x2]
- strh r0, [r4, 0x2]
- str r4, [r1]
- ldr r1, =0x04000202
- mov r2, r10
- ldrb r0, [r2]
- lsls r5, r0
- strh r5, [r1]
- movs r0, 0x1
- mov r3, r9
- strh r0, [r3]
- pop {r3-r5}
- mov r8, r3
- mov r9, r4
- mov r10, r5
- pop {r4-r6}
- pop {r0}
- bx r0
- .pool
- thumb_func_end StartFlashTimer
-
- thumb_func_start StopFlashTimer
-StopFlashTimer: @ 82E1A28
- ldr r3, =0x04000208
- movs r1, 0
- strh r1, [r3]
- ldr r2, =0x03001a74
- ldr r0, [r2]
- strh r1, [r0]
- adds r0, 0x2
- str r0, [r2]
- strh r1, [r0]
- subs r0, 0x2
- str r0, [r2]
- ldr r2, =0x04000200
- ldr r0, =0x03001a70
- ldrb r0, [r0]
- movs r1, 0x8
- lsls r1, r0
- ldrh r0, [r2]
- bics r0, r1
- strh r0, [r2]
- ldr r0, =0x03001a78
- ldrh r0, [r0]
- strh r0, [r3]
- bx lr
- .pool
- thumb_func_end StopFlashTimer
-
- thumb_func_start ReadFlash1
-@ u8 ReadFlash1(int address)
-ReadFlash1: @ 82E1A6C
- ldrb r0, [r0]
- bx lr
- thumb_func_end ReadFlash1
-
- thumb_func_start SetReadFlash1
-@ void SetReadFlash1(u8 ( *target_func)(int address))
-SetReadFlash1: @ 82E1A70
- push {lr}
- adds r2, r0, 0
- ldr r1, =0x03007844
- adds r0, r2, 0x1
- str r0, [r1]
- ldr r3, =ReadFlash1
- movs r0, 0x1
- eors r3, r0
- ldr r0, =SetReadFlash1
- ldr r1, =ReadFlash1
- subs r0, r1
- lsls r0, 15
- b _082E1AA4
- .pool
-_082E1A98:
- ldrh r0, [r3]
- strh r0, [r2]
- adds r3, 0x2
- adds r2, 0x2
- subs r0, r1, 0x1
- lsls r0, 16
-_082E1AA4:
- lsrs r1, r0, 16
- cmp r1, 0
- bne _082E1A98
- pop {r0}
- bx r0
- thumb_func_end SetReadFlash1
-
- thumb_func_start ReadFlash_Core
-ReadFlash_Core: @ 82E1AB0
- push {r4,lr}
- adds r4, r0, 0
- subs r3, r2, 0x1
- cmp r2, 0
- beq _082E1ACC
- movs r2, 0x1
- negs r2, r2
-_082E1ABE:
- ldrb r0, [r4]
- strb r0, [r1]
- adds r4, 0x1
- adds r1, 0x1
- subs r3, 0x1
- cmp r3, r2
- bne _082E1ABE
-_082E1ACC:
- pop {r4}
- pop {r0}
- bx r0
- thumb_func_end ReadFlash_Core
-
- thumb_func_start ReadFlash
-ReadFlash: @ 82E1AD4
- push {r4-r7,lr}
- sub sp, 0x80
- adds r5, r1, 0
- adds r6, r2, 0
- adds r7, r3, 0
- lsls r3, r0, 16
- lsrs r4, r3, 16
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- movs r1, 0x3
- orrs r0, r1
- strh r0, [r2]
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldr r1, [r0]
- movs r0, 0x80
- lsls r0, 10
- cmp r1, r0
- bne _082E1B0C
- lsrs r0, r3, 20
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ands r4, r0
-_082E1B0C:
- ldr r3, =ReadFlash_Core
- movs r0, 0x1
- eors r3, r0
- mov r2, sp
- ldr r0, =ReadFlash
- ldr r1, =ReadFlash_Core
- subs r0, r1
- lsls r0, 15
- b _082E1B40
- .pool
-_082E1B34:
- ldrh r0, [r3]
- strh r0, [r2]
- adds r3, 0x2
- adds r2, 0x2
- subs r0, r1, 0x1
- lsls r0, 16
-_082E1B40:
- lsrs r1, r0, 16
- cmp r1, 0
- bne _082E1B34
- mov r3, sp
- adds r3, 0x1
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrb r0, [r0, 0x8]
- lsls r4, r0
- adds r0, r4, 0
- movs r2, 0xE0
- lsls r2, 20
- adds r1, r5, r2
- adds r0, r1
- adds r1, r6, 0
- adds r2, r7, 0
- bl _call_via_r3
- add sp, 0x80
- pop {r4-r7}
- pop {r0}
- bx r0
- .pool
- thumb_func_end ReadFlash
-
- thumb_func_start VerifyFlashSector_Core
-VerifyFlashSector_Core: @ 82E1B70
- push {r4,r5,lr}
- adds r5, r0, 0
- adds r3, r1, 0
- subs r4, r2, 0x1
- cmp r2, 0
- beq _082E1B96
- movs r2, 0x1
- negs r2, r2
-_082E1B80:
- ldrb r1, [r3]
- ldrb r0, [r5]
- adds r5, 0x1
- adds r3, 0x1
- cmp r1, r0
- beq _082E1B90
- subs r0, r3, 0x1
- b _082E1B98
-_082E1B90:
- subs r4, 0x1
- cmp r4, r2
- bne _082E1B80
-_082E1B96:
- movs r0, 0
-_082E1B98:
- pop {r4,r5}
- pop {r1}
- bx r1
- thumb_func_end VerifyFlashSector_Core
-
- thumb_func_start VerifyFlashSector
-VerifyFlashSector: @ 82E1BA0
- push {r4,r5,lr}
- sub sp, 0x100
- adds r5, r1, 0
- lsls r3, r0, 16
- lsrs r4, r3, 16
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- movs r1, 0x3
- orrs r0, r1
- strh r0, [r2]
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldr r1, [r0]
- movs r0, 0x80
- lsls r0, 10
- cmp r1, r0
- bne _082E1BD4
- lsrs r0, r3, 20
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ands r4, r0
-_082E1BD4:
- ldr r3, =VerifyFlashSector_Core
- movs r0, 0x1
- eors r3, r0
- mov r2, sp
- ldr r0, =VerifyFlashSector
- ldr r1, =VerifyFlashSector_Core
- subs r0, r1
- lsls r0, 15
- b _082E1C08
- .pool
-_082E1BFC:
- ldrh r0, [r3]
- strh r0, [r2]
- adds r3, 0x2
- adds r2, 0x2
- subs r0, r1, 0x1
- lsls r0, 16
-_082E1C08:
- lsrs r1, r0, 16
- cmp r1, 0
- bne _082E1BFC
- mov r3, sp
- adds r3, 0x1
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrb r1, [r0, 0x8]
- lsls r4, r1
- adds r1, r4, 0
- movs r2, 0xE0
- lsls r2, 20
- adds r1, r2
- ldrh r2, [r0, 0x4]
- adds r0, r5, 0
- bl _call_via_r3
- add sp, 0x100
- pop {r4,r5}
- pop {r1}
- bx r1
- .pool
- thumb_func_end VerifyFlashSector
-
- thumb_func_start VerifyFlashSectorFirstNBytes
-VerifyFlashSectorFirstNBytes: @ 82E1C38
- push {r4-r6,lr}
- sub sp, 0x100
- adds r5, r1, 0
- adds r6, r2, 0
- lsls r2, r0, 16
- lsrs r4, r2, 16
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldr r1, [r0]
- movs r0, 0x80
- lsls r0, 10
- cmp r1, r0
- bne _082E1C60
- lsrs r0, r2, 20
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ands r4, r0
-_082E1C60:
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- movs r1, 0x3
- orrs r0, r1
- strh r0, [r2]
- ldr r3, =VerifyFlashSector_Core
- movs r0, 0x1
- eors r3, r0
- mov r2, sp
- ldr r0, =VerifyFlashSector
- ldr r1, =VerifyFlashSector_Core
- subs r0, r1
- lsls r0, 15
- b _082E1CA0
- .pool
-_082E1C94:
- ldrh r0, [r3]
- strh r0, [r2]
- adds r3, 0x2
- adds r2, 0x2
- subs r0, r1, 0x1
- lsls r0, 16
-_082E1CA0:
- lsrs r1, r0, 16
- cmp r1, 0
- bne _082E1C94
- mov r3, sp
- adds r3, 0x1
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrb r1, [r0, 0x8]
- lsls r4, r1
- adds r1, r4, 0
- movs r0, 0xE0
- lsls r0, 20
- adds r1, r0
- adds r0, r5, 0
- adds r2, r6, 0
- bl _call_via_r3
- add sp, 0x100
- pop {r4-r6}
- pop {r1}
- bx r1
- .pool
- thumb_func_end VerifyFlashSectorFirstNBytes
-
- thumb_func_start ProgramFlashSectorsAndVerify
-ProgramFlashSectorsAndVerify: @ 82E1CD0
- push {r4-r6,lr}
- adds r5, r1, 0
- lsls r0, 16
- lsrs r4, r0, 16
- movs r6, 0
- b _082E1CE2
-_082E1CDC:
- adds r0, r6, 0x1
- lsls r0, 24
- lsrs r6, r0, 24
-_082E1CE2:
- cmp r6, 0x2
- bhi _082E1D08
- ldr r0, =0x0300784c
- ldr r2, [r0]
- adds r0, r4, 0
- adds r1, r5, 0
- bl _call_via_r2
- lsls r0, 16
- lsrs r2, r0, 16
- cmp r2, 0
- bne _082E1CDC
- adds r0, r4, 0
- adds r1, r5, 0
- bl VerifyFlashSector
- adds r2, r0, 0
- cmp r2, 0
- bne _082E1CDC
-_082E1D08:
- adds r0, r2, 0
- pop {r4-r6}
- pop {r1}
- bx r1
- .pool
- thumb_func_end ProgramFlashSectorsAndVerify
-
- thumb_func_start ProgramFlashSectorsVerifyFirstNBytes
-ProgramFlashSectorsVerifyFirstNBytes: @ 82E1D14
- push {r4-r7,lr}
- adds r5, r1, 0
- adds r7, r2, 0
- lsls r0, 16
- lsrs r4, r0, 16
- movs r6, 0
- b _082E1D28
-_082E1D22:
- adds r0, r6, 0x1
- lsls r0, 24
- lsrs r6, r0, 24
-_082E1D28:
- cmp r6, 0x2
- bhi _082E1D50
- ldr r0, =0x0300784c
- ldr r2, [r0]
- adds r0, r4, 0
- adds r1, r5, 0
- bl _call_via_r2
- lsls r0, 16
- lsrs r3, r0, 16
- cmp r3, 0
- bne _082E1D22
- adds r0, r4, 0
- adds r1, r5, 0
- adds r2, r7, 0
- bl VerifyFlashSectorFirstNBytes
- adds r3, r0, 0
- cmp r3, 0
- bne _082E1D22
-_082E1D50:
- adds r0, r3, 0
- pop {r4-r7}
- pop {r1}
- bx r1
- .pool
- thumb_func_end ProgramFlashSectorsVerifyFirstNBytes
-
- thumb_func_start IdentifyFlash
-@ _BOOL2 IdentifyFlash()
-IdentifyFlash: @ 82E1D5C
- push {r4,lr}
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- movs r1, 0x3
- orrs r0, r1
- strh r0, [r2]
- bl ReadFlashID
- lsls r0, 16
- lsrs r3, r0, 16
- ldr r2, =gUnknown_089A30D0
- movs r4, 0x1
- b _082E1D8A
- .pool
-_082E1D88:
- adds r2, 0x4
-_082E1D8A:
- ldr r1, [r2]
- adds r0, r1, 0
- adds r0, 0x2C
- ldrb r0, [r0]
- cmp r0, 0
- beq _082E1D9E
- ldrh r0, [r1, 0x2C]
- cmp r3, r0
- bne _082E1D88
- movs r4, 0
-_082E1D9E:
- ldr r1, =0x03007854
- ldr r0, [r2]
- ldr r0, [r0]
- str r0, [r1]
- ldr r1, =0x0300784c
- ldr r0, [r2]
- ldr r0, [r0, 0x4]
- str r0, [r1]
- ldr r1, =0x0300785c
- ldr r0, [r2]
- ldr r0, [r0, 0x8]
- str r0, [r1]
- ldr r1, =0x03007860
- ldr r0, [r2]
- ldr r0, [r0, 0xC]
- str r0, [r1]
- ldr r1, =0x03007848
- ldr r0, [r2]
- ldr r0, [r0, 0x10]
- str r0, [r1]
- ldr r1, =0x03007864
- ldr r0, [r2]
- ldr r0, [r0, 0x14]
- str r0, [r1]
- ldr r1, =0x03007850
- ldr r0, [r2]
- adds r0, 0x18
- str r0, [r1]
- adds r0, r4, 0
- pop {r4}
- pop {r1}
- bx r1
- .pool
- thumb_func_end IdentifyFlash
-
- thumb_func_start PollingSR_COMMON
-PollingSR_COMMON: @ 82E1DFC
- push {r4-r7,lr}
- mov r7, r9
- mov r6, r8
- push {r6,r7}
- adds r4, r1, 0
- lsls r0, 24
- lsrs r7, r0, 24
- lsls r2, 24
- lsrs r5, r2, 24
- movs r0, 0
- mov r8, r0
- adds r0, r7, 0
- bl StartFlashTimer
- ldr r6, =0x03007844
- ldr r1, =0x0e005555
- mov r9, r1
- b _082E1E60
- .pool
-_082E1E28:
- movs r0, 0xF0
- mov r1, r9
- strb r0, [r1]
- movs r0, 0xA0
- lsls r0, 8
- b _082E1E56
-_082E1E34:
- ldr r0, =0x03007840
- ldrb r0, [r0]
- cmp r0, 0
- beq _082E1E60
- ldr r1, [r6]
- adds r0, r4, 0
- bl _call_via_r1
- lsls r0, 24
- lsrs r0, 24
- cmp r0, r5
- beq _082E1E88
- movs r0, 0xF0
- mov r1, r9
- strb r0, [r1]
- movs r0, 0xC0
- lsls r0, 8
-_082E1E56:
- orrs r7, r0
- mov r8, r7
- b _082E1E88
- .pool
-_082E1E60:
- ldr r1, [r6]
- adds r0, r4, 0
- bl _call_via_r1
- lsls r0, 24
- lsrs r1, r0, 24
- cmp r1, r5
- beq _082E1E88
- movs r0, 0x20
- ands r0, r1
- cmp r0, 0
- beq _082E1E34
- ldr r1, [r6]
- adds r0, r4, 0
- bl _call_via_r1
- lsls r0, 24
- lsrs r0, 24
- cmp r0, r5
- bne _082E1E28
-_082E1E88:
- bl StopFlashTimer
- mov r0, r8
- pop {r3,r4}
- mov r8, r3
- mov r9, r4
- pop {r4-r7}
- pop {r1}
- bx r1
- thumb_func_end PollingSR_COMMON
-
- thumb_func_start EraseFlashChip
-EraseFlashChip: @ 82E1E9C
- push {r4-r6,lr}
- sub sp, 0x40
- ldr r5, =0x04000204
- ldrh r1, [r5]
- ldr r6, =0x0000fffc
- ands r1, r6
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrh r0, [r0, 0x10]
- orrs r1, r0
- strh r1, [r5]
- ldr r1, =0x0e005555
- movs r4, 0xAA
- strb r4, [r1]
- ldr r3, =0x0e002aaa
- movs r2, 0x55
- strb r2, [r3]
- movs r0, 0x80
- strb r0, [r1]
- strb r4, [r1]
- strb r2, [r3]
- movs r0, 0x10
- strb r0, [r1]
- mov r0, sp
- bl SetReadFlash1
- ldr r0, =0x03007848
- movs r1, 0xE0
- lsls r1, 20
- ldr r3, [r0]
- movs r0, 0x3
- movs r2, 0xFF
- bl _call_via_r3
- lsls r0, 16
- lsrs r0, 16
- ldrh r1, [r5]
- ands r1, r6
- movs r2, 0x3
- orrs r1, r2
- strh r1, [r5]
- add sp, 0x40
- pop {r4-r6}
- pop {r1}
- bx r1
- .pool
- thumb_func_end EraseFlashChip
-
- thumb_func_start EraseFlashSector
-EraseFlashSector: @ 82E1F10
- push {r4-r7,lr}
- sub sp, 0x40
- lsls r0, 16
- lsrs r6, r0, 16
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrh r0, [r0, 0xA]
- cmp r6, r0
- bcc _082E1F30
- ldr r0, =0x000080ff
- b _082E1FD0
- .pool
-_082E1F30:
- lsrs r0, r6, 4
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ands r6, r0
- movs r7, 0
-_082E1F40:
- ldr r3, =0x04000204
- ldrh r1, [r3]
- ldr r0, =0x0000fffc
- ands r1, r0
- ldr r0, =0x03007850
- ldr r2, [r0]
- ldrh r0, [r2, 0x10]
- orrs r1, r0
- strh r1, [r3]
- ldrb r4, [r2, 0x8]
- adds r0, r6, 0
- lsls r0, r4
- adds r4, r0, 0
- movs r0, 0xE0
- lsls r0, 20
- adds r4, r0
- ldr r1, =0x0e005555
- movs r5, 0xAA
- strb r5, [r1]
- ldr r3, =0x0e002aaa
- movs r2, 0x55
- strb r2, [r3]
- movs r0, 0x80
- strb r0, [r1]
- strb r5, [r1]
- strb r2, [r3]
- movs r0, 0x30
- strb r0, [r4]
- mov r0, sp
- bl SetReadFlash1
- ldr r0, =0x03007848
- ldr r3, [r0]
- movs r0, 0x2
- adds r1, r4, 0
- movs r2, 0xFF
- bl _call_via_r3
- lsls r0, 16
- lsrs r3, r0, 16
- movs r0, 0xA0
- lsls r0, 8
- ands r0, r3
- cmp r0, 0
- beq _082E1FC0
- cmp r7, 0x3
- bhi _082E1FC0
- adds r0, r7, 0x1
- lsls r0, 16
- lsrs r7, r0, 16
- b _082E1F40
- .pool
-_082E1FC0:
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- movs r1, 0x3
- orrs r0, r1
- strh r0, [r2]
- adds r0, r3, 0
-_082E1FD0:
- add sp, 0x40
- pop {r4-r7}
- pop {r1}
- bx r1
- .pool
- thumb_func_end EraseFlashSector
-
- thumb_func_start ProgramFlashByte
-ProgramFlashByte: @ 82E1FE0
- push {r4-r7,lr}
- sub sp, 0x40
- adds r6, r1, 0
- lsls r1, r0, 16
- lsrs r4, r1, 16
- lsls r2, 24
- lsrs r7, r2, 24
- ldr r5, =0x03007850
- ldr r0, [r5]
- ldr r0, [r0, 0x4]
- cmp r6, r0
- bcs _082E2068
- lsrs r0, r1, 20
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ldr r1, [r5]
- ands r4, r0
- ldrb r1, [r1, 0x8]
- lsls r4, r1
- movs r1, 0xE0
- lsls r1, 20
- adds r0, r6, r1
- adds r4, r0
- mov r0, sp
- bl SetReadFlash1
- ldr r2, =0x04000204
- ldrh r0, [r2]
- ldr r1, =0x0000fffc
- ands r0, r1
- ldr r1, [r5]
- ldrh r1, [r1, 0x10]
- orrs r0, r1
- strh r0, [r2]
- ldr r2, =0x0e005555
- movs r0, 0xAA
- strb r0, [r2]
- ldr r1, =0x0e002aaa
- movs r0, 0x55
- strb r0, [r1]
- movs r0, 0xA0
- strb r0, [r2]
- strb r7, [r4]
- ldr r0, =0x03007848
- ldr r3, [r0]
- movs r0, 0x1
- adds r1, r4, 0
- adds r2, r7, 0
- bl _call_via_r3
- lsls r0, 16
- lsrs r0, 16
- b _082E206C
- .pool
-_082E2068:
- movs r0, 0x80
- lsls r0, 8
-_082E206C:
- add sp, 0x40
- pop {r4-r7}
- pop {r1}
- bx r1
- thumb_func_end ProgramFlashByte
-
- thumb_func_start ProgramFlashByteInternal
-ProgramFlashByteInternal: @ 82E2074
- push {r4,lr}
- ldr r4, =0x0e005555
- movs r2, 0xAA
- strb r2, [r4]
- ldr r3, =0x0e002aaa
- movs r2, 0x55
- strb r2, [r3]
- movs r2, 0xA0
- strb r2, [r4]
- ldrb r2, [r0]
- strb r2, [r1]
- ldr r3, =0x03007848
- ldrb r2, [r0]
- ldr r3, [r3]
- movs r0, 0x1
- bl _call_via_r3
- lsls r0, 16
- lsrs r0, 16
- pop {r4}
- pop {r1}
- bx r1
- .pool
- thumb_func_end ProgramFlashByteInternal
-
- thumb_func_start ProgramFlashSector
-ProgramFlashSector: @ 82E20AC
- push {r4-r7,lr}
- sub sp, 0x40
- adds r7, r1, 0
- lsls r0, 16
- lsrs r4, r0, 16
- ldr r0, =0x03007850
- ldr r0, [r0]
- ldrh r0, [r0, 0xA]
- cmp r4, r0
- bcc _082E20CC
- ldr r0, =0x000080ff
- b _082E2146
- .pool
-_082E20CC:
- adds r0, r4, 0
- bl EraseFlashSector
- lsls r0, 16
- lsrs r5, r0, 16
- cmp r5, 0
- bne _082E2144
- lsrs r0, r4, 4
- lsls r0, 24
- lsrs r0, 24
- bl SwitchFlashBank
- movs r0, 0xF
- ands r4, r0
- mov r0, sp
- bl SetReadFlash1
- ldr r3, =0x04000204
- ldrh r1, [r3]
- ldr r0, =0x0000fffc
- ands r1, r0
- ldr r0, =0x03007850
- ldr r2, [r0]
- ldrh r0, [r2, 0x10]
- orrs r1, r0
- strh r1, [r3]
- ldr r1, =0x03007858
- ldr r0, [r2, 0x4]
- strh r0, [r1]
- ldrb r0, [r2, 0x8]
- lsls r4, r0
- movs r0, 0xE0
- lsls r0, 20
- adds r4, r0
- adds r6, r1, 0
- b _082E212E
- .pool
-_082E2124:
- ldrh r0, [r6]
- subs r0, 0x1
- strh r0, [r6]
- adds r7, 0x1
- adds r4, 0x1
-_082E212E:
- ldrh r0, [r6]
- cmp r0, 0
- beq _082E2144
- adds r0, r7, 0
- adds r1, r4, 0
- bl ProgramFlashByteInternal
- lsls r0, 16
- lsrs r5, r0, 16
- cmp r5, 0
- beq _082E2124
-_082E2144:
- adds r0, r5, 0
-_082E2146:
- add sp, 0x40
- pop {r4-r7}
- pop {r1}
- bx r1
- thumb_func_end ProgramFlashSector
-
- .align 2, 0 @ Don't pad with nop.
diff --git a/asm/save.s b/asm/save.s
index 0cc13bad5..e20190db5 100644
--- a/asm/save.s
+++ b/asm/save.s
@@ -333,7 +333,7 @@ sub_8152908: @ 8152908
lsls r0, 24
lsrs r4, r0, 24
adds r0, r4, 0
- bl ProgramFlashSectorsAndVerify
+ bl ProgramFlashSectorAndVerify
cmp r0, 0
bne _08152924
movs r0, 0x1
@@ -1876,7 +1876,7 @@ _08153654:
ble _08153654
adds r0, r6, 0
adds r1, r7, 0
- bl ProgramFlashSectorsAndVerify
+ bl ProgramFlashSectorAndVerify
cmp r0, 0
bne _08153680
movs r0, 0x1
diff --git a/ld_script.txt b/ld_script.txt
index 6ff1860ff..1c668bf83 100644
--- a/ld_script.txt
+++ b/ld_script.txt
@@ -197,7 +197,9 @@ SECTIONS {
{
asm/libgcnmultiboot.o(.text);
asm/libmks4agb.o(.text);
- asm/libagbbackup.o(.text);
+ src/agb_flash.o(.text);
+ src/agb_flash_1m.o(.text);
+ src/agb_flash_mx.o(.text);
asm/librtc.o(.text);
asm/librfu.o(.text);
asm/libagbsyscall.o(.text);
@@ -230,7 +232,10 @@ SECTIONS {
lib_rodata :
ALIGN(4)
{
- data/libagbbackup_rodata.o(.rodata);
+ src/agb_flash.o(.rodata);
+ src/agb_flash_1m.o(.rodata);
+ src/agb_flash_mx.o(.rodata);
+ src/agb_flash_le.o(.rodata);
data/librtc_rodata.o(.rodata);
data/librfu_rodata.o(.rodata);
tools/agbcc/lib/libgcc.a:_divdi3.o(.rodata);
diff --git a/src/agb_flash.c b/src/agb_flash.c
new file mode 100644
index 000000000..34fb4e84a
--- /dev/null
+++ b/src/agb_flash.c
@@ -0,0 +1,295 @@
+#include "gba/gba.h"
+#include "gba/flash_internal.h"
+
+static u8 sTimerNum;
+static u16 sTimerCount;
+static vu16 *sTimerReg;
+static u16 sSavedIme;
+
+u8 gFlashTimeoutFlag;
+u8 (*PollFlashStatus)(u8 *);
+u16 (*WaitForFlashWrite)(u8 phase, u8 *addr, u8 lastData);
+u16 (*ProgramFlashSector)(u16 sectorNum, u8 *src);
+const struct FlashType *gFlash;
+u16 (*ProgramFlashByte)(u16 sectorNum, u32 offset, u8 data);
+u16 gFlashNumRemainingBytes;
+u16 (*EraseFlashChip)();
+u16 (*EraseFlashSector)(u16 sectorNum);
+const u16 *gFlashMaxTime;
+
+void SetReadFlash1(u16 *dest);
+
+void SwitchFlashBank(u8 bankNum)
+{
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0xB0);
+ FLASH_WRITE(0x0000, bankNum);
+}
+
+#define DELAY() \
+do { \
+ vu16 i; \
+ for (i = 20000; i != 0; i--) \
+ ; \
+} while (0)
+
+u16 ReadFlashId(void)
+{
+ u16 flashId;
+ u16 readFlash1Buffer[0x20];
+ u8 (*readFlash1)(u8 *);
+
+ SetReadFlash1(readFlash1Buffer);
+ readFlash1 = (u8 (*)(u8 *))((s32)readFlash1Buffer + 1);
+
+ // Enter ID mode.
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0x90);
+ DELAY();
+
+ flashId = readFlash1(FLASH_BASE + 1) << 8;
+ flashId |= readFlash1(FLASH_BASE);
+
+ // Leave ID mode.
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0xF0);
+ FLASH_WRITE(0x5555, 0xF0);
+ DELAY();
+
+ return flashId;
+}
+
+void FlashTimerIntr(void)
+{
+ if (sTimerCount != 0 && --sTimerCount == 0)
+ gFlashTimeoutFlag = 1;
+}
+
+u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void))
+{
+ if (timerNum >= 4)
+ return 1;
+
+ sTimerNum = timerNum;
+ sTimerReg = &REG_TMCNT(sTimerNum);
+ *intrFunc = FlashTimerIntr;
+ return 0;
+}
+
+void StartFlashTimer(u8 phase)
+{
+ const u16 *maxTime = &gFlashMaxTime[phase * 3];
+ sSavedIme = REG_IME;
+ REG_IME = 0;
+ sTimerReg[1] = 0;
+ REG_IE |= (INTR_FLAG_TIMER0 << sTimerNum);
+ gFlashTimeoutFlag = 0;
+ sTimerCount = *maxTime++;
+ *sTimerReg++ = *maxTime++;
+ *sTimerReg-- = *maxTime++;
+ REG_IF = (INTR_FLAG_TIMER0 << sTimerNum);
+ REG_IME = 1;
+}
+
+void StopFlashTimer(void)
+{
+ REG_IME = 0;
+ *sTimerReg++ = 0;
+ *sTimerReg-- = 0;
+ REG_IE &= ~(INTR_FLAG_TIMER0 << sTimerNum);
+ REG_IME = sSavedIme;
+}
+
+u8 ReadFlash1(u8 *addr)
+{
+ return *addr;
+}
+
+void SetReadFlash1(u16 *dest)
+{
+ u16 *src;
+ u16 i;
+
+ PollFlashStatus = (u8 (*)(u8 *))((s32)dest + 1);
+
+ src = (u16 *)ReadFlash1;
+ src = (u16 *)((s32)src ^ 1);
+
+ i = ((s32)SetReadFlash1 - (s32)ReadFlash1) >> 1;
+
+ while (i != 0)
+ {
+ *dest++ = *src++;
+ i--;
+ }
+}
+
+void ReadFlash_Core(u8 *src, u8 *dest, u32 size)
+{
+ while (size-- != 0)
+ {
+ *dest++ = *src++;
+ }
+}
+
+void ReadFlash(u16 sectorNum, u32 offset, u8 *dest, u32 size)
+{
+ u8 *src;
+ u16 i;
+ u16 readFlash_Core_Buffer[0x40];
+ u16 *funcSrc;
+ u16 *funcDest;
+ void (*readFlash_Core)(u8 *, u8 *, u32);
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ if (gFlash->romSize == FLASH_ROM_SIZE_1M)
+ {
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+ }
+
+ funcSrc = (u16 *)ReadFlash_Core;
+ funcSrc = (u16 *)((s32)funcSrc ^ 1);
+ funcDest = readFlash_Core_Buffer;
+
+ i = ((s32)ReadFlash - (s32)ReadFlash_Core) >> 1;
+
+ while (i != 0)
+ {
+ *funcDest++ = *funcSrc++;
+ i--;
+ }
+
+ readFlash_Core = (void (*)(u8 *, u8 *, u32))((s32)readFlash_Core_Buffer + 1);
+
+ src = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
+
+ readFlash_Core(src, dest, size);
+}
+
+u32 VerifyFlashSector_Core(u8 *src, u8 *tgt, u32 size)
+{
+ while (size-- != 0)
+ {
+ if (*tgt++ != *src++)
+ return (u32)(tgt - 1);
+ }
+
+ return 0;
+}
+
+u32 VerifyFlashSector(u16 sectorNum, u8 *src)
+{
+ u16 i;
+ u16 verifyFlashSector_Core_Buffer[0x80];
+ u16 *funcSrc;
+ u16 *funcDest;
+ u8 *tgt;
+ u16 size;
+ u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ if (gFlash->romSize == FLASH_ROM_SIZE_1M)
+ {
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+ }
+
+ funcSrc = (u16 *)VerifyFlashSector_Core;
+ funcSrc = (u16 *)((s32)funcSrc ^ 1);
+ funcDest = verifyFlashSector_Core_Buffer;
+
+ i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
+
+ while (i != 0)
+ {
+ *funcDest++ = *funcSrc++;
+ i--;
+ }
+
+ verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
+
+ tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
+ size = gFlash->sector.size;
+
+ return verifyFlashSector_Core(src, tgt, size);
+}
+
+u32 VerifyFlashSectorNBytes(u16 sectorNum, u8 *src, u32 n)
+{
+ u16 i;
+ u16 verifyFlashSector_Core_Buffer[0x80];
+ u16 *funcSrc;
+ u16 *funcDest;
+ u8 *tgt;
+ u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
+
+ if (gFlash->romSize == FLASH_ROM_SIZE_1M)
+ {
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+ }
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ funcSrc = (u16 *)VerifyFlashSector_Core;
+ funcSrc = (u16 *)((s32)funcSrc ^ 1);
+ funcDest = verifyFlashSector_Core_Buffer;
+
+ i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
+
+ while (i != 0)
+ {
+ *funcDest++ = *funcSrc++;
+ i--;
+ }
+
+ verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
+
+ tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
+
+ return verifyFlashSector_Core(src, tgt, n);
+}
+
+u32 ProgramFlashSectorAndVerify(u16 sectorNum, u8 *src)
+{
+ u8 i;
+ u32 result;
+
+ for (i = 0; i < 3; i++)
+ {
+ result = ProgramFlashSector(sectorNum, src);
+ if (result != 0)
+ continue;
+
+ result = VerifyFlashSector(sectorNum, src);
+ if (result == 0)
+ break;
+ }
+
+ return result;
+}
+
+u32 ProgramFlashSectorAndVerifyNBytes(u16 sectorNum, u8 *src, u32 n)
+{
+ u8 i;
+ u32 result;
+
+ for (i = 0; i < 3; i++)
+ {
+ result = ProgramFlashSector(sectorNum, src);
+ if (result != 0)
+ continue;
+
+ result = VerifyFlashSectorNBytes(sectorNum, src, n);
+ if (result == 0)
+ break;
+ }
+
+ return result;
+}
diff --git a/src/agb_flash_1m.c b/src/agb_flash_1m.c
new file mode 100644
index 000000000..e249fab9a
--- /dev/null
+++ b/src/agb_flash_1m.c
@@ -0,0 +1,86 @@
+#include "gba/gba.h"
+#include "gba/flash_internal.h"
+
+static const char AgbLibFlashVersion[] = "FLASH1M_V103";
+
+const struct FlashSetupInfo * const sSetupInfos[] =
+{
+ &MX29L010,
+ &LE26FV10N1TS,
+ &DefaultFlash
+};
+
+u16 IdentifyFlash(void)
+{
+ u16 result;
+ u16 flashId;
+ const struct FlashSetupInfo * const *setupInfo;
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ flashId = ReadFlashId();
+
+ setupInfo = sSetupInfos;
+ result = 1;
+
+ for (;;)
+ {
+ if ((*setupInfo)->type.ids.separate.makerId == 0)
+ break;
+
+ if (flashId == (*setupInfo)->type.ids.joined)
+ {
+ result = 0;
+ break;
+ }
+
+ setupInfo++;
+ }
+
+ ProgramFlashByte = (*setupInfo)->programFlashByte;
+ ProgramFlashSector = (*setupInfo)->programFlashSector;
+ EraseFlashChip = (*setupInfo)->eraseFlashChip;
+ EraseFlashSector = (*setupInfo)->eraseFlashSector;
+ WaitForFlashWrite = (*setupInfo)->WaitForFlashWrite;
+ gFlashMaxTime = (*setupInfo)->maxTime;
+ gFlash = &(*setupInfo)->type;
+
+ return result;
+}
+
+u16 WaitForFlashWrite_Common(u8 phase, u8 *addr, u8 lastData)
+{
+ u16 result = 0;
+ u8 status;
+
+ StartFlashTimer(phase);
+
+ while ((status = PollFlashStatus(addr)) != lastData)
+ {
+ if (status & 0x20)
+ {
+ // The write operation exceeded the flash chip's time limit.
+
+ if (PollFlashStatus(addr) == lastData)
+ break;
+
+ FLASH_WRITE(0x5555, 0xF0);
+ result = phase | 0xA000u;
+ break;
+ }
+
+ if (gFlashTimeoutFlag)
+ {
+ if (PollFlashStatus(addr) == lastData)
+ break;
+
+ FLASH_WRITE(0x5555, 0xF0);
+ result = phase | 0xC000u;
+ break;
+ }
+ }
+
+ StopFlashTimer();
+
+ return result;
+}
diff --git a/src/agb_flash_le.c b/src/agb_flash_le.c
new file mode 100644
index 000000000..39d956e27
--- /dev/null
+++ b/src/agb_flash_le.c
@@ -0,0 +1,31 @@
+#include "gba/gba.h"
+#include "gba/flash_internal.h"
+
+const u16 leMaxTime[] =
+{
+ 10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+};
+
+const struct FlashSetupInfo LE26FV10N1TS =
+{
+ ProgramFlashByte_MX,
+ ProgramFlashSector_MX,
+ EraseFlashChip_MX,
+ EraseFlashSector_MX,
+ WaitForFlashWrite_Common,
+ leMaxTime,
+ {
+ 131072, // ROM size
+ {
+ 4096, // sector size
+ 12, // bit shift to multiply by sector size (4096 == 1 << 12)
+ 32, // number of sectors
+ 0 // appears to be unused
+ },
+ { 3, 1 }, // wait state setup data
+ { { 0x62, 0x13 } } // ID
+ }
+};
diff --git a/src/agb_flash_mx.c b/src/agb_flash_mx.c
new file mode 100644
index 000000000..01f848901
--- /dev/null
+++ b/src/agb_flash_mx.c
@@ -0,0 +1,193 @@
+#include "gba/gba.h"
+#include "gba/flash_internal.h"
+
+const u16 mxMaxTime[] =
+{
+ 10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+ 2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
+};
+
+const struct FlashSetupInfo MX29L010 =
+{
+ ProgramFlashByte_MX,
+ ProgramFlashSector_MX,
+ EraseFlashChip_MX,
+ EraseFlashSector_MX,
+ WaitForFlashWrite_Common,
+ mxMaxTime,
+ {
+ 131072, // ROM size
+ {
+ 4096, // sector size
+ 12, // bit shift to multiply by sector size (4096 == 1 << 12)
+ 32, // number of sectors
+ 0 // appears to be unused
+ },
+ { 3, 1 }, // wait state setup data
+ { { 0xC2, 0x09 } } // ID
+ }
+};
+
+const struct FlashSetupInfo DefaultFlash =
+{
+ ProgramFlashByte_MX,
+ ProgramFlashSector_MX,
+ EraseFlashChip_MX,
+ EraseFlashSector_MX,
+ WaitForFlashWrite_Common,
+ mxMaxTime,
+ {
+ 131072, // ROM size
+ {
+ 4096, // sector size
+ 12, // bit shift to multiply by sector size (4096 == 1 << 12)
+ 32, // number of sectors
+ 0 // appears to be unused
+ },
+ { 3, 1 }, // wait state setup data
+ { { 0x00, 0x00 } } // ID of 0
+ }
+};
+
+u16 EraseFlashChip_MX(void)
+{
+ u16 result;
+ u16 readFlash1Buffer[0x20];
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
+
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0x80);
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0x10);
+
+ SetReadFlash1(readFlash1Buffer);
+
+ result = WaitForFlashWrite(3, FLASH_BASE, 0xFF);
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ return result;
+}
+
+u16 EraseFlashSector_MX(u16 sectorNum)
+{
+ u16 numTries;
+ u16 result;
+ u8 *addr;
+ u16 readFlash1Buffer[0x20];
+
+ if (sectorNum >= gFlash->sector.count)
+ return 0x80FF;
+
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+
+ numTries = 0;
+
+try_erase:
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
+
+ addr = FLASH_BASE + (sectorNum << gFlash->sector.shift);
+
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0x80);
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ *addr = 0x30;
+
+ SetReadFlash1(readFlash1Buffer);
+
+ result = WaitForFlashWrite(2, addr, 0xFF);
+
+ if (!(result & 0xA000) || numTries > 3)
+ goto done;
+
+ numTries++;
+
+ goto try_erase;
+
+done:
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
+
+ return result;
+}
+
+u16 ProgramFlashByte_MX(u16 sectorNum, u32 offset, u8 data)
+{
+ u8 *addr;
+ u16 readFlash1Buffer[0x20];
+
+ if (offset >= gFlash->sector.size)
+ return 0x8000;
+
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+
+ addr = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
+
+ SetReadFlash1(readFlash1Buffer);
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
+
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0xA0);
+ *addr = data;
+
+ return WaitForFlashWrite(1, addr, data);
+}
+
+static u16 ProgramByte(u8 *src, u8 *dest)
+{
+ FLASH_WRITE(0x5555, 0xAA);
+ FLASH_WRITE(0x2AAA, 0x55);
+ FLASH_WRITE(0x5555, 0xA0);
+ *dest = *src;
+
+ return WaitForFlashWrite(1, dest, *src);
+}
+
+u16 ProgramFlashSector_MX(u16 sectorNum, u8 *src)
+{
+ u16 result;
+ u8 *dest;
+ u16 readFlash1Buffer[0x20];
+
+ if (sectorNum >= gFlash->sector.count)
+ return 0x80FF;
+
+ result = EraseFlashSector_MX(sectorNum);
+
+ if (result != 0)
+ return result;
+
+ SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
+ sectorNum %= SECTORS_PER_BANK;
+
+ SetReadFlash1(readFlash1Buffer);
+
+ REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
+
+ gFlashNumRemainingBytes = gFlash->sector.size;
+ dest = FLASH_BASE + (sectorNum << gFlash->sector.shift);
+
+ while (gFlashNumRemainingBytes > 0)
+ {
+ result = ProgramByte(src, dest);
+
+ if (result != 0)
+ break;
+
+ gFlashNumRemainingBytes--;
+ src++;
+ dest++;
+ }
+
+ return result;
+}