mirror of https://github.com/mgba-emu/mgba.git
mGUI: Initial cheat support UI
This commit is contained in:
parent
4ba921ccc5
commit
990704e46b
1
CHANGES
1
CHANGES
|
@ -1,6 +1,7 @@
|
||||||
0.10.0: (Future)
|
0.10.0: (Future)
|
||||||
Features:
|
Features:
|
||||||
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
||||||
|
- Cheat code support in homebrew ports
|
||||||
Misc:
|
Misc:
|
||||||
- Qt: Rearrange menus some
|
- Qt: Rearrange menus some
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ set(SOURCE_FILES
|
||||||
video-logger.c)
|
video-logger.c)
|
||||||
|
|
||||||
set(GUI_FILES
|
set(GUI_FILES
|
||||||
|
gui/cheats.c
|
||||||
gui/gui-config.c
|
gui/gui-config.c
|
||||||
gui/gui-runner.c
|
gui/gui-runner.c
|
||||||
gui/remap.c)
|
gui/remap.c)
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/* Copyright (c) 2013-2021 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 <mgba/core/cheats.h>
|
||||||
|
#include <mgba/core/core.h>
|
||||||
|
#include "feature/gui/gui-runner.h"
|
||||||
|
#include <mgba-util/gui/menu.h>
|
||||||
|
|
||||||
|
enum mGUICheatAction {
|
||||||
|
CHEAT_ADD_LINE = 1,
|
||||||
|
CHEAT_RENAME,
|
||||||
|
CHEAT_DELETE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* const offOn[] = { "Off", "On" };
|
||||||
|
|
||||||
|
static void mGUIShowCheatSet(struct mGUIRunner* runner, struct mCheatDevice* device, struct mCheatSet* set) {
|
||||||
|
char cheatName[64];
|
||||||
|
snprintf(cheatName, sizeof(cheatName), "Edit cheat: %s", set->name);
|
||||||
|
struct GUIMenu menu = {
|
||||||
|
.title = cheatName,
|
||||||
|
.index = 0,
|
||||||
|
.background = &runner->background.d
|
||||||
|
};
|
||||||
|
GUIMenuItemListInit(&menu.items, 0);
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Enable",
|
||||||
|
.state = set->enabled,
|
||||||
|
.validStates = offOn,
|
||||||
|
.nStates = 2
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Add line",
|
||||||
|
.data = (void*) CHEAT_ADD_LINE,
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Rename",
|
||||||
|
.data = (void*) CHEAT_RENAME,
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Delete",
|
||||||
|
.data = (void*) CHEAT_DELETE,
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Back",
|
||||||
|
.data = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
struct GUIKeyboardParams keyboard;
|
||||||
|
GUIKeyboardParamsInit(&keyboard);
|
||||||
|
struct GUIMenuItem* item;
|
||||||
|
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &menu, &item);
|
||||||
|
set->enabled = GUIMenuItemListGetPointer(&menu.items, 0)->state;
|
||||||
|
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum mGUICheatAction action = (enum mGUICheatAction) item->data;
|
||||||
|
switch (action) {
|
||||||
|
case CHEAT_ADD_LINE:
|
||||||
|
strlcpy(keyboard.title, "Add line", sizeof(keyboard.title));
|
||||||
|
keyboard.maxLen = 12;
|
||||||
|
if (runner->params.getText(&keyboard) == GUI_KEYBOARD_DONE) {
|
||||||
|
mCheatAddLine(set, keyboard.result, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHEAT_RENAME:
|
||||||
|
strlcpy(keyboard.title, "Rename cheat", sizeof(keyboard.title));
|
||||||
|
strlcpy(keyboard.result, set->name, sizeof(keyboard.result));
|
||||||
|
keyboard.maxLen = 50;
|
||||||
|
if (runner->params.getText(&keyboard) == GUI_KEYBOARD_DONE) {
|
||||||
|
mCheatSetRename(set, keyboard.result);
|
||||||
|
snprintf(cheatName, sizeof(cheatName), "Edit cheat: %s", set->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHEAT_DELETE:
|
||||||
|
mCheatRemoveSet(device, set);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == CHEAT_DELETE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUIMenuItemListDeinit(&menu.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mGUIShowCheats(struct mGUIRunner* runner) {
|
||||||
|
struct mCheatDevice* device = runner->core->cheatDevice(runner->core);
|
||||||
|
if (!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct GUIMenu menu = {
|
||||||
|
.title = "Cheats",
|
||||||
|
.index = 0,
|
||||||
|
.background = &runner->background.d
|
||||||
|
};
|
||||||
|
GUIMenuItemListInit(&menu.items, 0);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
|
||||||
|
struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i);
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = set->name,
|
||||||
|
.data = set,
|
||||||
|
.state = set->enabled,
|
||||||
|
.validStates = offOn,
|
||||||
|
.nStates = 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Add new cheat set",
|
||||||
|
.data = 0,
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Back",
|
||||||
|
.data = (void*) -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GUIMenuItem* item;
|
||||||
|
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &menu, &item);
|
||||||
|
for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
|
||||||
|
struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i);
|
||||||
|
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu.items, i);
|
||||||
|
set->enabled = item->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason != GUI_MENU_EXIT_ACCEPT || item->data == (void*) -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
struct mCheatSet* set = NULL;
|
||||||
|
if (!item->data) {
|
||||||
|
struct GUIKeyboardParams keyboard;
|
||||||
|
GUIKeyboardParamsInit(&keyboard);
|
||||||
|
keyboard.maxLen = 50;
|
||||||
|
strlcpy(keyboard.title, "Cheat name", sizeof(keyboard.title));
|
||||||
|
strlcpy(keyboard.result, "New cheat", sizeof(keyboard.result));
|
||||||
|
if (runner->params.getText(&keyboard) == GUI_KEYBOARD_DONE) {
|
||||||
|
set = device->createSet(device, keyboard.result);
|
||||||
|
mCheatAddSet(device, set);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set = item->data;
|
||||||
|
}
|
||||||
|
if (set) {
|
||||||
|
mGUIShowCheatSet(runner, device, set);
|
||||||
|
}
|
||||||
|
GUIMenuItemListClear(&menu.items);
|
||||||
|
}
|
||||||
|
GUIMenuItemListDeinit(&menu.items);
|
||||||
|
mCheatAutosave(device);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* Copyright (c) 2013-2021 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_CHEATS_H
|
||||||
|
#define GUI_CHEATS_H
|
||||||
|
|
||||||
|
#include <mgba-util/common.h>
|
||||||
|
|
||||||
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
struct mGUIRunner;
|
||||||
|
void mGUIShowCheats(struct mGUIRunner* runner);
|
||||||
|
|
||||||
|
CXX_GUARD_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,6 +8,7 @@
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
#include <mgba/core/serialize.h>
|
#include <mgba/core/serialize.h>
|
||||||
#include "feature/gui/gui-config.h"
|
#include "feature/gui/gui-config.h"
|
||||||
|
#include "feature/gui/cheats.h"
|
||||||
#include <mgba/internal/gba/gba.h>
|
#include <mgba/internal/gba/gba.h>
|
||||||
#include <mgba/internal/gba/input.h>
|
#include <mgba/internal/gba/input.h>
|
||||||
#include <mgba/gba/interface.h>
|
#include <mgba/gba/interface.h>
|
||||||
|
@ -35,6 +36,7 @@ enum {
|
||||||
RUNNER_SCREENSHOT,
|
RUNNER_SCREENSHOT,
|
||||||
RUNNER_CONFIG,
|
RUNNER_CONFIG,
|
||||||
RUNNER_RESET,
|
RUNNER_RESET,
|
||||||
|
RUNNER_CHEATS,
|
||||||
RUNNER_COMMAND_MASK = 0xFFFF
|
RUNNER_COMMAND_MASK = 0xFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,7 +335,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
};
|
};
|
||||||
GUIMenuItemListInit(&pauseMenu.items, 0);
|
GUIMenuItemListInit(&pauseMenu.items, 0);
|
||||||
GUIMenuItemListInit(&stateSaveMenu.items, 9);
|
GUIMenuItemListInit(&stateSaveMenu.items, 9);
|
||||||
GUIMenuItemListInit(&stateLoadMenu.items, 9);
|
GUIMenuItemListInit(&stateLoadMenu.items, 10);
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .submenu = &stateSaveMenu };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .submenu = &stateSaveMenu };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .submenu = &stateLoadMenu };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .submenu = &stateLoadMenu };
|
||||||
|
@ -360,6 +362,9 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
*GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(9)) };
|
*GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(9)) };
|
||||||
|
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = (void*) RUNNER_SCREENSHOT };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = (void*) RUNNER_SCREENSHOT };
|
||||||
|
if (runner->params.getText) {
|
||||||
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Cheats", .data = (void*) RUNNER_CHEATS };
|
||||||
|
}
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = (void*) RUNNER_CONFIG };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = (void*) RUNNER_CONFIG };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Reset game", .data = (void*) RUNNER_RESET };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Reset game", .data = (void*) RUNNER_RESET };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
|
||||||
|
@ -616,6 +621,9 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
case RUNNER_CONFIG:
|
case RUNNER_CONFIG:
|
||||||
mGUIShowConfig(runner, runner->configExtra, runner->nConfigExtra);
|
mGUIShowConfig(runner, runner->configExtra, runner->nConfigExtra);
|
||||||
break;
|
break;
|
||||||
|
case RUNNER_CHEATS:
|
||||||
|
mGUIShowCheats(runner);
|
||||||
|
break;
|
||||||
case RUNNER_CONTINUE:
|
case RUNNER_CONTINUE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue