summaryrefslogtreecommitdiff
path: root/src/code/graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/code/graph.c')
-rw-r--r--src/code/graph.c385
1 files changed, 374 insertions, 11 deletions
diff --git a/src/code/graph.c b/src/code/graph.c
index 428bd8621..7ef1715fd 100644
--- a/src/code/graph.c
+++ b/src/code/graph.c
@@ -1,25 +1,388 @@
+#include "prevent_bss_reordering.h"
#include "global.h"
+#include "overlays/gamestates/ovl_daytelop/z_daytelop.h"
+#include "overlays/gamestates/ovl_file_choose/z_file_choose.h"
+#include "overlays/gamestates/ovl_opening/z_opening.h"
+#include "overlays/gamestates/ovl_select/z_select.h"
+#include "overlays/gamestates/ovl_title/z_title.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_FaultClient.s")
+FaultAddrConvClient sGraphFaultAddrConvClient;
+FaultClient sGraphFaultClient;
+GfxMasterList* gGfxMasterDL;
+CfbInfo sGraphCfbInfos[3];
+OSTime sGraphTaskStartTime;
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_DlAlloc.s")
+void* Graph_FaultClient(void) {
+ FaultDrawer_DrawText(30, 100, "ShowFrameBuffer PAGE 0/1");
+ osViSwapBuffer(SysCfb_GetFbPtr(0));
+ osViSetMode(D_801FBB88);
+ osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON | OS_VI_GAMMA_OFF);
+ Fault_WaitForInput();
+ osViSwapBuffer(SysCfb_GetFbPtr(1));
+ osViSetMode(D_801FBB88);
+ osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON | OS_VI_GAMMA_OFF);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_InitTHGA.s")
+void Graph_InitTHGA(TwoHeadGfxArena* arena, Gfx* buffer, s32 size) {
+ THGA_Ct(arena, buffer, size);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_GetNextGameState.s")
+void Graph_SetNextGfxPool(GraphicsContext* gfxCtx) {
+ GfxPool* pool = &gGfxPools[gfxCtx->gfxPoolIdx % 2];
+ gGfxMasterDL = &pool->master;
+ gSegments[0x0E] = gGfxMasterDL;
+
+ pool->headMagic = GFXPOOL_HEAD_MAGIC;
+ pool->tailMagic = GFXPOOL_TAIL_MAGIC;
+
+ Graph_InitTHGA(&gfxCtx->polyOpa, pool->polyOpaBuffer, sizeof(pool->polyOpaBuffer));
+ Graph_InitTHGA(&gfxCtx->polyXlu, pool->polyXluBuffer, sizeof(pool->polyXluBuffer));
+ Graph_InitTHGA(&gfxCtx->overlay, pool->overlayBuffer, sizeof(pool->overlayBuffer));
+ Graph_InitTHGA(&gfxCtx->work, pool->workBuffer, sizeof(pool->workBuffer));
+ Graph_InitTHGA(&gfxCtx->debug, pool->debugBuffer, sizeof(pool->debugBuffer));
+
+ gfxCtx->polyOpaBuffer = pool->polyOpaBuffer;
+ gfxCtx->polyXluBuffer = pool->polyXluBuffer;
+ gfxCtx->overlayBuffer = pool->overlayBuffer;
+ gfxCtx->workBuffer = pool->workBuffer;
+ gfxCtx->debugBuffer = pool->debugBuffer;
+
+ gfxCtx->curFrameBuffer = (u16*)SysCfb_GetFbPtr(gfxCtx->framebufferIdx % 2);
+ gSegments[0x0F] = gfxCtx->curFrameBuffer;
+
+ gfxCtx->zbuffer = SysCfb_GetZBuffer();
+
+ gSPBranchList(&gGfxMasterDL->disps[0], pool->polyOpaBuffer);
+ gSPBranchList(&gGfxMasterDL->disps[1], pool->polyXluBuffer);
+ gSPBranchList(&gGfxMasterDL->disps[2], pool->overlayBuffer);
+ gSPBranchList(&gGfxMasterDL->disps[3], pool->workBuffer);
+ gSPEndDisplayList(&gGfxMasterDL->disps[4]);
+ gSPBranchList(&gGfxMasterDL->debugDisp[0], pool->debugBuffer);
+}
+
+GameStateOverlay* Graph_GetNextGameState(GameState* gameState) {
+ GameStateFunc gameStateInit = GameState_GetNextStateInit(gameState);
+
+ if (gameStateInit == (GameStateFunc)TitleSetup_Init) {
+ return &gGameStateOverlayTable[0];
+ }
+ if (gameStateInit == (GameStateFunc)Select_Init) {
+ return &gGameStateOverlayTable[1];
+ }
+ if (gameStateInit == (GameStateFunc)Title_Init) {
+ return &gGameStateOverlayTable[2];
+ }
+ if (gameStateInit == (GameStateFunc)Play_Init) {
+ return &gGameStateOverlayTable[3];
+ }
+ if (gameStateInit == (GameStateFunc)Opening_Init) {
+ return &gGameStateOverlayTable[4];
+ }
+ if (gameStateInit == (GameStateFunc)FileChoose_Init) {
+ return &gGameStateOverlayTable[5];
+ }
+ if (gameStateInit == (GameStateFunc)Daytelop_Init) {
+ return &gGameStateOverlayTable[6];
+ }
+ return NULL;
+}
+
+#ifdef NON_MATCHING
+// Regalloc differences
+void* Graph_FaultAddrConvFunc(void* address, void* param) {
+ u32 addr = address;
+ GameStateOverlay* gamestateOvl;
+ u32 ramConv;
+ u32 ramStart;
+ u32 diff;
+ s32 i;
+
+ for (i = 0; i < graphNumGameStates; i++) {
+ gamestateOvl = &gGameStateOverlayTable[i];
+ ramStart = gamestateOvl->loadedRamAddr;
+ diff = (u32)gamestateOvl->vramEnd - (u32)gamestateOvl->vramStart;
+ ramConv = (u32)gamestateOvl->vramStart - ramStart;
+
+ if (gamestateOvl->loadedRamAddr != NULL) {
+ if (addr >= ramStart && addr < ramStart + diff) {
+ return addr + ramConv;
+ }
+ }
+ }
+ return NULL;
+}
+#else
#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_FaultAddrConvFunc.s")
+#endif
+
+void Graph_Init(GraphicsContext* gfxCtx) {
+ bzero(gfxCtx, sizeof(GraphicsContext));
+ gfxCtx->gfxPoolIdx = 0;
+ gfxCtx->framebufferIdx = 0;
+ gfxCtx->viMode = NULL;
+ gfxCtx->viConfigFeatures = gViConfigFeatures;
+ gfxCtx->xScale = gViConfigXScale;
+ gfxCtx->yScale = gViConfigYScale;
+ osCreateMesgQueue(&gfxCtx->queue, gfxCtx->msgBuff, ARRAY_COUNT(gfxCtx->msgBuff));
+ Fault_AddClient(&sGraphFaultClient, Graph_FaultClient, NULL, NULL);
+ Fault_AddAddrConvClient(&sGraphFaultAddrConvClient, Graph_FaultAddrConvFunc, NULL);
+}
+
+void Graph_Destroy(GraphicsContext* gfxCtx) {
+ Fault_RemoveClient(&sGraphFaultClient);
+ Fault_RemoveAddrConvClient(&sGraphFaultAddrConvClient);
+}
+
+/**
+ * Constructs the graphics OSTask and forwards it to the scheduler.
+ * Waits for up to 3 additional seconds for any current graphics task to complete.
+ * If it does not signal completion in that time, retry or trigger a crash.
+ */
+void Graph_TaskSet00(GraphicsContext* gfxCtx, GameState* gameState) {
+ static s32 retryCount = 10;
+ static s32 cfbIdx = 0;
+ OSTask_t* task = &gfxCtx->task.list.t;
+ OSScTask* scTask = &gfxCtx->task;
+ OSTimer timer;
+ OSMesg msg;
+ CfbInfo* cfb;
+
+retry:
+ osSetTimer(&timer, OS_USEC_TO_CYCLES(3 * 1000 * 1000), 0, &gfxCtx->queue, (OSMesg)666);
+ osRecvMesg(&gfxCtx->queue, &msg, OS_MESG_BLOCK);
+ osStopTimer(&timer);
+
+ if (msg == (OSMesg)666) {
+ osSyncPrintf("GRAPH SP TIMEOUT\n");
+ if (retryCount >= 0) {
+ retryCount--;
+ Sched_SendGfxCancelMsg(&gSchedContext);
+ goto retry;
+ } else {
+ // graph.c: No more! die!
+ osSyncPrintf("graph.c:もうダメ!死ぬ!\n");
+ Fault_AddHungupAndCrashImpl("RCP is HUNG UP!!", "Oh! MY GOD!!");
+ }
+ }
+
+ gfxCtx->masterList = gGfxMasterDL;
+ if (gfxCtx->callback != NULL) {
+ gfxCtx->callback(gfxCtx, gfxCtx->callbackParam);
+ }
+
+ task->type = M_GFXTASK;
+ task->flags = OS_SC_DRAM_DLIST;
+ task->ucodeBoot = SysUcode_GetUCodeBoot();
+ task->ucodeBootSize = SysUcode_GetUCodeBootSize();
+ task->ucode = SysUcode_GetUCode();
+ task->ucodeData = SysUcode_GetUCodeData();
+ task->ucodeSize = 0x1000;
+ task->ucodeDataSize = 0x800;
+ task->dramStack = (u64*)gGfxSPTaskStack;
+ task->dramStackSize = sizeof(gGfxSPTaskStack);
+ task->outputBuff = gGfxSPTaskOutputBufferPtr;
+ task->outputBuffSize = gGfxSPTaskOutputBufferSize;
+ task->dataPtr = (u64*)gGfxMasterDL;
+ task->dataSize = 0;
+ task->yieldDataPtr = (u64*)gGfxSPTaskYieldBuffer;
+ task->yieldDataSize = sizeof(gGfxSPTaskYieldBuffer);
+
+ scTask->next = NULL;
+ scTask->flags = OS_SC_RCP_MASK | OS_SC_SWAPBUFFER | OS_SC_LAST_TASK;
+
+ if (SREG(33) & 1) {
+ SREG(33) &= ~1;
+ scTask->flags &= ~OS_SC_SWAPBUFFER;
+ gfxCtx->framebufferIdx--;
+ }
+
+ scTask->msgQ = &gfxCtx->queue;
+ scTask->msg = NULL;
+
+ { s32 pad; }
+
+ cfb = &sGraphCfbInfos[cfbIdx];
+ cfbIdx = (cfbIdx + 1) % ARRAY_COUNT(sGraphCfbInfos);
+
+ cfb->fb1 = gfxCtx->curFrameBuffer;
+ cfb->swapBuffer = gfxCtx->curFrameBuffer;
+
+ if (gfxCtx->updateViMode) {
+ gfxCtx->updateViMode = false;
+ cfb->viMode = gfxCtx->viMode;
+ cfb->features = gfxCtx->viConfigFeatures;
+ cfb->xScale = gfxCtx->xScale;
+ cfb->yScale = gfxCtx->yScale;
+ } else {
+ cfb->viMode = NULL;
+ }
+ cfb->unk_10 = 0;
+ cfb->updateRate = gameState->framerateDivisor;
+
+ scTask->framebuffer = cfb;
+
+ while (gfxCtx->queue.validCount != 0) {
+ osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK);
+ }
+
+ gfxCtx->schedMsgQ = &gSchedContext.cmdQ;
+ osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK);
+ Sched_SendEntryMsg(&gSchedContext);
+}
+
+void Graph_UpdateGame(GameState* gameState) {
+ Game_UpdateInput(gameState);
+ Game_IncrementFrameCount(gameState);
+ if (SREG(20) < 3) {
+ func_8019E014();
+ }
+}
+
+/**
+ * Run the gamestate logic, then finalize the gfx buffer
+ * and run the graphics task for this frame.
+ */
+void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) {
+ u32 problem;
+
+ gameState->unk_A3 = 0;
+ Graph_SetNextGfxPool(gfxCtx);
+
+ Game_Update(gameState);
+
+ OPEN_DISPS(gfxCtx);
+
+ gSPEndDisplayList(WORK_DISP++);
+ gSPEndDisplayList(POLY_OPA_DISP++);
+ gSPEndDisplayList(POLY_XLU_DISP++);
+ gSPEndDisplayList(OVERLAY_DISP++);
+ gSPEndDisplayList(DEBUG_DISP++);
+
+ CLOSE_DISPS(gfxCtx);
+
+ {
+ Gfx* gfx = gGfxMasterDL->taskStart;
+
+ gSPSegment(gfx++, 0x0E, gGfxMasterDL);
+ gSPDisplayList(gfx++, &D_0E000000.disps[3]);
+ gSPDisplayList(gfx++, &D_0E000000.disps[0]);
+ gSPDisplayList(gfx++, &D_0E000000.disps[1]);
+ gSPDisplayList(gfx++, &D_0E000000.disps[2]);
+ gSPDisplayList(gfx++, &D_0E000000.debugDisp[0]);
+
+ gDPPipeSync(gfx++);
+ gDPFullSync(gfx++);
+ gSPEndDisplayList(gfx++);
+ }
+
+ problem = false;
+
+ {
+ GfxPool* pool = &gGfxPools[gfxCtx->gfxPoolIdx % 2];
+
+ if (pool->headMagic != GFXPOOL_HEAD_MAGIC) {
+ Fault_AddHungupAndCrash("../graph.c", 1054);
+ }
+ if (pool->tailMagic != GFXPOOL_TAIL_MAGIC) {
+ Fault_AddHungupAndCrash("../graph.c", 1066);
+ }
+ }
+
+ if (THGA_IsCrash(&gfxCtx->polyOpa)) {
+ problem = true;
+ }
+ if (THGA_IsCrash(&gfxCtx->polyXlu)) {
+ problem = true;
+ }
+ if (THGA_IsCrash(&gfxCtx->overlay)) {
+ problem = true;
+ }
+ if (THGA_IsCrash(&gfxCtx->work)) {
+ problem = true;
+ }
+ if (THGA_IsCrash(&gfxCtx->debug)) {
+ problem = true;
+ }
+
+ if (!problem) {
+ Graph_TaskSet00(gfxCtx, gameState);
+ gfxCtx->gfxPoolIdx++;
+ gfxCtx->framebufferIdx++;
+ }
+
+ {
+ OSTime time = osGetTime();
+
+ D_801FBAE8 = sRSPGFXTotalTime;
+ D_801FBAE0 = gRSPAudioTotalTime;
+ D_801FBAF0 = gRDPTotalTime;
+ sRSPGFXTotalTime = 0;
+ gRSPAudioTotalTime = 0;
+ gRDPTotalTime = 0;
+
+ if (sGraphTaskStartTime != 0) {
+ lastRenderFrameDuration = time - sGraphTaskStartTime;
+ }
+ sGraphTaskStartTime = time;
+ }
+}
+
+void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
+ gameState->unk_A3 = 0;
+
+ Graph_UpdateGame(gameState);
+ Graph_ExecuteAndDraw(gfxCtx, gameState);
+}
+
+void Graph_ThreadEntry(void* arg) {
+ GraphicsContext gfxCtx;
+ GameStateOverlay* nextOvl = &gGameStateOverlayTable[0];
+ GameStateOverlay* ovl;
+ GameState* gameState;
+ u32 size;
+ s32 pad[2];
+
+ gZBuffer = SystemArena_Malloc(sizeof(*gZBuffer) + sizeof(*gWorkBuffer) + 64 - 1);
+ gZBuffer = (void*)ALIGN64((u32)gZBuffer);
+
+ gWorkBuffer = (void*)((u8*)gZBuffer + sizeof(*gZBuffer));
+
+ gGfxSPTaskOutputBuffer2 = gGfxSPTaskOutputBuffer = SystemArena_Malloc(sizeof(*gGfxSPTaskOutputBuffer));
+
+ gGfxSPTaskOutputBufferEnd = (u8*)gGfxSPTaskOutputBuffer + sizeof(*gGfxSPTaskOutputBuffer);
+ gGfxSPTaskOutputBufferEnd2 = (u8*)gGfxSPTaskOutputBuffer2 + sizeof(*gGfxSPTaskOutputBuffer2);
+
+ func_80178978();
+ Fault_SetFB(D_801FBB90, SCREEN_WIDTH, SCREEN_HEIGHT);
+ Graph_Init(&gfxCtx);
+
+ while (nextOvl) {
+ ovl = nextOvl;
+
+ Overlay_LoadGameState(ovl);
+
+ size = ovl->instanceSize;
+
+ func_800809F4(ovl->vromStart);
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_Init.s")
+ gameState = SystemArena_Malloc(size);
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_Destroy.s")
+ bzero(gameState, size);
+ GameState_Init(gameState, ovl->init, &gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_Render.s")
+ while (GameState_IsRunning(gameState)) {
+ Graph_Update(&gfxCtx, gameState);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_FrameSetup.s")
+ nextOvl = Graph_GetNextGameState(gameState);
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_RenderFrame.s")
+ if (size) {}
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_DoFrame.s")
+ GameState_Destroy(gameState);
+ SystemArena_Free(gameState);
-#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_ThreadEntry.s")
+ Overlay_FreeGameState(ovl);
+ }
+ Graph_Destroy(&gfxCtx);
+}