#include "dolphin.h" #include "game/flag.h" #include "game/dvd.h" #include "game/pad.h" #include "game/audio.h" #include "game/thpmain.h" #define SR_DVD_LOADING 0 #define SR_DVD_COVER_OPEN 1 #define SR_DVD_NO_DISK 2 #define SR_DVD_WRONG_DISK 3 #define SR_DVD_RETRY_ERROR 4 #define SR_DVD_FATAL_ERROR 5 #define PAD_BTN_SRESET (PAD_BUTTON_START|PAD_BUTTON_X|PAD_BUTTON_B) #define PAD_BTN_SRESET_SHORT (PAD_BUTTON_X|PAD_BUTTON_B) extern s32 HuDvdErrWait; static s32 SR_PreRstChk[4] = {}; #include "coveropen_en.inc" #include "fatalerror_en.inc" #include "loading_en.inc" #include "nodisc_en.inc" #include "retryerror_en.inc" #include "wrongdisc_en.inc" static s16 SR_PushTime[4] = {}; static s8 SR_ResetPad = -1; static s16 XfbW; static s16 XfbH; static s32 XfbProg; static void *Xfb[2] = {}; static BOOL trychkBusyWait; s32 SR_ExecReset; static s32 SR_RestartChk; static BOOL H_ResetReady; void HuRestartSystem(void); s32 HuSoftResetCheck(void); s32 HuSoftResetCountCheck(void); static void HuSoftResetPostProc(void); s32 HuSoftResetButtonCheck(void) { if(SR_ExecReset) { HuRestartSystem(); } return (SR_ExecReset) ? 1 : 0; } static OSMessageQueue ToeMessageQueue; void HuDvdErrDispIntFunc(u32 retraceCount) { OSWakeupThread(&ToeMessageQueue.queueSend); } static void HuPreRstChk(void) { static PADStatus padStat[4]; int i; PADRead(padStat); for(i=0; i<4; i++) { PADStatus *status = &padStat[i]; if(status->err != 0) { continue; } if((status->button & PAD_BTN_SRESET) == PAD_BTN_SRESET) { SR_PreRstChk[i] = 1; } else { SR_PreRstChk[i] = 0; } } } static OSMessage ToeMessageArray[16]; static OSThread ToeThread; static u8 ToeThreadStack[4096]; static void *ToeThreadFunc(void *param); static void ToeDispCheck(void); void HuDvdErrDispInit(GXRenderModeObj *rmode, void *xfb1, void *xfb2) { BOOL intrOld; _ClearFlag(0x30000); SR_ResetPad = -1; SR_ExecReset = H_ResetReady = 0; SR_RestartChk = 0; SR_PushTime[0] = SR_PushTime[1] = SR_PushTime[2] = SR_PushTime[3] = 0; VIWaitForRetrace(); VIWaitForRetrace(); VIWaitForRetrace(); HuPreRstChk(); HuDvdErrWait = 0; Xfb[0] = xfb1; Xfb[1] = xfb2; if(rmode) { XfbW = (u16)(((u16)rmode->fbWidth+15) & ~0xF); XfbH = rmode->xfbHeight; } else { XfbW = 640; XfbH = 480; } if((u16)rmode->xFBmode == VI_XFBMODE_SF) { XfbProg = 0; } else { XfbProg = 1; } trychkBusyWait = FALSE; OSInitMessageQueue(&ToeMessageQueue, ToeMessageArray, 16); OSCreateThread(&ToeThread, ToeThreadFunc, NULL, &ToeThreadStack[4096], 4096, 8, OS_THREAD_ATTR_DETACH); OSResumeThread(&ToeThread); intrOld = OSDisableInterrupts(); VISetPreRetraceCallback(HuDvdErrDispIntFunc); OSRestoreInterrupts(intrOld); } static void *ToeThreadFunc(void *param) { while(1) { BOOL hide_disp; OSSleepThread(&ToeMessageQueue.queueSend); if(!_CheckFlag(0x30000)) { BOOL reset; if(!HuSoftResetCheck()) { if(SR_ExecReset) { reset = TRUE; } else { if(H_ResetReady == TRUE && OSGetResetButtonState() != TRUE) { reset = TRUE; } else { if(H_ResetReady != TRUE && OSGetResetButtonState() == TRUE) { H_ResetReady = TRUE; } reset = FALSE; } } if(reset) { proc_reset: HuSoftResetPostProc(); } } else { goto proc_reset; } } if(SR_ExecReset) { HuRestartSystem(); } if(SR_ExecReset) { hide_disp = TRUE; } else { hide_disp = FALSE; } if(!hide_disp) { ToeDispCheck(); } } } static void _HuDvdErrDispXFB(s32 error); static void ToeDispCheck(void) { s32 status; if(SR_ResetPad != -1 || SR_ExecReset != FALSE || SR_RestartChk != 0) { return; } status = DVDGetDriveStatus(); switch(status) { case DVD_STATE_FATAL_ERROR: status = SR_DVD_FATAL_ERROR; trychkBusyWait = TRUE; break; case DVD_STATE_END: HuDvdErrWait = 0; trychkBusyWait = FALSE; return; case DVD_STATE_COVER_OPEN: status = SR_DVD_COVER_OPEN; trychkBusyWait = TRUE; break; case DVD_STATE_BUSY: case DVD_STATE_COVER_CLOSED: if(!trychkBusyWait) { return; } status = SR_DVD_LOADING; break; case DVD_STATE_NO_DISK: status = SR_DVD_NO_DISK; trychkBusyWait = TRUE; break; case DVD_STATE_WRONG_DISK: status = SR_DVD_WRONG_DISK; trychkBusyWait = TRUE; break; case DVD_STATE_RETRY: status = SR_DVD_RETRY_ERROR; trychkBusyWait = TRUE; break; default: return; } HuDvdErrWait = 1; HuPadRumbleAllStop(); VISetBlack(FALSE); VIFlush(); if(msmSysCheckInit()) { HuAudSStreamAllStop(); } _HuDvdErrDispXFB(status); } static void _HuDvdErrDispXFB(s32 error) { static void *bmpMes[][6] = { loading_en, coveropen_en, nodisc_en, wrongdisc_en, retryerror_en, fatalerror_en }; volatile s32 status; u8 color[2]; s8 language; s16 *bmpData; u8 *xfb1_ptr; u8 *xfb2_ptr; u32 i; u32 data; u32 row; u32 *xfb1; u32 *xfb2; u32 j; u8 y1; u8 y2; s32 reset; u32 *data_ptr; u32 row_offset; u32 row_pitch; language = 0; xfb1 = Xfb[0]; xfb2 = Xfb[1]; for(i=0; i<0x25800; i++, xfb1++, xfb2++) { *xfb1 = *xfb2 = 0x800080; } DCStoreRangeNoSync(Xfb[0], 0x96000); DCStoreRangeNoSync(Xfb[1], 0x96000); bmpData = bmpMes[language][error]; data_ptr = (u32 *)(bmpData+2); row_offset = ((XfbW/2)-(bmpData[0]/2))*2; row_pitch = XfbW*2; color[1] = color[0] = 128; for(row=0; row>= 2, xfb1_ptr += 4, xfb2_ptr += 4) { if(data & 0x3){ if(data & 0x1) { y1 = 0xEB; } else { y1 = 0x10; } if(data & 0x2) { y2 = 0xEB; } else { y2 = 0x10; } xfb1_ptr[0] = y1; xfb1_ptr[1] = color[1]; xfb1_ptr[2] = y2; xfb1_ptr[3] = color[0]; xfb2_ptr[0] = y1; xfb2_ptr[1] = color[1]; xfb2_ptr[2] = y2; xfb2_ptr[3] = color[0]; } } } DCStoreRangeNoSync(sp14[1], bmpData[0]*2); DCStoreRangeNoSync(sp14[0], bmpData[0]*2); } status = DVDGetDriveStatus(); while(status) { if(status != DVDGetDriveStatus()) { break; } if(SR_ExecReset) { reset = TRUE; } else { if(H_ResetReady == TRUE && OSGetResetButtonState() != TRUE) { reset = TRUE; } else { if(H_ResetReady != TRUE && OSGetResetButtonState() == TRUE) { H_ResetReady = TRUE; } reset = FALSE; } } if(reset) { if(msmSysCheckInit()) { msmStreamSetMasterVolume(0); msmSeSetMasterVolume(0); msmMusSetMasterVolume(0); } HuRestartSystem(); } OSYieldThread(); } } void HuRestartSystem(void) { u32 retrace[2]; BOOL prevInt; if(SR_RestartChk) { return; } SR_RestartChk = TRUE; PADRecalibrate(PAD_CHAN0_BIT|PAD_CHAN1_BIT|PAD_CHAN2_BIT|PAD_CHAN3_BIT); msmSysCheckInit(); VISetBlack(TRUE); VIFlush(); prevInt = OSDisableInterrupts(); if(!prevInt) { OSReport("PrevInt=DISABLE!!\n"); } OSEnableInterrupts(); retrace[1] = VIGetRetraceCount(); retrace[0] = 0; while(retrace[1] == VIGetRetraceCount()) { if(retrace[0]++ >= 1349800) { break; } } OSReport("Timeout Count=%d\n", retrace[0]); __GXAbortWaitPECopyDone(); OSResetSystem(0, 0, 0); } s32 HuSoftResetCheck(void) { int i; if(VCounter == 0) { return 0; } if(SR_ExecReset) { return 1; } if(SR_ResetPad != -1) { if(!(_PadBtn[SR_ResetPad] & PAD_BTN_SRESET)) { return 1; } } else { for(i=0; i<4; i++) { if(SR_PreRstChk[i] && (_PadBtn[i] & PAD_BTN_SRESET) != PAD_BTN_SRESET) { SR_PreRstChk[i] = 0; } } } if(HuSoftResetCountCheck()) { return 1; } else { return 0; } } s32 HuSoftResetCountCheck(void) { int i; for(i=0; i<4; i++) { if((_PadBtn[i] & PAD_BTN_SRESET_SHORT) != PAD_BTN_SRESET_SHORT) { SR_PushTime[i] = 0; } else { if(!SR_PreRstChk[i]) { if(_PadBtn[i] & PAD_BUTTON_START) { if(SR_PushTime[i]++ >= 30) { SR_ResetPad = i; return 1; } } else { SR_PushTime[i] = 0; } } } } return 0; } static void HuSoftResetPostProc(void) { if(!SR_ExecReset) { VISetBlack(TRUE); VIFlush(); if(THPProc) { HuTHPStop(); HuTHPClose(); } if(msmSysCheckInit()) { msmStreamSetMasterVolume(0); msmSeSetMasterVolume(0); msmMusSetMasterVolume(0); } HuPadRumbleAllStop(); SR_ExecReset = TRUE; } }