Enabled more debugging techniques by default in debug builds.
Added more Arm intrinsics. ARM7 stub now waits for REG_VCOUNT == 126 (same as after BIOS intro). Enable ROM mirroring for all 8 Mbit games instead of just Classic NES Series. Other misc. changes.
This commit is contained in:
parent
5316c8938d
commit
5f25739286
|
@ -36,18 +36,24 @@ endif
|
|||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork
|
||||
|
||||
CFLAGS := $(ARCH) -std=gnu17 -O2 -g -flto -mword-relocations -ffunction-sections \
|
||||
-fno-math-errno -Wall -Wextra -Wno-unused-function
|
||||
CFLAGS := $(ARCH) -std=c17 -O2 -g -flto -mword-relocations \
|
||||
-ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
CXXFLAGS := $(ARCH) -std=c++17 -O2 -g -flto -fno-rtti -fno-exceptions \
|
||||
-mword-relocations -ffunction-sections -fno-math-errno -Wall -Wextra \
|
||||
-Wno-unused-function
|
||||
-mword-relocations -ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CXXFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES)
|
||||
LDFLAGS = $(ARCH) -g -flto -specs=../arm11.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
|
||||
|
||||
ifeq ($(strip $(NO_DEBUG)),)
|
||||
CFLAGS := $(subst -flto,,$(CFLAGS)) -fstack-protector-strong -fno-inline
|
||||
CXXFLAGS := $(subst -flto,,$(CXXFLAGS)) -fstack-protector-strong -fno-inline
|
||||
ASFLAGS := $(subst -flto,,$(ASFLAGS))
|
||||
LDFLAGS := $(subst -flto,,$(LDFLAGS)) -fstack-protector-strong -fno-inline -Wl,-wrap=malloc,-wrap=calloc,-wrap=free
|
||||
endif
|
||||
|
||||
LIBS := -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -188,4 +194,3 @@ endef
|
|||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
|
@ -197,6 +197,59 @@ ALWAYS_INLINE u32 __strex(vu32 *addr, u32 val)
|
|||
|
||||
MAKE_INTR_NO_INOUT(1, clrex, "memory")
|
||||
|
||||
// Debug ID Register
|
||||
MAKE_INTR_GET_REG(0, getDidr, "mrc p14, 0, %0, c0, c0, 0")
|
||||
|
||||
// Debug Status and Control Register
|
||||
MAKE_INTR_GET_REG(1, getDscr, "mrc p14, 0, %0, c0, c1, 0")
|
||||
MAKE_INTR_SET_REG(1, setDscr, "mcr p14, 0, %0, c0, c1, 0", "memory")
|
||||
|
||||
// Data Transfer Register
|
||||
|
||||
// Vector Catch Register
|
||||
MAKE_INTR_GET_REG(1, getVcr, "mrc p14, 0, %0, c0, c7, 0")
|
||||
MAKE_INTR_SET_REG(1, setVcr, "mcr p14, 0, %0, c0, c7, 0", "memory")
|
||||
|
||||
// Breakpoint Value Register 0-5
|
||||
MAKE_INTR_GET_REG(1, getBvr0, "mrc p14, 0, %0, c0, c0, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr0, "mcr p14, 0, %0, c0, c0, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr1, "mrc p14, 0, %0, c0, c1, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr1, "mcr p14, 0, %0, c0, c1, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr2, "mrc p14, 0, %0, c0, c2, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr2, "mcr p14, 0, %0, c0, c2, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr3, "mrc p14, 0, %0, c0, c3, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr3, "mcr p14, 0, %0, c0, c3, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr4, "mrc p14, 0, %0, c0, c4, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr4, "mcr p14, 0, %0, c0, c4, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr5, "mrc p14, 0, %0, c0, c5, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr5, "mcr p14, 0, %0, c0, c5, 4", "memory")
|
||||
|
||||
// Breakpoint Control Register 0-5
|
||||
MAKE_INTR_GET_REG(1, getBcr0, "mrc p14, 0, %0, c0, c0, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr0, "mcr p14, 0, %0, c0, c0, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr1, "mrc p14, 0, %0, c0, c1, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr1, "mcr p14, 0, %0, c0, c1, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr2, "mrc p14, 0, %0, c0, c2, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr2, "mcr p14, 0, %0, c0, c2, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr3, "mrc p14, 0, %0, c0, c3, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr3, "mcr p14, 0, %0, c0, c3, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr4, "mrc p14, 0, %0, c0, c4, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr4, "mcr p14, 0, %0, c0, c4, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr5, "mrc p14, 0, %0, c0, c5, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr5, "mcr p14, 0, %0, c0, c5, 5", "memory")
|
||||
|
||||
// Watchpoint Value Register 0-1
|
||||
MAKE_INTR_GET_REG(1, getWvr0, "mrc p14, 0, %0, c0, c0, 6")
|
||||
MAKE_INTR_SET_REG(1, setWvr0, "mcr p14, 0, %0, c0, c0, 6", "memory")
|
||||
MAKE_INTR_GET_REG(1, getWvr1, "mrc p14, 0, %0, c0, c1, 6")
|
||||
MAKE_INTR_SET_REG(1, setWvr1, "mcr p14, 0, %0, c0, c1, 6", "memory")
|
||||
|
||||
// Watchpoint Control Register 0-1
|
||||
MAKE_INTR_GET_REG(1, getWcr0, "mrc p14, 0, %0, c0, c0, 7")
|
||||
MAKE_INTR_SET_REG(1, setWcr0, "mcr p14, 0, %0, c0, c0, 7", "memory")
|
||||
MAKE_INTR_GET_REG(1, getWcr1, "mrc p14, 0, %0, c0, c1, 7")
|
||||
MAKE_INTR_SET_REG(1, setWcr1, "mcr p14, 0, %0, c0, c1, 7", "memory")
|
||||
|
||||
ALWAYS_INLINE u32 __getCpuId(void)
|
||||
{
|
||||
u32 cpuId;
|
||||
|
@ -224,6 +277,22 @@ MAKE_INTR_SET_REG(1, setTtbcr, "mcr p15, 0, %0, c2, c0, 2", "memory")
|
|||
MAKE_INTR_GET_REG(1, getDacr, "mrc p15, 0, %0, c3, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setDacr, "mcr p15, 0, %0, c3, c0, 0", "memory")
|
||||
|
||||
// Data Fault Status Register
|
||||
MAKE_INTR_GET_REG(1, getDfsr, "mrc p15, 0, %0, c5, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setDfsr, "mcr p15, 0, %0, c5, c0, 0", "memory")
|
||||
|
||||
// Instruction Fault Status Register
|
||||
MAKE_INTR_GET_REG(1, getIfsr, "mrc p15, 0, %0, c5, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setIfsr, "mcr p15, 0, %0, c5, c0, 1", "memory")
|
||||
|
||||
// Fault Address Register
|
||||
MAKE_INTR_GET_REG(1, getFar, "mrc p15, 0, %0, c6, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setFar, "mcr p15, 0, %0, c6, c0, 0", "memory")
|
||||
|
||||
// Watchpoint Fault Address Register
|
||||
MAKE_INTR_GET_REG(1, getWfar, "mrc p15, 0, %0, c6, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setWfar, "mcr p15, 0, %0, c6, c0, 1", "memory")
|
||||
|
||||
// Flush Prefetch Buffer
|
||||
// Data Synchronization Barrier
|
||||
// Data Memory Barrier
|
||||
|
|
|
@ -22,9 +22,8 @@
|
|||
|
||||
|
||||
|
||||
noreturn void panic();
|
||||
noreturn void panic(void);
|
||||
noreturn void panicMsg(const char *msg);
|
||||
//void debugMemdump(const char *filepath, void *mem, size_t size);
|
||||
|
||||
// Exception tests
|
||||
/*static inline regTest(void)
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
|
||||
|
||||
extern const u32 _arm7_stub_start[];
|
||||
extern const u32 _arm7_stub_swi[]; // Final ARM9 mem location.
|
||||
extern const u32 _arm7_stub_size[];
|
||||
noreturn void _a7_overlay_stub(void);
|
||||
extern const u32 _a7_overlay_stub_size[];
|
||||
|
||||
noreturn void _a7_stub_start(void);
|
||||
extern u16 _a7_stub9_swi[]; // Final ARM9 mem location.
|
||||
extern const u32 _a7_stub_size[];
|
||||
|
|
|
@ -111,6 +111,7 @@ ALWAYS_INLINE u64 __##inst(u32 op1, u32 op2, u64 acc)
|
|||
|
||||
|
||||
|
||||
// Pack Halfword Bottom Top.
|
||||
#define __pkhbt(op1, op2, sh) \
|
||||
({ \
|
||||
u32 __res; \
|
||||
|
@ -118,6 +119,7 @@ ALWAYS_INLINE u64 __##inst(u32 op1, u32 op2, u64 acc)
|
|||
__res; \
|
||||
})
|
||||
|
||||
// Pack Halfword Top Bottom.
|
||||
#define __pkhtb(op1, op2, sh) \
|
||||
({ \
|
||||
u32 __res, __sh = (sh); \
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef enum
|
|||
IPC_CMD9_BACKUP_GBA_SAVE = MAKE_CMD9(0, 0, 0),
|
||||
|
||||
// Miscellaneous API.
|
||||
IPC_CMD9_PREPARE_POWER = MAKE_CMD9(0, 0, 0)
|
||||
IPC_CMD9_PREPARE_POWER = MAKE_CMD9(0, 0, 0) // Also used for panic() and guruMeditation().
|
||||
} IpcCmd9;
|
||||
|
||||
enum {_CMD11_C_BASE = __COUNTER__ + 1}; // Start at 0.
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct
|
|||
|
||||
|
||||
|
||||
KRes switchContext(KRes res, void *oldSp, uintptr_t newSp);
|
||||
KRes switchContext(KRes res, uintptr_t *oldSp, uintptr_t newSp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ switchContextAllRegs_end:
|
|||
cpsie i
|
||||
bx lr*/
|
||||
|
||||
@ KRes switchContext(KRes res, void *oldSp, uintptr_t newSp);
|
||||
@ KRes switchContext(KRes res, uintptr_t *oldSp, uintptr_t newSp);
|
||||
BEGIN_ASM_FUNC switchContext
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
str sp, [r1]
|
||||
|
|
|
@ -195,6 +195,10 @@ bool waitQueueWakeN(ListNode *waitQueue, u32 wakeCount, KRes res, bool reschedul
|
|||
|
||||
static KRes scheduler(TaskState curTaskState)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if((__getCpsr() & PSR_MODE_MASK) != PSR_SYS_MODE) panic();
|
||||
#endif
|
||||
|
||||
TaskCb *const curDeadTask = g_curDeadTask;
|
||||
// TODO: Get rid of this and find a better way.
|
||||
if(UNLIKELY(curDeadTask != NULL))
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
@ -24,7 +25,6 @@
|
|||
#include "arm11/fmt.h"
|
||||
#include "hardware/pxi.h"
|
||||
#include "ipc_handler.h"
|
||||
#include "hardware/gfx.h"
|
||||
#include "arm11/hardware/interrupt.h"
|
||||
#include "arm.h"
|
||||
#include "arm11/hardware/mcu.h"
|
||||
|
@ -32,20 +32,17 @@
|
|||
|
||||
|
||||
|
||||
noreturn void panic()
|
||||
noreturn void panic(void)
|
||||
{
|
||||
enterCriticalSection();
|
||||
|
||||
consoleInit(SCREEN_BOT, NULL);
|
||||
ee_printf("\x1b[41m\x1b[0J\x1b[15C****PANIC!!!****\n");
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_PANIC);
|
||||
PXI_sendPanicCmd(IPC_CMD9_PREPARE_POWER);
|
||||
|
||||
// Wait for A/B/X or Y
|
||||
do
|
||||
{
|
||||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
while(!(REG_HID_PAD & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
|
@ -59,32 +56,21 @@ noreturn void panicMsg(const char *msg)
|
|||
ee_printf("\x1b[41m\x1b[0J\x1b[15C****PANIC!!!****\n\n");
|
||||
ee_printf("\nERROR MESSAGE:\n%s\n", msg);
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_PANIC);
|
||||
PXI_sendPanicCmd(IPC_CMD9_PREPARE_POWER);
|
||||
|
||||
// Wait for A/B/X or Y
|
||||
do
|
||||
{
|
||||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
while(!(REG_HID_PAD & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
}
|
||||
|
||||
// Expects the registers in the exception stack to be in the following order:
|
||||
// r0-r14, pc (unmodified), cpsr
|
||||
// r0-r14, pc (unmodified), CPSR, DFSR, IFSR, FAR, WFAR
|
||||
noreturn void guruMeditation(u8 type, const u32 *excStack)
|
||||
{
|
||||
const char *const typeStr[3] = {"Undefined instruction", "Prefetch abort", "Data abort"};
|
||||
u32 realPc, instSize = 4;
|
||||
//bool codeChanged = false;
|
||||
|
||||
|
||||
// verify text and rodata
|
||||
/*u32 prevHash = debugHash;
|
||||
debugHashCodeRoData();
|
||||
if(prevHash != debugHash)
|
||||
codeChanged = true;*/
|
||||
|
||||
consoleInit(SCREEN_BOT, NULL);
|
||||
|
||||
|
@ -123,32 +109,72 @@ noreturn void guruMeditation(u8 type, const u32 *excStack)
|
|||
}
|
||||
}
|
||||
|
||||
//if(codeChanged) ee_printf("Attention: RO section data changed!!");
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_EXCEPTION);
|
||||
PXI_sendPanicCmd(IPC_CMD9_PREPARE_POWER);
|
||||
|
||||
// Wait for A/B/X or Y
|
||||
do
|
||||
{
|
||||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
while(!(REG_HID_PAD & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
}
|
||||
|
||||
/*void debugMemdump(const char *filepath, void *mem, size_t size)
|
||||
#ifndef NDEBUG
|
||||
// Needs to be marked as used to work with LTO.
|
||||
// The used attribute also overrides the newlib symbol.
|
||||
// This is for debugging purposes only. For security this value needs to be random!
|
||||
__attribute__((used)) uintptr_t __stack_chk_guard = 0xC724B66D;
|
||||
|
||||
// Needs to be marked as noinline and used to work with LTO.
|
||||
// The used attribute also overrides the newlib symbol.
|
||||
// Combine -fstack-protector-all with -fno-inline to get the most effective detection.
|
||||
__attribute__((noinline, used)) noreturn void __stack_chk_fail(void)
|
||||
{
|
||||
s32 file;
|
||||
panicMsg("Stack smash!");
|
||||
}
|
||||
|
||||
if((file = fOpen(filepath, FS_CREATE_ALWAYS | FS_OPEN_WRITE)) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fWrite(file, mem, size);
|
||||
|
||||
fSync(file);
|
||||
|
||||
fClose(file);
|
||||
}*/
|
||||
// Add "-Wl,-wrap=malloc,-wrap=calloc,-wrap=free" to LDFLAGS to enable the heap check.
|
||||
static const u32 __heap_chk_guard[4] = {0x9240A724, 0x6A6594A0, 0x976F0392, 0xB3A669AB};
|
||||
|
||||
void* __real_malloc(size_t size);
|
||||
void __real_free(void *ptr);
|
||||
|
||||
void* __wrap_malloc(size_t size)
|
||||
{
|
||||
void *const buf = __real_malloc(size + 32);
|
||||
if(buf == NULL) return NULL;
|
||||
|
||||
memcpy(buf, &size, sizeof(size_t));
|
||||
memcpy(buf + sizeof(size_t), (u8*)__heap_chk_guard + sizeof(size_t), 16 - sizeof(size_t));
|
||||
memcpy(buf + 16 + size, __heap_chk_guard, 16);
|
||||
|
||||
return buf + 16;
|
||||
}
|
||||
|
||||
void* __wrap_calloc(size_t num, size_t size)
|
||||
{
|
||||
void *const buf = __wrap_malloc(num * size);
|
||||
if(buf == NULL) return NULL;
|
||||
|
||||
memset(buf, 0, num * size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void __wrap_free(void *ptr)
|
||||
{
|
||||
if(ptr == NULL) return;
|
||||
|
||||
if(memcmp(ptr - (16 - sizeof(size_t)), (u8*)__heap_chk_guard + sizeof(size_t), 16 - sizeof(size_t)) != 0)
|
||||
panicMsg("Heap underflow!");
|
||||
size_t size;
|
||||
memcpy(&size, ptr - 16, sizeof(size_t));
|
||||
|
||||
// Important! Adjust the size check if needed.
|
||||
// 1024u * 512 is roughly ok for AXIWRAM.
|
||||
if(size > (1024u * 512) || memcmp(ptr + size, __heap_chk_guard, 16) != 0)
|
||||
panicMsg("Heap overflow!");
|
||||
|
||||
__real_free(ptr - 16);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@ EXCEPTION_ENTRY undefInstrHandler, 0<<29
|
|||
EXCEPTION_ENTRY prefetchAbortHandler, 1<<29
|
||||
EXCEPTION_ENTRY dataAbortHandler, 2<<29
|
||||
BEGIN_ASM_FUNC exceptionHandler
|
||||
sub sp, #68
|
||||
sub sp, #84
|
||||
stmia sp, {r0-r14}^ @ Save all user/system mode regs except pc
|
||||
mrs r2, spsr @ Get saved cpsr
|
||||
mrs r3, cpsr
|
||||
|
@ -51,13 +51,21 @@ BEGIN_ASM_FUNC exceptionHandler
|
|||
exceptionHandler_skip_other_mode:
|
||||
str lr, [sp, #60] @ Save lr (pc) on exception stack
|
||||
str r2, [sp, #64] @ Save spsr (cpsr) on exception stack
|
||||
mrc p15, 0, r3, c5, c0, 0
|
||||
str r3, [sp, #68] @ DFSR
|
||||
mrc p15, 0, r3, c5, c0, 1
|
||||
str r3, [sp, #72] @ IFSR
|
||||
mrc p15, 0, r3, c6, c0, 0
|
||||
str r3, [sp, #76] @ FAR
|
||||
mrc p15, 0, r3, c6, c0, 1
|
||||
str r3, [sp, #80] @ WFAR
|
||||
mov r4, r0
|
||||
mov r5, sp
|
||||
bl deinitCpu
|
||||
mov r0, r4
|
||||
mov sp, r5
|
||||
mov r1, r5
|
||||
b guruMeditation @ r0 = exception type, r1 = reg dump ptr {r0-r14, pc (unmodified), cpsr}
|
||||
b guruMeditation @ r0 = exception type, r1 = reg dump ptr {r0-r14, pc (unmodified), CPSR, DFSR, IFSR, FAR, WFAR}
|
||||
END_ASM_FUNC
|
||||
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ static u8 fmt2PixSize(GfxFbFmt fmt);
|
|||
static void setupFramebufs(GfxFbFmt fmtTop, GfxFbFmt fmtBot);
|
||||
static void deallocFramebufs(void);
|
||||
static void setupDislayController(u8 lcd);
|
||||
static void gfxIrqHandler(u32 intSource);
|
||||
|
||||
void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@ static u32 padRomArea(u32 romFileSize)
|
|||
if(romSize < 0x100000u) romSize = 0x100000u;
|
||||
memset((void*)(ROM_LOC + romFileSize), 0xFFFFFFFFu, romSize - romFileSize);
|
||||
|
||||
if((*(u32*)(ROM_LOC + 0xAC) & 0xFFu) != 'F')
|
||||
if(romSize > 0x100000u)
|
||||
{
|
||||
// Fake "open bus" padding.
|
||||
u32 padding = (ROM_LOC + romSize) / 2;
|
||||
|
@ -62,13 +62,13 @@ static u32 padRomArea(u32 romFileSize)
|
|||
for(uintptr_t i = ROM_LOC + romSize; i < ROM_LOC + MAX_ROM_SIZE; i += 4)
|
||||
{
|
||||
*(u32*)i = padding;
|
||||
padding = __uadd16(padding, 0x00020002u); // 0xBA028B
|
||||
padding = __uadd16(padding, 0x00020002u); // Unsigned parallel halfword-wise addition.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Classic NES Series ROM mirroring.
|
||||
// Mirror ROM area across the entire 32 MiB range.
|
||||
// ROM mirroring (Classic NES Series/possibly others with 8 Mbit ROM).
|
||||
// Mirror ROM across the entire 32 MiB area.
|
||||
for(uintptr_t i = ROM_LOC + romSize; i < ROM_LOC + MAX_ROM_SIZE; i += romSize)
|
||||
{
|
||||
//memcpy((void*)i, (void*)(i - romSize), romSize); // 0x23A15DD
|
||||
|
@ -398,39 +398,30 @@ static void adjustGammaTableForGba(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void dumpFrameTex(void)
|
||||
static Result dumpFrameTex(void)
|
||||
{
|
||||
// 512x-512 (hight negative to flip vertically).
|
||||
alignas(4) static const u8 bmpHeader[122] =
|
||||
// Pixels at offset 0x40.
|
||||
alignas(4) static const u8 bmpHeader[54] =
|
||||
{
|
||||
0x42, 0x4D, 0x7A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x00,
|
||||
0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFE,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0C, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
0x42, 0x4D, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFE,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x13, 0x0B,
|
||||
0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/*GX_displayTransfer((u32*)0x18200000, 160u<<16 | 256u, (u32*)0x18400000, 160u<<16 | 256u, 1u<<12 | 1u<<8);
|
||||
GFX_waitForPPF();
|
||||
//fsQuickWrite("sdmc:/lgyfb_dbg_frame.bgr", (void*)0x18400000, 256 * 160 * 3);*/
|
||||
GX_displayTransfer((u32*)0x18200000, 240u<<16 | 512u, (u32*)0x18400000, 240u<<16 | 512u, 1u<<12 | 1u<<8);
|
||||
GX_displayTransfer((u32*)0x18200000, 240u<<16 | 512u, (u32*)0x18400040, 240u<<16 | 512u, 1u<<12 | 1u<<8);
|
||||
GFX_waitForPPF();
|
||||
|
||||
FHandle f;
|
||||
if(fOpen(&f, "sdmc:/texture_dump.bmp", FA_CREATE_ALWAYS | FA_WRITE) == RES_OK)
|
||||
{
|
||||
fLseek(f, 0x0C007A);
|
||||
fLseek(f, 0);
|
||||
fWrite(f, bmpHeader, sizeof(bmpHeader), NULL);
|
||||
fWrite(f, (void*)0x18400000, 512 * 512 * 3, NULL);
|
||||
fClose(f);
|
||||
}
|
||||
memcpy((void*)0x18400000, bmpHeader, sizeof(bmpHeader));
|
||||
|
||||
return fsQuickWrite("sdmc:/texture_dump.bmp", (void*)0x18400000, 0x40 + 512 * 512 * 3);
|
||||
}
|
||||
|
||||
static void gbaGfxHandler(void *args)
|
||||
|
|
|
@ -6,48 +6,55 @@
|
|||
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC _a7_overlay_stub
|
||||
mov r0, #1
|
||||
mov r1, #0x4000000
|
||||
strb r0, [r1, #0x300] @ "POSTFLG"
|
||||
ldr pc, =0x3007E00
|
||||
|
||||
.pool
|
||||
.global _a7_overlay_stub_size
|
||||
_a7_overlay_stub_size = . - _a7_overlay_stub
|
||||
END_ASM_FUNC
|
||||
|
||||
@ Must be located at 0x3007E00.
|
||||
BEGIN_ASM_FUNC _arm7_stub_start
|
||||
mov r0, #PSR_INT_OFF | PSR_SVC_MODE
|
||||
adr r1, _arm7_stub_start + 0x200 @ 0x3008000
|
||||
msr CPSR_cxsf, r0
|
||||
@mov r0, #PSR_INT_OFF | PSR_IRQ_MODE
|
||||
mov sp, r1
|
||||
@msr CPSR_cxsf, r0
|
||||
mov r0, #PSR_INT_OFF | PSR_SYS_MODE
|
||||
@sub sp, r1, #0x60 @ 0x3007FA0
|
||||
msr CPSR_cxsf, r0
|
||||
BEGIN_ASM_FUNC _a7_stub_start
|
||||
adr r1, _a7_stub_thumb + 1 @ 0x3007E1D
|
||||
msr CPSR_fsxc, #PSR_INT_OFF | PSR_SVC_MODE
|
||||
add sp, r1, #0x6B @ 0x3007E88
|
||||
msr CPSR_fsxc, #PSR_INT_OFF | PSR_SYS_MODE
|
||||
add sp, r1, #0x5B @ 0x3007E78
|
||||
mov r3, #0x4700000
|
||||
adr r2, _arm7_stub_16 + 1
|
||||
sub sp, r1, #0x80 @ 0x3007F80
|
||||
bx r2
|
||||
bx r1
|
||||
|
||||
.thumb
|
||||
_arm7_stub_16:
|
||||
_a7_stub_thumb:
|
||||
mov r0, #1
|
||||
str r0, [r3] @ Disable BIOS overlay.
|
||||
@ The original ARM7 stub waits 256 cycles here (for the BIOS overlay disable?).
|
||||
@ The original ARM7 stub waits 1677800 cycles (100 ms) here for LCD/LgyFb sync.
|
||||
@ The original ARM7 stub waits for REG_VCOUNT = 160 here.
|
||||
|
||||
lsl r3, r0, #26 @ 0x4000000
|
||||
wait_vcount_160_lp:
|
||||
ldrb r0, [r3, #6] @ REG_VCOUNT
|
||||
cmp r0, #160 @ Wait for REG_VCOUNT == 160.
|
||||
bne wait_vcount_160_lp
|
||||
lsl r4, r0, #26 @ 0x4000000 Needed for "function" call 0xBC below.
|
||||
mov r0, #0xFF @ Clear WRAM, iWRAM, palette RAM, VRAM, OAM
|
||||
@ + reset SIO, sound and all other registers.
|
||||
|
||||
mov r4, r3 @ Needed for "function" call 0xBC below.
|
||||
mov r0, #0xFF @ Clear WRAM, iWRAM, palette RAM, VRAM, OAM
|
||||
@ + reset SIO, sound and all other registers.
|
||||
|
||||
.global _arm7_stub_swi
|
||||
_arm7_stub_swi = . - _arm7_stub_start + 0x80BFE00 @ Final ARM9 mem location.
|
||||
.global _a7_stub9_swi
|
||||
_a7_stub9_swi = . - _a7_stub_start + 0x80BFE00 @ Final ARM9 mem location.
|
||||
swi 0x01 @ RegisterRamReset
|
||||
|
||||
mov r0, #0xBC @ SoftReset (0xB4) but skipping r2 & r4 loading.
|
||||
mov r2, #0
|
||||
|
||||
@ REG_VCOUNT should be 126 at ROM entry like after BIOS intro.
|
||||
_a7_stub_vcount_lp:
|
||||
ldrb r1, [r4, #6] @ REG_VCOUNT
|
||||
cmp r1, #126 @ Loop until REG_VCOUNT == 126.
|
||||
bne _a7_stub_vcount_lp
|
||||
|
||||
bx r0
|
||||
|
||||
.pool
|
||||
.align 2
|
||||
.global _arm7_stub_size
|
||||
_arm7_stub_size = . - _arm7_stub_start
|
||||
.global _a7_stub_size
|
||||
_a7_stub_size = . - _a7_stub_start
|
||||
END_ASM_FUNC
|
||||
|
|
|
@ -31,28 +31,15 @@ static char g_savePath[512] = {0};
|
|||
|
||||
|
||||
|
||||
#define STRINGIFY(s) #s
|
||||
#define STR(s) STRINGIFY(s)
|
||||
NAKED static void _overlay_stub(void)
|
||||
{
|
||||
__asm__("mov r0, #0x4000000\n\t"
|
||||
"mov r1, #1\n\t"
|
||||
"strb r1, [r0, #0x300]\n\t" // "POSTFLG"
|
||||
"ldr pc, _overlay_stub_jmp\n\t"
|
||||
"_overlay_stub_jmp: .4byte " STR(ARM7_STUB_LOC) "\n\t"
|
||||
"_overlay_stub_size = . - _overlay_stub\n\t" : : : );
|
||||
}
|
||||
extern const u32 _overlay_stub_size[];
|
||||
|
||||
static void setupBiosOverlay(bool biosIntro)
|
||||
{
|
||||
iomemcpy(REGs_LGY_A7_VECTOR, (u32*)_overlay_stub, (u32)_overlay_stub_size);
|
||||
iomemcpy(REGs_LGY_A7_VECTOR, (u32*)_a7_overlay_stub, (u32)_a7_overlay_stub_size);
|
||||
//static const u32 biosVectors[8] = {0xEA000018, 0xEA000004, 0xEA00004C, 0xEA000002,
|
||||
// 0xEA000001, 0xEA000000, 0xEA000042, 0xE59FD1A0};
|
||||
//iomemcpy(REGs_LGY_A7_VECTOR, biosVectors, 32);
|
||||
|
||||
NDMA_copy((u32*)ARM7_STUB_LOC9, _arm7_stub_start, (u32)_arm7_stub_size);
|
||||
if(biosIntro) *((vu8*)_arm7_stub_swi) = 0x26; // Patch swi 0x01 (RegisterRamReset) to swi 0x26 (HardReset).
|
||||
NDMA_copy((u32*)ARM7_STUB_LOC9, (u32*)_a7_stub_start, (u32)_a7_stub_size);
|
||||
if(biosIntro) *((vu8*)_a7_stub9_swi) = 0x26; // Patch swi 0x01 (RegisterRamReset) to swi 0x26 (HardReset).
|
||||
}
|
||||
|
||||
static u32 setupSaveType(u16 saveType)
|
||||
|
|
|
@ -108,6 +108,7 @@ u32 IPC_handleCmd(u8 cmdId, u32 inBufs, u32 outBufs, const u32 *const buf)
|
|||
|
||||
// Miscellaneous API.
|
||||
case IPC_CMD_ID_MASK(IPC_CMD9_PREPARE_POWER):
|
||||
fsDeinit();
|
||||
break;
|
||||
default:
|
||||
panic();
|
||||
|
|
|
@ -43,12 +43,7 @@ Result fsQuickWrite(const char *const path, const void *const buf, u32 size)
|
|||
FHandle f;
|
||||
if((res = fOpen(&f, path, FA_OPEN_ALWAYS | FA_WRITE)) == RES_OK)
|
||||
{
|
||||
if((res = fLseek(f, size)) == RES_OK && fTell(f) == size)
|
||||
{
|
||||
fLseek(f, 0);
|
||||
res = fWrite(f, buf, size, NULL);
|
||||
}
|
||||
else if(res == RES_OK) res = RES_DISK_FULL; // Seek pre-allocation fail.
|
||||
res = fWrite(f, buf, size, NULL);
|
||||
|
||||
fClose(f);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue