diff options
Diffstat (limited to 'src/code/graph.c')
| -rw-r--r-- | src/code/graph.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/src/code/graph.c b/src/code/graph.c new file mode 100644 index 0000000..1fe2a06 --- /dev/null +++ b/src/code/graph.c @@ -0,0 +1,449 @@ +#include "graph.h" +#include "global.h" + +#include "audio.h" +#include "buffers.h" +#include "cfbinfo.h" +#include "fault.h" +#include "game.h" +#include "getcurrentms.h" +#include "gfx.h" +#include "idle.h" +#include "irqmgr.h" +#include "m_debug.h" +#include "m_DLF.h" +#include "speed_meter.h" +#include "sys_ucode.h" +#include "zurumode.h" +#include "6FB340.h" +#include "6FD190.h" +#include "6FD410.h" + +#include "overlays/gamestates/ovl_first_game/first_game.h" +#include "overlays/gamestates/ovl_select/m_select.h" +#include "overlays/gamestates/ovl_play/m_play.h" +#include "overlays/gamestates/ovl_second_game/second_game.h" +#include "overlays/gamestates/ovl_cpedit/m_cpedit.h" +#include "overlays/gamestates/ovl_trademark/m_trademark.h" +#include "overlays/gamestates/ovl_player_select/player_select.h" +#include "overlays/gamestates/ovl_save_menu/save_menu.h" +#include "overlays/gamestates/ovl_famicom_emu/famicom_emu.h" +#include "overlays/gamestates/ovl_prenmi/m_prenmi.h" + +void graph_FaultClient(void) { + s32 i; + void* fb; + + FaultDrawer_DrawText(30, 100, "ShowFrameBuffer PAGE 0/1/2"); + + for (i = 0; i < 3; i++) { + fb = func_800D96E8_jp(i); + if (fb != NULL) { + osViSwapBuffer(fb); + osViSetMode(&gViConfigMode); + osViSetSpecialFeatures(gViConfigFeatures); + osViSetXScale(gViConfigXScale); + osViSetYScale(gViConfigYScale); + fault_WaitForInput(); + } + } +} + +void graph_setup_double_buffer(GraphicsContext* gfxCtx) { + GfxPool* pool = &gGfxPools[gfxCtx->gfxPoolIndex % 2]; + + pool->headMagic = GFXPOOL_HEAD_MAGIC; + pool->tailMagic = GFXPOOL_TAIL_MAGIC; + + THA_GA_ct(&gfxCtx->polyOpa, pool->polyOpaBuffer, sizeof(pool->polyOpaBuffer)); + THA_GA_ct(&gfxCtx->polyXlu, pool->polyXluBuffer, sizeof(pool->polyXluBuffer)); + THA_GA_ct(&gfxCtx->overlay, pool->overlayBuffer, sizeof(pool->overlayBuffer)); + THA_GA_ct(&gfxCtx->work, pool->workBuffer, sizeof(pool->workBuffer)); + THA_GA_ct(&gfxCtx->font, pool->fontBuffer, sizeof(pool->fontBuffer)); + THA_GA_ct(&gfxCtx->shadow, pool->shadowBuffer, sizeof(pool->shadowBuffer)); + THA_GA_ct(&gfxCtx->light, pool->lightBuffer, sizeof(pool->lightBuffer)); + + gfxCtx->polyOpaBuffer = pool->polyOpaBuffer; + gfxCtx->polyXluBuffer = pool->polyXluBuffer; + gfxCtx->overlayBuffer = pool->overlayBuffer; + gfxCtx->workBuffer = pool->workBuffer; + gfxCtx->fontBuffer = pool->fontBuffer; + gfxCtx->shadowBuffer = pool->shadowBuffer; + gfxCtx->lightBuffer = pool->lightBuffer; + + while (gfxCtx->unk_2E4 == NULL) { + s32 temp_s1_2 = func_800D9700_jp(); + + gfxCtx->unk_2E4 = func_800D96E8_jp(gfxCtx->unk_2F3); + if (gfxCtx->unk_2E4 == B_80146084_jp) { + gfxCtx->unk_2E4 = NULL; + } + + gfxCtx->unk_2F3 = ((gfxCtx->unk_2F3 + 1) < temp_s1_2) ? gfxCtx->unk_2F3 + 1 : 0; + } + + gfxCtx->unk_008 = func_800D9750_jp(); + gfxCtx->unk_20 = 0; +} + +GameStateOverlay* game_get_next_game_dlftbl(Game* game) { + GameStateFunc init = game_get_next_game_init(game); + + if (init == first_game_init) { + return &game_dlftbls[0]; + } + if (init == select_init) { + return &game_dlftbls[1]; + } + if (init == play_init) { + return &game_dlftbls[2]; + } + if (init == second_game_init) { + return &game_dlftbls[3]; + } + if (init == cpedit_init) { + return &game_dlftbls[4]; + } + if (init == trademark_init) { + return &game_dlftbls[5]; + } + if (init == player_select_init) { + return &game_dlftbls[6]; + } + if (init == save_menu_init) { + return &game_dlftbls[7]; + } + if (init == famicom_emu_init) { + return &game_dlftbls[8]; + } + if (init == prenmi_init) { + return &game_dlftbls[9]; + } + + return NULL; +} + +uintptr_t graph_FaultAddrConv(uintptr_t address, UNUSED void* param) { + uintptr_t addr = address; + GameStateOverlay* gameStateOvl = &game_dlftbls[0]; + uintptr_t ramConv; + void* ramStart; + size_t diff; + s32 i; + + for (i = 0; i < game_dlftbls_num; i++, gameStateOvl++) { + diff = (uintptr_t)gameStateOvl->vramEnd - (uintptr_t)gameStateOvl->vramStart; + ramStart = gameStateOvl->loadedRamAddr; + ramConv = (uintptr_t)gameStateOvl->vramStart - (uintptr_t)ramStart; + + if (ramStart != NULL) { + if ((addr >= (uintptr_t)ramStart) && (addr < (uintptr_t)ramStart + diff)) { + return addr + ramConv; + } + } + } + return 0; +} + +void graph_ct(GraphicsContext* gfxCtx) { + bzero(gfxCtx, sizeof(GraphicsContext)); + gfxCtx->gfxPoolIndex = 0; + gfxCtx->unk_2F3 = 0; + gfxCtx->unk_25C = &osViModeNtscLan1; + gfxCtx->unk_2EC = 66; + gfxCtx->unk_2FC = 1.0f; + gfxCtx->unk_300 = 1.0f; + osCreateMesgQueue(&gfxCtx->queue, gfxCtx->msgBuff, ARRAY_COUNT(gfxCtx->msgBuff)); + SREG(33) &= ~2; + SREG(33) &= ~1; + zurumode_init(); + fault_AddClient(&sGraphFaultClient, (void*)graph_FaultClient, NULL, NULL); + fault_AddressConverterAddClient(&sGraphFaultAddrConvClient, graph_FaultAddrConv, NULL); + gfxCtx->unk_2F0 = 1; +} + +void graph_dt(GraphicsContext* gfxCtx) { + gfxCtx->unk_2F0 = 0x15; + zurumode_cleanup(); + fault_RemoveClient(&sGraphFaultClient); + fault_AddressConverterRemoveClient(&sGraphFaultAddrConvClient); +} + +void func_800D3E14_jp(GraphicsContext* gfxCtx) { + osSendMesg(&gfxCtx->queue, NULL, OS_MESG_BLOCK); +} + +void func_800D3E40_jp(GraphicsContext* gfxCtx) { + static s32 sRetryCount = 100; + UNUSED s32 pad; + OSTimer timer; + OSMesg msg; + +retry: + osSetTimer(&timer, OS_USEC_TO_CYCLES(1000000), 0, &gfxCtx->queue, (OSMesg)666); + osRecvMesg(&gfxCtx->queue, &msg, OS_MESG_BLOCK); + osStopTimer(&timer); + if ((ResetStatus < 2) && (msg == (OSMesg)666)) { + if (sRetryCount >= 0) { + if (1) { + sRetryCount--; + func_800D8644_jp(); + } + goto retry; + } + fault_AddHungupAndCrashImpl("RCP is HUNG UP!!", "Oh! MY GOD!!"); + } +} + +void graph_task_set00(GraphicsContext* gfxCtx) { + UNUSED s32 pad; + OSTask* task = &gfxCtx->task.list; + OSScTask* scTask = &gfxCtx->task; + uintptr_t temp_a1; + uintptr_t temp_a0; + uintptr_t temp_a2; + + gfxCtx->unk_2F0 = 0xD; + + func_800D3E40_jp(gfxCtx); + gfxCtx->unk_2F0 = 0xE; + + if (ResetStatus < 2) { + gfxCtx->unk_304 = gfxCtx->workBuffer; + if (gfxCtx->callback != NULL) { + gfxCtx->callback(gfxCtx, gfxCtx->callbackArg); + } + if (SREG(33) & 2) { + SREG(33) &= ~2; + task->t.type = 0; + } else { + task->t.type = M_GFXTASK; + task->t.flags = OS_SC_DRAM_DLIST; + + OPEN_DISPS(gfxCtx); + + task->t.ucode_boot = ucode_GetRspBootTextStart(); + task->t.ucode_boot_size = ucode_GetRspBootTextSize(); + task->t.ucode = ucode_GetPolyTextStart(); + task->t.ucode_data = ucode_GetPolyDataStart(); + task->t.ucode_size = SP_UCODE_SIZE; + task->t.ucode_data_size = SP_UCODE_DATA_SIZE; + task->t.dram_stack = D_80153CC0_jp; + task->t.dram_stack_size = sizeof(D_80153CC0_jp); + + temp_a1 = (uintptr_t)POLY_OPA_DISP; + temp_a0 = ALIGN16(temp_a1); + temp_a2 = ALIGN16(THA_GA_getFreeBytes(&gfxCtx->polyOpa) - temp_a0 + temp_a1 - 0xF); + + if (((uintptr_t)(D_801524C0_jp + ARRAY_COUNT(D_801524C0_jp)) - (uintptr_t)D_801524C0_jp) < temp_a2) { + task->t.output_buff = (u64*)temp_a0; + task->t.output_buff_size = (u64*)(temp_a0 + temp_a2); + } else { + task->t.output_buff = D_801524C0_jp; + task->t.output_buff_size = D_801524C0_jp + ARRAY_COUNT(D_801524C0_jp); + } + CLOSE_DISPS(gfxCtx); + + task->t.data_ptr = (u64*)gfxCtx->workBuffer; + + OPEN_DISPS(gfxCtx); + task->t.data_size = (uintptr_t)WORK_DISP - (uintptr_t)gfxCtx->workBuffer; + CLOSE_DISPS(gfxCtx); + + task->t.yield_data_ptr = D_801530C0_jp; + task->t.yield_data_size = sizeof(D_801530C0_jp); + } + scTask->next = NULL; + + if (SREG(33) & 1) { + scTask->flags = OS_SC_NEEDS_RSP | OS_SC_NEEDS_RDP | OS_SC_LAST_TASK; + } else { + scTask->flags = OS_SC_NEEDS_RSP | OS_SC_NEEDS_RDP | OS_SC_SWAPBUFFER | OS_SC_LAST_TASK; + } + scTask->msgQ = &gfxCtx->queue; + scTask->msg = NULL; + + { + cfbStruct* cfb = func_800D2C10_jp(); + + cfb->unk_00 = gfxCtx->unk_2E4; + cfb->unk_04 = NULL; + cfb->unk_09 = game_GameFrame; + cfb->unk_0C = NULL; + if (scTask->flags & OS_SC_SWAPBUFFER) { + cfb->unk_04 = gfxCtx->unk_2E4; + if (gfxCtx->unk_2F2 != 0) { + gfxCtx->unk_2F2 = 0; + cfb->unk_0C = gfxCtx->unk_25C; + cfb->unk_10 = gfxCtx->unk_2EC; + cfb->unk_14 = gfxCtx->unk_2FC; + cfb->unk_18 = gfxCtx->unk_300; + } + if (B_80146080_jp == 1) { + B_80146084_jp = cfb->unk_04; + cfb->unk_0B = 1; + B_80146080_jp = 2; + } + } + + scTask->framebuffer = cfb; + } + + while (gfxCtx->queue.validCount != 0) { + osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK); + } + + if (ResetStatus < 2) { + gfxCtx->unk_064 = &B_80145DB8_jp; + osSendMesg(&B_80145DB8_jp, (OSMesg)scTask, OS_MESG_BLOCK); + func_800D85EC_jp(); + } + } +} + +u32 graph_draw_finish(GraphicsContext* gfxCtx) { + u32 err; + UNUSED s32 pad[2]; + + OPEN_DISPS(gfxCtx); + + gSPBranchList(WORK_DISP++, gfxCtx->polyOpaBuffer); + gSPBranchList(POLY_OPA_DISP++, gfxCtx->shadowBuffer); + gSPBranchList(SHADOW_DISP++, gfxCtx->polyXluBuffer); + gSPBranchList(POLY_XLU_DISP++, gfxCtx->lightBuffer); + gSPBranchList(LIGHT_DISP++, gfxCtx->fontBuffer); + gSPBranchList(FONT_DISP++, gfxCtx->overlayBuffer); + + gDPPipeSync(OVERLAY_DISP++); + gDPFullSync(OVERLAY_DISP++); + gSPEndDisplayList(OVERLAY_DISP++); + + CLOSE_DISPS(gfxCtx); + + err = false; + { + GfxPool* pool = &gGfxPools[gfxCtx->gfxPoolIndex & 1]; + + if (pool->headMagic != GFXPOOL_HEAD_MAGIC) { + fault_AddHungupAndCrash("../graph.c", 606); + } + if (pool->tailMagic != GFXPOOL_TAIL_MAGIC) { + err = true; + fault_AddHungupAndCrash("../graph.c", 614); + } + } + + if (THA_GA_isCrash(&gfxCtx->polyOpa)) { + err = true; + } + if (THA_GA_isCrash(&gfxCtx->polyXlu)) { + err = true; + } + if (THA_GA_isCrash(&gfxCtx->overlay)) { + err = true; + } + if (THA_GA_isCrash(&gfxCtx->font)) { + err = true; + } + if (THA_GA_isCrash(&gfxCtx->shadow)) { + err = true; + } + if (THA_GA_isCrash(&gfxCtx->light)) { + err = true; + } + + return err; +} + +void graph_main(GraphicsContext* gfxCtx, Game* game) { + game->unk_A4 = false; + graph_setup_double_buffer(gfxCtx); + game_get_controller(game); + game->unk_9E = false; + gfxCtx->unk_2F0 = 4; + + game_main(game); + + gfxCtx->unk_2F0 = 0xB; + + if ((ResetStatus < 2) && !game->unk_9E && !graph_draw_finish(gfxCtx)) { + gfxCtx->unk_2F0 = 0xC; + + graph_task_set00(gfxCtx); + gfxCtx->unk_2F0 = 0xF; + + gfxCtx->gfxPoolIndex++; + if (SREG(33) & 1) { + SREG(33) &= ~1; + } else { + gfxCtx->unk_2E4 = NULL; + } + } + if (SREG(20) < 2) { + gfxCtx->unk_2F0 = 0x10; + + sAdo_GameFrame(); + gfxCtx->unk_2F0 = 0x11; + } + + func_800D93F4_jp(); + + if ((ResetStatus == 1) && !game->unk_A4) { + STOP_GAMESTATE(game); + SET_NEXT_GAMESTATE(game, prenmi_init, sizeof(Game_Prenmi)); + } +} + +void graph_proc(UNUSED void* arg) { + s32 state; + GameStateOverlay* nextOvl = &game_dlftbls[0]; + GameStateOverlay* ovl; + size_t size; + Game* game; + char msg[80]; + + graph_ct(&graph_class); + + while (nextOvl != NULL) { + ovl = nextOvl; + + Overlay_LoadGameState(ovl); + + state = 2; + size = ovl->instanceSize; + game = malloc(size); + game_class_p = game; + if (game == NULL) { + sprintf(msg, "CLASS SIZE= %d bytes", size); + fault_AddHungupAndCrashImpl("GAME CLASS MALLOC FAILED", msg); + } + bzero(game, size); + graph_class.unk_2F0 = state; + + state = 3; + game_ct(game, ovl->init, &graph_class); + graph_class.unk_2F0 = state; + + state = 0x12; + while (game_is_doing(game)) { + graph_main(&graph_class, game); + B_80145FF8_jp = GetCurrentMilliseconds(); + } + nextOvl = game_get_next_game_dlftbl(game); + graph_class.unk_2F0 = state; + + state = 0x13; + func_800D79F4_jp(); + graph_class.unk_2F0 = state; + + state = 0x14; + game_dt(game); + graph_class.unk_2F0 = state; + + free(game); + game_class_p = NULL; + Overlay_FreeGameState(ovl); + } + + graph_dt(&graph_class); +} |
