GUI: Support single-shot runs

This commit is contained in:
Extrems 2015-11-18 08:35:37 -05:00 committed by Jeffrey Pfau
parent 2725d6ed2f
commit 396d097db4
2 changed files with 175 additions and 171 deletions

View File

@ -129,7 +129,7 @@ void GBAGUIDeinit(struct GBAGUIRunner* runner) {
GBAContextDeinit(&runner->context);
}
void GBAGUIRunloop(struct GBAGUIRunner* runner) {
void GBAGUIRun(struct GBAGUIRunner* runner, const char* path) {
struct GBAGUIBackground drawState = {
.d = {
.draw = _drawState
@ -185,177 +185,170 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Reset game", .data = (void*) RUNNER_RESET };
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
while (true) {
char path[256];
if (!GUISelectFile(&runner->params, path, sizeof(path), 0)) {
break;
}
// TODO: Message box API
runner->params.drawStart();
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
runner->params.drawEnd();
if (!GBAContextLoadROM(&runner->context, path, true)) {
int i;
for (i = 0; i < 300; ++i) {
runner->params.drawStart();
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Load failed!");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
runner->params.drawEnd();
}
continue;
}
bool running = GBAContextStart(&runner->context);
if (runner->gameLoaded) {
runner->gameLoaded(runner);
}
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);
if (guiKeys & (1 << GUI_INPUT_CANCEL)) {
break;
}
if (guiKeys & (1 << GBA_GUI_INPUT_INCREASE_BRIGHTNESS)) {
if (runner->luminanceSource.luxLevel < 10) {
++runner->luminanceSource.luxLevel;
}
}
if (guiKeys & (1 << GBA_GUI_INPUT_DECREASE_BRIGHTNESS)) {
if (runner->luminanceSource.luxLevel > 0) {
--runner->luminanceSource.luxLevel;
}
}
if (guiKeys & (1 << GBA_GUI_INPUT_SCREEN_MODE) && runner->incrementScreenMode) {
runner->incrementScreenMode(runner);
}
uint16_t keys = runner->pollGameInput(runner);
if (runner->prepareForFrame) {
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) {
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrintf(runner->params.font, 0, GUIFontHeight(runner->params.font), GUI_TEXT_LEFT, 0x7FFFFFFF, "%.2f fps", runner->fps);
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
}
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));
}
}
}
}
if (runner->paused) {
runner->paused(runner);
}
GUIInvalidateKeys(&runner->params);
uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable!
struct GUIMenuItem* item;
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
if (reason == GUI_MENU_EXIT_ACCEPT) {
struct VFile* vf;
switch (((int) item->data) & RUNNER_COMMAND_MASK) {
case RUNNER_EXIT:
running = false;
keys = 0;
break;
case RUNNER_RESET:
GBAContextReset(&runner->context);
break;
case RUNNER_SAVE_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, true);
if (vf) {
GBASaveStateNamed(runner->context.gba, vf, SAVESTATE_SCREENSHOT);
vf->close(vf);
}
break;
case RUNNER_LOAD_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, false);
if (vf) {
GBALoadStateNamed(runner->context.gba, vf, SAVESTATE_SCREENSHOT);
vf->close(vf);
}
break;
case RUNNER_SCREENSHOT:
GBATakeScreenshot(runner->context.gba, 0);
break;
case RUNNER_CONFIG:
GBAGUIShowConfig(runner, runner->configExtra, runner->nConfigExtra);
GBAConfigGetIntValue(&runner->context.config, "frameskip", &runner->context.gba->video.frameskip);
break;
case RUNNER_CONTINUE:
break;
}
}
int frames = 0;
GUIPollInput(&runner->params, 0, &keys);
while (keys && frames < 30) {
++frames;
runner->params.drawStart();
runner->drawFrame(runner, true);
runner->params.drawEnd();
GUIPollInput(&runner->params, 0, &keys);
}
if (runner->unpaused) {
runner->unpaused(runner);
}
}
GBAContextStop(&runner->context);
if (runner->gameUnloaded) {
runner->gameUnloaded(runner);
}
GBAContextUnloadROM(&runner->context);
drawState.screenshotId = 0;
// TODO: Message box API
runner->params.drawStart();
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
runner->params.drawEnd();
if (!GBAContextLoadROM(&runner->context, path, true)) {
int i;
for (i = 0; i < 300; ++i) {
runner->params.drawStart();
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Load failed!");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
runner->params.drawEnd();
}
return;
}
bool running = GBAContextStart(&runner->context);
if (runner->gameLoaded) {
runner->gameLoaded(runner);
}
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);
if (guiKeys & (1 << GUI_INPUT_CANCEL)) {
break;
}
if (guiKeys & (1 << GBA_GUI_INPUT_INCREASE_BRIGHTNESS)) {
if (runner->luminanceSource.luxLevel < 10) {
++runner->luminanceSource.luxLevel;
}
}
if (guiKeys & (1 << GBA_GUI_INPUT_DECREASE_BRIGHTNESS)) {
if (runner->luminanceSource.luxLevel > 0) {
--runner->luminanceSource.luxLevel;
}
}
if (guiKeys & (1 << GBA_GUI_INPUT_SCREEN_MODE) && runner->incrementScreenMode) {
runner->incrementScreenMode(runner);
}
uint16_t keys = runner->pollGameInput(runner);
if (runner->prepareForFrame) {
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) {
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrintf(runner->params.font, 0, GUIFontHeight(runner->params.font), GUI_TEXT_LEFT, 0x7FFFFFFF, "%.2f fps", runner->fps);
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
}
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));
}
}
}
}
if (runner->paused) {
runner->paused(runner);
}
GUIInvalidateKeys(&runner->params);
uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable!
struct GUIMenuItem* item;
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
if (reason == GUI_MENU_EXIT_ACCEPT) {
struct VFile* vf;
switch (((int) item->data) & RUNNER_COMMAND_MASK) {
case RUNNER_EXIT:
running = false;
keys = 0;
break;
case RUNNER_RESET:
GBAContextReset(&runner->context);
break;
case RUNNER_SAVE_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, true);
if (vf) {
GBASaveStateNamed(runner->context.gba, vf, SAVESTATE_SCREENSHOT);
vf->close(vf);
}
break;
case RUNNER_LOAD_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, false);
if (vf) {
GBALoadStateNamed(runner->context.gba, vf, SAVESTATE_SCREENSHOT);
vf->close(vf);
}
break;
case RUNNER_SCREENSHOT:
GBATakeScreenshot(runner->context.gba, 0);
break;
case RUNNER_CONFIG:
GBAGUIShowConfig(runner, runner->configExtra, runner->nConfigExtra);
GBAConfigGetIntValue(&runner->context.config, "frameskip", &runner->context.gba->video.frameskip);
break;
case RUNNER_CONTINUE:
break;
}
}
int frames = 0;
GUIPollInput(&runner->params, 0, &keys);
while (keys && frames < 30) {
++frames;
runner->params.drawStart();
runner->drawFrame(runner, true);
runner->params.drawEnd();
GUIPollInput(&runner->params, 0, &keys);
}
if (runner->unpaused) {
runner->unpaused(runner);
}
}
GBAContextStop(&runner->context);
if (runner->gameUnloaded) {
runner->gameUnloaded(runner);
}
GBAContextUnloadROM(&runner->context);
drawState.screenshotId = 0;
if (drawState.screenshot) {
mappedMemoryFree(drawState.screenshot, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4);
}
@ -363,3 +356,13 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
GUIMenuItemListDeinit(&stateSaveMenu.items);
GUIMenuItemListDeinit(&stateLoadMenu.items);
}
void GBAGUIRunloop(struct GBAGUIRunner* runner) {
while (true) {
char path[PATH_MAX];
if (!GUISelectFile(&runner->params, path, sizeof(path), GBAIsROM)) {
break;
}
GBAGUIRun(runner, path);
}
}

View File

@ -59,6 +59,7 @@ struct GBAGUIRunner {
void GBAGUIInit(struct GBAGUIRunner*, const char* port);
void GBAGUIDeinit(struct GBAGUIRunner*);
void GBAGUIRun(struct GBAGUIRunner*, const char* path);
void GBAGUIRunloop(struct GBAGUIRunner*);
#endif