610 lines
14 KiB
ArmAsm
610 lines
14 KiB
ArmAsm
#include "nes.inc"
|
|
|
|
map_prg_32kB:
|
|
ldr r1, [r9, #s_prg_size]
|
|
ldr r2, [r9, #s_prg_ptr]
|
|
and r0, r1, r0, lsl #15
|
|
add r0, r0, r2
|
|
map_prg_32kB_from_pointer:
|
|
sub r0, r0, #0x8000
|
|
str r0, [r9, #s_mem_map + 16] @ 8000
|
|
str r0, [r9, #s_mem_map + 20] @ A000
|
|
str r0, [r9, #s_mem_map + 24] @ C000
|
|
str r0, [r9, #s_mem_map + 28] @ E000
|
|
bx lr
|
|
map_prg_16kB_to_8000:
|
|
ldr r1, [r9, #s_prg_size]
|
|
ldr r2, [r9, #s_prg_ptr]
|
|
and r0, r1, r0, lsl #14
|
|
add r0, r0, r2
|
|
sub r0, r0, #0x8000
|
|
str r0, [r9, #s_mem_map + 16] @ 8000
|
|
str r0, [r9, #s_mem_map + 20] @ A000
|
|
bx lr
|
|
map_prg_16kB_to_C000:
|
|
ldr r1, [r9, #s_prg_size]
|
|
ldr r2, [r9, #s_prg_ptr]
|
|
and r0, r1, r0, lsl #14
|
|
add r0, r0, r2
|
|
sub r0, r0, #0xC000
|
|
str r0, [r9, #s_mem_map + 24] @ C000
|
|
str r0, [r9, #s_mem_map + 28] @ E000
|
|
bx lr
|
|
|
|
map_prg_8kB:
|
|
ldr r2, [r9, #s_prg_size]
|
|
ldr r3, [r9, #s_prg_ptr]
|
|
and r0, r2, r0, lsl #13
|
|
add r0, r0, r3
|
|
sub r0, r0, r1
|
|
add r1, r9, r1, lsr #11
|
|
str r0, [r1, #s_mem_map]
|
|
bx lr
|
|
|
|
|
|
map_chr_8kB:
|
|
ldr r2, [r9, #s_chr_size]
|
|
ldr r3, [r9, #s_chr_ptr]
|
|
and r0, r2, r0, lsl #13
|
|
add r0, r0, r3
|
|
str r0, [r9, #s_ppu_mem_map + 0x00] @ 0000
|
|
str r0, [r9, #s_ppu_mem_map + 0x04] @ 0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x08] @ 0800
|
|
str r0, [r9, #s_ppu_mem_map + 0x0C] @ 0C00
|
|
str r0, [r9, #s_ppu_mem_map + 0x10] @ 1000
|
|
str r0, [r9, #s_ppu_mem_map + 0x14] @ 1400
|
|
str r0, [r9, #s_ppu_mem_map + 0x18] @ 1800
|
|
str r0, [r9, #s_ppu_mem_map + 0x1C] @ 1C00
|
|
bx lr
|
|
map_chr_4kB_to_0000:
|
|
mov r1, #0x0000
|
|
b map_chr_4kB
|
|
map_chr_4kB_to_1000:
|
|
mov r1, #0x1000
|
|
map_chr_4kB:
|
|
ldr r2, [r9, #s_chr_size]
|
|
ldr r3, [r9, #s_chr_ptr]
|
|
and r0, r2, r0, lsl #12
|
|
add r0, r0, r3
|
|
sub r0, r0, r1
|
|
add r1, r9, r1, lsr #8
|
|
str r0, [r1, #s_ppu_mem_map + 0x00] @ +0000
|
|
str r0, [r1, #s_ppu_mem_map + 0x04] @ +0400
|
|
str r0, [r1, #s_ppu_mem_map + 0x08] @ +0800
|
|
str r0, [r1, #s_ppu_mem_map + 0x0C] @ +0C00
|
|
bx lr
|
|
map_chr_2kB:
|
|
ldr r2, [r9, #s_chr_size]
|
|
ldr r3, [r9, #s_chr_ptr]
|
|
and r0, r2, r0, lsl #10
|
|
add r0, r0, r3
|
|
sub r0, r0, r1
|
|
add r1, r9, r1, lsr #8
|
|
str r0, [r1, #s_ppu_mem_map + 0x00] @ +0000
|
|
str r0, [r1, #s_ppu_mem_map + 0x04] @ +0400
|
|
bx lr
|
|
map_chr_1kB:
|
|
ldr r2, [r9, #s_chr_size]
|
|
ldr r3, [r9, #s_chr_ptr]
|
|
and r0, r2, r0, lsl #10
|
|
add r0, r0, r3
|
|
sub r0, r0, r1
|
|
add r1, r9, r1, lsr #8
|
|
str r0, [r1, #s_ppu_mem_map]
|
|
bx lr
|
|
|
|
mirror_1screen_lo:
|
|
add r0, r9, #s_name_table_ram - 0x2000
|
|
b mirror_1screen
|
|
mirror_1screen_hi:
|
|
add r0, r9, #s_name_table_ram + 0x0400 - 0x2000
|
|
mirror_1screen:
|
|
str r0, [r9, #s_ppu_mem_map + 0x20] @ 2000
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x24] @ 2400
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x28] @ 2800
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x2C] @ 2C00
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x30] @ 3000
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x34] @ 3400
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x38] @ 3800
|
|
sub r0, r0, #0x0400
|
|
str r0, [r9, #s_ppu_mem_map + 0x3C] @ 3C00
|
|
bx lr
|
|
|
|
mirror_vert:
|
|
add r0, r9, #s_name_table_ram - 0x2000
|
|
str r0, [r9, #s_ppu_mem_map + 0x20] @ 2000
|
|
str r0, [r9, #s_ppu_mem_map + 0x24] @ 2400
|
|
add r0, r9, #s_name_table_ram - 0x2800
|
|
str r0, [r9, #s_ppu_mem_map + 0x28] @ 2800
|
|
str r0, [r9, #s_ppu_mem_map + 0x2C] @ 2C00
|
|
add r0, r9, #s_name_table_ram - 0x3000
|
|
str r0, [r9, #s_ppu_mem_map + 0x30] @ 3000
|
|
str r0, [r9, #s_ppu_mem_map + 0x34] @ 3400
|
|
add r0, r9, #s_name_table_ram - 0x3800
|
|
str r0, [r9, #s_ppu_mem_map + 0x38] @ 3800
|
|
str r0, [r9, #s_ppu_mem_map + 0x3C] @ 3C00
|
|
bx lr
|
|
|
|
mirror_horiz:
|
|
add r0, r9, #s_name_table_ram - 0x2000
|
|
str r0, [r9, #s_ppu_mem_map + 0x20] @ 2000
|
|
add r0, r9, #s_name_table_ram - 0x2400
|
|
str r0, [r9, #s_ppu_mem_map + 0x24] @ 2400
|
|
str r0, [r9, #s_ppu_mem_map + 0x28] @ 2800
|
|
add r0, r9, #s_name_table_ram - 0x2800
|
|
str r0, [r9, #s_ppu_mem_map + 0x2C] @ 2C00
|
|
add r0, r9, #s_name_table_ram - 0x3000
|
|
str r0, [r9, #s_ppu_mem_map + 0x30] @ 2000
|
|
add r0, r9, #s_name_table_ram - 0x3400
|
|
str r0, [r9, #s_ppu_mem_map + 0x34] @ 2400
|
|
str r0, [r9, #s_ppu_mem_map + 0x38] @ 2800
|
|
add r0, r9, #s_name_table_ram - 0x3800
|
|
str r0, [r9, #s_ppu_mem_map + 0x3C] @ 2C00
|
|
bx lr
|
|
|
|
mirror_4screen:
|
|
add r0, r9, #s_name_table_ram - 0x2000
|
|
str r0, [r9, #s_ppu_mem_map + 0x20] @ 2000
|
|
str r0, [r9, #s_ppu_mem_map + 0x24] @ 2400
|
|
str r0, [r9, #s_ppu_mem_map + 0x28] @ 2800
|
|
str r0, [r9, #s_ppu_mem_map + 0x2C] @ 2C00
|
|
add r0, r9, #s_name_table_ram - 0x3000
|
|
str r0, [r9, #s_ppu_mem_map + 0x30] @ 3000
|
|
str r0, [r9, #s_ppu_mem_map + 0x34] @ 3400
|
|
str r0, [r9, #s_ppu_mem_map + 0x38] @ 3800
|
|
str r0, [r9, #s_ppu_mem_map + 0x3C] @ 3C00
|
|
bx lr
|
|
|
|
.globl load_rom
|
|
load_rom:
|
|
push {r4-r11, lr}
|
|
|
|
adr r1, file_mode
|
|
swi e_fopen
|
|
movs r4, r0
|
|
moveq r5, #error_open - error_messages
|
|
beq error
|
|
|
|
@ Read ROM header
|
|
add r0, r9, #s_rom_header
|
|
mov r1, #16
|
|
mov r2, #1
|
|
mov r3, r4
|
|
swi e_fread
|
|
mov r5, #error_bad_header - error_messages
|
|
movs r0, r0
|
|
beq error_fclose
|
|
ldr r1, [r9, #s_rom_header]
|
|
ldr r2, =0x1A53454E
|
|
cmp r1, r2
|
|
bne error_fclose
|
|
|
|
ldrb r5, [r9, #s_rom_header + 4] @ Number of PRG-ROM banks
|
|
movs r5, r5, lsl #14
|
|
moveq r5, #0x400000
|
|
sub r0, r5, #1
|
|
str r0, [r9, #s_prg_size]
|
|
|
|
ldrb r7, [r9, #s_rom_header + 5] @ Number of CHR-ROM banks
|
|
movs r6, r7, lsl #13
|
|
moveq r6, #0x2000
|
|
sub r0, r6, #1
|
|
str r0, [r9, #s_chr_size]
|
|
|
|
add r0, r5, r6
|
|
swi e_malloc
|
|
movs r0, r0
|
|
moveq r5, #error_no_memory - error_messages
|
|
beq error_fclose
|
|
str r0, [r9, #s_prg_ptr]
|
|
add r0, r5
|
|
str r0, [r9, #s_chr_ptr]
|
|
|
|
@ Clear CHR-RAM if present
|
|
movs r1, r7
|
|
moveq r2, #0x2000
|
|
moveq r6, #0
|
|
swieq e_memset
|
|
|
|
@ Read PRG-ROM and CHR-ROM from file
|
|
ldr r0, [r9, #s_prg_ptr]
|
|
add r1, r5, r6
|
|
mov r2, #1
|
|
mov r3, r4
|
|
swi e_fread
|
|
movs r0, r0
|
|
moveq r5, #error_rom_read - error_messages
|
|
beq error_fclose
|
|
|
|
mov r0, r4
|
|
swi e_fclose
|
|
|
|
@ Initialize CPU memory map
|
|
@ RAM
|
|
str r9, [r9, #s_mem_map + 0] @ 0000
|
|
@ SRAM
|
|
add r1, r9, #s_sram - 0x6000
|
|
str r1, [r9, #s_mem_map + 12] @ 6000
|
|
@ ROM low
|
|
mov r0, #0
|
|
bl map_prg_16kB_to_8000
|
|
@ ROM high
|
|
mov r0, #-1
|
|
bl map_prg_16kB_to_C000
|
|
@ RAM wraparound
|
|
sub r1, r9, #0x10000
|
|
str r1, [r9, #s_mem_map + 32] @ 10000
|
|
|
|
@ Initialize PPU memory map
|
|
mov r0, #0
|
|
bl map_chr_8kB
|
|
|
|
@ Name table
|
|
ldrb r6, [r9, #s_rom_header + 6]
|
|
adr lr, 1f
|
|
tst r6, #8
|
|
bne mirror_4screen
|
|
tst r6, #1
|
|
bne mirror_vert
|
|
beq mirror_horiz
|
|
1:
|
|
|
|
@ Get low 4 bits of mapper number
|
|
mov r0, r6, lsr #4
|
|
@ Get high 4 bits of mapper number (unless it looks like
|
|
@ there's junk in the header, in which case ignore them)
|
|
ldr r1, [r9, #s_rom_header + 12]
|
|
movs r1, r1
|
|
ldreqb r1, [r9, #s_rom_header + 7]
|
|
andeq r1, r1, #0xF0
|
|
orreq r0, r0, r1
|
|
|
|
adr r1, mapper_table
|
|
adr r2, mapper_table_end
|
|
1: cmp r2, r1
|
|
moveq r5, #error_bad_mapper - error_messages
|
|
beq error
|
|
ldrh r5, [r2, #-2]!
|
|
ldrh r4, [r2, #-2]!
|
|
cmp r0, r4
|
|
bne 1b
|
|
add r0, r1, r5
|
|
str r0, [r9, #s_mapper]
|
|
|
|
mov r0, #0
|
|
pop {r4-r11, pc}
|
|
.pool
|
|
|
|
file_mode:
|
|
.string "rb"
|
|
error_open:
|
|
.string "couldn't open file"
|
|
error_bad_header:
|
|
.string "not an NES file"
|
|
error_no_memory:
|
|
.string "not enough memory"
|
|
error_rom_read:
|
|
.string "couldn't read ROM"
|
|
error_bad_mapper:
|
|
.string "unimplemented mapper"
|
|
.align 4
|
|
|
|
error_fclose:
|
|
mov r0, r4
|
|
swi e_fclose
|
|
error:
|
|
ldr r0, [r9, #s_prg_ptr]
|
|
swi e_free
|
|
mov r0, #0
|
|
str r0, [r9, #s_prg_ptr]
|
|
error_messages = .+8
|
|
add r0, pc, r5
|
|
pop {r4-r11, pc}
|
|
|
|
mapper_table:
|
|
.macro MAPPER n, addr; .hword \n, \addr - mapper_table; .endm
|
|
MAPPER 0, mapper_NROM
|
|
MAPPER 1, mapper_MMC1
|
|
MAPPER 2, mapper_UxROM
|
|
MAPPER 3, mapper_CNROM
|
|
MAPPER 4, mapper_MMC3
|
|
MAPPER 7, mapper_AxROM
|
|
MAPPER 11, mapper_Color_Dreams
|
|
MAPPER 34, mapper_BxROM
|
|
MAPPER 66, mapper_GxROM
|
|
MAPPER 228, mapper_Action_Enterprises
|
|
mapper_table_end:
|
|
|
|
mapper_NROM:
|
|
bx lr
|
|
|
|
#define s_mmc1_shift_reg (s_mapper_state)
|
|
#define s_mmc1_control (s_mapper_state+4)
|
|
#define s_mmc1_chr0 (s_mapper_state+5)
|
|
#define s_mmc1_chr1 (s_mapper_state+6)
|
|
#define s_mmc1_prg (s_mapper_state+7)
|
|
mapper_MMC1:
|
|
push {lr}
|
|
ldrb r3, [r9, #s_mmc1_shift_reg]
|
|
tst r0, #0x80
|
|
bne mmc1_reset
|
|
and r0, r0, #1
|
|
movs r3, r3, lsr #1
|
|
orr r0, r3, r0, lsl #4
|
|
strb r0, [r9, #s_mmc1_shift_reg]
|
|
popcc {pc}
|
|
and r2, r2, #0x6000
|
|
add r2, r9, r2, lsr #13
|
|
strb r0, [r2, #s_mmc1_control]
|
|
b mmc1_update
|
|
mmc1_reset:
|
|
ldrb r0, [r9, #s_mmc1_control]
|
|
orr r0, r0, #0x0C
|
|
strb r0, [r9, #s_mmc1_control]
|
|
mmc1_update:
|
|
mov r0, #0x10
|
|
strb r0, [r9, #s_mmc1_shift_reg]
|
|
|
|
ldrb r3, [r9, #s_mmc1_control]
|
|
adr lr, 1f
|
|
and r3, r3, #3
|
|
add pc, pc, r3, lsl #2
|
|
nop
|
|
b mirror_1screen_lo
|
|
b mirror_1screen_hi
|
|
b mirror_vert
|
|
b mirror_horiz
|
|
1:
|
|
|
|
@ Update CHR
|
|
ldrb r3, [r9, #s_mmc1_control]
|
|
ldrb r0, [r9, #s_mmc1_chr0]
|
|
tst r3, #0x10
|
|
bne 1f
|
|
mov r0, r0, lsr #1
|
|
bl map_chr_8kB
|
|
b 2f
|
|
1: bl map_chr_4kB_to_0000
|
|
ldrb r0, [r9, #s_mmc1_chr1]
|
|
bl map_chr_4kB_to_1000
|
|
2:
|
|
|
|
@ Update PRG
|
|
ldrb r3, [r9, #s_mmc1_control]
|
|
ldrb r0, [r9, #s_mmc1_prg]
|
|
@ Mode 0-1
|
|
tst r3, #0x08
|
|
bne 1f
|
|
mov r0, r0, lsr #1
|
|
bl map_prg_32kB
|
|
pop {pc}
|
|
1:
|
|
|
|
@ Mode 2
|
|
tst r3, #0x04
|
|
bne 1f
|
|
bl map_prg_16kB_to_C000
|
|
mov r0, #0
|
|
bl map_prg_16kB_to_8000
|
|
pop {pc}
|
|
@ Mode 3
|
|
1: bl map_prg_16kB_to_8000
|
|
mov r0, #-1
|
|
bl map_prg_16kB_to_C000
|
|
pop {pc}
|
|
|
|
mapper_UxROM:
|
|
b map_prg_16kB_to_8000
|
|
|
|
mapper_CNROM:
|
|
b map_chr_8kB
|
|
|
|
#define s_mmc3_bank (s_mapper_state)
|
|
#define s_mmc3_bank_select (s_mapper_state+8)
|
|
#define s_mmc3_counter_reload (s_mapper_state+9)
|
|
#define s_mmc3_counter (s_mapper_state+10)
|
|
#define s_mmc3_counter_reset (s_mapper_state+11)
|
|
#define s_mmc3_irq_enabled (s_mapper_state+12)
|
|
mapper_MMC3:
|
|
and r1, r2, #0x6000
|
|
and r2, r2, #0x0001
|
|
orr r2, r2, r1, lsr #12
|
|
add pc, pc, r2, lsl #2
|
|
nop
|
|
b mmc3_bank_select
|
|
b mmc3_bank_data
|
|
b mmc3_mirroring
|
|
bx lr
|
|
b mmc3_irq_latch
|
|
b mmc3_irq_reload
|
|
b mmc3_irq_disable
|
|
b mmc3_irq_enable
|
|
mmc3_bank_select:
|
|
strb r0, [r9, #s_mmc3_bank_select]
|
|
b mmc3_update
|
|
mmc3_bank_data:
|
|
ldrb r1, [r9, #s_mmc3_bank_select]
|
|
and r3, r1, #7
|
|
add r3, r3, r9
|
|
strb r0, [r3, #s_mmc3_bank]
|
|
b mmc3_update
|
|
mmc3_mirroring:
|
|
@ Don't do anything if game uses 4-screen mirroring
|
|
ldrb r3, [r9, #s_rom_header+6]
|
|
tst r3, #8
|
|
bxne lr
|
|
tst r0, #1
|
|
beq mirror_vert
|
|
b mirror_horiz
|
|
mmc3_irq_latch:
|
|
strb r0, [r9, #s_mmc3_counter_reload]
|
|
bx lr
|
|
mmc3_irq_reload:
|
|
mov r0, #0xFF
|
|
strb r0, [r9, #s_mmc3_counter_reset]
|
|
bx lr
|
|
mmc3_irq_disable:
|
|
mov r0, #0
|
|
strb r0, [r9, #s_irq_from_mapper]
|
|
mmc3_irq_enable:
|
|
and r0, r2, #1
|
|
strb r0, [r9, #s_mmc3_irq_enabled]
|
|
bx lr
|
|
.globl mmc3_scanline
|
|
mmc3_scanline:
|
|
ldrb r0, [r9, #s_mmc3_counter]
|
|
|
|
ldrb r1, [r9, #s_mmc3_counter_reset]
|
|
bic r1, r0, r1
|
|
subs r1, r1, #1
|
|
ldrmib r1, [r9, #s_mmc3_counter_reload]
|
|
strb r1, [r9, #s_mmc3_counter]
|
|
mov r2, #0
|
|
strb r2, [r9, #s_mmc3_counter_reset]
|
|
|
|
cmp r1, #0
|
|
bxne lr
|
|
cmp r0, #0
|
|
bxeq lr
|
|
|
|
ldrb r0, [r9, #s_mmc3_irq_enabled]
|
|
strb r0, [r9, #s_irq_from_mapper]
|
|
bx lr
|
|
mmc3_update:
|
|
push {r4, r5, lr}
|
|
ldrb r5, [r9, #s_mmc3_bank_select]
|
|
|
|
mov r4, #0x1000
|
|
and r4, r4, r5, lsl #5
|
|
ldrb r0, [r9, #s_mmc3_bank+0]; eor r1, r4, #0x0000; bl map_chr_2kB
|
|
ldrb r0, [r9, #s_mmc3_bank+1]; eor r1, r4, #0x0800; bl map_chr_2kB
|
|
ldrb r0, [r9, #s_mmc3_bank+2]; eor r1, r4, #0x1000; bl map_chr_1kB
|
|
ldrb r0, [r9, #s_mmc3_bank+3]; eor r1, r4, #0x1400; bl map_chr_1kB
|
|
ldrb r0, [r9, #s_mmc3_bank+4]; eor r1, r4, #0x1800; bl map_chr_1kB
|
|
ldrb r0, [r9, #s_mmc3_bank+5]; eor r1, r4, #0x1C00; bl map_chr_1kB
|
|
|
|
mov r4, #0x4000
|
|
and r4, r4, r5, lsl #8
|
|
ldrb r0, [r9, #s_mmc3_bank+6]; eor r1, r4, #0x8000; bl map_prg_8kB
|
|
ldrb r0, [r9, #s_mmc3_bank+7]; mov r1, #0xA000; bl map_prg_8kB
|
|
mov r0, #-2; eor r1, r4, #0xC000; bl map_prg_8kB
|
|
|
|
pop {r4, r5, pc}
|
|
|
|
mapper_AxROM:
|
|
push {r4, lr}
|
|
mov r4, r0
|
|
tst r4, #0x10
|
|
bleq mirror_1screen_lo
|
|
blne mirror_1screen_hi
|
|
mov r0, r4
|
|
pop {r4, lr}
|
|
b map_prg_32kB
|
|
|
|
mapper_Color_Dreams:
|
|
push {r4, lr}
|
|
mov r4, r0
|
|
bl map_prg_32kB
|
|
mov r0, r4, lsr #4
|
|
pop {r4, lr}
|
|
b map_chr_8kB
|
|
|
|
mapper_BxROM:
|
|
b map_prg_32kB
|
|
|
|
mapper_GxROM:
|
|
push {r4, lr}
|
|
mov r4, r0
|
|
bl map_chr_8kB
|
|
mov r0, r4, lsr #4
|
|
pop {r4, lr}
|
|
b map_prg_32kB
|
|
|
|
mapper_Action_Enterprises:
|
|
push {r4, lr}
|
|
mov r4, r2
|
|
and r0, r0, #3
|
|
orr r0, r0, r2, lsl #2
|
|
bl map_chr_8kB
|
|
mov r0, r4, lsr #7
|
|
and r0, r0, #0x3F
|
|
mov r0, r0, lsl #15
|
|
ldr r1, [r9, #s_prg_size]
|
|
ldr r2, [r9, #s_prg_ptr]
|
|
cmp r0, r1
|
|
andhi r0, r0, r1
|
|
add r0, r0, r2
|
|
bl map_prg_32kB_from_pointer
|
|
bl mirror_vert
|
|
pop {r4, pc}
|
|
|
|
.globl sram_load
|
|
sram_load:
|
|
ldrb r0, [r9, #s_rom_header+6]
|
|
tst r0, #0x02
|
|
bxeq lr
|
|
push {r4, lr}
|
|
ldr r0, [r9, #s_path_extension]
|
|
adr r1, save_ext
|
|
swi e_strcpy
|
|
add r0, r9, #s_path
|
|
adr r1, save_read_mode
|
|
swi e_fopen
|
|
movs r4, r0
|
|
popeq {r4, pc}
|
|
add r0, r9, #s_sram
|
|
mov r1, #0x2000
|
|
mov r2, #1
|
|
mov r3, r4
|
|
swi e_fread
|
|
mov r0, r4
|
|
swi e_fclose
|
|
pop {r4, pc}
|
|
.globl sram_save
|
|
sram_save:
|
|
push {r4-r5, lr}
|
|
ldrb r0, [r9, #s_rom_header+6]
|
|
tst r0, #0x02
|
|
adreq r5, no_saves
|
|
beq 1f
|
|
ldr r0, [r9, #s_path_extension]
|
|
adr r1, save_ext
|
|
swi e_strcpy
|
|
add r0, r9, #s_path
|
|
adr r1, save_write_mode
|
|
swi e_fopen
|
|
adr r5, save_error
|
|
movs r4, r0
|
|
beq 1f
|
|
add r0, r9, #s_sram
|
|
mov r1, #0x2000
|
|
mov r2, #1
|
|
mov r3, r4
|
|
swi e_fwrite
|
|
movs r0, r0
|
|
adrne r5, save_success
|
|
mov r0, r4
|
|
swi e_fclose
|
|
1: mov r0, r5
|
|
pop {r4-r5, lr}
|
|
b display_ingame_message
|
|
save_ext:
|
|
.string "sav.tns"
|
|
save_read_mode:
|
|
.string "rb"
|
|
save_write_mode:
|
|
.string "wb"
|
|
no_saves:
|
|
.string "Game has no save memory"
|
|
save_error:
|
|
.string "File error while saving"
|
|
save_success:
|
|
.string "Saved"
|
|
.align 4
|