mirror of https://github.com/mgba-emu/mgba.git
GUI: Input remapping, part 1
This commit is contained in:
parent
2254fc68c2
commit
331d92d363
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* Copyright (c) 2013-2016 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
|
||||
|
@ -6,9 +6,14 @@
|
|||
#include "gui-config.h"
|
||||
|
||||
#include "gba/gui/gui-runner.h"
|
||||
#include "gba/gui/remap.h"
|
||||
#include "util/gui/file-select.h"
|
||||
#include "util/gui/menu.h"
|
||||
|
||||
#ifndef GUI_MAX_INPUTS
|
||||
#define GUI_MAX_INPUTS 7
|
||||
#endif
|
||||
|
||||
void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, size_t nExtra) {
|
||||
struct GUIMenu menu = {
|
||||
.title = "Configure",
|
||||
|
@ -22,8 +27,9 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
.submenu = 0,
|
||||
.state = 0,
|
||||
.validStates = (const char*[]) {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 0
|
||||
}
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
},
|
||||
.nStates = 10
|
||||
};
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Show framerate",
|
||||
|
@ -31,8 +37,9 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
.submenu = 0,
|
||||
.state = false,
|
||||
.validStates = (const char*[]) {
|
||||
"Off", "On", 0
|
||||
}
|
||||
"Off", "On"
|
||||
},
|
||||
.nStates = 2
|
||||
};
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Use BIOS if found",
|
||||
|
@ -40,20 +47,38 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
.submenu = 0,
|
||||
.state = true,
|
||||
.validStates = (const char*[]) {
|
||||
"Off", "On", 0
|
||||
}
|
||||
"Off", "On"
|
||||
},
|
||||
.nStates = 2
|
||||
};
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Select BIOS path",
|
||||
.data = "bios",
|
||||
};
|
||||
size_t i;
|
||||
const char* mapNames[GUI_MAX_INPUTS + 1];
|
||||
if (runner->keySources) {
|
||||
for (i = 0; runner->keySources[i].id && i < GUI_MAX_INPUTS; ++i) {
|
||||
mapNames[i] = runner->keySources[i].name;
|
||||
}
|
||||
if (i == 1) {
|
||||
// Don't display a name if there's only one input source
|
||||
i = 0;
|
||||
}
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Remap controls",
|
||||
.data = "*REMAP",
|
||||
.state = 0,
|
||||
.validStates = i ? mapNames : 0,
|
||||
.nStates = i
|
||||
};
|
||||
}
|
||||
for (i = 0; i < nExtra; ++i) {
|
||||
*GUIMenuItemListAppend(&menu.items) = extra[i];
|
||||
}
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Save",
|
||||
.data = "[SAVE]",
|
||||
.data = "*SAVE",
|
||||
};
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Cancel",
|
||||
|
@ -76,7 +101,7 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
||||
break;
|
||||
}
|
||||
if (!strcmp(item->data, "[SAVE]")) {
|
||||
if (!strcmp(item->data, "*SAVE")) {
|
||||
if (biosPath[0]) {
|
||||
GBAConfigSetValue(&runner->context.config, "bios", biosPath);
|
||||
}
|
||||
|
@ -90,6 +115,10 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
GBAConfigSave(&runner->context.config);
|
||||
break;
|
||||
}
|
||||
if (!strcmp(item->data, "*REMAP")) {
|
||||
GBAGUIRemapKeys(&runner->params, &runner->context.inputMap, &runner->keySources[item->state]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(item->data, "bios")) {
|
||||
// TODO: show box if failed
|
||||
if (!GUISelectFile(&runner->params, biosPath, sizeof(biosPath), GBAIsBIOS)) {
|
||||
|
@ -99,7 +128,7 @@ void GBAGUIShowConfig(struct GBAGUIRunner* runner, struct GUIMenuItem* extra, si
|
|||
}
|
||||
if (item->validStates) {
|
||||
++item->state;
|
||||
if (!item->validStates[item->state]) {
|
||||
if (item->state >= item->nStates) {
|
||||
item->state = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,13 @@ void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
|
|||
if (runner->setup) {
|
||||
runner->setup(runner);
|
||||
}
|
||||
|
||||
if (runner->context.config.port && runner->keySources) {
|
||||
size_t i;
|
||||
for (i = 0; runner->keySources[i].id; ++i) {
|
||||
GBAInputMapLoad(&runner->context.inputMap, runner->keySources[i].id, GBAConfigGetInput(&runner->context.config));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GBAGUIDeinit(struct GBAGUIRunner* runner) {
|
||||
|
@ -123,6 +130,12 @@ void GBAGUIDeinit(struct GBAGUIRunner* runner) {
|
|||
runner->teardown(runner);
|
||||
}
|
||||
if (runner->context.config.port) {
|
||||
if (runner->keySources) {
|
||||
size_t i;
|
||||
for (i = 0; runner->keySources[i].id; ++i) {
|
||||
GBAInputMapSave(&runner->context.inputMap, runner->keySources[i].id, GBAConfigGetInput(&runner->context.config));
|
||||
}
|
||||
}
|
||||
GBAConfigSave(&runner->context.config);
|
||||
}
|
||||
CircleBufferDeinit(&runner->fpsBuffer);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* Copyright (c) 2013-2016 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
|
||||
|
@ -7,6 +7,7 @@
|
|||
#define GUI_RUNNER_H
|
||||
|
||||
#include "gba/context/context.h"
|
||||
#include "gba/gui/remap.h"
|
||||
#include "util/circle-buffer.h"
|
||||
#include "util/gui.h"
|
||||
|
||||
|
@ -39,6 +40,8 @@ struct GBAGUIRunner {
|
|||
struct GUIMenuItem* configExtra;
|
||||
size_t nConfigExtra;
|
||||
|
||||
struct GUIInputKeys* keySources;
|
||||
|
||||
float fps;
|
||||
int64_t lastFpsCheck;
|
||||
int32_t totalDelta;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (c) 2013-2016 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 "remap.h"
|
||||
|
||||
#include "gba/input.h"
|
||||
#include "util/gui.h"
|
||||
#include "util/gui/menu.h"
|
||||
|
||||
void GBAGUIRemapKeys(struct GUIParams* params, struct GBAInputMap* map, const struct GUIInputKeys* keys) {
|
||||
struct GUIMenu menu = {
|
||||
.title = "Remap keys",
|
||||
.index = 0,
|
||||
.background = 0
|
||||
};
|
||||
GUIMenuItemListInit(&menu.items, 0);
|
||||
const char* keyNames[keys->nKeys + 1];
|
||||
memcpy(&keyNames[1], keys->keyNames, keys->nKeys * sizeof(keyNames[0]));
|
||||
keyNames[0] = "Unmapped";
|
||||
size_t i;
|
||||
for (i = 0; i < GBA_KEY_MAX; ++i) {
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = GBAKeyNames[i],
|
||||
.data = (void*) (GUI_INPUT_MAX + i),
|
||||
.submenu = 0,
|
||||
.state = GBAInputQueryBinding(map, keys->id, i) + 1,
|
||||
.validStates = keyNames,
|
||||
.nStates = keys->nKeys + 1
|
||||
};
|
||||
}
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Save",
|
||||
.data = (void*) (GUI_INPUT_MAX + GBA_KEY_MAX + 2),
|
||||
};
|
||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||
.title = "Cancel",
|
||||
.data = 0,
|
||||
};
|
||||
|
||||
struct GUIMenuItem* item;
|
||||
while (true) {
|
||||
enum GUIMenuExitReason reason;
|
||||
reason = GUIShowMenu(params, &menu, &item);
|
||||
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
||||
break;
|
||||
}
|
||||
if (item->data == (void*) (GUI_INPUT_MAX + GBA_KEY_MAX + 2)) {
|
||||
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
||||
item = GUIMenuItemListGetPointer(&menu.items, i);
|
||||
if (i < GBA_KEY_MAX) {
|
||||
GBAInputBindKey(map, keys->id, item->state - 1, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (item->validStates) {
|
||||
// TODO: Open remap menu
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* Copyright (c) 2013-2016 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_REMAP_H
|
||||
#define GUI_REMAP_H
|
||||
|
||||
#include "util/common.h"
|
||||
|
||||
struct GUIInputKeys {
|
||||
const char* name;
|
||||
uint32_t id;
|
||||
const char* const* keyNames;
|
||||
size_t nKeys;
|
||||
};
|
||||
|
||||
struct GUIParams;
|
||||
struct GBAInputMap;
|
||||
|
||||
void GBAGUIRemapKeys(struct GUIParams*, struct GBAInputMap*, const struct GUIInputKeys*);
|
||||
|
||||
#endif
|
|
@ -30,6 +30,8 @@ static enum ScreenMode {
|
|||
SM_MAX
|
||||
} screenMode = SM_PA_TOP;
|
||||
|
||||
#define _3DS_INPUT 0x3344534B
|
||||
|
||||
#define AUDIO_SAMPLES 0x80
|
||||
#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 24)
|
||||
|
||||
|
@ -68,6 +70,10 @@ enum {
|
|||
|
||||
extern bool allocateRomBuffer(void);
|
||||
|
||||
static void _map3DSKey(struct GBAInputMap* map, int ctrKey, enum GBAKey key) {
|
||||
GBAInputBindKey(map, _3DS_INPUT, __builtin_ctz(ctrKey), key);
|
||||
}
|
||||
|
||||
static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, void* right, u32 size)
|
||||
{
|
||||
u32 pleft = 0, pright = 0;
|
||||
|
@ -185,6 +191,17 @@ static void _setup(struct GBAGUIRunner* runner) {
|
|||
runner->context.gba->stream = &stream;
|
||||
}
|
||||
|
||||
_map3DSKey(&runner->context.inputMap, KEY_A, GBA_KEY_A);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_B, GBA_KEY_B);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_START, GBA_KEY_START);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_SELECT, GBA_KEY_SELECT);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_UP, GBA_KEY_UP);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_DOWN, GBA_KEY_DOWN);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_LEFT, GBA_KEY_LEFT);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_RIGHT, GBA_KEY_RIGHT);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_L, GBA_KEY_L);
|
||||
_map3DSKey(&runner->context.inputMap, KEY_R, GBA_KEY_R);
|
||||
|
||||
GBAVideoSoftwareRendererCreate(&renderer);
|
||||
renderer.outputBuffer = linearMemAlign(256 * VIDEO_VERTICAL_PIXELS * 2, 0x80);
|
||||
renderer.outputBufferStride = 256;
|
||||
|
@ -343,9 +360,10 @@ static uint16_t _pollGameInput(struct GBAGUIRunner* runner) {
|
|||
UNUSED(runner);
|
||||
|
||||
hidScanInput();
|
||||
uint32_t activeKeys = hidKeysHeld() & 0xF00003FF;
|
||||
activeKeys |= activeKeys >> 24;
|
||||
return activeKeys;
|
||||
uint32_t activeKeys = hidKeysHeld();
|
||||
uint16_t keys = GBAInputMapKeyBits(&runner->context.inputMap, _3DS_INPUT, activeKeys, 0);
|
||||
keys |= (activeKeys >> 24) & 0xF0;
|
||||
return keys;
|
||||
}
|
||||
|
||||
static void _incrementScreenMode(struct GBAGUIRunner* runner) {
|
||||
|
@ -519,6 +537,26 @@ int main() {
|
|||
|
||||
GUI_PARAMS_TRAIL
|
||||
},
|
||||
.keySources = (struct GUIInputKeys[]) {
|
||||
{
|
||||
.name = "3DS Input",
|
||||
.id = _3DS_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
"A",
|
||||
"B",
|
||||
"Select",
|
||||
"Start",
|
||||
"D-Pad Right",
|
||||
"D-Pad Left",
|
||||
"D-Pad Up",
|
||||
"D-Pad Down",
|
||||
"R",
|
||||
"L",
|
||||
},
|
||||
.nKeys = 10
|
||||
},
|
||||
{ .id = 0 }
|
||||
},
|
||||
.configExtra = (struct GUIMenuItem[]) {
|
||||
{
|
||||
.title = "Screen mode",
|
||||
|
@ -532,8 +570,8 @@ int main() {
|
|||
"Pixel-Accurate/Top",
|
||||
"Aspect-Ratio Fit/Top",
|
||||
"Stretched/Top",
|
||||
0
|
||||
}
|
||||
},
|
||||
.nStates = 6
|
||||
}
|
||||
},
|
||||
.nConfigExtra = 1,
|
||||
|
|
|
@ -117,10 +117,36 @@ int main() {
|
|||
"With Background",
|
||||
"Without Background",
|
||||
"Stretched",
|
||||
0
|
||||
}
|
||||
},
|
||||
.nStates = 3
|
||||
}
|
||||
},
|
||||
.keySources = (struct GUIInputKeys[]) {
|
||||
{
|
||||
.name = "Vita Input",
|
||||
.id = PSP2_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
"Select",
|
||||
0,
|
||||
0,
|
||||
"Start",
|
||||
"Up",
|
||||
"Right",
|
||||
"Down",
|
||||
"Left",
|
||||
"L",
|
||||
"R",
|
||||
0, // L2?
|
||||
0, // R2?
|
||||
"Triangle",
|
||||
"Circle",
|
||||
"Cross",
|
||||
"Square"
|
||||
},
|
||||
.nKeys = 16
|
||||
},
|
||||
{ .id = 0 }
|
||||
},
|
||||
.nConfigExtra = 1,
|
||||
.setup = GBAPSP2Setup,
|
||||
.teardown = GBAPSP2Teardown,
|
||||
|
|
|
@ -11,4 +11,6 @@
|
|||
#define PSP2_HORIZONTAL_PIXELS 960
|
||||
#define PSP2_VERTICAL_PIXELS 544
|
||||
|
||||
#define PSP2_INPUT 0x50535032
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,6 @@ static struct GBASceRotationSource {
|
|||
extern const uint8_t _binary_backdrop_png_start[];
|
||||
static vita2d_texture* backdrop = 0;
|
||||
|
||||
#define PSP2_INPUT 0x50535032
|
||||
#define PSP2_SAMPLES 64
|
||||
#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 19)
|
||||
|
||||
|
@ -138,11 +137,6 @@ uint16_t GBAPSP2PollInput(struct GBAGUIRunner* runner) {
|
|||
|
||||
void GBAPSP2Setup(struct GBAGUIRunner* runner) {
|
||||
scePowerSetArmClockFrequency(80);
|
||||
struct GBAOptions opts = {
|
||||
.useBios = true,
|
||||
.idleOptimization = IDLE_LOOP_DETECT
|
||||
};
|
||||
GBAConfigLoadDefaults(&runner->context.config, &opts);
|
||||
_mapVitaKey(&runner->context.inputMap, PSP2_CTRL_CROSS, GBA_KEY_A);
|
||||
_mapVitaKey(&runner->context.inputMap, PSP2_CTRL_CIRCLE, GBA_KEY_B);
|
||||
_mapVitaKey(&runner->context.inputMap, PSP2_CTRL_START, GBA_KEY_START);
|
||||
|
@ -158,7 +152,6 @@ void GBAPSP2Setup(struct GBAGUIRunner* runner) {
|
|||
GBAInputBindAxis(&runner->context.inputMap, PSP2_INPUT, 0, &desc);
|
||||
desc = (struct GBAAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 192, 64 };
|
||||
GBAInputBindAxis(&runner->context.inputMap, PSP2_INPUT, 1, &desc);
|
||||
GBAInputMapLoad(&runner->context.inputMap, PSP2_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
|
||||
tex = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
screenshot = vita2d_create_empty_texture_format(256, 256, SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR);
|
||||
|
@ -221,7 +214,6 @@ void GBAPSP2UnloadROM(struct GBAGUIRunner* runner) {
|
|||
}
|
||||
|
||||
void GBAPSP2Teardown(struct GBAGUIRunner* runner) {
|
||||
GBAInputMapSave(&runner->context.inputMap, PSP2_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
vita2d_free_texture(tex);
|
||||
vita2d_free_texture(screenshot);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ static void _guiPrepare(void);
|
|||
static void _guiFinish(void);
|
||||
|
||||
static void _setup(struct GBAGUIRunner* runner);
|
||||
static void _teardown(struct GBAGUIRunner* runner);
|
||||
static void _gameLoaded(struct GBAGUIRunner* runner);
|
||||
static void _gameUnloaded(struct GBAGUIRunner* runner);
|
||||
static void _unpaused(struct GBAGUIRunner* runner);
|
||||
|
@ -215,6 +214,113 @@ int main() {
|
|||
|
||||
GUI_PARAMS_TRAIL
|
||||
},
|
||||
.keySources = (struct GUIInputKeys[]) {
|
||||
{
|
||||
.name = "GameCube Input (1)",
|
||||
.id = GCN1_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
"D-Pad Left",
|
||||
"D-Pad Right",
|
||||
"D-Pad Down",
|
||||
"D-Pad Up",
|
||||
"Z",
|
||||
"R",
|
||||
"L",
|
||||
0,
|
||||
"A",
|
||||
"B",
|
||||
"X",
|
||||
"Y",
|
||||
"Start"
|
||||
},
|
||||
.nKeys = 13
|
||||
},
|
||||
{
|
||||
.name = "GameCube Input (2)",
|
||||
.id = GCN2_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
"D-Pad Left",
|
||||
"D-Pad Right",
|
||||
"D-Pad Down",
|
||||
"D-Pad Up",
|
||||
"Z",
|
||||
"R",
|
||||
"L",
|
||||
0,
|
||||
"A",
|
||||
"B",
|
||||
"X",
|
||||
"Y",
|
||||
"Start"
|
||||
},
|
||||
.nKeys = 13
|
||||
},
|
||||
{
|
||||
.name = "Wii Remote Input",
|
||||
.id = WIIMOTE_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
"2",
|
||||
"1",
|
||||
"B",
|
||||
"A",
|
||||
"Minus",
|
||||
0,
|
||||
0,
|
||||
"Home",
|
||||
"Left",
|
||||
"Right",
|
||||
"Down",
|
||||
"Up",
|
||||
"Plus",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"Z",
|
||||
"C",
|
||||
},
|
||||
.nKeys = 18
|
||||
},
|
||||
{
|
||||
.name = "Classic Controller Input",
|
||||
.id = CLASSIC_INPUT,
|
||||
.keyNames = (const char*[]) {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"Up",
|
||||
"Left",
|
||||
"ZR",
|
||||
"X",
|
||||
"A",
|
||||
"Y",
|
||||
"B",
|
||||
"ZL",
|
||||
0,
|
||||
"R",
|
||||
"Plus",
|
||||
"Home",
|
||||
"Minus",
|
||||
"L",
|
||||
"Down",
|
||||
"Right",
|
||||
},
|
||||
.nKeys = 32
|
||||
},
|
||||
{ .id = 0 }
|
||||
},
|
||||
.configExtra = (struct GUIMenuItem[]) {
|
||||
{
|
||||
.title = "Screen mode",
|
||||
|
@ -224,8 +330,8 @@ int main() {
|
|||
.validStates = (const char*[]) {
|
||||
"Pixel-Accurate",
|
||||
"Stretched",
|
||||
0
|
||||
}
|
||||
},
|
||||
.nStates = 2
|
||||
},
|
||||
{
|
||||
.title = "Filtering",
|
||||
|
@ -235,13 +341,13 @@ int main() {
|
|||
.validStates = (const char*[]) {
|
||||
"Pixelated",
|
||||
"Resampled",
|
||||
0
|
||||
}
|
||||
},
|
||||
.nStates = 2
|
||||
}
|
||||
},
|
||||
.nConfigExtra = 2,
|
||||
.setup = _setup,
|
||||
.teardown = _teardown,
|
||||
.teardown = 0,
|
||||
.gameLoaded = _gameLoaded,
|
||||
.gameUnloaded = _gameUnloaded,
|
||||
.prepareForFrame = 0,
|
||||
|
@ -407,11 +513,6 @@ void _setup(struct GBAGUIRunner* runner) {
|
|||
runner->context.gba->rumble = &rumble;
|
||||
runner->context.gba->rotationSource = &rotation;
|
||||
|
||||
struct GBAOptions opts = {
|
||||
.useBios = true,
|
||||
.idleOptimization = IDLE_LOOP_DETECT
|
||||
};
|
||||
GBAConfigLoadDefaults(&runner->context.config, &opts);
|
||||
_mapKey(&runner->context.inputMap, GCN1_INPUT, PAD_BUTTON_A, GBA_KEY_A);
|
||||
_mapKey(&runner->context.inputMap, GCN1_INPUT, PAD_BUTTON_B, GBA_KEY_B);
|
||||
_mapKey(&runner->context.inputMap, GCN1_INPUT, PAD_BUTTON_START, GBA_KEY_START);
|
||||
|
@ -452,10 +553,6 @@ void _setup(struct GBAGUIRunner* runner) {
|
|||
desc = (struct GBAAxis) { GBA_KEY_UP, GBA_KEY_DOWN, 0x40, -0x40 };
|
||||
GBAInputBindAxis(&runner->context.inputMap, GCN1_INPUT, 1, &desc);
|
||||
GBAInputBindAxis(&runner->context.inputMap, CLASSIC_INPUT, 1, &desc);
|
||||
GBAInputMapLoad(&runner->context.inputMap, GCN1_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapLoad(&runner->context.inputMap, GCN2_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapLoad(&runner->context.inputMap, WIIMOTE_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapLoad(&runner->context.inputMap, CLASSIC_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
|
||||
GBAVideoSoftwareRendererCreate(&renderer);
|
||||
renderer.outputBuffer = memalign(32, 256 * 256 * BYTES_PER_PIXEL);
|
||||
|
@ -471,13 +568,6 @@ void _setup(struct GBAGUIRunner* runner) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void _teardown(struct GBAGUIRunner* runner) {
|
||||
GBAInputMapSave(&runner->context.inputMap, GCN1_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapSave(&runner->context.inputMap, GCN2_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapSave(&runner->context.inputMap, WIIMOTE_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
GBAInputMapSave(&runner->context.inputMap, CLASSIC_INPUT, GBAConfigGetInput(&runner->context.config));
|
||||
}
|
||||
|
||||
void _gameUnloaded(struct GBAGUIRunner* runner) {
|
||||
UNUSED(runner);
|
||||
AUDIO_StopDMA();
|
||||
|
|
|
@ -38,7 +38,13 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
|||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
||||
if (item->validStates) {
|
||||
if (item->state > 0) {
|
||||
--item->state;
|
||||
unsigned oldState = item->state;
|
||||
do {
|
||||
--item->state;
|
||||
} while (!item->validStates[item->state] && item->state > 0);
|
||||
if (!item->validStates[item->state]) {
|
||||
item->state = oldState;
|
||||
}
|
||||
}
|
||||
} else if (menu->index >= pageSize) {
|
||||
menu->index -= pageSize;
|
||||
|
@ -49,8 +55,14 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
|||
if (newInput & (1 << GUI_INPUT_RIGHT)) {
|
||||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
||||
if (item->validStates) {
|
||||
if (item->validStates[item->state + 1]) {
|
||||
++item->state;
|
||||
if (item->state < item->nStates - 1) {
|
||||
unsigned oldState = item->state;
|
||||
do {
|
||||
++item->state;
|
||||
} while (!item->validStates[item->state] && item->state < item->nStates - 1);
|
||||
if (!item->validStates[item->state]) {
|
||||
item->state = oldState;
|
||||
}
|
||||
}
|
||||
} else if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
|
||||
menu->index += pageSize;
|
||||
|
@ -120,7 +132,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
|||
}
|
||||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, i);
|
||||
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, item->title);
|
||||
if (item->validStates) {
|
||||
if (item->validStates && item->validStates[item->state]) {
|
||||
GUIFontPrintf(params->font, params->width, y, GUI_TEXT_RIGHT, color, "%s ", item->validStates[item->state]);
|
||||
}
|
||||
y += lineHeight;
|
||||
|
|
|
@ -13,7 +13,8 @@ struct GUIMenuItem {
|
|||
const char* title;
|
||||
void* data;
|
||||
unsigned state;
|
||||
const char** validStates;
|
||||
const char* const* validStates;
|
||||
unsigned nStates;
|
||||
struct GUIMenu* submenu;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue