diff --git a/JGE/exceptionHandler/README.txt b/JGE/exceptionHandler/README.txt new file mode 100644 index 000000000..582cec36d --- /dev/null +++ b/JGE/exceptionHandler/README.txt @@ -0,0 +1,34 @@ +Exception Handler for Kernel 3.71 +--------------------------------- +All credits goes to crazyc (for the prx code) and SamuraiX (sample usage code) + +What is it? +----------- +exception.prx is a prx that handle exception and can be used +to show usefull information abuot a crash. + + +How to build: +------------- +To build exception.prx + +$cd prx +$make + +To build the test program: +$cd test +$make + + +How to use it: +-------------- +Include utility/exception.h in your main.c and init the handler with: + +initExceptionHandler(); + +Copy exception.prx in the same directory your EBOOT is. + +Please check the test program. ;) + +Note: +--> For Wagic, the code is already included in JGE's main.cpp. You just need to copy the prx with the EBOOT \ No newline at end of file diff --git a/JGE/exceptionHandler/prx/exception.prx b/JGE/exceptionHandler/prx/exception.prx new file mode 100644 index 000000000..220ac3a29 Binary files /dev/null and b/JGE/exceptionHandler/prx/exception.prx differ diff --git a/JGE/exceptionHandler/prx/exception_asm.S b/JGE/exceptionHandler/prx/exception_asm.S new file mode 100644 index 000000000..b42fb68b1 --- /dev/null +++ b/JGE/exceptionHandler/prx/exception_asm.S @@ -0,0 +1,214 @@ +#include "as_reg_compat.h" + .set noreorder + .set noat + +#define BadVAddr $8 // Address for the most recent address-related exception +#define Status $12 // Processor status and control +#define Cause $13 // Cause of last general exception +#define EPC $14 // Program counter at last exception +#define PRId $15 // Processor identification and revision + +#define FSR $31 +#define FIR $0 + +#define REG_GPR_0 (6*4) +#define REG_GPR_1 (REG_GPR_0 + 4) +#define REG_GPR_2 (REG_GPR_1 + 4) +#define REG_GPR_3 (REG_GPR_2 + 4) +#define REG_GPR_4 (REG_GPR_3 + 4) +#define REG_GPR_5 (REG_GPR_4 + 4) +#define REG_GPR_6 (REG_GPR_5 + 4) +#define REG_GPR_7 (REG_GPR_6 + 4) +#define REG_GPR_8 (REG_GPR_7 + 4) +#define REG_GPR_9 (REG_GPR_8 + 4) +#define REG_GPR_10 (REG_GPR_9 + 4) +#define REG_GPR_11 (REG_GPR_10 + 4) +#define REG_GPR_12 (REG_GPR_11 + 4) +#define REG_GPR_13 (REG_GPR_12 + 4) +#define REG_GPR_14 (REG_GPR_13 + 4) +#define REG_GPR_15 (REG_GPR_14 + 4) +#define REG_GPR_16 (REG_GPR_15 + 4) +#define REG_GPR_17 (REG_GPR_16 + 4) +#define REG_GPR_18 (REG_GPR_17 + 4) +#define REG_GPR_19 (REG_GPR_18 + 4) +#define REG_GPR_20 (REG_GPR_19 + 4) +#define REG_GPR_21 (REG_GPR_20 + 4) +#define REG_GPR_22 (REG_GPR_21 + 4) +#define REG_GPR_23 (REG_GPR_22 + 4) +#define REG_GPR_24 (REG_GPR_23 + 4) +#define REG_GPR_25 (REG_GPR_24 + 4) +#define REG_GPR_26 (REG_GPR_25 + 4) +#define REG_GPR_27 (REG_GPR_26 + 4) +#define REG_GPR_28 (REG_GPR_27 + 4) +#define REG_GPR_29 (REG_GPR_28 + 4) +#define REG_GPR_30 (REG_GPR_29 + 4) +#define REG_GPR_31 (REG_GPR_30 + 4) + +#define REG_STATUS (REG_GPR_31 + 4) +#define REG_LO (REG_STATUS + 4) +#define REG_HI (REG_LO + 4) +#define REG_BADVADDR (REG_HI + 4) +#define REG_CAUSE (REG_BADVADDR + 4) +#define REG_EPC (REG_CAUSE + 4) + +#define REG_FPR_0 (REG_EPC + 4) +#define REG_FPR_1 (REG_FPR_0 + 4) +#define REG_FPR_2 (REG_FPR_1 + 4) +#define REG_FPR_3 (REG_FPR_2 + 4) +#define REG_FPR_4 (REG_FPR_3 + 4) +#define REG_FPR_5 (REG_FPR_4 + 4) +#define REG_FPR_6 (REG_FPR_5 + 4) +#define REG_FPR_7 (REG_FPR_6 + 4) +#define REG_FPR_8 (REG_FPR_7 + 4) +#define REG_FPR_9 (REG_FPR_8 + 4) +#define REG_FPR_10 (REG_FPR_9 + 4) +#define REG_FPR_11 (REG_FPR_10 + 4) +#define REG_FPR_12 (REG_FPR_11 + 4) +#define REG_FPR_13 (REG_FPR_12 + 4) +#define REG_FPR_14 (REG_FPR_13 + 4) +#define REG_FPR_15 (REG_FPR_14 + 4) +#define REG_FPR_16 (REG_FPR_15 + 4) +#define REG_FPR_17 (REG_FPR_16 + 4) +#define REG_FPR_18 (REG_FPR_17 + 4) +#define REG_FPR_19 (REG_FPR_18 + 4) +#define REG_FPR_20 (REG_FPR_19 + 4) +#define REG_FPR_21 (REG_FPR_20 + 4) +#define REG_FPR_22 (REG_FPR_21 + 4) +#define REG_FPR_23 (REG_FPR_22 + 4) +#define REG_FPR_24 (REG_FPR_23 + 4) +#define REG_FPR_25 (REG_FPR_24 + 4) +#define REG_FPR_26 (REG_FPR_25 + 4) +#define REG_FPR_27 (REG_FPR_26 + 4) +#define REG_FPR_28 (REG_FPR_27 + 4) +#define REG_FPR_29 (REG_FPR_28 + 4) +#define REG_FPR_30 (REG_FPR_29 + 4) +#define REG_FPR_31 (REG_FPR_30 + 4) + +#define REG_FSR (REG_FPR_31 + 4) +#define REG_FIR (REG_FSR + 4) +#define REG_FP (REG_FIR + 4) + + .extern exception_regs + .extern curr_handler + + .global _pspDebugExceptionHandler + .ent _pspDebugExceptionHandler +_pspDebugExceptionHandler: + nop + nop + + lw $v0, exception_regs + sw $0, REG_GPR_0($v0) + sw $1, REG_GPR_1($v0) + + cfc0 $1, $4 # Get original v0 + sw $1, REG_GPR_2($v0) + cfc0 $1, $5 # Get original v1 + sw $1, REG_GPR_3($v0) + sw $4, REG_GPR_4($v0) + sw $5, REG_GPR_5($v0) + sw $6, REG_GPR_6($v0) + sw $7, REG_GPR_7($v0) + sw $8, REG_GPR_8($v0) + sw $9, REG_GPR_9($v0) + sw $10, REG_GPR_10($v0) + sw $11, REG_GPR_11($v0) + sw $12, REG_GPR_12($v0) + sw $13, REG_GPR_13($v0) + sw $14, REG_GPR_14($v0) + sw $15, REG_GPR_15($v0) + sw $16, REG_GPR_16($v0) + sw $17, REG_GPR_17($v0) + sw $18, REG_GPR_18($v0) + sw $19, REG_GPR_19($v0) + sw $20, REG_GPR_20($v0) + sw $21, REG_GPR_21($v0) + sw $22, REG_GPR_22($v0) + sw $23, REG_GPR_23($v0) + sw $24, REG_GPR_24($v0) + sw $25, REG_GPR_25($v0) + sw $26, REG_GPR_26($v0) + sw $27, REG_GPR_27($v0) + sw $28, REG_GPR_28($v0) + sw $29, REG_GPR_29($v0) + sw $30, REG_GPR_30($v0) + sw $31, REG_GPR_31($v0) + + mflo $v1 + sw $v1, REG_LO($v0) + mfhi $v1 + sw $v1, REG_HI($v0) + mfc0 $v1, BadVAddr + sw $v1, REG_BADVADDR($v0) + mfc0 $v1, Cause + sw $v1, REG_CAUSE($v0) + mfc0 $v1, EPC + sw $v1, REG_EPC($v0) + mfc0 $v1, Status + sw $v1, REG_STATUS($v0) + +# Check if cop1 is enable and skip if not + lui $a0, 0x2000 + and $a0, $a0, $v1 + beq $a0, $0, 1f + nop + + swc1 $0, REG_FPR_0($v0) + swc1 $1, REG_FPR_1($v0) + swc1 $2, REG_FPR_2($v0) + swc1 $3, REG_FPR_3($v0) + swc1 $4, REG_FPR_4($v0) + swc1 $5, REG_FPR_5($v0) + swc1 $6, REG_FPR_6($v0) + swc1 $7, REG_FPR_7($v0) + swc1 $8, REG_FPR_8($v0) + swc1 $9, REG_FPR_9($v0) + swc1 $10, REG_FPR_10($v0) + swc1 $11, REG_FPR_11($v0) + swc1 $12, REG_FPR_12($v0) + swc1 $13, REG_FPR_13($v0) + swc1 $14, REG_FPR_14($v0) + swc1 $15, REG_FPR_15($v0) + swc1 $16, REG_FPR_16($v0) + swc1 $17, REG_FPR_17($v0) + swc1 $18, REG_FPR_18($v0) + swc1 $19, REG_FPR_19($v0) + swc1 $20, REG_FPR_20($v0) + swc1 $21, REG_FPR_21($v0) + swc1 $22, REG_FPR_22($v0) + swc1 $23, REG_FPR_23($v0) + swc1 $24, REG_FPR_24($v0) + swc1 $25, REG_FPR_25($v0) + swc1 $26, REG_FPR_26($v0) + swc1 $27, REG_FPR_27($v0) + swc1 $28, REG_FPR_28($v0) + swc1 $29, REG_FPR_29($v0) + swc1 $30, REG_FPR_30($v0) + swc1 $31, REG_FPR_31($v0) + + cfc1 $t0, FSR + sw $t0, REG_FSR($v0) + cfc1 $t0, FIR + sw $t0, REG_FIR($v0) + ctc1 $0, FSR # Clear any cause flags + +# Jump target for ignore cop1 +1: + + sw $sp, REG_FP($v0) + move $a0, $v0 + + lw $2, curr_handler + mtc0 $2, $14 + nop + nop + eret + nop + nop + + .end _pspDebugExceptionHandler + + #include "pspimport.s" + + IMPORT_START "ExceptionManagerForKernel",0x00010011 + IMPORT_FUNC "ExceptionManagerForKernel",0x565C0B0E,sceKernelRegisterDefaultExceptionHandler371 diff --git a/JGE/exceptionHandler/prx/exports.exp b/JGE/exceptionHandler/prx/exports.exp new file mode 100644 index 000000000..821c55b2b --- /dev/null +++ b/JGE/exceptionHandler/prx/exports.exp @@ -0,0 +1,7 @@ +PSP_BEGIN_EXPORTS +PSP_EXPORT_START(syslib, 0, 0x8000) +PSP_EXPORT_FUNC_HASH(module_start) +PSP_EXPORT_VAR_HASH(module_info) +PSP_EXPORT_END + +PSP_END_EXPORTS diff --git a/JGE/exceptionHandler/prx/main.c b/JGE/exceptionHandler/prx/main.c new file mode 100644 index 000000000..6d5821774 --- /dev/null +++ b/JGE/exceptionHandler/prx/main.c @@ -0,0 +1,25 @@ +#include +#include +#include + +PSP_MODULE_INFO("exception", 0x1007, 1, 1); // better not unload + +PspDebugErrorHandler curr_handler; +PspDebugRegBlock *exception_regs; + +void _pspDebugExceptionHandler(void); +int sceKernelRegisterDefaultExceptionHandler(void *func); +int sceKernelRegisterDefaultExceptionHandler371(void *func); + +int module_start(SceSize args, void *argp) +{ + if(args != 8) return -1; + curr_handler = (PspDebugErrorHandler)((int *)argp)[0]; + exception_regs = (PspDebugRegBlock *)((int *)argp)[1]; + if(!curr_handler || !exception_regs) return -1; + + if(sceKernelDevkitVersion() < 0x03070110) + return sceKernelRegisterDefaultExceptionHandler((void *)_pspDebugExceptionHandler); + else + return sceKernelRegisterDefaultExceptionHandler371((void *)_pspDebugExceptionHandler); +} diff --git a/JGE/exceptionHandler/prx/makefile b/JGE/exceptionHandler/prx/makefile new file mode 100644 index 000000000..96c654ebb --- /dev/null +++ b/JGE/exceptionHandler/prx/makefile @@ -0,0 +1,20 @@ +TARGET = exception +OBJS = main.o exception_asm.o + +# Define to build this as a prx (instead of a static elf) +BUILD_PRX=1 +# Define the name of our custom exports (minus the .exp extension) +PRX_EXPORTS=exports.exp + +USE_KERNEL_LIBC = 1 +USE_KERNEL_LIBS = 1 + +INCDIR = +CFLAGS = -Os -G0 -Wall -nostartfiles +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) + +LIBDIR = + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build.mak diff --git a/JGE/exceptionHandler/test/main.c b/JGE/exceptionHandler/test/main.c new file mode 100644 index 000000000..40e213893 --- /dev/null +++ b/JGE/exceptionHandler/test/main.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +#include "../utility/exception.h" +PSP_MODULE_INFO("Exception Handler Test", 0, 1, 0); +PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); +//PSP_HEAP_SIZE_KB(22000); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Globals: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int runningFlag = 1; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Callbacks: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* Exit callback */ +int exit_callback(int arg1, int arg2, void *common) { + runningFlag = 0; + return 0; +} + +/* Callback thread */ +int CallbackThread(SceSize args, void *argp) { + int cbid; + cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); + sceKernelRegisterExitCallback(cbid); + sceKernelSleepThreadCB(); + return 0; +} + +/* Sets up the callback thread and returns its thread id */ +int SetupCallbacks(void) { + int thid = 0; + thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0); + if(thid >= 0) + sceKernelStartThread(thid, 0, 0); + return thid; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Main: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int main(){ + pspDebugScreenInit(); + SetupCallbacks(); + + pspDebugScreenPrintf("Expcetion Handler Test\n"); + + initExceptionHandler(); + + pspDebugScreenPrintf("Press X for a breakpoint\n"); + pspDebugScreenPrintf("Press O for a bus error\n"); + + SceCtrlData pad; + while(runningFlag){ + sceCtrlReadBufferPositive(&pad, 1); + if (pad.Buttons & PSP_CTRL_CROSS){ + /* Cause a break exception */ + asm( + "break\r\n" + ); + }else if (pad.Buttons & PSP_CTRL_CIRCLE){ + /* Cause a bus error */ + _sw(0, 0); + } + } + sceKernelExitGame(); + return 0; + +} diff --git a/JGE/exceptionHandler/test/makefile b/JGE/exceptionHandler/test/makefile new file mode 100644 index 000000000..a0ef01a51 --- /dev/null +++ b/JGE/exceptionHandler/test/makefile @@ -0,0 +1,19 @@ +TARGET = exception_handler_test +OBJS = ../utility/exception.o main.o + +#To build for custom firmware: +BUILD_PRX = 1 + +#CFLAGS = -O3 -G0 -Wall +CFLAGS = -O3 -frename-registers -G0 -Wall +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) +LIBDIR = + +LIBS = +LDFLAGS = +EXTRA_TARGETS = EBOOT.PBP +PSP_EBOOT_TITLE = Exception Handler Test +#PSP_EBOOT_ICON = ICON0.PNG +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build.mak diff --git a/JGE/exceptionHandler/utility/exception.c b/JGE/exceptionHandler/utility/exception.c new file mode 100644 index 000000000..58885a155 --- /dev/null +++ b/JGE/exceptionHandler/utility/exception.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include + +PspDebugRegBlock exception_regs; + +extern SceModule module_info; +extern int _ftext; + +static const char *codeTxt[32] = +{ + "Interrupt", "TLB modification", "TLB load/inst fetch", "TLB store", + "Address load/inst fetch", "Address store", "Bus error (instr)", + "Bus error (data)", "Syscall", "Breakpoint", "Reserved instruction", + "Coprocessor unusable", "Arithmetic overflow", "Unknown 14", + "Unknown 15", "Unknown 16", "Unknown 17", "Unknown 18", "Unknown 19", + "Unknown 20", "Unknown 21", "Unknown 22", "Unknown 23", "Unknown 24", + "Unknown 25", "Unknown 26", "Unknown 27", "Unknown 28", "Unknown 29", + "Unknown 31" +}; + +static const unsigned char regName[32][5] = +{ + "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; + +void ExceptionHandler(PspDebugRegBlock * regs) +{ + int i; + SceCtrlData pad; + + pspDebugScreenInit(); + pspDebugScreenSetBackColor(0x00FF0000); + pspDebugScreenSetTextColor(0xFFFFFFFF); + pspDebugScreenClear(); + pspDebugScreenPrintf("Your PSP has just crashed!\n"); + pspDebugScreenPrintf("Exception details:\n\n"); + + pspDebugScreenPrintf("Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]); + pspDebugScreenPrintf("EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext)); + pspDebugScreenPrintf("Cause - %08X\n", (int)regs->cause); + pspDebugScreenPrintf("Status - %08X\n", (int)regs->status); + pspDebugScreenPrintf("BadVAddr - %08X\n", (int)regs->badvaddr); + for(i=0; i<32; i+=4) pspDebugScreenPrintf("%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]); + + sceKernelDelayThread(1000000); + pspDebugScreenPrintf("\n\nPress X to dump information on file exception.log and quit"); + pspDebugScreenPrintf("\nPress O to quit"); + + for (;;){ + sceCtrlReadBufferPositive(&pad, 1); + if (pad.Buttons & PSP_CTRL_CROSS){ + FILE *log = fopen("exception.log", "w"); + if (log != NULL){ + char testo[512]; + sprintf(testo, "Exception details:\n\n"); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext)); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Cause - %08X\n", (int)regs->cause); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Status - %08X\n", (int)regs->status); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "BadVAddr - %08X\n", (int)regs->badvaddr); + fwrite(testo, 1, strlen(testo), log); + for(i=0; i<32; i+=4){ + sprintf(testo, "%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]); + fwrite(testo, 1, strlen(testo), log); + } + fclose(log); + } + break; + }else if (pad.Buttons & PSP_CTRL_CIRCLE){ + break; + } + sceKernelDelayThread(100000); + } + sceKernelExitGame(); +} + +void initExceptionHandler() +{ + SceKernelLMOption option; + int args[2], fd, modid; + + memset(&option, 0, sizeof(option)); + option.size = sizeof(option); + option.mpidtext = PSP_MEMORY_PARTITION_KERNEL; + option.mpiddata = PSP_MEMORY_PARTITION_KERNEL; + option.position = 0; + option.access = 1; + + if((modid = sceKernelLoadModule("exception.prx", 0, &option)) >= 0) + { + args[0] = (int)ExceptionHandler; + args[1] = (int)&exception_regs; + sceKernelStartModule(modid, 8, args, &fd, NULL); + } +} diff --git a/JGE/exceptionHandler/utility/exception.h b/JGE/exceptionHandler/utility/exception.h new file mode 100644 index 000000000..6dc7c6101 --- /dev/null +++ b/JGE/exceptionHandler/utility/exception.h @@ -0,0 +1,3 @@ +void initExceptionHandler(); + + diff --git a/JGE/lib/win/jge.lib b/JGE/lib/win/jge.lib index ab8be0949..12fe1fc9b 100644 Binary files a/JGE/lib/win/jge.lib and b/JGE/lib/win/jge.lib differ diff --git a/JGE/src/main.cpp b/JGE/src/main.cpp index d40077908..7da401ecc 100644 --- a/JGE/src/main.cpp +++ b/JGE/src/main.cpp @@ -13,6 +13,10 @@ #include #include +#include +#include +#include + //#include @@ -21,13 +25,13 @@ #include "../../JGE/include/JGameLauncher.h" #include "../../JGE/include/JRenderer.h" + #ifndef JGEApp_Title #define JGEApp_Title "JGE++" #endif #ifdef DEVHOOK - PSP_MODULE_INFO(JGEApp_Title, 0, 1, 1); PSP_MAIN_THREAD_ATTR(0); PSP_HEAP_SIZE_KB(-256); @@ -161,7 +165,107 @@ int SetupCallbacks(void) #ifdef DEVHOOK +//code by sakya, crazyc, samuraiX +//http://forums.ps2dev.org/viewtopic.php?t=9591&sid=2056889f6b9531194cab9b2d487df844 +PspDebugRegBlock exception_regs; +extern int _ftext; + +static const char *codeTxt[32] = +{ + "Interrupt", "TLB modification", "TLB load/inst fetch", "TLB store", + "Address load/inst fetch", "Address store", "Bus error (instr)", + "Bus error (data)", "Syscall", "Breakpoint", "Reserved instruction", + "Coprocessor unusable", "Arithmetic overflow", "Unknown 14", + "Unknown 15", "Unknown 16", "Unknown 17", "Unknown 18", "Unknown 19", + "Unknown 20", "Unknown 21", "Unknown 22", "Unknown 23", "Unknown 24", + "Unknown 25", "Unknown 26", "Unknown 27", "Unknown 28", "Unknown 29", + "Unknown 31" +}; + +static const unsigned char regName[32][5] = +{ + "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; + +void ExceptionHandler(PspDebugRegBlock * regs) +{ + int i; + SceCtrlData pad; + + pspDebugScreenInit(); + pspDebugScreenSetBackColor(0x00FF0000); + pspDebugScreenSetTextColor(0xFFFFFFFF); + pspDebugScreenClear(); + pspDebugScreenPrintf("Your PSP has just crashed!\n"); + pspDebugScreenPrintf("Exception details:\n\n"); + + pspDebugScreenPrintf("Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]); + pspDebugScreenPrintf("EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext)); + pspDebugScreenPrintf("Cause - %08X\n", (int)regs->cause); + pspDebugScreenPrintf("Status - %08X\n", (int)regs->status); + pspDebugScreenPrintf("BadVAddr - %08X\n", (int)regs->badvaddr); + for(i=0; i<32; i+=4) pspDebugScreenPrintf("%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]); + + sceKernelDelayThread(1000000); + pspDebugScreenPrintf("\n\nPress X to dump information on file exception.log and quit"); + pspDebugScreenPrintf("\nPress O to quit"); + + for (;;){ + sceCtrlReadBufferPositive(&pad, 1); + if (pad.Buttons & PSP_CTRL_CROSS){ + FILE *log = fopen("exception.log", "w"); + if (log != NULL){ + char testo[512]; + sprintf(testo, "Exception details:\n\n"); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext)); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Cause - %08X\n", (int)regs->cause); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "Status - %08X\n", (int)regs->status); + fwrite(testo, 1, strlen(testo), log); + sprintf(testo, "BadVAddr - %08X\n", (int)regs->badvaddr); + fwrite(testo, 1, strlen(testo), log); + for(i=0; i<32; i+=4){ + sprintf(testo, "%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]); + fwrite(testo, 1, strlen(testo), log); + } + fclose(log); + } + break; + }else if (pad.Buttons & PSP_CTRL_CIRCLE){ + break; + } + sceKernelDelayThread(100000); + } + sceKernelExitGame(); +} + +void initExceptionHandler() +{ + SceKernelLMOption option; + int args[2], fd, modid; + + memset(&option, 0, sizeof(option)); + option.size = sizeof(option); + option.mpidtext = PSP_MEMORY_PARTITION_KERNEL; + option.mpiddata = PSP_MEMORY_PARTITION_KERNEL; + option.position = 0; + option.access = 1; + + if((modid = sceKernelLoadModule("exception.prx", 0, &option)) >= 0) + { + args[0] = (int)ExceptionHandler; + args[1] = (int)&exception_regs; + sceKernelStartModule(modid, 8, args, &fd, NULL); + } +} #else //------------------------------------------------------------------------------------------------ // Custom exception handler @@ -201,22 +305,15 @@ int SetupCallbacks(void) //------------------------------------------------------------------------------------------------ // The main loop int main() -{ - //scePowerSetClockFrequency(333, 333, 166); +{ SetupCallbacks(); - -// pspDebugScreenInit(); - -// if ((mikModThreadID = sceKernelCreateThread("MikMod" , AudioChannelThread, 0x12,0x10000,0,0)) > 0) -// { -// sceKernelStartThread(mikModThreadID, 0 , 0); -// } - +#ifdef DEVHOOK + initExceptionHandler(); +#endif engine = NULL; - //engine->Init(0); -// + JGameLauncher* launcher = new JGameLauncher(); u32 flags = launcher->GetInitFlags(); @@ -232,9 +329,6 @@ int main() engine->SetApp(game); engine->Run(); - //pspDebugScreenSetXY(10,10); - //pspDebugScreenPrintf("Hello world!"); - game->Destroy(); delete game; game = NULL; @@ -243,28 +337,12 @@ int main() done = true; -// if (mikModThreadID > 0) -// { -// ////SceUInt timeout = 100000; -// ////sceKernelWaitThreadEnd(mikModThreadID, &timeout); -// // not 100% sure if this is necessary after a clean exit, but just to make sure any resources are freed: -// sceKernelDeleteThread(mikModThreadID); -// } - -// JFileSystem::Destroy(); -// JParticleSystem::Destroy(); -// JMotionSystem::Destroy(); - -// launcher->CleanUp(); delete launcher; JGE::Destroy(); engine = NULL; - -// sceKernelSleepThread(); - sceKernelExitGame(); return 0;