Advertisement
Guest User

src/game/game_init.m

a guest
Jun 4th, 2023
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <ultra64.h>
  2. #import <Foundation/Foundation.h>
  3.  
  4. #include "sm64.h"
  5. #include "data/dynos.c.h"
  6. #include "gfx_dimensions.h"
  7. #include "audio/external.h"
  8. #include "buffers/buffers.h"
  9. #include "gfx_dimensions.h"
  10. #include "buffers/gfx_output_buffer.h"
  11. #include "buffers/framebuffers.h"
  12. #include "buffers/zbuffer.h"
  13. #include "engine/level_script.h"
  14. #include "game_init.h"
  15. #include "main.h"
  16. #include "memory.h"
  17. #include "profiler.h"
  18. #include "save_file.h"
  19. #include "seq_ids.h"
  20. #include "sound_init.h"
  21. #include "print.h"
  22. #include "segment2.h"
  23. #include "segment_symbols.h"
  24. #include "thread6.h"
  25. #include <prevent_bss_reordering.h>
  26. #ifdef BETTERCAMERA
  27. #include "bettercamera.h"
  28. #endif
  29.  
  30. // FIXME: I'm not sure all of these variables belong in this file, but I don't
  31. // know of a good way to split them
  32. struct Controller gControllers[3];
  33. struct SPTask *gGfxSPTask;
  34. Gfx *gDisplayListHead;
  35. u8 *gGfxPoolEnd;
  36. struct GfxPool *gGfxPool;
  37. OSContStatus gControllerStatuses[4];
  38. OSContPad gControllerPads[4];
  39. u8 gControllerBits;
  40. s8 gEepromProbe;
  41. OSMesgQueue gGameVblankQueue;
  42. OSMesgQueue D_80339CB8;
  43. OSMesg D_80339CD0;
  44. OSMesg D_80339CD4;
  45. struct VblankHandler gGameVblankHandler;
  46. uintptr_t gPhysicalFrameBuffers[3];
  47. uintptr_t gPhysicalZBuffer;
  48. void *D_80339CF0;
  49. void *D_80339CF4;
  50. struct MarioAnimation D_80339D10;
  51. struct MarioAnimation gDemo;
  52. UNUSED u8 filler80339D30[0x90];
  53.  
  54. int unused8032C690 = 0;
  55. u32 gGlobalTimer = 0;
  56.  
  57. static u16 sCurrFBNum = 0;
  58. u16 frameBufferIndex = 0;
  59. void (*D_8032C6A0)(void) = NULL;
  60. struct Controller *gPlayer1Controller = &gControllers[0];
  61. struct Controller *gPlayer2Controller = &gControllers[1];
  62. // probably debug only, see note below
  63. struct Controller *gPlayer3Controller = &gControllers[2];
  64. struct DemoInput *gCurrDemoInput = NULL; // demo input sequence
  65. u16 gDemoInputListID = 0;
  66. struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check
  67. bool simulatedStartFlag = false;
  68.  
  69. /**
  70.  * Initializes the Reality Display Processor (RDP).
  71.  * This function initializes settings such as texture filtering mode,
  72.  * scissoring, and render mode (although keep in mind that this render
  73.  * mode is not used in-game, where it is set in render_graph_node.c).
  74.  */
  75. void my_rdp_init(void) {
  76.     gDPPipeSync(gDisplayListHead++);
  77.     gDPPipelineMode(gDisplayListHead++, G_PM_1PRIMITIVE);
  78.  
  79.     gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  80.     gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
  81.  
  82.     gDPSetTextureLOD(gDisplayListHead++, G_TL_TILE);
  83.     gDPSetTextureLUT(gDisplayListHead++, G_TT_NONE);
  84.     gDPSetTextureDetail(gDisplayListHead++, G_TD_CLAMP);
  85.     gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
  86.     gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
  87.     gDPSetTextureConvert(gDisplayListHead++, G_TC_FILT);
  88.  
  89.     gDPSetCombineKey(gDisplayListHead++, G_CK_NONE);
  90.     gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
  91.     gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
  92.     gDPSetColorDither(gDisplayListHead++, G_CD_MAGICSQ);
  93.     gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
  94.  
  95. #ifdef VERSION_SH
  96.     gDPSetAlphaDither(gDisplayListHead++, G_AD_PATTERN);
  97. #endif
  98.     gDPPipeSync(gDisplayListHead++);
  99. }
  100.  
  101. /**
  102.  * Initializes the RSP's built-in geometry and lighting engines.
  103.  * Most of these (with the notable exception of gSPNumLights), are
  104.  * almost immediately overwritten.
  105.  */
  106. void my_rsp_init(void) {
  107.     gSPClearGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CULL_BOTH | G_FOG
  108.                         | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD);
  109.  
  110.     gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CULL_BACK | G_LIGHTING);
  111.  
  112.     gSPNumLights(gDisplayListHead++, NUMLIGHTS_1);
  113.     gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
  114.  
  115.     // @bug Nintendo did not explicitly define the clipping ratio.
  116.     // For Fast3DEX2, this causes the dreaded warped vertices issue
  117.     // unless the clipping ratio is changed back to the intended value,
  118.     // as Fast3DEX2 uses a different initial value than Fast3D(EX).
  119. #ifdef F3DEX_GBI_2
  120.     gSPClipRatio(gDisplayListHead++, FRUSTRATIO_1);
  121. #endif
  122. }
  123.  
  124. /** Clear the Z buffer. */
  125. void clear_z_buffer(void) {
  126.     gDPPipeSync(gDisplayListHead++);
  127.  
  128.     gDPSetDepthSource(gDisplayListHead++, G_ZS_PIXEL);
  129.     gDPSetDepthImage(gDisplayListHead++, gPhysicalZBuffer);
  130.  
  131.     gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH, gPhysicalZBuffer);
  132.     gDPSetFillColor(gDisplayListHead++,
  133.                     GPACK_ZDZ(G_MAXFBZ, 0) << 16 | GPACK_ZDZ(G_MAXFBZ, 0));
  134.  
  135.     gDPFillRectangle(gDisplayListHead++, 0, BORDER_HEIGHT, SCREEN_WIDTH - 1,
  136.                      SCREEN_HEIGHT - 1 - BORDER_HEIGHT);
  137. }
  138.  
  139. /** Sets up the final framebuffer image. */
  140. void display_frame_buffer(void) {
  141.     gDPPipeSync(gDisplayListHead++);
  142.  
  143.     gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
  144.     gDPSetColorImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH,
  145.                      gPhysicalFrameBuffers[frameBufferIndex]);
  146.     gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
  147.                   SCREEN_HEIGHT - BORDER_HEIGHT);
  148. }
  149.  
  150. /** Clears the framebuffer, allowing it to be overwritten. */
  151. void clear_frame_buffer(s32 color) {
  152.     gDPPipeSync(gDisplayListHead++);
  153.  
  154.     gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
  155.     gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
  156.  
  157.     gDPSetFillColor(gDisplayListHead++, color);
  158.     gDPFillRectangle(gDisplayListHead++,
  159.                      GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), BORDER_HEIGHT,
  160.                      GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - BORDER_HEIGHT - 1);
  161.  
  162.     gDPPipeSync(gDisplayListHead++);
  163.  
  164.     gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
  165. }
  166.  
  167. /** Clears and initializes the viewport. */
  168. void clear_viewport(Vp *viewport, s32 color) {
  169.     s16 vpUlx = (viewport->vp.vtrans[0] - viewport->vp.vscale[0]) / 4 + 1;
  170.     s16 vpUly = (viewport->vp.vtrans[1] - viewport->vp.vscale[1]) / 4 + 1;
  171.     s16 vpLrx = (viewport->vp.vtrans[0] + viewport->vp.vscale[0]) / 4 - 2;
  172.     s16 vpLry = (viewport->vp.vtrans[1] + viewport->vp.vscale[1]) / 4 - 2;
  173.  
  174.     vpUlx = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(vpUlx);
  175.     vpLrx = GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(SCREEN_WIDTH - vpLrx);
  176.  
  177.     gDPPipeSync(gDisplayListHead++);
  178.  
  179.     gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
  180.     gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
  181.  
  182.     gDPSetFillColor(gDisplayListHead++, color);
  183.     gDPFillRectangle(gDisplayListHead++, vpUlx, vpUly, vpLrx, vpLry);
  184.  
  185.     gDPPipeSync(gDisplayListHead++);
  186.  
  187.     gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
  188. }
  189.  
  190. /** Draws the horizontal screen borders */
  191. void draw_screen_borders(void) {
  192.     gDPPipeSync(gDisplayListHead++);
  193.  
  194.     gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  195.     gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
  196.     gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
  197.  
  198.     gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(0, 0, 0, 0) << 16 | GPACK_RGBA5551(0, 0, 0, 0));
  199.  
  200. #if BORDER_HEIGHT != 0
  201.     gDPFillRectangle(gDisplayListHead++, GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), 0,
  202.                      GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, BORDER_HEIGHT - 1);
  203.     gDPFillRectangle(gDisplayListHead++,
  204.                      GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), SCREEN_HEIGHT - BORDER_HEIGHT,
  205.                      GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - 1);
  206. #endif
  207. }
  208.  
  209. void make_viewport_clip_rect(Vp *viewport) {
  210.     s16 vpUlx = (viewport->vp.vtrans[0] - viewport->vp.vscale[0]) / 4 + 1;
  211.     s16 vpPly = (viewport->vp.vtrans[1] - viewport->vp.vscale[1]) / 4 + 1;
  212.     s16 vpLrx = (viewport->vp.vtrans[0] + viewport->vp.vscale[0]) / 4 - 1;
  213.     s16 vpLry = (viewport->vp.vtrans[1] + viewport->vp.vscale[1]) / 4 - 1;
  214.  
  215.     gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, vpUlx, vpPly, vpLrx, vpLry);
  216. }
  217.  
  218. /**
  219.  * Loads the F3D microcodes.
  220.  * Refer to this function if you would like to load
  221.  * other microcodes (i.e. S2DEX).
  222.  */
  223. void create_task_structure(void) {
  224.     s32 entries = gDisplayListHead - gGfxPool->buffer;
  225.  
  226.     gGfxSPTask->msgqueue = &D_80339CB8;
  227.     gGfxSPTask->msg = (OSMesg) 2;
  228.     gGfxSPTask->task.t.type = M_GFXTASK;
  229.  
  230.     gGfxSPTask->task.t.ucode_size = SP_UCODE_SIZE; // (this size is ignored)
  231.     gGfxSPTask->task.t.ucode_data_size = SP_UCODE_DATA_SIZE;
  232.     gGfxSPTask->task.t.dram_stack = (u64 *) gGfxSPTaskStack;
  233.     gGfxSPTask->task.t.dram_stack_size = SP_DRAM_STACK_SIZE8;
  234.     gGfxSPTask->task.t.output_buff = gGfxSPTaskOutputBuffer;
  235.     gGfxSPTask->task.t.output_buff_size =
  236.         (u64 *)((u8 *) gGfxSPTaskOutputBuffer + sizeof(gGfxSPTaskOutputBuffer));
  237.     gGfxSPTask->task.t.data_ptr = (u64 *) &gGfxPool->buffer;
  238.     gGfxSPTask->task.t.data_size = entries * sizeof(Gfx);
  239.     gGfxSPTask->task.t.yield_data_ptr = (u64 *) gGfxSPTaskYieldBuffer;
  240.     gGfxSPTask->task.t.yield_data_size = OS_YIELD_DATA_SIZE;
  241. }
  242.  
  243. /** Starts rendering the scene. */
  244. void init_render_image(void) {
  245.     move_segment_table_to_dmem();
  246.     my_rdp_init();
  247.     my_rsp_init();
  248.     clear_z_buffer();
  249.     display_frame_buffer();
  250. }
  251.  
  252. /** Ends the master display list. */
  253. void end_master_display_list(void) {
  254.     draw_screen_borders();
  255.     if (gShowProfiler) {
  256.         draw_profiler();
  257.     }
  258.  
  259.     gDPFullSync(gDisplayListHead++);
  260.     gSPEndDisplayList(gDisplayListHead++);
  261.  
  262.     create_task_structure();
  263. }
  264.  
  265. //void draw_reset_bars(void) { // TARGET_64 only
  266. // Stubbed. Only N64 target uses this
  267. // }
  268.  
  269. void rendering_init(void) {
  270.     gGfxPool = &gGfxPools[0];
  271.     set_segment_base_addr(1, gGfxPool->buffer);
  272.     gGfxSPTask = &gGfxPool->spTask;
  273.     gDisplayListHead = gGfxPool->buffer;
  274.     gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
  275.     init_render_image();
  276.     clear_frame_buffer(0);
  277.     end_master_display_list();
  278.     send_display_list(&gGfxPool->spTask);
  279.  
  280.     frameBufferIndex++;
  281.     gGlobalTimer++;
  282. }
  283.  
  284. void config_gfx_pool(void) {
  285.     gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS];
  286.     set_segment_base_addr(1, gGfxPool->buffer);
  287.     gGfxSPTask = &gGfxPool->spTask;
  288.     gDisplayListHead = gGfxPool->buffer;
  289.     gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
  290. }
  291.  
  292. /** Handles vsync. */
  293. void display_and_vsync(void) {
  294.     profiler_log_thread5_time(BEFORE_DISPLAY_LISTS);
  295.     osRecvMesg(&D_80339CB8, &D_80339BEC, OS_MESG_BLOCK);
  296.     if (D_8032C6A0 != NULL) {
  297.         D_8032C6A0();
  298.         D_8032C6A0 = NULL;
  299.     }
  300.     send_display_list(&gGfxPool->spTask);
  301.     profiler_log_thread5_time(AFTER_DISPLAY_LISTS);
  302.     osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
  303.     osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sCurrFBNum]));
  304.     profiler_log_thread5_time(THREAD5_END);
  305.     osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
  306.     if (++sCurrFBNum == 3) {
  307.         sCurrFBNum = 0;
  308.     }
  309.     if (++frameBufferIndex == 3) {
  310.         frameBufferIndex = 0;
  311.     }
  312.     gGlobalTimer++;
  313. }
  314.  
  315. // this function records distinct inputs over a 255-frame interval to RAM locations and was likely
  316. // used to record the demo sequences seen in the final game. This function is unused.
  317. static void record_demo(void) {
  318.     // record the player's button mask and current rawStickX and rawStickY.
  319.     u8 buttonMask =
  320.         ((gPlayer1Controller->buttonDown & (A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON)) >> 8)
  321.         | (gPlayer1Controller->buttonDown & (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS));
  322.     s8 rawStickX = gPlayer1Controller->rawStickX;
  323.     s8 rawStickY = gPlayer1Controller->rawStickY;
  324.  
  325.     // if the stick is in deadzone, set its value to 0 to
  326.     // nullify the effects. We do not record deadzone inputs.
  327.     if (rawStickX > -8 && rawStickX < 8) {
  328.         rawStickX = 0;
  329.     }
  330.  
  331.     if (rawStickY > -8 && rawStickY < 8) {
  332.         rawStickY = 0;
  333.     }
  334.  
  335.     // record the distinct input and timer so long as they
  336.     // are unique. If the timer hits 0xFF, reset the timer
  337.     // for the next demo input.
  338.     if (gRecordedDemoInput.timer == 0xFF || buttonMask != gRecordedDemoInput.buttonMask
  339.         || rawStickX != gRecordedDemoInput.rawStickX || rawStickY != gRecordedDemoInput.rawStickY) {
  340.         gRecordedDemoInput.timer = 0;
  341.         gRecordedDemoInput.buttonMask = buttonMask;
  342.         gRecordedDemoInput.rawStickX = rawStickX;
  343.         gRecordedDemoInput.rawStickY = rawStickY;
  344.     }
  345.     gRecordedDemoInput.timer++;
  346. }
  347.  
  348. // take the updated controller struct and calculate
  349. // the new x, y, and distance floats.
  350. void adjust_analog_stick(struct Controller *controller) {
  351.     UNUSED u8 pad[8];
  352.  
  353.     // reset the controller's x and y floats.
  354.     controller->stickX = 0;
  355.     controller->stickY = 0;
  356.  
  357.     // modulate the rawStickX and rawStickY to be the new f32 values by adding/subtracting 6.
  358.     if (controller->rawStickX <= -8) {
  359.         controller->stickX = controller->rawStickX + 6;
  360.     }
  361.  
  362.     if (controller->rawStickX >= 8) {
  363.         controller->stickX = controller->rawStickX - 6;
  364.     }
  365.  
  366.     if (controller->rawStickY <= -8) {
  367.         controller->stickY = controller->rawStickY + 6;
  368.     }
  369.  
  370.     if (controller->rawStickY >= 8) {
  371.         controller->stickY = controller->rawStickY - 6;
  372.     }
  373.  
  374.     // calculate f32 magnitude from the center by vector length.
  375.     controller->stickMag =
  376.         sqrtf(controller->stickX * controller->stickX + controller->stickY * controller->stickY);
  377.  
  378.     // magnitude cannot exceed 64.0f: if it does, modify the values appropriately to
  379.     // flatten the values down to the allowed maximum value.
  380.     if (controller->stickMag > 64) {
  381.         controller->stickX *= 64 / controller->stickMag;
  382.         controller->stickY *= 64 / controller->stickMag;
  383.         controller->stickMag = 64;
  384.     }
  385. }
  386.  
  387. // if a demo sequence exists, this will run the demo
  388. // input list until it is complete. called every frame.
  389. void run_demo_inputs(void) {
  390.     /*
  391.         Check if a demo inputs list
  392.         exists and if so, run the
  393.         active demo input list.
  394.     */
  395.     if (gCurrDemoInput != NULL) {
  396.         /*
  397.             clear player 2's inputs if they exist. Player 2's controller
  398.             cannot be used to influence a demo. At some point, Nintendo
  399.             may have planned for there to be a demo where 2 players moved
  400.             around instead of just one, so clearing player 2's influence from
  401.             the demo had to have been necessary to perform this. Co-op mode, perhaps?
  402.         */
  403.         if (gControllers[1].controllerData != NULL) {
  404.             gControllers[1].controllerData->stick_x = 0;
  405.             gControllers[1].controllerData->stick_y = 0;
  406.             gControllers[1].controllerData->button = 0;
  407.         }
  408.  
  409.         // the timer variable being 0 at the current input means the demo is over.
  410.         // set the button to the END_DEMO mask to end the demo.
  411.         if (gCurrDemoInput->timer == 0) {
  412.             gControllers[0].controllerData->stick_x = 0;
  413.             gControllers[0].controllerData->stick_y = 0;
  414.             gControllers[0].controllerData->button = END_DEMO;
  415.         } else {
  416.             // backup the start button if it is pressed, since we don't want the
  417.             // demo input to override the mask where start may have been pressed.
  418.             u16 startPushed = gControllers[0].controllerData->button & START_BUTTON;
  419.  
  420.             // perform the demo inputs by assigning the current button mask and the stick inputs.
  421.             gControllers[0].controllerData->stick_x = gCurrDemoInput->rawStickX;
  422.             gControllers[0].controllerData->stick_y = gCurrDemoInput->rawStickY;
  423.  
  424.             /*
  425.                 to assign the demo input, the button information is stored in
  426.                 an 8-bit mask rather than a 16-bit mask. this is because only
  427.                 A, B, Z, Start, and the C-Buttons are used in a demo, as bits
  428.                 in that order. In order to assign the mask, we need to take the
  429.                 upper 4 bits (A, B, Z, and Start) and shift then left by 8 to
  430.                 match the correct input mask. We then add this to the masked
  431.                 lower 4 bits to get the correct button mask.
  432.             */
  433.             gControllers[0].controllerData->button =
  434.                 ((gCurrDemoInput->buttonMask & 0xF0) << 8) + ((gCurrDemoInput->buttonMask & 0xF));
  435.  
  436.             // if start was pushed, put it into the demo sequence being input to
  437.             // end the demo.
  438.             gControllers[0].controllerData->button |= startPushed;
  439.  
  440.             // run the current demo input's timer down. if it hits 0, advance the
  441.             // demo input list.
  442.             if (--gCurrDemoInput->timer == 0) {
  443.                 gCurrDemoInput++;
  444.             }
  445.         }
  446.     }
  447. }
  448.  
  449. // update the controller struct with available inputs if present.
  450. void read_controller_inputs(void) {
  451.     s32 i;
  452.  
  453.     // if any controllers are plugged in, update the
  454.     // controller information.
  455.     if (gControllerBits) {
  456.         osRecvMesg(&gSIEventMesgQueue, &D_80339BEC, OS_MESG_BLOCK);
  457.         osContGetReadData(&gControllerPads[0]);
  458.         dynos_update_opt((void *) &gControllerPads[0]);
  459.         if(simulatedStartFlag) {
  460.             simulatedStartFlag = false;
  461.             gControllerPads[0].button |= START_BUTTON;
  462.         }
  463.     }
  464.     run_demo_inputs();
  465.  
  466.     for (i = 0; i < 2; i++) {
  467.         struct Controller *controller = &gControllers[i];
  468.  
  469.         // if we're receiving inputs, update the controller struct
  470.         // with the new button info.
  471.         if (controller->controllerData != NULL) {
  472.             controller->rawStickX = controller->controllerData->stick_x;
  473.             controller->rawStickY = controller->controllerData->stick_y;
  474.             controller->extStickX = controller->controllerData->ext_stick_x;
  475.             controller->extStickY = controller->controllerData->ext_stick_y;
  476.             controller->buttonPressed = controller->controllerData->button
  477.                                         & (controller->controllerData->button ^ controller->buttonDown);
  478.             // 0.5x A presses are a good meme
  479.             controller->buttonDown = controller->controllerData->button;
  480.             adjust_analog_stick(controller);
  481.         } else {
  482.             // otherwise, if the controllerData is NULL, 0 out all of the inputs.
  483.             controller->rawStickX = 0;
  484.             controller->rawStickY = 0;
  485.             controller->extStickX = 0;
  486.             controller->extStickY = 0;
  487.             controller->buttonPressed = 0;
  488.             controller->buttonDown = 0;
  489.             controller->stickX = 0;
  490.             controller->stickY = 0;
  491.             controller->stickMag = 0;
  492.         }
  493.     }
  494.  
  495.     // For some reason, player 1's inputs are copied to player 3's port. This
  496.     // potentially may have been a way the developers "recorded" the inputs
  497.     // for demos, despite record_demo existing.
  498.     gPlayer3Controller->rawStickX = gPlayer1Controller->rawStickX;
  499.     gPlayer3Controller->rawStickY = gPlayer1Controller->rawStickY;
  500.     gPlayer3Controller->stickX = gPlayer1Controller->stickX;
  501.     gPlayer3Controller->stickY = gPlayer1Controller->stickY;
  502.     gPlayer3Controller->stickMag = gPlayer1Controller->stickMag;
  503.     gPlayer3Controller->buttonPressed = gPlayer1Controller->buttonPressed;
  504.     gPlayer3Controller->buttonDown = gPlayer1Controller->buttonDown;
  505. }
  506.  
  507. void simulate_start_button_press(void) {
  508.     simulatedStartFlag = true;
  509. }
  510.  
  511. // initialize the controller structs to point at the OSCont information.
  512. void init_controllers(void) {
  513.     s16 port, cont;
  514.  
  515.     // set controller 1 to point to the set of status/pads for input 1 and
  516.     // init the controllers.
  517.     gControllers[0].statusData = &gControllerStatuses[0];
  518.     gControllers[0].controllerData = &gControllerPads[0];
  519.     osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
  520.  
  521.     // strangely enough, the EEPROM probe for save data is done in this function.
  522.     // save pak detection?
  523.     gEepromProbe = osEepromProbe(&gSIEventMesgQueue);
  524.  
  525.     // loop over the 4 ports and link the controller structs to the appropriate
  526.     // status and pad. Interestingly, although there are pointers to 3 controllers,
  527.     // only 2 are connected here. The third seems to have been reserved for debug
  528.     // purposes and was never connected in the retail ROM, thus gPlayer3Controller
  529.     // cannot be used, despite being referenced in various code.
  530.     for (cont = 0, port = 0; port < 4 && cont < 2; port++) {
  531.         // is controller plugged in?
  532.         if (gControllerBits & (1 << port)) {
  533.             // the game allows you to have just 1 controller plugged
  534.             // into any port in order to play the game. this was probably
  535.             // so if any of the ports didn't work, you can have controllers
  536.             // plugged into any of them and it will work.
  537.             gControllers[cont].port = port;
  538.             gControllers[cont].statusData = &gControllerStatuses[port];
  539.             gControllers[cont++].controllerData = &gControllerPads[port];
  540.         }
  541.     }
  542.  
  543. #ifdef BETTERCAMERA
  544.     // load bettercam settings from the config file
  545.     newcam_init_settings();
  546. #endif
  547. }
  548.  
  549. void setup_game_memory(void) {
  550.     UNUSED u8 pad[8];
  551.  
  552.     set_segment_base_addr(0, (void *) 0x80000000);
  553.     osCreateMesgQueue(&D_80339CB8, &D_80339CD4, 1);
  554.     osCreateMesgQueue(&gGameVblankQueue, &D_80339CD0, 1);
  555.     gPhysicalZBuffer = VIRTUAL_TO_PHYSICAL(gZBuffer);
  556.     gPhysicalFrameBuffers[0] = VIRTUAL_TO_PHYSICAL(gFrameBuffer0);
  557.     gPhysicalFrameBuffers[1] = VIRTUAL_TO_PHYSICAL(gFrameBuffer1);
  558.     gPhysicalFrameBuffers[2] = VIRTUAL_TO_PHYSICAL(gFrameBuffer2);
  559.     D_80339CF0 = main_pool_alloc(0x4000, MEMORY_POOL_LEFT);
  560.     set_segment_base_addr(17, (void *) D_80339CF0);
  561.     func_80278A78(&D_80339D10, gMarioAnims, D_80339CF0);
  562.     D_80339CF4 = main_pool_alloc(2048, MEMORY_POOL_LEFT);
  563.     set_segment_base_addr(24, (void *) D_80339CF4);
  564.     func_80278A78(&gDemo, gDemoInputs, D_80339CF4);
  565.     load_segment(0x10, _entrySegmentRomStart, _entrySegmentRomEnd, MEMORY_POOL_LEFT);
  566.     load_segment_decompress(2, _segment2_mio0SegmentRomStart, _segment2_mio0SegmentRomEnd);
  567. }
  568.  
  569.  
  570. static struct LevelCommand *levelCommandAddr;
  571.  
  572. // main game loop thread. runs forever as long as the game
  573. // continues.
  574. void thread5_game_loop(UNUSED void *arg) {
  575.  
  576.     setup_game_memory();
  577.     init_rumble_pak_scheduler_queue();
  578.     init_controllers();
  579.     create_thread_6();
  580.     save_file_load_all();
  581.  
  582.     set_vblank_handler(2, &gGameVblankHandler, &gGameVblankQueue, (OSMesg) 1);
  583.  
  584.     // point levelCommandAddr to the entry point into the level script data.
  585.     levelCommandAddr = segmented_to_virtual(level_script_entry);
  586.  
  587.     play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0);
  588.     set_sound_mode(save_file_get_sound_mode());
  589.  
  590.     gGlobalTimer++;
  591. }
  592.  
  593. void game_loop_one_iteration(void) {
  594.     profiler_log_thread5_time(THREAD5_START);
  595.  
  596.     // if any controllers are plugged in, start read the data for when
  597.     // read_controller_inputs is called later.
  598.     if (gControllerBits) {
  599.         // block_until_rumble_pak_free();
  600.         osContStartReadData(&gSIEventMesgQueue);
  601.     }
  602.  
  603.     audio_game_loop_tick();
  604.     config_gfx_pool();
  605.     read_controller_inputs();
  606.     levelCommandAddr = level_script_execute(levelCommandAddr);
  607.     display_and_vsync();
  608.    
  609.  
  610.     // when debug info is enabled, print the "BUF %d" information.
  611.     if (gShowDebugText) {
  612.         // subtract the end of the gfx pool with the display list to obtain the
  613.         // amount of free space remaining.
  614.         print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead);
  615.     }
  616. }
  617.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement