mirror of https://github.com/mgba-emu/mgba.git
GBA Context: Add fps counter and frameskip
This commit is contained in:
parent
c45315b96b
commit
fafcfebf2e
|
@ -60,7 +60,7 @@ bool GBAContextInit(struct GBAContext* context, const char* port) {
|
||||||
GBAConfigLoadDefaults(&context->config, &opts);
|
GBAConfigLoadDefaults(&context->config, &opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->gba->sync = 0;
|
context->gba->sync = &context->sync;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,11 @@ void GBAContextFrame(struct GBAContext* context, uint16_t keys) {
|
||||||
while (frameCounter == context->gba->video.frameCounter) {
|
while (frameCounter == context->gba->video.frameCounter) {
|
||||||
ARMRunLoop(context->cpu);
|
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) {
|
static void _GBAContextLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
#include "gba/context/config.h"
|
#include "gba/context/config.h"
|
||||||
|
#include "gba/context/sync.h"
|
||||||
#include "gba/input.h"
|
#include "gba/input.h"
|
||||||
|
|
||||||
struct GBAContext {
|
struct GBAContext {
|
||||||
|
@ -23,6 +24,7 @@ struct GBAContext {
|
||||||
struct GBAConfig config;
|
struct GBAConfig config;
|
||||||
struct GBAOptions opts;
|
struct GBAOptions opts;
|
||||||
struct GBAInputMap inputMap;
|
struct GBAInputMap inputMap;
|
||||||
|
struct GBASync sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool GBAContextInit(struct GBAContext* context, const char* port);
|
bool GBAContextInit(struct GBAContext* context, const char* port);
|
||||||
|
|
|
@ -16,6 +16,24 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
||||||
.background = &runner->background.d
|
.background = &runner->background.d
|
||||||
};
|
};
|
||||||
GUIMenuItemListInit(&menu.items, 0);
|
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) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Use BIOS if found",
|
.title = "Use BIOS if found",
|
||||||
.data = "useBios",
|
.data = "useBios",
|
||||||
|
|
|
@ -108,6 +108,10 @@ void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
|
||||||
runner->context.gba->luminanceSource = &runner->luminanceSource.d;
|
runner->context.gba->luminanceSource = &runner->luminanceSource.d;
|
||||||
runner->background.d.draw = _drawBackground;
|
runner->background.d.draw = _drawBackground;
|
||||||
runner->background.p = runner;
|
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) {
|
if (runner->setup) {
|
||||||
runner->setup(runner);
|
runner->setup(runner);
|
||||||
}
|
}
|
||||||
|
@ -120,6 +124,7 @@ void GBAGUIDeinit(struct GBAGUIRunner* runner) {
|
||||||
if (runner->context.config.port) {
|
if (runner->context.config.port) {
|
||||||
GBAConfigSave(&runner->context.config);
|
GBAConfigSave(&runner->context.config);
|
||||||
}
|
}
|
||||||
|
CircleBufferDeinit(&runner->fpsBuffer);
|
||||||
GBAContextDeinit(&runner->context);
|
GBAContextDeinit(&runner->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,8 +217,16 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
||||||
if (runner->gameLoaded) {
|
if (runner->gameLoaded) {
|
||||||
runner->gameLoaded(runner);
|
runner->gameLoaded(runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while (running) {
|
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) {
|
while (true) {
|
||||||
uint32_t guiKeys;
|
uint32_t guiKeys;
|
||||||
GUIPollInput(&runner->params, &guiKeys, 0);
|
GUIPollInput(&runner->params, &guiKeys, 0);
|
||||||
|
@ -239,9 +252,37 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
||||||
}
|
}
|
||||||
GBAContextFrame(&runner->context, keys);
|
GBAContextFrame(&runner->context, keys);
|
||||||
if (runner->drawFrame) {
|
if (runner->drawFrame) {
|
||||||
|
int drawFps = false;
|
||||||
|
GBAConfigGetIntValue(&runner->context.config, "fpsCounter", &drawFps);
|
||||||
|
|
||||||
runner->params.drawStart();
|
runner->params.drawStart();
|
||||||
runner->drawFrame(runner, false);
|
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();
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define GUI_RUNNER_H
|
#define GUI_RUNNER_H
|
||||||
|
|
||||||
#include "gba/context/context.h"
|
#include "gba/context/context.h"
|
||||||
|
#include "util/circle-buffer.h"
|
||||||
#include "util/gui.h"
|
#include "util/gui.h"
|
||||||
|
|
||||||
enum GBAGUIInput {
|
enum GBAGUIInput {
|
||||||
|
@ -38,6 +39,11 @@ struct GBAGUIRunner {
|
||||||
struct GUIMenuItem* configExtra;
|
struct GUIMenuItem* configExtra;
|
||||||
size_t nConfigExtra;
|
size_t nConfigExtra;
|
||||||
|
|
||||||
|
float fps;
|
||||||
|
int64_t lastFpsCheck;
|
||||||
|
int32_t totalDelta;
|
||||||
|
struct CircleBuffer fpsBuffer;
|
||||||
|
|
||||||
void (*setup)(struct GBAGUIRunner*);
|
void (*setup)(struct GBAGUIRunner*);
|
||||||
void (*teardown)(struct GBAGUIRunner*);
|
void (*teardown)(struct GBAGUIRunner*);
|
||||||
void (*gameLoaded)(struct GBAGUIRunner*);
|
void (*gameLoaded)(struct GBAGUIRunner*);
|
||||||
|
|
Loading…
Reference in New Issue