summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c475
1 files changed, 226 insertions, 249 deletions
diff --git a/src/main.c b/src/main.c
index f2a2a21ff..1435944b0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -117,7 +117,9 @@ u8 gControllerBits;
CollisionGrid gCollisionGrid[1024];
u16 gNumActors;
u16 gMatrixObjectCount;
-s32 gTickSpeed;
+s32 gTickLogic; // Tick game physics at 60fps
+s32 gTickVisuals; // Tick animations at 30fps
+s32 gTickGame;
f32 D_80150118;
u16 wasSoftReset;
@@ -146,7 +148,7 @@ u16* gPhysicalFramebuffers[3];
uintptr_t gPhysicalZBuffer;
UNUSED u32 D_801502B8;
UNUSED u32 D_801502BC;
-Mat4 D_801502C0;
+Mat4 sBillBoardMtx; // Faces 2D actors at the camera
s32 padding[2048];
@@ -483,7 +485,7 @@ void* clear_framebuffer(s32 color) {
void rendering_init(void) {
gGfxPool = &gGfxPools[0];
- set_segment_base_addr(1, gGfxPool);
+ set_segment_base_addr_x64(1, gGfxPool);
gGfxSPTask = &gGfxPool->spTask;
gDisplayListHead = gGfxPool->gfxPool;
init_rcp();
@@ -496,7 +498,7 @@ void rendering_init(void) {
void config_gfx_pool(void) {
gGfxPool = &gGfxPools[gGlobalTimer & 1];
- set_segment_base_addr(1, gGfxPool);
+ set_segment_base_addr_x64(1, gGfxPool);
gDisplayListHead = gGfxPool->gfxPool;
gGfxSPTask = &gGfxPool->spTask;
}
@@ -526,7 +528,9 @@ void display_and_vsync(void) {
if (++sRenderingFramebuffer == 3) {
sRenderingFramebuffer = 0;
}
- gGlobalTimer++;
+ if (gTickVisuals) {
+ gGlobalTimer++;
+ }
}
void init_segment_ending_sequences(void) {
@@ -625,12 +629,166 @@ void game_init_clear_framebuffer(void) {
clear_framebuffer(0);
}
-void race_logic_loop(void) {
- s16 i;
+void calculate_updaterate(void) {
+ static u32 prevtime = 0;
+ static u32 remainder = 0;
+ static u32 logicAccumulator = 0;
+ static u32 visualsAccumulator = 0;
+ static u32 frameCounter = 0; // For tracking frames for logic updates
+ u32 now = SDL_GetTicks(); // Replaces osGetTime()
+ u32 frameRate = 0;
+ s32 total;
+
+ // Get target FPS from configuration variable
+ s32 targetFPS = CVarGetInteger("gInterpolationFPS", 30);
+
+ if (targetFPS < 60) {
+ targetFPS = 30;
+ }
+
+ // Detect frame rate based on time passed
+ if (now > prevtime) {
+ total = (now - prevtime) + remainder;
+ } else {
+ // Handle counter reset (shouldn't happen with SDL_GetTicks, but kept for logic parity)
+ total = (0xffffffff - prevtime) + 1 + now + remainder;
+ }
+
+ prevtime = now;
+
+ // Avoid division by zero
+ if (total > 0) {
+ // Calculate approximate frame rate (milliseconds per frame)
+ frameRate = 1000 / total; // Frame rate in frames per second
+ } else {
+ frameRate = targetFPS; // Fallback to target FPS
+ }
+
+ // Default both to no updates
+ gTickLogic = 0;
+ gTickVisuals = 0;
+
+ // Calculate the update rates based on target FPS
+ s32 logicUpdateInterval = 1000 / 60; // Time in ms between logic updates
+ s32 visualsUpdateInterval = 1000 / 30; // 30 FPS for visuals
+
+ // Accumulate time for logic updates
+ logicAccumulator += total;
+ if (logicAccumulator >= logicUpdateInterval) {
+ logicAccumulator -= logicUpdateInterval; // Subtract full interval
+ if (targetFPS < 60) {
+ gTickLogic = 2;
+ } else {
+ gTickLogic = 1; // Perform logic update
+ }
+ }
+
+ // Visual updates (based on 30 FPS equivalent)
+ visualsAccumulator += total; // Increment for each frame
+ if (visualsAccumulator >= visualsUpdateInterval) { // Check if it's time to update visuals
+ visualsAccumulator -= visualsUpdateInterval;
+ gTickVisuals = 1; // Perform visual update
+ }
+}
+
+
+
+
+
+void display_debug_info(void) {
u16 rotY;
+ if (!gEnableDebugMode) {
+ D_800DC514 = false;
+ } else if (D_800DC514) {
+ if ((gControllerOne->buttonPressed & R_TRIG) &&
+ (gControllerOne->button & A_BUTTON) &&
+ (gControllerOne->button & B_BUTTON)) {
+ D_800DC514 = false;
+ }
+ rotY = camera1->rot[1];
+ gDebugPathCount = D_800DC5EC->pathCounter;
+
+ if (rotY < 0x2000) {
+ func_80057A50(40, 100, "SOUTH ", gDebugPathCount);
+ } else if (rotY < 0x6000) {
+ func_80057A50(40, 100, "EAST ", gDebugPathCount);
+ } else if (rotY < 0xA000) {
+ func_80057A50(40, 100, "NORTH ", gDebugPathCount);
+ } else if (rotY < 0xE000) {
+ func_80057A50(40, 100, "WEST ", gDebugPathCount);
+ } else {
+ func_80057A50(40, 100, "SOUTH ", gDebugPathCount);
+ }
+ } else if ((gControllerOne->buttonPressed & L_TRIG) &&
+ (gControllerOne->button & A_BUTTON) &&
+ (gControllerOne->button & B_BUTTON)) {
+ D_800DC514 = true;
+ }
+
+ if (!gEnableDebugMode) {
+ gEnableResourceMeters = 0;
+ } else {
+ if (gEnableResourceMeters) {
+ resource_display();
+ if (!(gControllerOne->button & L_TRIG) &&
+ (gControllerOne->button & R_TRIG) &&
+ (gControllerOne->buttonPressed & B_BUTTON)) {
+ gEnableResourceMeters = 0;
+ }
+ } else if (!(gControllerOne->button & L_TRIG) &&
+ (gControllerOne->button & R_TRIG) &&
+ (gControllerOne->buttonPressed & B_BUTTON)) {
+ gEnableResourceMeters = 1;
+ }
+ }
+}
+
+void process_game_tick(void) {
+ if (D_8015011E) {
+ gCourseTimer += COURSE_TIMER_ITER;
+ }
+ func_802909F0();
+ evaluate_collision_for_players_and_actors();
+ func_800382DC();
+ func_8001EE98(gPlayerOneCopy, camera1, 0);
+
+ switch(gActiveScreenMode) {
+ case SCREEN_MODE_1P:
+ func_80028F70();
+ break;
+ case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
+ case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
+ func_80029060();
+ func_8001EE98(gPlayerTwoCopy, camera2, 1);
+ func_80029150();
+ break;
+ case SCREEN_MODE_3P_4P_SPLITSCREEN:
+ func_80029158();
+ func_8001EE98(gPlayerTwo, camera2, 1);
+ func_800291E8();
+ func_8001EE98(gPlayerThree, camera3, 2);
+ func_800291F0();
+ func_8001EE98(gPlayerFour, camera4, 3);
+ func_800291F8();
+ break;
+ }
+
+ func_8028F474();
+ func_80059AC8();
+ update_course_actors();
+ CourseManager_TickActors();
+ func_802966A0();
+ func_8028FCBC();
+}
+
+void race_logic_loop(void) {
+ ClearMatrixPools();
+ ClearObjectsMatrixPool();
+ ClearEffectsMatrixPool();
gMatrixObjectCount = 0;
gMatrixEffectCount = 0;
+
if (gIsGamePaused != 0) {
func_80290B14();
}
@@ -645,276 +803,94 @@ void race_logic_loop(void) {
if (sNumVBlanks < 0) {
sNumVBlanks = 1;
}
- func_802A4EF4();
-
- switch (gActiveScreenMode) {
- case SCREEN_MODE_1P:
- gTickSpeed = 2;
- staff_ghosts_loop();
- // Wait for all racers to load
- if (gNetwork.enabled) {
- network_all_players_loaded();
- }
+ func_802A4EF4();
- if (gIsGamePaused == 0) {
- for (i = 0; i < gTickSpeed; i++) {
- if (D_8015011E) {
- gCourseTimer += COURSE_TIMER_ITER;
- }
- func_802909F0();
- evaluate_collision_for_players_and_actors();
- func_800382DC();
- func_8001EE98(gPlayerOneCopy, camera1, 0);
- func_80028F70();
- func_8028F474();
- func_80059AC8();
- update_course_actors();
- CourseManager_TickActors();
- func_802966A0();
- func_8028FCBC();
- }
- func_80022744();
- }
- func_8005A070();
- sNumVBlanks = 0;
- profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE);
- D_8015F788 = 0;
- render_player_one_1p_screen();
- if (!gEnableDebugMode) {
- D_800DC514 = false;
- } else {
- if (D_800DC514) {
+ if (gModeSelection == TIME_TRIALS) {
+ staff_ghosts_loop();
+ }
- if ((gControllerOne->buttonPressed & R_TRIG) && (gControllerOne->button & A_BUTTON) &&
- (gControllerOne->button & B_BUTTON)) {
- D_800DC514 = false;
- }
+ // Wait for all racers to load
+ if (gNetwork.enabled) {
+ network_all_players_loaded();
+ }
- rotY = camera1->rot[1];
- gDebugPathCount = D_800DC5EC->pathCounter;
- if (rotY < 0x2000) {
- func_80057A50(40, 100, "SOUTH ", gDebugPathCount);
- } else if (rotY < 0x6000) {
- func_80057A50(40, 100, "EAST ", gDebugPathCount);
- } else if (rotY < 0xA000) {
- func_80057A50(40, 100, "NORTH ", gDebugPathCount);
- } else if (rotY < 0xE000) {
- func_80057A50(40, 100, "WEST ", gDebugPathCount);
- } else {
- func_80057A50(40, 100, "SOUTH ", gDebugPathCount);
- }
+ if (gIsGamePaused == 0) {
+ for (size_t i = 0; i < gTickLogic; i++) {
+ process_game_tick();
+ }
+ func_80022744();
+ }
+ func_8005A070();
+ profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE);
+ sNumVBlanks = 0;
+ gNumScreens = 0;
+ move_segment_table_to_dmem();
+ init_rdp();
+ if (D_800DC5B0 != 0) {
+ select_framebuffer();
+ }
- } else {
- if ((gControllerOne->buttonPressed & L_TRIG) && (gControllerOne->button & A_BUTTON) &&
- (gControllerOne->button & B_BUTTON)) {
- D_800DC514 = true;
- }
- }
- }
+ switch(gActiveScreenMode) {
+ case SCREEN_MODE_1P:
+ render_screens(RENDER_SCREEN_MODE_1P_PLAYER_ONE, 0, 0);
break;
-
- case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
- if (GetCourse() == GetDkJungle()) {
- gTickSpeed = 3;
- } else {
- gTickSpeed = 2;
- }
- if (gIsGamePaused == 0) {
- for (i = 0; i < gTickSpeed; i++) {
- if (D_8015011E != 0) {
- gCourseTimer += COURSE_TIMER_ITER;
- }
- func_802909F0();
- evaluate_collision_for_players_and_actors();
- func_800382DC();
- func_8001EE98(gPlayerOneCopy, camera1, 0);
- func_80029060();
- func_8001EE98(gPlayerTwoCopy, camera2, 1);
- func_80029150();
- func_8028F474();
- func_80059AC8();
- update_course_actors();
- func_802966A0();
- func_8028FCBC();
- }
- func_80022744();
- }
- func_8005A070();
- profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE);
- sNumVBlanks = 0;
- move_segment_table_to_dmem();
- init_rdp();
- if (D_800DC5B0 != 0) {
- select_framebuffer();
- }
- D_8015F788 = 0;
+ case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
if (gPlayerWinningIndex == 0) {
- render_player_two_2p_screen_vertical();
- render_player_one_2p_screen_vertical();
+ // In VS Mode the winning player's viewport takes over the whole screen.
+ // Rendering the winning player last places their screen above the other screens
+ render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 1, 1);
+ render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 0, 0);
} else {
- render_player_one_2p_screen_vertical();
- render_player_two_2p_screen_vertical();
+ render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_ONE, 0, 0);
+ render_screens(RENDER_SCREEN_MODE_2P_HORIZONTAL_PLAYER_TWO, 1, 1);
}
break;
-
- case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
-
- if (GetCourse() == GetDkJungle()) {
- gTickSpeed = 3;
- } else {
- gTickSpeed = 2;
- }
-
- if (gIsGamePaused == 0) {
- for (i = 0; i < gTickSpeed; i++) {
- if (D_8015011E != 0) {
- gCourseTimer += COURSE_TIMER_ITER;
- }
- func_802909F0();
- evaluate_collision_for_players_and_actors();
- func_800382DC();
- func_8001EE98(gPlayerOneCopy, camera1, 0);
- func_80029060();
- func_8001EE98(gPlayerTwoCopy, camera2, 1);
- func_80029150();
- func_8028F474();
- func_80059AC8();
- update_course_actors();
- func_802966A0();
- func_8028FCBC();
- }
- func_80022744();
- }
- profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE);
- sNumVBlanks = (u16) 0;
- func_8005A070();
- move_segment_table_to_dmem();
- init_rdp();
- if (D_800DC5B0 != 0) {
- select_framebuffer();
- }
- D_8015F788 = 0;
+ case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
if (gPlayerWinningIndex == 0) {
- render_player_two_2p_screen_horizontal();
- render_player_one_2p_screen_horizontal();
+ render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 1, 1);
+ render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 0, 0);
} else {
- render_player_one_2p_screen_horizontal();
- render_player_two_2p_screen_horizontal();
+ render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_ONE, 0, 0);
+ render_screens(RENDER_SCREEN_MODE_2P_VERTICAL_PLAYER_TWO, 1, 1);
}
-
break;
-
case SCREEN_MODE_3P_4P_SPLITSCREEN:
- if (gPlayerCountSelection1 == 3) {
- switch (gCurrentCourseId) {
- case COURSE_BOWSER_CASTLE:
- case COURSE_MOO_MOO_FARM:
- case COURSE_SKYSCRAPER:
- case COURSE_DK_JUNGLE:
- gTickSpeed = 3;
- break;
- default:
- gTickSpeed = 2;
- break;
- }
- } else {
- // Four players
- switch (gCurrentCourseId) {
- case COURSE_BLOCK_FORT:
- case COURSE_DOUBLE_DECK:
- case COURSE_BIG_DONUT:
- gTickSpeed = 2;
- break;
- case COURSE_DK_JUNGLE:
- gTickSpeed = 4;
- break;
- default:
- gTickSpeed = 3;
- break;
- }
- }
- if (gIsGamePaused == 0) {
- for (i = 0; i < gTickSpeed; i++) {
- if (D_8015011E != 0) {
- gCourseTimer += COURSE_TIMER_ITER;
- }
- func_802909F0();
- evaluate_collision_for_players_and_actors();
- func_800382DC();
- func_8001EE98(gPlayerOneCopy, camera1, 0);
- func_80029158();
- func_8001EE98(gPlayerTwo, camera2, 1);
- func_800291E8();
- func_8001EE98(gPlayerThree, camera3, 2);
- func_800291F0();
- func_8001EE98(gPlayerFour, camera4, 3);
- func_800291F8();
- func_8028F474();
- func_80059AC8();
- update_course_actors();
- func_802966A0();
- func_8028FCBC();
- }
- func_80022744();
- }
- func_8005A070();
- sNumVBlanks = 0;
- profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE);
- move_segment_table_to_dmem();
- init_rdp();
- if (D_800DC5B0 != 0) {
- select_framebuffer();
- }
- D_8015F788 = 0;
if (gPlayerWinningIndex == 0) {
- render_player_two_3p_4p_screen();
- render_player_three_3p_4p_screen();
- render_player_four_3p_4p_screen();
- render_player_one_3p_4p_screen();
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
} else if (gPlayerWinningIndex == 1) {
- render_player_one_3p_4p_screen();
- render_player_three_3p_4p_screen();
- render_player_four_3p_4p_screen();
- render_player_two_3p_4p_screen();
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
} else if (gPlayerWinningIndex == 2) {
- render_player_one_3p_4p_screen();
- render_player_two_3p_4p_screen();
- render_player_four_3p_4p_screen();
- render_player_three_3p_4p_screen();
+
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
} else {
- render_player_one_3p_4p_screen();
- render_player_two_3p_4p_screen();
- render_player_three_3p_4p_screen();
- render_player_four_3p_4p_screen();
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_ONE, 0, 0);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_TWO, 1, 1);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_THREE, 2, 2);
+ render_screens(RENDER_SCREEN_MODE_3P_4P_PLAYER_FOUR, 3, 3);
}
break;
}
- if (!gEnableDebugMode) {
- gEnableResourceMeters = 0;
- } else {
- if (gEnableResourceMeters) {
- resource_display();
- if ((!(gControllerOne->button & L_TRIG)) && (gControllerOne->button & R_TRIG) &&
- (gControllerOne->buttonPressed & B_BUTTON)) {
- gEnableResourceMeters = 0;
- }
- } else {
- if ((!(gControllerOne->button & L_TRIG)) && (gControllerOne->button & R_TRIG) &&
- (gControllerOne->buttonPressed & B_BUTTON)) {
- gEnableResourceMeters = 1;
- }
- }
- }
+ display_debug_info();
+
func_802A4300();
func_800591B4();
func_80093E20();
#if DVDL
display_dvdl();
#endif
- // gDPFullSync(gDisplayListHead++);
- // gSPEndDisplayList(gDisplayListHead++);
+ gDPFullSync(gDisplayListHead++);
+ gSPEndDisplayList(gDisplayListHead++);
}
/**
@@ -1265,6 +1241,7 @@ void thread5_iteration(void) {
}
#endif
+ calculate_updaterate();
if (GfxDebuggerIsDebugging()) {
Graphics_PushFrame(gGfxPool->gfxPool);
return;
@@ -1280,7 +1257,7 @@ void thread5_iteration(void) {
read_controllers();
game_state_handler();
- call_render_hook();
+ //call_render_hook();
end_master_display_list();
display_and_vsync();