diff --git a/include/PR/sched.h b/include/PR/sched.h index 2777fb9a1..497c2ae86 100644 --- a/include/PR/sched.h +++ b/include/PR/sched.h @@ -100,6 +100,8 @@ typedef struct { u32 alt; OSMesgQueue *audmq; OSMesgQueue *gfxmq; + void *scheduledFB; + void *queuedFB; } OSSched; void osCreateScheduler(OSSched *s, OSThread *thread, u8 mode, u32 numFields); diff --git a/src/game/game_165360.s b/src/game/game_165360.s index 68d1b3e61..b470c7922 100644 --- a/src/game/game_165360.s +++ b/src/game/game_165360.s @@ -15,7 +15,7 @@ glabel func0f165360 lui $a3, %hi(g_Vars) addiu $a3, $a3, %lo(g_Vars) lw $a3, 0x284($a3) - lw $a3, 0x1740($a3) + lw $a3, 0x1750($a3) lui $t0, %hi(var800a4cf0) addiu $t0, $t0, %lo(var800a4cf0) lui $at, %hi(var7f1b76d0) diff --git a/src/game/menu.c b/src/game/menu.c index 3f9ab4b52..56cd60646 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -62,7 +62,7 @@ s32 g_MenuScissorX1; s32 g_MenuScissorX2; s32 g_MenuScissorY1; s32 g_MenuScissorY2; -Vp var800a2048[4][2]; +Vp var800a2048[4][3]; struct menudialogdef g_PakCannotReadGameBoyMenuDialog; struct menudialogdef g_PakDamagedMenuDialog; diff --git a/src/game/playermgr.c b/src/game/playermgr.c index 786ff6871..2d92ed370 100644 --- a/src/game/playermgr.c +++ b/src/game/playermgr.c @@ -371,7 +371,7 @@ void playermgrAllocatePlayer(s32 index) g_Vars.players[index]->floorflags = 0; - for (i = 0; i < 2; i++) { + for (i = 0; i < 3; i++) { g_Vars.players[index]->viewport[i].vp.vscale[0] = 640; g_Vars.players[index]->viewport[i].vp.vscale[1] = (PAL ? 544 : 480); g_Vars.players[index]->viewport[i].vp.vscale[2] = 511; diff --git a/src/include/types.h b/src/include/types.h index 9d209b491..9e19dad8d 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -2515,7 +2515,7 @@ struct player { /*0x0494*/ union modelrwdata *bondheadsave[30]; /*0x050c*/ u32 unk050c; /*0x0510*/ Mtxf bondheadmatrices[4]; - /*0x0610*/ Vp viewport[2]; + /*0x0610*/ Vp viewport[3]; /*0x0630*/ s16 viewwidth; // 320 lo-res, 640 hi-res /*0x0632*/ s16 viewheight; // 220 regardless of res /*0x0634*/ s16 viewleft; // 0 diff --git a/src/lib/modelasm.s b/src/lib/modelasm.s index d46102329..1f6c52ca4 100644 --- a/src/lib/modelasm.s +++ b/src/lib/modelasm.s @@ -785,7 +785,7 @@ glabel model00018680 lwc1 $f0, 0x38($t0) lw $t2, 0x284($t2) neg.s $f0, $f0 - lwc1 $f1, 0x1774($t2) + lwc1 $f1, 0x1784($t2) mul.s $f0, $f0, $f1 lui $t0, %hi(g_ModelDistanceScale) addiu $t0, $t0, %lo(g_ModelDistanceScale) diff --git a/src/lib/sched.c b/src/lib/sched.c index a75fcffff..b4f92ea0b 100644 --- a/src/lib/sched.c +++ b/src/lib/sched.c @@ -77,7 +77,7 @@ static void __scTryDispatch(OSSched *sc) OSScTask *t = sc->nextAudTask; sc->nextAudTask = NULL; __scExec(sc, t); - } else if (sc->curRDPTask == NULL) { + } else if (sc->curRDPTask == NULL && sc->queuedFB == NULL) { OSScTask *t = sc->nextGfxTask; if (t) { @@ -89,56 +89,68 @@ static void __scTryDispatch(OSSched *sc) } } +static void __scSwap(OSSched *sc, void *framebuffer) +{ + if (g_SchedIsFirstTask) { + osViBlack(false); + g_SchedIsFirstTask = false; + } + + var8005ce74 = (var8005ce74 + 1) % 2; + + if (g_SchedViModesPending[1 - var8005ce74]) { + if (var8008dd60[1 - var8005ce74]->comRegs.width != var8008dcc0[1 - var8005ce74].comRegs.width + || var8008dd60[1 - var8005ce74]->comRegs.xScale != var8008dcc0[1 - var8005ce74].comRegs.xScale + || var8008dd60[1 - var8005ce74]->fldRegs[0].yScale != var8008dcc0[1 - var8005ce74].fldRegs[0].yScale + || var8008dd60[1 - var8005ce74]->fldRegs[1].yScale != var8008dcc0[1 - var8005ce74].fldRegs[1].yScale + || var8008dd60[1 - var8005ce74]->fldRegs[0].origin != var8008dcc0[1 - var8005ce74].fldRegs[0].origin + || var8008dd60[1 - var8005ce74]->fldRegs[1].origin != var8008dcc0[1 - var8005ce74].fldRegs[1].origin) { + s32 mask = osSetIntMask(0x80401); + + *var8008dd60[1 - var8005ce74] = var8008dcc0[1 - var8005ce74]; + + osSetIntMask(mask); + + osViSetMode(var8008dd60[1 - var8005ce74]); + osViBlack(g_ViUnblackTimer); + osViSetXScale(g_ViXScalesBySlot[1 - var8005ce74]); + osViSetYScale(g_ViYScalesBySlot[1 - var8005ce74]); + +#ifdef ANTIALIAS + osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_ON); +#else + osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_OFF); +#endif + } + + g_SchedViModesPending[1 - var8005ce74] = false; + } + + if (g_ViUnblackTimer != 0 && g_ViUnblackTimer < 3) { + g_ViUnblackTimer--; + } + + osViSwapBuffer(framebuffer); +} + static void __scTaskComplete(OSSched *sc, OSScTask *t) { if (t->list.t.type == M_AUDTASK) { profileHandleRspEvent(RSPEVENT_AUD_FINISH); + osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK); } else { profileHandleRspEvent(RSPEVENT_GFX_FINISH); - if (g_SchedIsFirstTask) { - osViBlack(false); - g_SchedIsFirstTask = false; + if (sc->scheduledFB == NULL) { + sc->scheduledFB = t->framebuffer; + __scSwap(sc, t->framebuffer); + } else { + sc->queuedFB = t->framebuffer; } - var8005ce74 = (var8005ce74 + 1) % 2; - - if (g_SchedViModesPending[1 - var8005ce74]) { - if (var8008dd60[1 - var8005ce74]->comRegs.width != var8008dcc0[1 - var8005ce74].comRegs.width - || var8008dd60[1 - var8005ce74]->comRegs.xScale != var8008dcc0[1 - var8005ce74].comRegs.xScale - || var8008dd60[1 - var8005ce74]->fldRegs[0].yScale != var8008dcc0[1 - var8005ce74].fldRegs[0].yScale - || var8008dd60[1 - var8005ce74]->fldRegs[1].yScale != var8008dcc0[1 - var8005ce74].fldRegs[1].yScale - || var8008dd60[1 - var8005ce74]->fldRegs[0].origin != var8008dcc0[1 - var8005ce74].fldRegs[0].origin - || var8008dd60[1 - var8005ce74]->fldRegs[1].origin != var8008dcc0[1 - var8005ce74].fldRegs[1].origin) { - s32 mask = osSetIntMask(0x80401); - - *var8008dd60[1 - var8005ce74] = var8008dcc0[1 - var8005ce74]; - - osSetIntMask(mask); - - osViSetMode(var8008dd60[1 - var8005ce74]); - osViBlack(g_ViUnblackTimer); - osViSetXScale(g_ViXScalesBySlot[1 - var8005ce74]); - osViSetYScale(g_ViYScalesBySlot[1 - var8005ce74]); - -#ifdef ANTIALIAS - osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_ON); -#else - osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_OFF); -#endif - } - - g_SchedViModesPending[1 - var8005ce74] = false; - } - - if (g_ViUnblackTimer != 0 && g_ViUnblackTimer < 3) { - g_ViUnblackTimer--; - } - - osViSwapBuffer(t->framebuffer); + osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK); + osSendMesg(sc->gfxmq, (OSMesg) &sc->retraceMsg, OS_MESG_BLOCK); } - - osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK); } //-----------------------------------------------------------------------------\ @@ -147,23 +159,35 @@ static void __scTaskComplete(OSSched *sc, OSScTask *t) static void __scHandleRetrace(OSSched *sc) { - if (osViGetCurrentFramebuffer() == osViGetNextFramebuffer()) { - osDpSetStatus(DPC_CLR_FREEZE); + if (sc->scheduledFB && osViGetCurrentFramebuffer() == sc->scheduledFB) { + if (sc->queuedFB) { + sc->scheduledFB = sc->queuedFB; + sc->queuedFB = NULL; + __scSwap(sc, sc->scheduledFB); + __scTryDispatch(sc); + } else { + sc->scheduledFB = NULL; + } } sc->alt ^= 1; -#if PAL - if (!g_Resetting && sc->alt) { + /** + * On every second retrace, we set a ~6ms timer to prompt the audio thread + * to start making another frame. When the audio task is ready, we try to + * give it to the RSP after the next gfx task finishes rather than yield the + * gfx task. But if we're at the second retrace and the previous gfx task is + * still not done then we must yield it. + */ + if (sc->alt && !g_Resetting) { osStopTimer(&g_SchedRspTimer); osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg); + + if (sc->nextAudTask && sc->curRSPTask->list.t.type == M_GFXTASK) { + osSpTaskYield(); + sc->curRSPTask->state |= OS_SC_YIELD; + } } -#else - if (!g_Resetting && sc->alt) { - osStopTimer(&g_SchedRspTimer); - osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg); - } -#endif if (!g_Resetting) { vi00009ed4(); @@ -204,8 +228,6 @@ static void __scHandleRDP(OSSched *sc) { OSScTask *t; - osDpSetStatus(DPC_SET_FREEZE); - schedUpdatePendingArtifacts(); if (var8005dd18 == 0) { @@ -229,8 +251,6 @@ static void __scHandleRDP(OSSched *sc) } __scTryDispatch(sc); - - osSendMesg(sc->gfxmq, (OSMesg) &sc->retraceMsg, OS_MESG_NOBLOCK); } static void __scMain(void *arg) @@ -258,11 +278,6 @@ void schedSubmitAudTask(OSSched *sc, OSScTask *t) if (sc->curRSPTask == NULL) { __scExec(sc, t); } else { - if (sc->curRSPTask->list.t.type == M_GFXTASK) { - osSpTaskYield(); - sc->curRSPTask->state |= OS_SC_YIELD; - } - t->state = OS_SC_NEEDS_RSP; sc->nextAudTask = t; } @@ -277,22 +292,15 @@ void schedSubmitGfxTask(OSSched *sc, OSScTask *t) t->state = OS_SC_NEEDS_RSP | OS_SC_NEEDS_RDP; - //if (sc->curRSPTask == NULL && sc->curRDPTask == NULL) { - // __scExec(sc, t); - //} else { - // if (sc->nextGfxTask == NULL) { - // sc->nextGfxTask = t; - // } else { - // sc->nextGfxTask2 = t; - // } - //} - - if (sc->nextGfxTask == NULL) { - sc->nextGfxTask = t; + if (sc->curRSPTask == NULL && sc->curRDPTask == NULL && sc->queuedFB == NULL) { + __scExec(sc, t); } else { - sc->nextGfxTask2 = t; + if (sc->nextGfxTask == NULL) { + sc->nextGfxTask = t; + } else { + sc->nextGfxTask2 = t; + } } - __scTryDispatch(sc); osSetThreadPri(0, prevpri); } @@ -325,6 +333,8 @@ void osCreateScheduler(OSSched *sc, OSThread *thread, u8 mode, u32 numFields) sc->retraceMsg.type = OS_SC_RETRACE_MSG; sc->prenmiMsg.type = OS_SC_PRE_NMI_MSG; sc->thread = thread; + sc->scheduledFB = NULL; + sc->queuedFB = NULL; resetThreadCreate(); diff --git a/src/lib/vi.c b/src/lib/vi.c index 3612d1436..021cbcc15 100644 --- a/src/lib/vi.c +++ b/src/lib/vi.c @@ -26,7 +26,7 @@ Mtx *var80092870; u16 g_ViPerspScale; u8 g_ViFrontIndex; u8 g_ViBackIndex; -u16 *g_FrameBuffers[2]; +u16 *g_FrameBuffers[3]; struct rend_vidat g_ViDataArray[] = { { @@ -53,6 +53,18 @@ struct rend_vidat g_ViDataArray[] = { 0, 0, // viewleft and viewtop true, // usezbuf 0, + }, { + 0, 0, 0, 0, + 320, 220, // x and y + 60, // fovy + 1.4545454978943f, // aspect + 30, // znear + 10000, // zfar + 320, 220, // bufx and bufy + 320, 220, // viewx and viewy + 0, 0, // viewleft and viewtop + true, // usezbuf + 0, }, }; @@ -60,7 +72,6 @@ s32 var8005d588 = 0; s32 var8005d58c = 0; struct rend_vidat *g_ViFrontData = &g_ViDataArray[0]; struct rend_vidat *g_ViBackData = &g_ViDataArray[0]; -bool g_ViIs16Bit = true; bool g_ViReconfigured = false; s32 g_ViSlot = 0; @@ -87,7 +98,7 @@ void viConfigureForCopyright(u16 *texturedata) { s32 i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 3; i++) { g_FrameBuffers[i] = texturedata; g_ViDataArray[i].x = 576; @@ -115,7 +126,7 @@ void viConfigureForLegal(void) { s32 i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 3; i++) { g_ViDataArray[i].x = 320; g_ViDataArray[i].bufx = 320; g_ViDataArray[i].viewx = 320; @@ -155,6 +166,7 @@ void viReset(s32 stagenum) u8 *ptr; u8 *fb0; u8 *fb1; + u8 *fb2; if (stagenum == STAGE_TITLE) { viSetMode(VIMODE_HI); @@ -164,22 +176,25 @@ void viReset(s32 stagenum) fbsize = 320 * 220 * 2; } - ptr = mempAlloc(fbsize * 2 + 0x40, MEMPOOL_STAGE); + ptr = mempAlloc(fbsize * 3 + 0x40, MEMPOOL_STAGE); ptr = (u8 *)(((u32)ptr + 0x3f) & 0xffffffc0); g_FrameBuffers[0] = (u16 *) ptr; - g_FrameBuffers[1] = (u16 *) (fbsize + ptr); + g_FrameBuffers[1] = (u16 *) (ptr + fbsize); + g_FrameBuffers[2] = (u16 *) (ptr + fbsize * 2); g_ViFrontData->fb = g_FrameBuffers[g_ViFrontIndex]; g_ViBackData->fb = g_FrameBuffers[g_ViBackIndex]; fb0 = (u8 *) g_FrameBuffers[0]; fb1 = (u8 *) g_FrameBuffers[1]; + fb2 = (u8 *) g_FrameBuffers[2]; for (i = 0; i < fbsize; i++) { fb0[i] = 0; fb1[i] = 0; + fb2[i] = 0; } g_ViReconfigured = true; @@ -360,12 +375,12 @@ void viUpdateMode(void) // 908 g_ViSlot = (g_ViSlot + 1) % 2; - g_RdpCurTask->framebuffer = g_ViIs16Bit ? g_ViBackData->fb : g_FrameBuffers[0]; + g_RdpCurTask->framebuffer = g_ViBackData->fb; prevdata = g_ViBackData; - g_ViFrontIndex = (g_ViFrontIndex + 1) % 2; - g_ViBackIndex = (g_ViBackIndex + 1) % 2; + g_ViFrontIndex = (g_ViFrontIndex + 1) % 3; + g_ViBackIndex = (g_ViBackIndex + 1) % 3; g_ViFrontData = g_ViDataArray + g_ViFrontIndex; g_ViBackData = g_ViDataArray + g_ViBackIndex; @@ -544,11 +559,7 @@ Gfx *vi0000b1d0(Gfx *gdl) { gdl = vi0000b1a8(gdl); - if (g_ViIs16Bit) { - gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_ViBackData->fb)); - } else { - gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_32b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_FrameBuffers[0])); - } + gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_ViBackData->fb)); return gdl; } @@ -784,11 +795,7 @@ void viGetZRange(struct zrange *zrange) Gfx *viSetFillColour(Gfx *gdl, s32 r, s32 g, s32 b) { - if (g_ViIs16Bit) { - gDPSetFillColor(gdl++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); - } else { - gDPSetFillColor(gdl++, r << 24 | g << 16 | b << 8 | 0xff); - } + gDPSetFillColor(gdl++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); return gdl; }