mirror of
https://gitlab.com/ryandwyer/perfect-dark
synced 2026-09-01 09:22:53 -04:00
Introduce triple buffer and remove RDP freeze
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+84
-74
@@ -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();
|
||||
|
||||
|
||||
+26
-19
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user