GBA Context: Add fps counter and frameskip

This commit is contained in:
Jeffrey Pfau 2015-09-17 19:54:07 -07:00
parent c45315b96b
commit fafcfebf2e
5 changed files with 73 additions and 1 deletions

View File

@ -60,7 +60,7 @@ bool GBAContextInit(struct GBAContext* context, const char* port) {
GBAConfigLoadDefaults(&context->config, &opts);
}
context->gba->sync = 0;
context->gba->sync = &context->sync;
return true;
}
@ -191,6 +191,11 @@ void GBAContextFrame(struct GBAContext* context, uint16_t keys) {
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;
}
}
static void _GBAContextLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {

View File

@ -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 GBAContext {
struct GBAConfig config;
struct GBAOptions opts;
struct GBAInputMap inputMap;
struct GBASync sync;
};
bool GBAContextInit(struct GBAContext* context, const char* port);

View File

@ -16,6 +16,24 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
.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",

View File

@ -108,6 +108,10 @@ void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
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 @@ void GBAGUIDeinit(struct GBAGUIRunner* runner) {
if (runner->context.config.port) {
GBAConfigSave(&runner->context.config);
}
CircleBufferDeinit(&runner->fpsBuffer);
GBAContextDeinit(&runner->context);
}
@ -212,8 +217,16 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
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 @@ void GBAGUIRunloop(struct GBAGUIRunner* 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));
}
}
}
}

View File

@ -7,6 +7,7 @@
#define GUI_RUNNER_H
#include "gba/context/context.h"
#include "util/circle-buffer.h"
#include "util/gui.h"
enum GBAGUIInput {
@ -38,6 +39,11 @@ struct GBAGUIRunner {
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*);
void (*gameLoaded)(struct GBAGUIRunner*);