GBA Context: Add fps counter and frameskip
Jeffrey Pfau jeffrey@endrift.com
Thu, 17 Sep 2015 19:54:07 -0700
5 files changed,
73 insertions(+),
1 deletions(-)
M
src/gba/context/context.c
→
src/gba/context/context.c
@@ -60,7 +60,7 @@ GBAConfigLoad(&context->config);
GBAConfigLoadDefaults(&context->config, &opts); } - context->gba->sync = 0; + context->gba->sync = &context->sync; return true; }@@ -190,6 +190,11 @@
int frameCounter = context->gba->video.frameCounter; while (frameCounter == context->gba->video.frameCounter) { ARMRunLoop(context->cpu); + } + if (context->sync.videoFrameSkip < 0) { + int frameskip = 0; + GBAConfigGetIntValue(&context->config, "frameskip", &frameskip); + context->sync.videoFrameSkip = frameskip; } }
M
src/gba/context/context.h
→
src/gba/context/context.h
@@ -9,6 +9,7 @@
#include "util/common.h" #include "gba/context/config.h" +#include "gba/context/sync.h" #include "gba/input.h" struct GBAContext {@@ -23,6 +24,7 @@ struct ARMComponent* components[GBA_COMPONENT_MAX];
struct GBAConfig config; struct GBAOptions opts; struct GBAInputMap inputMap; + struct GBASync sync; }; bool GBAContextInit(struct GBAContext* context, const char* port);
M
src/gba/gui/gui-config.c
→
src/gba/gui/gui-config.c
@@ -17,6 +17,24 @@ .background = &runner->background.d
}; GUIMenuItemListInit(&menu.items, 0); *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Frameskip", + .data = "frameskip", + .submenu = 0, + .state = 0, + .validStates = (const char*[]) { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 0 + } + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Show framerate", + .data = "fpsCounter", + .submenu = 0, + .state = false, + .validStates = (const char*[]) { + "Off", "On", 0 + } + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { .title = "Use BIOS if found", .data = "useBios", .submenu = 0,
M
src/gba/gui/gui-runner.c
→
src/gba/gui/gui-runner.c
@@ -108,6 +108,10 @@ runner->luminanceSource.luxLevel = 0;
runner->context.gba->luminanceSource = &runner->luminanceSource.d; runner->background.d.draw = _drawBackground; runner->background.p = runner; + runner->fps = 0; + runner->lastFpsCheck = 0; + runner->totalDelta = 0; + CircleBufferInit(&runner->fpsBuffer, FPS_BUFFER_SIZE * sizeof(uint32_t)); if (runner->setup) { runner->setup(runner); }@@ -120,6 +124,7 @@ }
if (runner->context.config.port) { GBAConfigSave(&runner->context.config); } + CircleBufferDeinit(&runner->fpsBuffer); GBAContextDeinit(&runner->context); }@@ -212,8 +217,16 @@ GBAContextStart(&runner->context);
if (runner->gameLoaded) { runner->gameLoaded(runner); } + bool running = true; while (running) { + CircleBufferClear(&runner->fpsBuffer); + runner->totalDelta = 0; + runner->fps = 0; + struct timeval tv; + gettimeofday(&tv, 0); + runner->lastFpsCheck = 1000000LL * tv.tv_sec + tv.tv_usec; + while (true) { uint32_t guiKeys; GUIPollInput(&runner->params, &guiKeys, 0);@@ -239,9 +252,37 @@ runner->prepareForFrame(runner);
} GBAContextFrame(&runner->context, keys); if (runner->drawFrame) { + int drawFps = false; + GBAConfigGetIntValue(&runner->context.config, "fpsCounter", &drawFps); + runner->params.drawStart(); runner->drawFrame(runner, false); + if (drawFps) { + GUIFontPrintf(runner->params.font, 0, GUIFontHeight(runner->params.font), GUI_TEXT_LEFT, 0x7FFFFFFF, "%.2f fps", runner->fps); + } runner->params.drawEnd(); + + if (runner->context.gba->video.frameCounter % FPS_GRANULARITY == 0) { + if (drawFps) { + struct timeval tv; + gettimeofday(&tv, 0); + uint64_t t = 1000000LL * tv.tv_sec + tv.tv_usec; + uint64_t delta = t - runner->lastFpsCheck; + runner->lastFpsCheck = t; + if (delta > 0x7FFFFFFFLL) { + CircleBufferClear(&runner->fpsBuffer); + runner->fps = 0; + } + if (CircleBufferSize(&runner->fpsBuffer) == CircleBufferCapacity(&runner->fpsBuffer)) { + int32_t last; + CircleBufferRead32(&runner->fpsBuffer, &last); + runner->totalDelta -= last; + } + CircleBufferWrite32(&runner->fpsBuffer, delta); + runner->totalDelta += delta; + runner->fps = (CircleBufferSize(&runner->fpsBuffer) * FPS_GRANULARITY * 1000000.0f) / (runner->totalDelta * sizeof(uint32_t)); + } + } } }
M
src/gba/gui/gui-runner.h
→
src/gba/gui/gui-runner.h
@@ -7,6 +7,7 @@ #ifndef GUI_RUNNER_H
#define GUI_RUNNER_H #include "gba/context/context.h" +#include "util/circle-buffer.h" #include "util/gui.h" enum GBAGUIInput {@@ -37,6 +38,11 @@ struct GBAGUIRunnerLux luminanceSource;
struct GUIMenuItem* configExtra; size_t nConfigExtra; + + float fps; + int64_t lastFpsCheck; + int32_t totalDelta; + struct CircleBuffer fpsBuffer; void (*setup)(struct GBAGUIRunner*); void (*teardown)(struct GBAGUIRunner*);