diff --git a/src/game/game.c b/src/game/game.c index ad800839..4a37549b 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -52,6 +52,47 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence u16 gDemoInputListID = 0; struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check +// SDK states that 1 cycle takes about 21.33 nanoseconds +#define SECONDS_PER_CYCLE 0.00000002133f + +#define FPS_COUNTER_X_POS 24 +#define FPS_COUNTER_Y_POS 190 + +static OSTime gLastOSTime = 0; +static float gFrameTime = 0.0f; +static u16 gFrames = 0; +static u16 gFPS = 0; +static u8 gRenderFPS = FALSE; + +static void calculate_frameTime_from_OSTime(OSTime diff) { + gFrameTime += diff * SECONDS_PER_CYCLE; + gFrames++; +} + +static void render_fps(void) { + // Toggle rendering framerate with the L button. + if (gPlayer1Controller->buttonPressed & L_TRIG) { + gRenderFPS ^= 1; + } + + if (gRenderFPS) { + OSTime newTime = osGetTime(); + + calculate_frameTime_from_OSTime(newTime - gLastOSTime); + + // If frame time is longer or equal to a second, update FPS counter. + if (gFrameTime >= 1.0f) { + gFPS = gFrames; + gFrames = 0; + gFrameTime -= 1.0f; + } + + print_text_fmt_int(FPS_COUNTER_X_POS, FPS_COUNTER_Y_POS, "FPS %d", gFPS); + + gLastOSTime = newTime; + } +} + // this function records distinct inputs over a 255-frame interval to RAM locations and was likely // used to record the demo sequences seen in the final game. This function is unused. static void record_demo(void) { @@ -334,5 +375,7 @@ void thread5_game_loop(UNUSED void *arg) { // amount of free space remaining. print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead); } + + render_fps(); } }