#include #include "constants.h" #include "lib/reset.h" #include "bss.h" #include "data.h" #include "types.h" OSMesg g_ResetMesgs[10]; OSMesgQueue g_ResetMesgQueue; OSThread g_ResetThread; u8 g_ResetStack[STACKSIZE_RESET]; s8 g_Resetting = false; /** * When the reset button is pressed, a PRENMI event occurs, followed by the NMI * (actual reset) at least 0.5 seconds later. During PRENMI, the system must * prepare the system for reset. */ void resetproc(void *data) { OSMesg msg = 0; OSViMode *mode; #if VERSION >= VERSION_NTSC_1_0 u32 stack[4]; #else u32 stack[2]; #endif static u64 prenmitime; // Wait until a PRENMI message is received osRecvMesg(&g_ResetMesgQueue, &msg, OS_MESG_BLOCK); // Set a global variable so the scheduler knows the system is about to reset // and can stop scheduling new RSP tasks g_Resetting = true; // Stop the audio and main threads and ensure the reset thread's priority is set correctly amgrStopThread(); osStopThread(&g_MainThread); osSetThreadPri(0, THREADPRI_RESET); // Reset the Y scale for the current VI mode #if PAL mode = &osViModeTable[OS_VI_PAL_LAN1]; #else if (osTvType == OS_TV_MPAL) { mode = &osViModeTable[OS_VI_MPAL_LAN1]; } else { mode = &osViModeTable[OS_VI_NTSC_LAN1]; } #endif mode->fldRegs[0].yScale = 1024; mode->fldRegs[1].yScale = 1024; osViSetMode(mode); // Blank the screen osViBlack(1); // Wait about 0.048 seconds prenmitime = osGetTime(); while (osGetTime() < prenmitime + OS_NSEC_TO_CYCLES(48484848)) { // empty } // Stop controller rumbles if active joyDestroy(); // Wait for the system to reset while (1); } void resetThreadCreate(void) { osCreateMesgQueue(&g_ResetMesgQueue, g_ResetMesgs, ARRAYCOUNT(g_ResetMesgs)); osSetEventMesg(OS_EVENT_PRENMI, &g_ResetMesgQueue, (OSMesg) 669); osCreateThread(&g_ResetThread, THREAD_RESET, resetproc, 0, &g_ResetStack[STACKSIZE_RESET], THREADPRI_RESET); osStartThread(&g_ResetThread); }