#include <ultra64.h>
#include "sm64.h"
#include "gfx_dimensions.h"
#include "audio/external.h"
#include "buffers/buffers.h"
#include "buffers/gfx_output_buffer.h"
#include "buffers/framebuffers.h"
#include "buffers/zbuffer.h"
#include "engine/level_script.h"
#include "game_init.h"
#include "main.h"
#include "memory.h"
#include "profiler.h"
#include "save_file.h"
#include "seq_ids.h"
#include "sound_init.h"
#include "print.h"
#include "segment2.h"
#include "segment_symbols.h"
#include "rumble_init.h"
#include <prevent_bss_reordering.h>
#include "settings.h"
struct Controller gControllers[3];
struct SPTask *gGfxSPTask;
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool *gGfxAllocOnlyPool;
Gfx *gDisplayListHeadInChunk;
Gfx *gDisplayListEndInChunk;
#else
Gfx *gDisplayListHead;
u8 *gGfxPoolEnd;
#endif
struct GfxPool *gGfxPool;
OSContStatus gControllerStatuses[4];
OSContPad gControllerPads[4];
u8 gControllerBits;
s8 gEepromProbe;
OSMesgQueue gGameVblankQueue;
OSMesgQueue gGfxVblankQueue;
OSMesg gGameMesgBuf[1];
OSMesg gGfxMesgBuf[1];
struct VblankHandler gGameVblankHandler;
uintptr_t gPhysicalFrameBuffers[3];
uintptr_t gPhysicalZBuffer;
s8 gCanMirror = 0;
s8 gReimportTextures = 0;
s8 gBooDialogueWasSaid = 0;
void *gMarioAnimsMemAlloc;
void *gDemoInputsMemAlloc;
struct DmaHandlerList gMarioAnimsBuf;
struct DmaHandlerList gDemoInputsBuf;
UNUSED static u8 sfillerGameInit[0x90];
static s32 sUnusedGameInitValue = 0;
u32 gGlobalTimer = 0;
u16 sRenderedFramebuffer = 0;
u16 sRenderingFrameBuffer = 0;
void (*gGoddardVblankCallback)(void) = NULL;
struct Controller *gPlayer1Controller = &gControllers[0];
struct Controller *gPlayer2Controller = &gControllers[1];
struct Controller *gPlayer3Controller = &gControllers[2];
struct DemoInput *gCurrDemoInput = NULL;
u16 gDemoInputListID = 0;
struct DemoInput gRecordedDemoInput = { 0 };
s8 get_mirror() {
if (configEncoreMode == 0 || configEncoreMode == 2 || gCurrCourseNum == COURSE_CAKE_END) {
return 0;
}
return gCanMirror;
}
s16 get_palette() {
if (configEncoreMode == 0 || configEncoreMode == 3 || !gCanMirror) {
return 0;
}
return gCurrCourseNum+1;
}
void init_rdp(void) {
gDPPipeSync(gDisplayListHead++);
gDPPipelineMode(gDisplayListHead++, G_PM_1PRIMITIVE);
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetTextureLOD(gDisplayListHead++, G_TL_TILE);
gDPSetTextureLUT(gDisplayListHead++, G_TT_NONE);
gDPSetTextureDetail(gDisplayListHead++, G_TD_CLAMP);
gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
if (configTextureFiltering > -1) {
gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
}
else {
gDPSetTextureFilter(gDisplayListHead++, G_TF_POINT);
}
gDPSetTextureConvert(gDisplayListHead++, G_TC_FILT);
gDPSetCombineKey(gDisplayListHead++, G_CK_NONE);
gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gDPSetColorDither(gDisplayListHead++, G_CD_MAGICSQ);
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
#ifdef VERSION_SH
gDPSetAlphaDither(gDisplayListHead++, G_AD_PATTERN);
#endif
gDPPipeSync(gDisplayListHead++);
}
void init_rsp(void) {
gSPClearGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CULL_BOTH | G_FOG
| G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CULL_BACK | G_LIGHTING);
gSPNumLights(gDisplayListHead++, NUMLIGHTS_1);
gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
#ifdef F3DEX_GBI_2
gSPClipRatio(gDisplayListHead++, FRUSTRATIO_1);
#endif
}
void init_z_buffer(void) {
gDPPipeSync(gDisplayListHead++);
gDPSetDepthSource(gDisplayListHead++, G_ZS_PIXEL);
gDPSetDepthImage(gDisplayListHead++, gPhysicalZBuffer);
gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH, gPhysicalZBuffer);
gDPSetFillColor(gDisplayListHead++,
GPACK_ZDZ(G_MAXFBZ, 0) << 16 | GPACK_ZDZ(G_MAXFBZ, 0));
gDPFillRectangle(gDisplayListHead++, 0, BORDER_HEIGHT, SCREEN_WIDTH - 1,
SCREEN_HEIGHT - 1 - BORDER_HEIGHT);
}
void select_frame_buffer(void) {
gDPPipeSync(gDisplayListHead++);
gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH,
gPhysicalFrameBuffers[sRenderingFrameBuffer]);
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
SCREEN_HEIGHT - BORDER_HEIGHT);
}
void clear_frame_buffer(s32 color) {
gDPPipeSync(gDisplayListHead++);
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
gDPSetFillColor(gDisplayListHead++, color);
gDPFillRectangle(gDisplayListHead++,
GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), BORDER_HEIGHT,
GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - BORDER_HEIGHT - 1);
gDPPipeSync(gDisplayListHead++);
gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
}
void clear_viewport(Vp *viewport, s32 color) {
s16 vpUlx = (viewport->vp.vtrans[0] - viewport->vp.vscale[0]) / 4 + 1;
s16 vpUly = (viewport->vp.vtrans[1] - viewport->vp.vscale[1]) / 4 + 1;
s16 vpLrx = (viewport->vp.vtrans[0] + viewport->vp.vscale[0]) / 4 - 2;
s16 vpLry = (viewport->vp.vtrans[1] + viewport->vp.vscale[1]) / 4 - 2;
#ifdef WIDESCREEN
if (configAspectRatio != 1) {
vpUlx = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(vpUlx);
vpLrx = GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(SCREEN_WIDTH - vpLrx);
}
#endif
gDPPipeSync(gDisplayListHead++);
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
gDPSetFillColor(gDisplayListHead++, color);
gDPFillRectangle(gDisplayListHead++, vpUlx, vpUly, vpLrx, vpLry);
gDPPipeSync(gDisplayListHead++);
gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
}
void draw_screen_borders(void) {
gDPPipeSync(gDisplayListHead++);
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(0, 0, 0, 0) << 16 | GPACK_RGBA5551(0, 0, 0, 0));
#if BORDER_HEIGHT != 0
gDPFillRectangle(gDisplayListHead++, GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), 0,
GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, BORDER_HEIGHT - 1);
gDPFillRectangle(gDisplayListHead++,
GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), SCREEN_HEIGHT - BORDER_HEIGHT,
GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - 1);
#endif
}
void make_viewport_clip_rect(Vp *viewport) {
s16 vpUlx = (viewport->vp.vtrans[0] - viewport->vp.vscale[0]) / 4 + 1;
s16 vpPly = (viewport->vp.vtrans[1] - viewport->vp.vscale[1]) / 4 + 1;
s16 vpLrx = (viewport->vp.vtrans[0] + viewport->vp.vscale[0]) / 4 - 1;
s16 vpLry = (viewport->vp.vtrans[1] + viewport->vp.vscale[1]) / 4 - 1;
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, vpUlx, vpPly, vpLrx, vpLry);
}
void create_gfx_task_structure(void) {
s32 entries = gDisplayListHead - gGfxPool->buffer;
gGfxSPTask->msgqueue = &gGfxVblankQueue;
gGfxSPTask->msg = (OSMesg) 2;
gGfxSPTask->task.t.type = M_GFXTASK;
#ifdef TARGET_N64
gGfxSPTask->task.t.ucode_boot = rspF3DBootStart;
gGfxSPTask->task.t.ucode_boot_size = ((u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart);
gGfxSPTask->task.t.flags = 0;
gGfxSPTask->task.t.ucode = rspF3DStart;
gGfxSPTask->task.t.ucode_data = rspF3DDataStart;
#endif
gGfxSPTask->task.t.ucode_size = SP_UCODE_SIZE;
gGfxSPTask->task.t.ucode_data_size = SP_UCODE_DATA_SIZE;
gGfxSPTask->task.t.dram_stack = (u64 *) gGfxSPTaskStack;
gGfxSPTask->task.t.dram_stack_size = SP_DRAM_STACK_SIZE8;
gGfxSPTask->task.t.output_buff = gGfxSPTaskOutputBuffer;
gGfxSPTask->task.t.output_buff_size =
(u64 *)((u8 *) gGfxSPTaskOutputBuffer + sizeof(gGfxSPTaskOutputBuffer));
gGfxSPTask->task.t.data_ptr = (u64 *) &gGfxPool->buffer;
gGfxSPTask->task.t.data_size = entries * sizeof(Gfx);
gGfxSPTask->task.t.yield_data_ptr = (u64 *) gGfxSPTaskYieldBuffer;
gGfxSPTask->task.t.yield_data_size = OS_YIELD_DATA_SIZE;
}
void init_rcp(void) {
move_segment_table_to_dmem();
init_rdp();
init_rsp();
init_z_buffer();
select_frame_buffer();
}
void end_master_display_list(void) {
draw_screen_borders();
if (gShowProfiler) {
draw_profiler();
}
gDPFullSync(gDisplayListHead++);
gSPEndDisplayList(gDisplayListHead++);
create_gfx_task_structure();
}
void draw_reset_bars(void) {
s32 width, height;
s32 fbNum;
u64 *fbPtr;
if (gResetTimer != 0 && gNmiResetBarsTimer < 15) {
if (sRenderedFramebuffer == 0) {
fbNum = 2;
} else {
fbNum = sRenderedFramebuffer - 1;
}
fbPtr = (u64 *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[fbNum]);
fbPtr += gNmiResetBarsTimer++ * (SCREEN_WIDTH / 4);
for (width = 0; width < ((SCREEN_HEIGHT / 16) + 1); width++) {
for (height = 0; height < (SCREEN_WIDTH / 4); height++) *fbPtr++ = 0;
fbPtr += ((SCREEN_WIDTH / 4) * 14);
}
}
osWritebackDCacheAll();
osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
}
#ifdef TARGET_N64
void render_init(void) {
gGfxPool = &gGfxPools[0];
set_segment_base_addr(1, gGfxPool->buffer);
gGfxSPTask = &gGfxPool->spTask;
gDisplayListHead = gGfxPool->buffer;
gGfxPoolEnd = (u8 *)(gGfxPool->buffer + GFX_POOL_SIZE);
init_rcp();
clear_frame_buffer(0);
end_master_display_list();
exec_display_list(&gGfxPool->spTask);
sRenderingFrameBuffer++;
gGlobalTimer++;
}
#endif
#ifdef USE_SYSTEM_MALLOC
Gfx **alloc_next_dl(void) {
u32 size = 10000;
Gfx *new_chunk = alloc_only_pool_alloc(gGfxAllocOnlyPool, size * sizeof(Gfx));
gSPBranchList(gDisplayListHeadInChunk++, new_chunk);
gDisplayListHeadInChunk = new_chunk;
gDisplayListEndInChunk = new_chunk + size;
return &gDisplayListHeadInChunk;
}
#endif
void select_gfx_pool(void) {
gGfxPool = &gGfxPools[gGlobalTimer % ARRAY_COUNT(gGfxPools)];
set_segment_base_addr(1, gGfxPool->buffer);
gGfxSPTask = &gGfxPool->spTask;
#ifdef USE_SYSTEM_MALLOC
gDisplayListHeadInChunk = gGfxPool->buffer;
gDisplayListEndInChunk = gDisplayListHeadInChunk + 1;
alloc_only_pool_clear(gGfxAllocOnlyPool);
#else
gDisplayListHead = gGfxPool->buffer;
gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
#endif
}
void display_and_vsync(void) {
profiler_log_thread5_time(BEFORE_DISPLAY_LISTS);
osRecvMesg(&gGfxVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
if (gGoddardVblankCallback != NULL) {
gGoddardVblankCallback();
gGoddardVblankCallback = NULL;
}
exec_display_list(&gGfxPool->spTask);
profiler_log_thread5_time(AFTER_DISPLAY_LISTS);
osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sRenderedFramebuffer]));
profiler_log_thread5_time(THREAD5_END);
osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
if (++sRenderedFramebuffer == 3) {
sRenderedFramebuffer = 0;
}
if (++sRenderingFrameBuffer == 3) {
sRenderingFrameBuffer = 0;
}
gGlobalTimer++;
}
UNUSED static void record_demo(void) {
u8 buttonMask =
((gPlayer1Controller->buttonDown & (A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON)) >> 8)
| (gPlayer1Controller->buttonDown & (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS));
s8 rawStickX = gPlayer1Controller->rawStickX;
s8 rawStickY = gPlayer1Controller->rawStickY;
if (rawStickX > -8 && rawStickX < 8) {
rawStickX = 0;
}
if (rawStickY > -8 && rawStickY < 8) {
rawStickY = 0;
}
if (gRecordedDemoInput.timer == 0xFF || buttonMask != gRecordedDemoInput.buttonMask
|| rawStickX != gRecordedDemoInput.rawStickX || rawStickY != gRecordedDemoInput.rawStickY) {
gRecordedDemoInput.timer = 0;
gRecordedDemoInput.buttonMask = buttonMask;
gRecordedDemoInput.rawStickX = rawStickX;
gRecordedDemoInput.rawStickY = rawStickY;
}
gRecordedDemoInput.timer++;
}
void adjust_analog_stick(struct Controller *controller) {
UNUSED u8 pad[8];
controller->stickX = 0;
controller->stickY = 0;
controller->stick2X = 0;
controller->stick2Y = 0;
if (controller->rawStickX <= -8) {
controller->stickX = controller->rawStickX + 6;
}
if (controller->rawStickX >= 8) {
controller->stickX = controller->rawStickX - 6;
}
if (controller->rawStickY <= -8) {
controller->stickY = controller->rawStickY + 6;
}
if (controller->rawStickY >= 8) {
controller->stickY = controller->rawStickY - 6;
}
if (controller->rawStick2X <= -8) {
controller->stick2X = controller->rawStick2X + 6;
}
if (controller->rawStick2X >= 8) {
controller->stick2X = controller->rawStick2X - 6;
}
if (controller->rawStick2Y <= -8) {
controller->stick2Y = controller->rawStick2Y + 6;
}
if (controller->rawStick2Y >= 8) {
controller->stick2Y = controller->rawStick2Y - 6;
}
controller->stickMag =
sqrtf(controller->stickX * controller->stickX + controller->stickY * controller->stickY);
controller->stick2Mag =
sqrtf(controller->stick2X * controller->stick2X + controller->stick2Y * controller->stick2Y);
if (controller->stickMag > 64) {
controller->stickX *= 64 / controller->stickMag;
controller->stickY *= 64 / controller->stickMag;
controller->stickMag = 64;
}
if (controller->stick2Mag > 768) {
controller->stick2X *= 768 / controller->stick2Mag;
controller->stick2Y *= 768 / controller->stick2Mag;
controller->stick2Mag = 768;
}
}
void run_demo_inputs(void) {
gControllers[0].controllerData->button &= VALID_BUTTONS;
if (gCurrDemoInput != NULL) {
if (gControllers[1].controllerData != NULL) {
gControllers[1].controllerData->stick_x = 0;
gControllers[1].controllerData->stick_y = 0;
gControllers[1].controllerData->button = 0;
}
if (gCurrDemoInput->timer == 0) {
gControllers[0].controllerData->stick_x = 0;
gControllers[0].controllerData->stick_y = 0;
gControllers[0].controllerData->button = END_DEMO;
} else {
u16 startPushed = gControllers[0].controllerData->button & START_BUTTON;
gControllers[0].controllerData->stick_x = gCurrDemoInput->rawStickX;
gControllers[0].controllerData->stick_y = gCurrDemoInput->rawStickY;
gControllers[0].controllerData->button =
((gCurrDemoInput->buttonMask & 0xF0) << 8) + ((gCurrDemoInput->buttonMask & 0xF));
gControllers[0].controllerData->button |= startPushed;
if (--gCurrDemoInput->timer == 0) {
gCurrDemoInput++;
}
}
}
}
void read_controller_inputs(void) {
s32 i;
if (gControllerBits) {
osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
osContGetReadData(&gControllerPads[0]);
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
}
run_demo_inputs();
for (i = 0; i < 2; i++) {
struct Controller *controller = &gControllers[i];
if (controller->controllerData != NULL) {
controller->rawStickX = controller->controllerData->stick_x;
controller->rawStickY = controller->controllerData->stick_y;
if (configDpadControls && !configDebugMovementMode) {
controller->rawStickX += (((controller->buttonDown & R_JPAD) > 0) - ((controller->buttonDown & L_JPAD) > 0))*80;
controller->rawStickY += (((controller->buttonDown & U_JPAD) > 0) - ((controller->buttonDown & D_JPAD) > 0))*80;
}
controller->rawStick2X = controller->controllerData->stick2_x;
controller->rawStick2Y = controller->controllerData->stick2_y;
if (get_mirror()) {
controller->rawStickX *= -1;
controller->rawStick2X *= -1;
}
controller->buttonPressed = controller->controllerData->button
& (controller->controllerData->button ^ controller->buttonDown);
controller->buttonDown = controller->controllerData->button;
adjust_analog_stick(controller);
} else
{
controller->rawStickX = 0;
controller->rawStickY = 0;
controller->rawStick2X = 0;
controller->rawStick2Y = 0;
controller->buttonPressed = 0;
controller->buttonDown = 0;
controller->stickX = 0;
controller->stickY = 0;
controller->stick2X = 0;
controller->stick2Y = 0;
controller->stickMag = 0;
}
}
gPlayer3Controller->rawStickX = gPlayer1Controller->rawStickX;
gPlayer3Controller->rawStickY = gPlayer1Controller->rawStickY;
gPlayer3Controller->stickX = gPlayer1Controller->stickX;
gPlayer3Controller->stickY = gPlayer1Controller->stickY;
gPlayer3Controller->stickMag = gPlayer1Controller->stickMag;
gPlayer3Controller->buttonPressed = gPlayer1Controller->buttonPressed;
gPlayer3Controller->buttonDown = gPlayer1Controller->buttonDown;
}
void init_controllers(void) {
s16 port, cont;
gControllers[0].statusData = &gControllerStatuses[0];
gControllers[0].controllerData = &gControllerPads[0];
osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
gEepromProbe = osEepromProbe(&gSIEventMesgQueue);
for (cont = 0, port = 0; port < 4 && cont < 2; port++) {
if (gControllerBits & (1 << port)) {
#if ENABLE_RUMBLE
gControllers[cont].port = port;
#endif
gControllers[cont].statusData = &gControllerStatuses[port];
gControllers[cont++].controllerData = &gControllerPads[port];
}
}
}
void setup_game_memory(void) {
UNUSED u64 padding;
set_segment_base_addr(0, (void *) 0x80000000);
osCreateMesgQueue(&gGfxVblankQueue, gGfxMesgBuf, ARRAY_COUNT(gGfxMesgBuf));
osCreateMesgQueue(&gGameVblankQueue, gGameMesgBuf, ARRAY_COUNT(gGameMesgBuf));
gPhysicalZBuffer = VIRTUAL_TO_PHYSICAL(gZBuffer);
gPhysicalFrameBuffers[0] = VIRTUAL_TO_PHYSICAL(gFrameBuffer0);
gPhysicalFrameBuffers[1] = VIRTUAL_TO_PHYSICAL(gFrameBuffer1);
gPhysicalFrameBuffers[2] = VIRTUAL_TO_PHYSICAL(gFrameBuffer2);
gMarioAnimsMemAlloc = main_pool_alloc(0x4000, MEMORY_POOL_LEFT);
set_segment_base_addr(17, (void *) gMarioAnimsMemAlloc);
setup_dma_table_list(&gMarioAnimsBuf, gMarioAnims, gMarioAnimsMemAlloc);
gDemoInputsMemAlloc = main_pool_alloc(0x800, MEMORY_POOL_LEFT);
set_segment_base_addr(24, (void *) gDemoInputsMemAlloc);
setup_dma_table_list(&gDemoInputsBuf, gDemoInputs, gDemoInputsMemAlloc);
load_segment(0x10, _entrySegmentRomStart, _entrySegmentRomEnd, MEMORY_POOL_LEFT);
load_segment_decompress(2, _segment2_mio0SegmentRomStart, _segment2_mio0SegmentRomEnd);
}
#ifndef TARGET_N64
static struct LevelCommand *levelCommandAddr;
#endif
void thread5_game_loop(UNUSED void *arg) {
#ifdef TARGET_N64
struct LevelCommand *levelCommandAddr;
#endif
setup_game_memory();
#if ENABLE_RUMBLE
init_rumble_pak_scheduler_queue();
#endif
init_controllers();
#if ENABLE_RUMBLE
create_thread_6();
#endif
save_file_load_all();
set_vblank_handler(2, &gGameVblankHandler, &gGameVblankQueue, (OSMesg) 1);
levelCommandAddr = segmented_to_virtual(level_script_entry);
play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0);
set_sound_mode(save_file_get_sound_mode());
#ifdef TARGET_N64
render_init();
while (TRUE) {
#else
gGlobalTimer++;
}
void game_loop_one_iteration(void) {
#endif
if (gResetTimer) {
draw_reset_bars();
#ifdef TARGET_N64
continue;
#else
return;
#endif
}
profiler_log_thread5_time(THREAD5_START);
if (gControllerBits) {
#if ENABLE_RUMBLE
block_until_rumble_pak_free();
#endif
osContStartReadData(&gSIEventMesgQueue);
}
audio_game_loop_tick();
select_gfx_pool();
read_controller_inputs();
levelCommandAddr = level_script_execute(levelCommandAddr);
display_and_vsync();
if (gShowDebugText) {
#ifndef USE_SYSTEM_MALLOC
print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead);
#endif
}
#ifdef TARGET_N64
}
#endif
}