diff --git a/Makefile b/Makefile index d899015225..ea7adb0e66 100644 --- a/Makefile +++ b/Makefile @@ -473,7 +473,7 @@ endif $(OBJ_DIR)/ld_script.ld: $(LD_SCRIPT) $(LD_SCRIPT_DEPS) cd $(OBJ_DIR) && sed "s#tools/#../../tools/#g" ../../$(LD_SCRIPT) > ld_script.ld -LDFLAGS = -Map ../../$(MAP) +LDFLAGS = -Map ../../$(MAP) --no-warn-rwx-segments $(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS) libagbsyscall @echo "cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ " @cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld --print-memory-usage -o ../../$@ $(OBJS_REL) $(LIB) | cat diff --git a/include/crt0.h b/include/crt0.h index a4a5c7f79b..c60ed3b0b7 100644 --- a/include/crt0.h +++ b/include/crt0.h @@ -3,4 +3,6 @@ extern u32 IntrMain[]; +extern void ReInitializeEWRAM(); + #endif //GUARD_CRT0_H diff --git a/include/gba/defines.h b/include/gba/defines.h index 0601f1b47e..6366355875 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -6,8 +6,10 @@ #define TRUE 1 #define FALSE 0 -#define IWRAM_DATA __attribute__((section("iwram_data"))) -#define EWRAM_DATA __attribute__((section("ewram_data"))) +#define IWRAM_DATA __attribute__((section(".bss"))) +#define EWRAM_DATA __attribute__((section(".sbss"))) +#define IWRAM_INIT __attribute__((section(".iwram"))) +#define EWRAM_INIT __attribute__((section(".ewram"))) #define UNUSED __attribute__((unused)) #if MODERN diff --git a/ld_script.ld b/ld_script.ld index 642480d35d..e9cbae8957 100644 --- a/ld_script.ld +++ b/ld_script.ld @@ -13,19 +13,35 @@ MEMORY SECTIONS { - ewram 0x2000000 (NOLOAD) : + .ewram ORIGIN(EWRAM) : AT (__ewram_lma) + ALIGN(4) + { + __ewram_start = .; + *(.ewram*) + __ewram_end = .; + } > EWRAM + + .ewram.sbss (NOLOAD) : ALIGN(4) { INCLUDE "sym_ewram.ld" - src/*.o(ewram_data); - gflib/*.o(ewram_data); + src/*.o(.sbss); + gflib/*.o(.sbss); *libc.a:impure.o(.data); *libc.a:locale.o(.data); *libc.a:mallocr.o(.data); } > EWRAM - iwram 0x3000000 (NOLOAD) : + .iwram ORIGIN(IWRAM) : AT (__iwram_lma) + ALIGN(4) + { + __iwram_start = .; + *(.iwram*); + __iwram_end = .; + } > IWRAM + + .iwram.bss (NOLOAD) : ALIGN(4) { /* .bss starts at 0x3000000 */ @@ -1324,6 +1340,20 @@ SECTIONS { data/*.o(.rodata); } > ROM = 0 + .data.iwram : + ALIGN(4) + { + __iwram_lma = .; + . = . + (__iwram_end - __iwram_start); + } > ROM = 0 + + .data.ewram : + ALIGN(4) + { + __ewram_lma = .; + . = . + (__ewram_end - __ewram_start); + } > ROM = 0 + __rom_end = .; /* DWARF debug sections. diff --git a/ld_script_modern.ld b/ld_script_modern.ld index f3bf7b6798..fd35a1ca31 100644 --- a/ld_script_modern.ld +++ b/ld_script_modern.ld @@ -12,15 +12,32 @@ MEMORY } SECTIONS { - ewram 0x2000000 (NOLOAD) : + + + .ewram ORIGIN(EWRAM) : AT (__ewram_lma) ALIGN(4) { - src/*.o(ewram_data); - gflib/*.o(ewram_data); - + __ewram_start = .; + *(.ewram*) + __ewram_end = .; } > EWRAM - iwram 0x3000000 (NOLOAD) : + .ewram.sbss (NOLOAD) : + ALIGN(4) + { + src/*.o(.sbss); + gflib/*.o(.sbss); + } > EWRAM + + .iwram ORIGIN(IWRAM) : AT (__iwram_lma) + ALIGN(4) + { + __iwram_start = .; + *(.iwram*); + __iwram_end = .; + } > IWRAM + + .iwram.bss (NOLOAD) : ALIGN(4) { src/*.o(.bss); @@ -38,9 +55,8 @@ SECTIONS { } > IWRAM /* BEGIN ROM DATA */ - . = 0x8000000; - .text : + .text ORIGIN(ROM) : ALIGN(4) { src/rom_header.o(.text*); @@ -125,6 +141,20 @@ SECTIONS { src/graphics.o(.rodata); } > ROM =0 + .data.iwram : + ALIGN(4) + { + __iwram_lma = .; + . = . + (__iwram_end - __iwram_start); + } > ROM = 0 + + .data.ewram : + ALIGN(4) + { + __ewram_lma = .; + . = . + (__ewram_end - __ewram_start); + } > ROM = 0 + __rom_end = .; /* DWARF debug sections. diff --git a/ld_script_test.ld b/ld_script_test.ld index 49a0ec35b0..ec99609a7e 100644 --- a/ld_script_test.ld +++ b/ld_script_test.ld @@ -12,15 +12,32 @@ MEMORY } SECTIONS { - ewram 0x2000000 (NOLOAD) : + + .ewram ORIGIN(EWRAM) : AT (__ewram_lma) ALIGN(4) { - src/*.o(ewram_data); - gflib/*.o(ewram_data); - test/*.o(ewram_data); + __ewram_start = .; + *(.ewram*) + __ewram_end = .; } > EWRAM - iwram 0x3000000 (NOLOAD) : + .ewram.sbss (NOLOAD) : + ALIGN(4) + { + src/*.o(.sbss); + gflib/*.o(.sbss); + test/*.o(.sbss); + } > EWRAM + + .iwram ORIGIN(IWRAM) : AT (__iwram_lma) + ALIGN(4) + { + __iwram_start = .; + *(.iwram*); + __iwram_end = .; + } > IWRAM + + .iwram.sbss (NOLOAD) : ALIGN(4) { src/*.o(.bss); @@ -97,6 +114,20 @@ SECTIONS { src/libisagbprn.o(.rodata); } > ROM =0 + .data.iwram : + ALIGN(4) + { + __iwram_lma = .; + . = . + (__iwram_end - __iwram_start); + } > ROM = 0 + + .data.ewram : + ALIGN(4) + { + __ewram_lma = .; + . = . + (__ewram_end - __ewram_start); + } > ROM = 0 + tests : ALIGN(4) { diff --git a/src/crt0.s b/src/crt0.s index 5808147220..af6ea0bc95 100644 --- a/src/crt0.s +++ b/src/crt0.s @@ -6,22 +6,28 @@ .align 2, 0 Init:: +@ Set up location for IRQ stack mov r0, #PSR_IRQ_MODE msr cpsr_cf, r0 ldr sp, sp_irq +@ Set up location for system stack mov r0, #PSR_SYS_MODE msr cpsr_cf, r0 ldr sp, sp_sys +@ Prepare for interrupt handling ldr r1, =INTR_VECTOR adr r0, IntrMain str r0, [r1] - .if MODERN +@ Dispatch memory reset request to hardware mov r0, #255 @ RESET_ALL svc #1 << 16 - .endif @ MODERN +@ Fill RAM areas with appropriate data + bl InitializeWorkingMemory +@ Jump to AgbMain ldr r1, =AgbMain + 1 mov lr, pc bx r1 +@ Re-init if AgbMain exits b Init .align 2, 0 @@ -124,3 +130,54 @@ IntrMain_RetAddr: .pool .align 2, 0 @ Don't pad with nop. + +@ Fills initialized IWRAM and EWRAM sections in RAM from LMA areas in ROM +InitializeWorkingMemory: + push {r0-r3,lr} + ldr r0, =__iwram_lma + ldr r1, =__iwram_start + ldr r2, =__iwram_end + cmp r1, r2 + beq skip_iwram_copy + bl CopyMemory_DMA +skip_iwram_copy: + ldr r0, =__ewram_lma + ldr r1, =__ewram_start + ldr r2, =__ewram_end + cmp r1, r2 + beq skip_ewram_copy + bl CopyMemory_DMA +skip_ewram_copy: + pop {r0-r3,lr} + bx lr + +@ Uses a DMA transfer to load from r0 into r1 until r2 +CopyMemory_DMA: + subs r2, r2, r1 + lsr r2, r2, #2 + mov r4, #0x80000000 + orr r4, r4, #(1 << 26) + orr r2, r2, r4 + ldr r3, =REG_DMA3 + stmia r3, {r0, r1, r2} + bx lr + +.thumb +@ Called from C code to reinitialize working memory after a link connection failure +ReInitializeEWRAM:: + ldr r0, =__ewram_lma + ldr r1, =__ewram_start + ldr r2, =__ewram_end + cmp r1, r2 + beq EndReinitializeEWRAM + subs r2, r1 + movs r3, #1 + lsls r3, r3, #26 + orrs r2, r2, r3 + swi 0x0B +EndReinitializeEWRAM: + bx lr + + .pool + + .align 2, 0 @ Don't pad with nop. diff --git a/src/main.c b/src/main.c index 1f2b712750..1d23daa3e3 100644 --- a/src/main.c +++ b/src/main.c @@ -93,11 +93,6 @@ void EnableVCountIntrAtLine150(void); void AgbMain() { - // Modern compilers are liberal with the stack on entry to this function, - // so RegisterRamReset may crash if it resets IWRAM. -#if !MODERN - RegisterRamReset(RESET_ALL); -#endif //MODERN *(vu16 *)BG_PLTT = RGB_WHITE; // Set the backdrop to white on startup InitGpuRegManager(); REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3; diff --git a/src/reload_save.c b/src/reload_save.c index 5425d1c7c4..f6104c1db7 100644 --- a/src/reload_save.c +++ b/src/reload_save.c @@ -1,5 +1,6 @@ #include "global.h" #include "main.h" +#include "crt0.h" #include "gpu_regs.h" #include "m4a.h" #include "load_save.h" @@ -15,6 +16,7 @@ void ReloadSave(void) u16 imeBackup = REG_IME; REG_IME = 0; RegisterRamReset(RESET_EWRAM); + ReInitializeEWRAM(); ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); REG_IME = imeBackup; gMain.inBattle = FALSE;