GBA Context: Configuration options

This commit is contained in:
Jeffrey Pfau 2015-09-17 19:53:27 -07:00
parent 94ffa0d2d7
commit c45315b96b
11 changed files with 197 additions and 17 deletions

View File

@ -56,8 +56,8 @@ bool GBAContextInit(struct GBAContext* context, const char* port) {
.idleOptimization = IDLE_LOOP_DETECT,
.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS
};
GBAConfigLoadDefaults(&context->config, &opts);
GBAConfigLoad(&context->config);
GBAConfigLoadDefaults(&context->config, &opts);
}
context->gba->sync = 0;

89
src/gba/gui/gui-config.c Normal file
View File

@ -0,0 +1,89 @@
/* Copyright (c) 2013-2015 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gui-config.h"
#include "gba/gui/gui-runner.h"
#include "util/gui/file-select.h"
#include "util/gui/menu.h"
void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, size_t nExtra) {
struct GUIMenu menu = {
.title = "Configure",
.index = 0,
.background = &runner->background.d
};
GUIMenuItemListInit(&menu.items, 0);
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
.title = "Use BIOS if found",
.data = "useBios",
.submenu = 0,
.state = true,
.validStates = (const char*[]) {
"Off", "On", 0
}
};
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
.title = "Select BIOS path",
.data = "bios",
};
size_t i;
for (i = 0; i < nExtra; ++i) {
*GUIMenuItemListAppend(&menu.items) = extra[i];
}
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
.title = "Save",
.data = "[SAVE]",
};
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
.title = "Cancel",
.data = 0,
};
enum GUIMenuExitReason reason;
char biosPath[256] = "";
struct GUIMenuItem* item;
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
item = GUIMenuItemListGetPointer(&menu.items, i);
if (!item->validStates || !item->data) {
continue;
}
GBAConfigGetUIntValue(&runner->context.config, item->data, &item->state);
}
while (true) {
reason = GUIShowMenu(&runner->params, &menu, &item);
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
break;
}
if (!strcmp(item->data, "[SAVE]")) {
if (biosPath[0]) {
GBAConfigSetValue(&runner->context.config, "bios", biosPath);
}
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
item = GUIMenuItemListGetPointer(&menu.items, i);
if (!item->validStates || !item->data) {
continue;
}
GBAConfigSetUIntValue(&runner->context.config, item->data, item->state);
}
GBAConfigSave(&runner->context.config);
break;
}
if (!strcmp(item->data, "bios")) {
// TODO: show box if failed
if (!GUISelectFile(&runner->params, biosPath, sizeof(biosPath), GBAIsBIOS)) {
biosPath[0] = '\0';
}
continue;
}
if (item->validStates) {
++item->state;
if (!item->validStates[item->state]) {
item->state = 0;
}
}
}
}

15
src/gba/gui/gui-config.h Normal file
View File

@ -0,0 +1,15 @@
/* Copyright (c) 2013-2015 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GUI_CONFIG_H
#define GUI_CONFIG_H
#include "util/common.h"
struct GBAGUIRunner;
struct GUIMenuItem;
void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, size_t nExtra);
#endif

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gui-runner.h"
#include "gba/gui/gui-config.h"
#include "gba/interface.h"
#include "gba/serialize.h"
#include "util/gui/file-select.h"
@ -176,6 +177,7 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
*GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_9) };
#endif
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = (void*) RUNNER_SCREENSHOT };
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = (void*) RUNNER_CONFIG };
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
while (true) {
@ -248,24 +250,24 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
}
GUIInvalidateKeys(&runner->params);
uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable!
struct GUIMenuItem item;
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) {
switch (((int) item->data) & RUNNER_COMMAND_MASK) {
case RUNNER_EXIT:
running = false;
keys = 0;
break;
case RUNNER_SAVE_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item.data) >> 16, true);
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, true);
if (vf) {
GBASaveStateNamed(runner->context.gba, vf, true);
vf->close(vf);
}
break;
case RUNNER_LOAD_STATE:
vf = GBAGetState(runner->context.gba, 0, ((int) item.data) >> 16, false);
vf = GBAGetState(runner->context.gba, 0, ((int) item->data) >> 16, false);
if (vf) {
GBALoadStateNamed(runner->context.gba, vf);
vf->close(vf);
@ -274,6 +276,9 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
case RUNNER_SCREENSHOT:
GBATakeScreenshot(runner->context.gba, 0);
break;
case RUNNER_CONFIG:
GBAGUIShowConfig(runner, runner->configExtra, runner->nConfigExtra);
break;
case RUNNER_CONTINUE:
break;
}

View File

@ -35,6 +35,9 @@ struct GBAGUIRunner {
struct GBAGUIBackground background;
struct GBAGUIRunnerLux luminanceSource;
struct GUIMenuItem* configExtra;
size_t nConfigExtra;
void (*setup)(struct GBAGUIRunner*);
void (*teardown)(struct GBAGUIRunner*);
void (*gameLoaded)(struct GBAGUIRunner*);

View File

@ -11,6 +11,7 @@
#include "util/gui.h"
#include "util/gui/file-select.h"
#include "util/gui/font.h"
#include "util/gui/menu.h"
#include "util/memory.h"
#include "3ds-vfs.h"
@ -82,6 +83,11 @@ static void _setup(struct GBAGUIRunner* runner) {
renderer.outputBufferStride = 256;
runner->context.renderer = &renderer.d;
unsigned mode;
if (GBAConfigGetUIntValue(&runner->context.config, "screenMode", &mode) && mode < SM_MAX) {
screenMode = mode;
}
GBAAudioResizeBuffer(&runner->context.gba->audio, AUDIO_SAMPLES);
}
@ -235,7 +241,13 @@ static void _incrementScreenMode(struct GBAGUIRunner* runner) {
_drawEnd();
_drawStart();
_drawEnd();
screenMode = (screenMode + 1) % SM_MAX;
unsigned mode;
if (GBAConfigGetUIntValue(&runner->context.config, "screenMode", &mode) && mode != screenMode) {
screenMode = mode;
} else {
screenMode = (screenMode + 1) % SM_MAX;
GBAConfigSetUIntValue(&runner->context.config, "screenMode", screenMode);
}
}
static uint32_t _pollInput(void) {
@ -395,6 +407,24 @@ int main() {
GUI_PARAMS_TRAIL
},
.configExtra = (struct GUIMenuItem[]) {
{
.title = "Screen mode",
.data = "screenMode",
.submenu = 0,
.state = SM_PA_TOP,
.validStates = (const char*[]) {
"Pixel-Accurate/Bottom",
"Aspect-Ratio Fit/Bottom",
"Stretched/Bottom",
"Pixel-Accurate/Top",
"Aspect-Ratio Fit/Top",
"Stretched/Top",
0
}
}
},
.nConfigExtra = 1,
.setup = _setup,
.teardown = 0,
.gameLoaded = _gameLoaded,

View File

@ -10,6 +10,7 @@
#include "util/gui.h"
#include "util/gui/font.h"
#include "util/gui/file-select.h"
#include "util/gui/menu.h"
#include <psp2/ctrl.h>
#include <psp2/kernel/processmgr.h>
@ -88,6 +89,21 @@ int main() {
GUI_PARAMS_TRAIL
},
.configExtra = (struct GUIMenuItem[]) {
{
.title = "Screen mode",
.data = "screenMode",
.submenu = 0,
.state = 0,
.validStates = (const char*[]) {
"With Background",
"Without Background",
"Stretched",
0
}
}
},
.nConfigExtra = 1,
.setup = GBAPSP2Setup,
.teardown = GBAPSP2Teardown,
.gameLoaded = GBAPSP2LoadROM,

View File

@ -263,7 +263,13 @@ void GBAPSP2DrawScreenshot(struct GBAGUIRunner* runner, const uint32_t* pixels,
}
void GBAPSP2IncrementScreenMode(struct GBAGUIRunner* runner) {
screenMode = (screenMode + 1) % SM_MAX;
unsigned mode;
if (GBAConfigGetUIntValue(&runner->context.config, "screenMode", &mode) && mode != screenMode) {
screenMode = mode;
} else {
screenMode = (screenMode + 1) % SM_MAX;
GBAConfigSetUIntValue(&runner->context.config, "screenMode", screenMode);
}
}
__attribute__((noreturn, weak)) void __assert_func(const char* file, int line, const char* func, const char* expr) {

View File

@ -137,7 +137,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool
_refreshDirectory(params, params->currentPath, &menu.items, filter);
while (true) {
struct GUIMenuItem item;
struct GUIMenuItem* item;
enum GUIMenuExitReason reason = GUIShowMenu(params, &menu, &item);
params->fileIndex = menu.index;
if (reason == GUI_MENU_EXIT_CANCEL) {
@ -155,7 +155,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool
if (params->currentPath[len - 1] == *sep) {
sep = "";
}
snprintf(outPath, outLen, "%s%s%s", params->currentPath, sep, item.title);
snprintf(outPath, outLen, "%s%s%s", params->currentPath, sep, item->title);
struct GUIMenuItemList newFiles;
GUIMenuItemListInit(&newFiles, 0);

View File

@ -10,7 +10,7 @@
DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem);
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem* item) {
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item) {
size_t start = 0;
size_t lineHeight = GUIFontHeight(params->font);
size_t pageSize = params->height / lineHeight;
@ -35,14 +35,24 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
++menu->index;
}
if (newInput & (1 << GUI_INPUT_LEFT)) {
if (menu->index >= pageSize) {
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
if (item->validStates) {
if (item->state > 0) {
--item->state;
}
} else if (menu->index >= pageSize) {
menu->index -= pageSize;
} else {
menu->index = 0;
}
}
if (newInput & (1 << GUI_INPUT_RIGHT)) {
if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
if (item->validStates) {
if (item->validStates[item->state + 1]) {
++item->state;
}
} else if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
menu->index += pageSize;
} else {
menu->index = GUIMenuItemListSize(&menu->items) - 1;
@ -70,9 +80,9 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
break;
}
if (newInput & (1 << GUI_INPUT_SELECT) || (cursorOverItem == 2 && cursor == GUI_CURSOR_CLICKED)) {
*item = *GUIMenuItemListGetPointer(&menu->items, menu->index);
if (item->submenu) {
enum GUIMenuExitReason reason = GUIShowMenu(params, item->submenu, item);
*item = GUIMenuItemListGetPointer(&menu->items, menu->index);
if ((*item)->submenu) {
enum GUIMenuExitReason reason = GUIShowMenu(params, (*item)->submenu, item);
if (reason != GUI_MENU_EXIT_BACK) {
return reason;
}
@ -105,7 +115,11 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
color = 0xFFFFFFFF;
bullet = '>';
}
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, GUIMenuItemListGetPointer(&menu->items, i)->title);
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, i);
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, item->title);
if (item->validStates) {
GUIFontPrintf(params->font, params->width, y, GUI_TEXT_RIGHT, color, "%s ", item->validStates[item->state]);
}
y += lineHeight;
if (y + lineHeight > params->height) {
break;

View File

@ -12,6 +12,8 @@ struct GUIMenu;
struct GUIMenuItem {
const char* title;
void* data;
unsigned state;
const char** validStates;
struct GUIMenu* submenu;
};
@ -32,6 +34,6 @@ enum GUIMenuExitReason {
};
struct GUIParams;
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem* item);
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item);
#endif