mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2024-06-22 06:02:26 -04:00
FLTK: Cheats reimplemented
This commit is contained in:
parent
9b2f86dbb8
commit
0ad4790576
|
@ -710,8 +710,8 @@ nestopia_SOURCES = \
|
|||
source/nes_ntsc/demo_impl.h
|
||||
|
||||
nestopia_SOURCES += \
|
||||
source/fltkui/cheats.cpp \
|
||||
source/fltkui/cheats.h \
|
||||
source/fltkui/chtmanager.cpp \
|
||||
source/fltkui/chtmanager.h \
|
||||
source/fltkui/cli.cpp \
|
||||
source/fltkui/cli.h \
|
||||
source/fltkui/video.cpp \
|
||||
|
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
* Nestopia UE
|
||||
*
|
||||
* Copyright (C) 2012-2018 R. Danbrook
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "cheats.h"
|
||||
|
||||
static Xml savexml;
|
||||
static Xml::Node saveroot;
|
||||
|
||||
std::vector<NstCheat> chtlist;
|
||||
|
||||
//extern Emulator emulator;
|
||||
|
||||
void nst_cheats_init(const char *cheatpath) {
|
||||
// Initialize cheat engine
|
||||
/*Cheats cheats(emulator);
|
||||
Xml xml;
|
||||
|
||||
cheats.ClearCodes();
|
||||
|
||||
std::ifstream cheatfile(cheatpath, std::ifstream::in|std::ifstream::binary);
|
||||
|
||||
if (cheatfile.is_open()) {
|
||||
xml.Read(cheatfile);
|
||||
|
||||
if (xml.GetRoot().IsType(L"cheats")) {
|
||||
|
||||
Xml::Node root(xml.GetRoot());
|
||||
Xml::Node node(root.GetFirstChild());
|
||||
|
||||
for (int i = 0; i < root.NumChildren(L"cheat"); i++) {
|
||||
|
||||
if (node.GetAttribute(L"enabled").IsValue(L"1")) {
|
||||
|
||||
if (node.GetChild(L"genie")) { // Game Genie
|
||||
nst_cheats_code_gg_add(node.GetChild(L"genie").GetValue());
|
||||
}
|
||||
|
||||
else if (node.GetChild(L"rocky")) { // Pro Action Rocky
|
||||
nst_cheats_code_par_add(node.GetChild(L"rocky").GetValue());
|
||||
}
|
||||
|
||||
else if (node.GetChild(L"address")) { // Raw
|
||||
Cheats::Code code;
|
||||
code.useCompare = false;
|
||||
|
||||
code.address = node.GetChild(L"address").GetUnsignedValue();
|
||||
if (node.GetChild(L"value")) {
|
||||
code.value = node.GetChild(L"value").GetUnsignedValue();
|
||||
}
|
||||
if (node.GetChild(L"compare")) {
|
||||
code.compare = node.GetChild(L"compare").GetUnsignedValue();
|
||||
code.useCompare = true;
|
||||
}
|
||||
cheats.SetCode(code);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "Cheat: %ls\n", node.GetChild(L"description").GetValue());
|
||||
}
|
||||
NstCheat cht = {
|
||||
node.GetAttribute(L"enabled").IsValue(L"1"),
|
||||
node.GetChild(L"genie").GetValue(),
|
||||
node.GetChild(L"rocky").GetValue(),
|
||||
node.GetChild(L"address").GetUnsignedValue(),
|
||||
node.GetChild(L"value").GetUnsignedValue(),
|
||||
node.GetChild(L"compare").GetUnsignedValue(),
|
||||
node.GetChild(L"description").GetValue()
|
||||
};
|
||||
chtlist.push_back(cht);
|
||||
node = node.GetNextSibling();
|
||||
}
|
||||
}
|
||||
cheatfile.close();
|
||||
}*/
|
||||
}
|
||||
|
||||
void nst_cheats_save(const char *cheatpath) {
|
||||
// Save the cheat list
|
||||
/*std::ofstream cheatfile(cheatpath, std::ifstream::out|std::ifstream::binary);
|
||||
|
||||
if (cheatfile.is_open()) {
|
||||
saveroot = (savexml.GetRoot());
|
||||
|
||||
saveroot = savexml.Create( L"cheats" );
|
||||
saveroot.AddAttribute( L"version", L"1.0" );
|
||||
|
||||
char buf[9];
|
||||
wchar_t wbuf[9];
|
||||
|
||||
for (int i = 0; i < chtlist.size(); i++) {
|
||||
Xml::Node node(saveroot.AddChild(L"cheat"));
|
||||
node.AddAttribute(L"enabled", chtlist[i].enabled ? L"1" : L"0");
|
||||
|
||||
if (chtlist[i].gg.size() > 0) {
|
||||
node.AddChild(L"genie", chtlist[i].gg.c_str());
|
||||
}
|
||||
|
||||
if (chtlist[i].par.size() > 0) {
|
||||
node.AddChild(L"rocky", chtlist[i].par.c_str());
|
||||
}
|
||||
|
||||
if (chtlist[i].address != 0) {
|
||||
snprintf(buf, sizeof(buf), "0x%04X", chtlist[i].address);
|
||||
mbstowcs(wbuf, buf, 9);
|
||||
node.AddChild(L"address", wbuf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%02x", chtlist[i].value);
|
||||
mbstowcs(wbuf, buf, 9);
|
||||
node.AddChild(L"value", wbuf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%02x", chtlist[i].compare);
|
||||
mbstowcs(wbuf, buf, 9);
|
||||
node.AddChild(L"compare", wbuf);
|
||||
}
|
||||
|
||||
if (chtlist[i].description.size() > 0) {
|
||||
node.AddChild(L"description", chtlist[i].description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
savexml.Write(saveroot, cheatfile);
|
||||
cheatfile.close();
|
||||
}*/
|
||||
}
|
||||
|
||||
void nst_cheats_code_gg_add(const std::wstring data) {
|
||||
// Add a Game Genie code
|
||||
/*Cheats cheats(emulator);
|
||||
Cheats::Code code;
|
||||
|
||||
char gg[9];
|
||||
snprintf(gg, sizeof(gg), "%ls", data.c_str());
|
||||
|
||||
cheats.GameGenieDecode(gg, code);
|
||||
cheats.SetCode(code);*/
|
||||
}
|
||||
|
||||
void nst_cheats_code_par_add(const std::wstring data) {
|
||||
// Add a Pro Action Rocky code
|
||||
/*Cheats cheats(emulator);
|
||||
Cheats::Code code;
|
||||
|
||||
char par[9];
|
||||
snprintf(par, sizeof(par), "%ls", data.c_str());
|
||||
|
||||
cheats.ProActionRockyDecode(par, code);
|
||||
cheats.SetCode(code);*/
|
||||
}
|
||||
|
||||
void nst_cheats_refresh() {
|
||||
/*Cheats cheats(emulator);
|
||||
cheats.ClearCodes();
|
||||
|
||||
for (int i = 0; i < chtlist.size(); i++) {
|
||||
if (chtlist[i].enabled) {
|
||||
if (chtlist[i].gg.size()) {
|
||||
nst_cheats_code_gg_add(chtlist[i].gg);
|
||||
}
|
||||
else if (chtlist[i].par.size()) {
|
||||
nst_cheats_code_par_add(chtlist[i].par);
|
||||
}
|
||||
else if (chtlist[i].address) {
|
||||
Cheats::Code code;
|
||||
code.useCompare = false;
|
||||
code.address = chtlist[i].address;
|
||||
code.value = chtlist[i].value;
|
||||
code.compare = chtlist[i].compare;
|
||||
code.useCompare = code.compare != 0;
|
||||
cheats.SetCode(code);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// DIP Switches
|
||||
void nst_dip_handle(const char *dippath) {
|
||||
// Handle the DIP switch file
|
||||
/*DipSwitches dipswitches(emulator);
|
||||
Xml xml;
|
||||
|
||||
std::ifstream dipfile(dippath, std::ifstream::in|std::ifstream::binary);
|
||||
|
||||
if (dipfile.is_open()) {
|
||||
xml.Read(dipfile);
|
||||
|
||||
if (xml.GetRoot().IsType(L"dipswitches")) {
|
||||
Xml::Node root(xml.GetRoot());
|
||||
Xml::Node node(root.GetFirstChild());
|
||||
|
||||
for (int i = 0; i < root.NumChildren(L"dip"); i++) {
|
||||
|
||||
if (node.GetChild(L"value")) {
|
||||
dipswitches.SetValue(i, node.GetChild(L"value").GetUnsignedValue());
|
||||
}
|
||||
node = node.GetNextSibling();
|
||||
}
|
||||
}
|
||||
dipfile.close();
|
||||
}
|
||||
else {
|
||||
Xml::Node root(xml.GetRoot());
|
||||
|
||||
root = xml.Create(L"dipswitches");
|
||||
root.AddAttribute(L"version", L"1.0");
|
||||
|
||||
wchar_t wbuf[32];
|
||||
char buf[32];
|
||||
|
||||
int numdips = dipswitches.NumDips();
|
||||
|
||||
if (numdips > 0) {
|
||||
for (int i = 0; i < numdips; i++) {
|
||||
Xml::Node node(root.AddChild(L"dip"));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", dipswitches.GetDipName(i));
|
||||
mbstowcs(wbuf, buf, sizeof(buf));
|
||||
node.AddChild(L"description", wbuf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", dipswitches.GetValue(i));
|
||||
mbstowcs(wbuf, buf, sizeof(buf));
|
||||
node.AddChild(L"value", wbuf);
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream dipout(dippath, std::ifstream::out|std::ifstream::binary);
|
||||
|
||||
if (dipout.is_open()) {
|
||||
xml.Write(root, dipout);
|
||||
}
|
||||
|
||||
dipout.close();
|
||||
}*/
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef _CHEATS_H_
|
||||
#define _CHEATS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/api/NstApiEmulator.hpp"
|
||||
#include "core/api/NstApiCheats.hpp"
|
||||
#include "core/api/NstApiDipSwitches.hpp"
|
||||
#include "core/NstStream.hpp"
|
||||
#include "core/NstXml.hpp"
|
||||
|
||||
using namespace Nes::Api;
|
||||
|
||||
typedef Nes::Core::Xml Xml;
|
||||
|
||||
typedef struct NstCheat {
|
||||
bool enabled;
|
||||
std::wstring gg;
|
||||
std::wstring par;
|
||||
unsigned short address;
|
||||
unsigned char value;
|
||||
unsigned char compare;
|
||||
std::wstring description;
|
||||
} NstCheat;
|
||||
|
||||
void nst_cheats_init(const char *cheatpath);
|
||||
void nst_cheats_save(const char *cheatpath);
|
||||
void nst_cheats_refresh();
|
||||
void nst_cheats_code_gg_add(const std::wstring data);
|
||||
void nst_cheats_code_par_add(const std::wstring data);
|
||||
|
||||
// DIP Switches
|
||||
void nst_dip_handle(const char *dippath);
|
||||
|
||||
#endif
|
242
source/fltkui/chtmanager.cpp
Normal file
242
source/fltkui/chtmanager.cpp
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Nestopia UE
|
||||
*
|
||||
* Copyright (C) 2012-2024 R. Danbrook
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "jg/jg.h"
|
||||
|
||||
#include "chtmanager.h"
|
||||
|
||||
CheatManager::CheatManager(JGManager& jgm) : jgm(jgm) {
|
||||
}
|
||||
|
||||
std::vector<NstCheat>& CheatManager::get_list() {
|
||||
return chtlist;
|
||||
}
|
||||
|
||||
void CheatManager::clear() {
|
||||
chtlist.clear();
|
||||
jgm.cheat_clear();
|
||||
}
|
||||
|
||||
void CheatManager::refresh() {
|
||||
// First clear the active cheats
|
||||
jgm.cheat_clear();
|
||||
|
||||
// Apply any enabled cheats
|
||||
for (auto& cht : chtlist) {
|
||||
if (cht.enabled) {
|
||||
if (cht.gg.size()) {
|
||||
jgm.cheat_set(cht.gg.c_str());
|
||||
}
|
||||
else if (cht.par.size()) {
|
||||
jgm.cheat_set(cht.par.c_str());
|
||||
}
|
||||
else if (cht.raw.size()) {
|
||||
jgm.cheat_set(cht.raw.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManager::load(const char *cheatpath) {
|
||||
Xml xml;
|
||||
|
||||
clear();
|
||||
|
||||
std::ifstream cheatfile(cheatpath, std::ifstream::in|std::ifstream::binary);
|
||||
|
||||
if (cheatfile.is_open()) {
|
||||
xml.Read(cheatfile);
|
||||
|
||||
if (xml.GetRoot().IsType(L"cheats")) {
|
||||
|
||||
Xml::Node root(xml.GetRoot());
|
||||
Xml::Node node(root.GetFirstChild());
|
||||
|
||||
for (int i = 0; i < root.NumChildren(L"cheat"); i++) {
|
||||
std::string ggcode{};
|
||||
std::string parcode{};
|
||||
std::string rawcode{};
|
||||
|
||||
if (node.GetChild(L"genie")) { // Game Genie
|
||||
std::wstring ws = node.GetChild(L"genie").GetValue();
|
||||
ggcode = std::string(ws.begin(), ws.end());
|
||||
}
|
||||
|
||||
else if (node.GetChild(L"rocky")) { // Pro Action Rocky
|
||||
std::wstring ws = node.GetChild(L"rocky").GetValue();
|
||||
parcode = std::string(ws.begin(), ws.end());
|
||||
}
|
||||
|
||||
else if (node.GetChild(L"address")) { // Raw
|
||||
std::wstring ws = node.GetChild(L"address").GetValue();
|
||||
rawcode = std::string(ws.begin(), ws.end());
|
||||
|
||||
if (node.GetChild(L"value")) {
|
||||
std::wstring vws = node.GetChild(L"value").GetValue();
|
||||
rawcode += ' ' + std::string(vws.begin(), vws.end());
|
||||
}
|
||||
|
||||
if (node.GetChild(L"compare")) {
|
||||
std::wstring cws = node.GetChild(L"compare").GetValue();
|
||||
rawcode += ' ' + std::string(cws.begin(), cws.end());
|
||||
}
|
||||
}
|
||||
|
||||
NstCheat cht = {
|
||||
node.GetAttribute(L"enabled").IsValue(L"1"),
|
||||
ggcode,
|
||||
parcode,
|
||||
rawcode,
|
||||
node.GetChild(L"description").GetValue()
|
||||
};
|
||||
|
||||
chtlist.push_back(cht);
|
||||
node = node.GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
cheatfile.close();
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManager::save(const char *cheatpath) {
|
||||
// Save the cheat list
|
||||
std::ofstream cheatfile(cheatpath, std::ifstream::out|std::ifstream::binary);
|
||||
|
||||
if (cheatfile.is_open()) {
|
||||
saveroot = (savexml.GetRoot());
|
||||
|
||||
saveroot = savexml.Create( L"cheats" );
|
||||
saveroot.AddAttribute( L"version", L"1.0" );
|
||||
|
||||
for (auto& cht : chtlist) {
|
||||
Xml::Node node(saveroot.AddChild(L"cheat"));
|
||||
node.AddAttribute(L"enabled", cht.enabled ? L"1" : L"0");
|
||||
|
||||
if (cht.gg.size()) {
|
||||
std::wstring ggcode = std::wstring(cht.gg.begin(), cht.gg.end());
|
||||
node.AddChild(L"genie", ggcode.c_str());
|
||||
}
|
||||
|
||||
if (cht.par.size()) {
|
||||
std::wstring parcode = std::wstring(cht.par.begin(), cht.par.end());
|
||||
node.AddChild(L"rocky", parcode.c_str());
|
||||
}
|
||||
|
||||
if (cht.raw.size()) {
|
||||
std::vector<std::string> tokens;
|
||||
std::stringstream rawcode(cht.raw);
|
||||
std::string token;
|
||||
|
||||
while (std::getline(rawcode, token, ' ')) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
if ((tokens.size() == 2) || (tokens.size() == 3)) {
|
||||
std::wstring ws = std::wstring(tokens[0].begin(), tokens[0].end());
|
||||
node.AddChild(L"address", ws.c_str());
|
||||
|
||||
ws = std::wstring(tokens[1].begin(), tokens[1].end());
|
||||
node.AddChild(L"value", ws.c_str());
|
||||
|
||||
if (tokens.size() == 3) {
|
||||
ws = std::wstring(tokens[2].begin(), tokens[2].end());
|
||||
node.AddChild(L"compare", ws.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cht.description.size() > 0) {
|
||||
node.AddChild(L"description", cht.description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
savexml.Write(saveroot, cheatfile);
|
||||
cheatfile.close();
|
||||
}
|
||||
}
|
||||
|
||||
// DIP Switches
|
||||
void nst_dip_handle(const char *dippath) {
|
||||
// Handle the DIP switch file
|
||||
/*DipSwitches dipswitches(emulator);
|
||||
Xml xml;
|
||||
|
||||
std::ifstream dipfile(dippath, std::ifstream::in|std::ifstream::binary);
|
||||
|
||||
if (dipfile.is_open()) {
|
||||
xml.Read(dipfile);
|
||||
|
||||
if (xml.GetRoot().IsType(L"dipswitches")) {
|
||||
Xml::Node root(xml.GetRoot());
|
||||
Xml::Node node(root.GetFirstChild());
|
||||
|
||||
for (int i = 0; i < root.NumChildren(L"dip"); i++) {
|
||||
|
||||
if (node.GetChild(L"value")) {
|
||||
dipswitches.SetValue(i, node.GetChild(L"value").GetUnsignedValue());
|
||||
}
|
||||
node = node.GetNextSibling();
|
||||
}
|
||||
}
|
||||
dipfile.close();
|
||||
}
|
||||
else {
|
||||
Xml::Node root(xml.GetRoot());
|
||||
|
||||
root = xml.Create(L"dipswitches");
|
||||
root.AddAttribute(L"version", L"1.0");
|
||||
|
||||
wchar_t wbuf[32];
|
||||
char buf[32];
|
||||
|
||||
int numdips = dipswitches.NumDips();
|
||||
|
||||
if (numdips > 0) {
|
||||
for (int i = 0; i < numdips; i++) {
|
||||
Xml::Node node(root.AddChild(L"dip"));
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", dipswitches.GetDipName(i));
|
||||
mbstowcs(wbuf, buf, sizeof(buf));
|
||||
node.AddChild(L"description", wbuf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", dipswitches.GetValue(i));
|
||||
mbstowcs(wbuf, buf, sizeof(buf));
|
||||
node.AddChild(L"value", wbuf);
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream dipout(dippath, std::ifstream::out|std::ifstream::binary);
|
||||
|
||||
if (dipout.is_open()) {
|
||||
xml.Write(root, dipout);
|
||||
}
|
||||
|
||||
dipout.close();
|
||||
}*/
|
||||
}
|
44
source/fltkui/chtmanager.h
Normal file
44
source/fltkui/chtmanager.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/api/NstApiDipSwitches.hpp"
|
||||
#include "core/NstStream.hpp"
|
||||
#include "core/NstXml.hpp"
|
||||
|
||||
#include "jgmanager.h"
|
||||
|
||||
typedef Nes::Core::Xml Xml;
|
||||
|
||||
typedef struct NstCheat {
|
||||
bool enabled{false};
|
||||
std::string gg;
|
||||
std::string par;
|
||||
std::string raw;
|
||||
std::wstring description;
|
||||
} NstCheat;
|
||||
|
||||
// DIP Switches
|
||||
void nst_dip_handle(const char *dippath);
|
||||
|
||||
class CheatManager {
|
||||
public:
|
||||
CheatManager() = delete;
|
||||
CheatManager(JGManager& jgm);
|
||||
~CheatManager() {}
|
||||
|
||||
void clear();
|
||||
void refresh();
|
||||
void load(const char *cheatpath);
|
||||
void save(const char *cheatpath);
|
||||
|
||||
std::vector<NstCheat>& get_list();
|
||||
|
||||
private:
|
||||
std::vector<NstCheat> chtlist;
|
||||
Xml savexml;
|
||||
Xml::Node saveroot;
|
||||
|
||||
JGManager& jgm;
|
||||
};
|
|
@ -43,12 +43,11 @@
|
|||
#include "jgmanager.h"
|
||||
#include "setmanager.h"
|
||||
#include "inputmanager.h"
|
||||
#include "chtmanager.h"
|
||||
|
||||
#include "audio.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "cheats.h"
|
||||
|
||||
#include "fltkui.h"
|
||||
#include "fltkui_archive.h"
|
||||
#include "fltkui_cheats.h"
|
||||
|
@ -67,6 +66,7 @@ static NstSettingsWindow *setwin;
|
|||
static JGManager *jgm = nullptr;
|
||||
static SettingManager *setmgr = nullptr;
|
||||
static InputManager *inputmgr = nullptr;
|
||||
static CheatManager *chtmgr = nullptr;
|
||||
|
||||
static std::vector<uint8_t> game;
|
||||
|
||||
|
@ -153,6 +153,8 @@ static void fltkui_rom_open(Fl_Widget* w, void* userdata) {
|
|||
fltkui_load_file(fc.filename());
|
||||
|
||||
if (jgm->is_loaded()) {
|
||||
chtmgr->clear();
|
||||
chtwin->refresh();
|
||||
fltkui_enable_menu();
|
||||
nstwin->label(jgm->get_gamename().c_str());
|
||||
jg_setup_audio();
|
||||
|
@ -538,7 +540,7 @@ void makenstwin(const char *name) {
|
|||
Fl::add_handler(handle);
|
||||
|
||||
// Cheats Window
|
||||
chtwin = new NstChtWindow(660, 500, "Cheat Manager");
|
||||
chtwin = new NstChtWindow(720, 500, "Cheat Manager", *chtmgr);
|
||||
chtwin->populate();
|
||||
|
||||
// Settings Window
|
||||
|
@ -601,6 +603,7 @@ int main(int argc, char *argv[]) {
|
|||
//nst_archive_select = &fltkui_archive_select;
|
||||
|
||||
inputmgr = new InputManager(*jgm, *setmgr);
|
||||
chtmgr = new CheatManager(*jgm);
|
||||
|
||||
makenstwin(argv[0]);
|
||||
nstwin->label("Nestopia UE");
|
||||
|
@ -683,6 +686,10 @@ int main(int argc, char *argv[]) {
|
|||
delete setmgr;
|
||||
}
|
||||
|
||||
if (chtmgr) {
|
||||
delete chtmgr;
|
||||
}
|
||||
|
||||
delete chtwin;
|
||||
delete setwin;
|
||||
delete glarea;
|
||||
|
|
|
@ -30,247 +30,299 @@
|
|||
#include <FL/Fl_Gl_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "cheats.h"
|
||||
|
||||
#include "video.h"
|
||||
#include "fltkui.h"
|
||||
#include "fltkui_cheats.h"
|
||||
|
||||
static Fl_Input *input_desc;
|
||||
static Fl_Input *input_gg;
|
||||
static Fl_Input *input_par;
|
||||
static int rsel = 0;
|
||||
namespace {
|
||||
|
||||
extern Emulator emulator;
|
||||
extern std::vector<NstCheat> chtlist;
|
||||
NstChtWindow *chtwin = nullptr;
|
||||
|
||||
Fl_Input *input_desc;
|
||||
Fl_Input *input_gg;
|
||||
Fl_Input *input_par;
|
||||
|
||||
}
|
||||
|
||||
class ChtTable : public Fl_Table_Row
|
||||
{
|
||||
protected:
|
||||
void draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0);
|
||||
|
||||
public:
|
||||
ChtTable(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l) { end(); }
|
||||
ChtTable(int x, int y, int w, int h, const char *l, CheatManager& chtmgr) :
|
||||
Fl_Table_Row(x,y,w,h,l), chtmgr(chtmgr) { end(); }
|
||||
|
||||
private:
|
||||
CheatManager& chtmgr;
|
||||
|
||||
protected:
|
||||
void draw_cell(TableContext context, int r = 0, int c = 0,
|
||||
int x = 0, int y = 0, int w = 0, int h = 0);
|
||||
};
|
||||
|
||||
static ChtTable *ctable;
|
||||
|
||||
NstChtWindow::NstChtWindow(int w, int h, const char* t, CheatManager& chtmgr) :
|
||||
Fl_Double_Window(w, h, t), chtmgr(chtmgr) {
|
||||
chtwin = this;
|
||||
}
|
||||
|
||||
static void cb_ok(Fl_Widget *w, long) {
|
||||
w->parent()->hide();
|
||||
w->parent()->hide();
|
||||
}
|
||||
|
||||
static void cb_table(Fl_Widget* w, long rn) {
|
||||
Fl_Table *table = (Fl_Table*)w;
|
||||
void NstChtWindow::cb_table(Fl_Widget* w, long rn) {
|
||||
Fl_Table *table = (Fl_Table*)w;
|
||||
|
||||
if (!table->rows()) { return; }
|
||||
if (!table->rows()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rn = table->callback_row();
|
||||
rsel = rn;
|
||||
rn = table->callback_row();
|
||||
rsel = rn;
|
||||
|
||||
if (Fl::event_clicks() > 0) {
|
||||
chtlist[rn].enabled = !chtlist[rn].enabled;
|
||||
nst_cheats_refresh();
|
||||
}
|
||||
if (Fl::event_clicks() > 0) {
|
||||
Fl::event_clicks(0);
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
chtlist[rn].enabled = !chtlist[rn].enabled;
|
||||
chtmgr.refresh();
|
||||
}
|
||||
|
||||
ctable->redraw();
|
||||
ctable->redraw();
|
||||
}
|
||||
|
||||
void cb_toggle(Fl_Widget* w, long) {
|
||||
if (!chtlist.size()) { return; }
|
||||
chtlist[rsel].enabled = !chtlist[rsel].enabled;
|
||||
nst_cheats_refresh();
|
||||
ctable->redraw();
|
||||
void NstChtWindow::cb_table_s(Fl_Widget *w, long rn) {
|
||||
chtwin->cb_table(w, rn);
|
||||
}
|
||||
|
||||
void cb_add(Fl_Widget* w, long) {
|
||||
NstCheat cht;
|
||||
bool addgg = false;
|
||||
bool addpar = false;
|
||||
cht.enabled = true;
|
||||
void NstChtWindow::cb_toggle(Fl_Widget *w, void*) {
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
if (!chtlist.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t wtmp[256];
|
||||
chtlist[rsel].enabled = !chtlist[rsel].enabled;
|
||||
|
||||
mbstowcs(wtmp, input_desc->value(), 256);
|
||||
cht.description = std::wstring(wtmp);
|
||||
|
||||
if (strlen(input_gg->value())) {
|
||||
mbstowcs(wtmp, input_gg->value(), 256);
|
||||
cht.gg = std::wstring(wtmp);
|
||||
addgg = true;
|
||||
}
|
||||
|
||||
if (strlen(input_par->value())) {
|
||||
mbstowcs(wtmp, input_par->value(), 256);
|
||||
cht.par = std::wstring(wtmp);
|
||||
addpar = true;
|
||||
}
|
||||
|
||||
cht.address = cht.value = cht.compare = 0;
|
||||
|
||||
if (addgg || addpar) {
|
||||
chtlist.push_back(cht);
|
||||
nst_cheats_refresh();
|
||||
ctable->rows(chtlist.size());
|
||||
input_desc->value("");
|
||||
input_gg->value("");
|
||||
input_par->value("");
|
||||
return;
|
||||
}
|
||||
chtmgr.refresh();
|
||||
ctable->redraw();
|
||||
}
|
||||
|
||||
void cb_del(Fl_Widget* w, long) {
|
||||
if (chtlist.size()) {
|
||||
chtlist.erase(chtlist.begin() + rsel);
|
||||
nst_cheats_refresh();
|
||||
ctable->rows(chtlist.size());
|
||||
}
|
||||
void NstChtWindow::cb_toggle_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_toggle(w, nullptr);
|
||||
}
|
||||
|
||||
void cb_clr(Fl_Widget* w, long) {
|
||||
chtlist.clear();
|
||||
nst_cheats_refresh();
|
||||
ctable->rows(chtlist.size());
|
||||
void NstChtWindow::cb_add(Fl_Widget *w, void*) {
|
||||
NstCheat cht;
|
||||
bool addgg = false;
|
||||
bool addpar = false;
|
||||
cht.enabled = true;
|
||||
|
||||
wchar_t wtmp[256];
|
||||
|
||||
mbstowcs(wtmp, input_desc->value(), 256);
|
||||
cht.description = std::wstring(wtmp);
|
||||
|
||||
if (strlen(input_gg->value())) {
|
||||
cht.gg = std::string(input_gg->value());
|
||||
addgg = true;
|
||||
}
|
||||
|
||||
if (strlen(input_par->value())) {
|
||||
cht.par = std::string(input_par->value());
|
||||
addpar = true;
|
||||
}
|
||||
|
||||
cht.raw = std::string{};
|
||||
|
||||
if (addgg || addpar) {
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
chtlist.push_back(cht);
|
||||
chtmgr.refresh();
|
||||
ctable->rows(chtlist.size());
|
||||
input_desc->value("");
|
||||
input_gg->value("");
|
||||
input_par->value("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cb_load(Fl_Widget* w, long) {
|
||||
Fl_Native_File_Chooser fc;
|
||||
fc.title("Select a Cheat List");
|
||||
fc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
||||
//fc.directory((const char*)nstpaths.cheatpath); // FIXME
|
||||
fc.filter("Nestopia Cheats\t*.xml");
|
||||
|
||||
// Show file chooser
|
||||
switch (fc.show()) {
|
||||
case -1: fprintf(stderr, "Error: %s\n", fc.errmsg()); break;
|
||||
case 1: break; // Cancel
|
||||
default:
|
||||
if (fc.filename()) {
|
||||
chtlist.clear();
|
||||
nst_cheats_init(fc.filename());
|
||||
ctable->rows(chtlist.size());
|
||||
}
|
||||
break;
|
||||
}
|
||||
void NstChtWindow::cb_add_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_add(w, nullptr);
|
||||
}
|
||||
|
||||
void cb_save(Fl_Widget* w, long) {
|
||||
Fl_Native_File_Chooser fc;
|
||||
fc.title("Save Cheat List");
|
||||
fc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
|
||||
//fc.directory((const char*)nstpaths.cheatpath); // FIXME
|
||||
//std::string preset = std::string(nstpaths.cheatpath) + "/" + std::string(nstpaths.gamename) + ".xml";
|
||||
//fc.preset_file(preset.c_str());
|
||||
fc.filter("Nestopia Cheats\t*.xml");
|
||||
fc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT);
|
||||
void NstChtWindow::cb_del(Fl_Widget *w, void*) {
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
if (chtlist.size()) {
|
||||
chtlist.erase(chtlist.begin() + rsel);
|
||||
chtmgr.refresh();
|
||||
ctable->rows(chtlist.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Show file chooser
|
||||
if (fc.show()) { return; }
|
||||
void NstChtWindow::cb_del_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_del(w, nullptr);
|
||||
}
|
||||
|
||||
nst_cheats_save(fc.filename());
|
||||
void NstChtWindow::cb_clear(Fl_Widget *w, void*) {
|
||||
chtmgr.clear();
|
||||
ctable->rows(0);
|
||||
}
|
||||
|
||||
void NstChtWindow::cb_clear_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_clear(w, nullptr);
|
||||
}
|
||||
|
||||
void NstChtWindow::cb_load(Fl_Widget*, void*) {
|
||||
Fl_Native_File_Chooser fc;
|
||||
fc.title("Select a Cheat List");
|
||||
fc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
||||
//fc.directory((const char*)nstpaths.cheatpath); // FIXME
|
||||
fc.filter("Nestopia Cheats\t*.xml");
|
||||
|
||||
// Show file chooser
|
||||
switch (fc.show()) {
|
||||
case -1: fprintf(stderr, "Error: %s\n", fc.errmsg()); break;
|
||||
case 1: break; // Cancel
|
||||
default:
|
||||
if (fc.filename()) {
|
||||
chtmgr.load(fc.filename());
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
ctable->rows(chtlist.size());
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NstChtWindow::cb_load_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_load(w, nullptr);
|
||||
}
|
||||
|
||||
void NstChtWindow::cb_save(Fl_Widget *w, void*) {
|
||||
Fl_Native_File_Chooser fc;
|
||||
fc.title("Save Cheat List");
|
||||
fc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
|
||||
//fc.directory((const char*)nstpaths.cheatpath); // FIXME
|
||||
//std::string preset = std::string(nstpaths.cheatpath) + "/" + std::string(nstpaths.gamename) + ".xml";
|
||||
//fc.preset_file(preset.c_str());
|
||||
fc.filter("Nestopia Cheats\t*.xml");
|
||||
fc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT);
|
||||
|
||||
// Show file chooser
|
||||
if (fc.show()) {
|
||||
return;
|
||||
}
|
||||
|
||||
chtmgr.save(fc.filename());
|
||||
}
|
||||
|
||||
void NstChtWindow::cb_save_s(Fl_Widget *w, void*) {
|
||||
chtwin->cb_save(w, nullptr);
|
||||
}
|
||||
|
||||
// Handle drawing all cells in table
|
||||
void ChtTable::draw_cell(TableContext context, int r, int c, int X, int Y, int W, int H) {
|
||||
static char s[128];
|
||||
static char s[128];
|
||||
|
||||
switch (context) {
|
||||
case CONTEXT_COL_HEADER:
|
||||
switch (c) {
|
||||
case 0: s[0] = '\0'; break;
|
||||
case 1: snprintf(s, sizeof(s), "Game Genie"); break;
|
||||
case 2: snprintf(s, sizeof(s), "PAR"); break;
|
||||
case 3: snprintf(s, sizeof(s), "Raw"); break;
|
||||
case 4: snprintf(s, sizeof(s), "Description"); break;
|
||||
}
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
|
||||
fl_push_clip(X, Y, W, H);
|
||||
switch (context) {
|
||||
case CONTEXT_COL_HEADER:
|
||||
switch (c) {
|
||||
case 0: s[0] = '\0'; break;
|
||||
case 1: snprintf(s, sizeof(s), "Game Genie"); break;
|
||||
case 2: snprintf(s, sizeof(s), "PAR"); break;
|
||||
case 3: snprintf(s, sizeof(s), "Raw"); break;
|
||||
case 4: snprintf(s, sizeof(s), "Description"); break;
|
||||
}
|
||||
|
||||
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color());
|
||||
fl_color(FL_BLACK);
|
||||
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
|
||||
fl_push_clip(X, Y, W, H);
|
||||
|
||||
fl_pop_clip();
|
||||
return;
|
||||
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color());
|
||||
fl_color(FL_BLACK);
|
||||
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
|
||||
|
||||
case CONTEXT_CELL:
|
||||
fl_push_clip(X, Y, W, H);
|
||||
fl_pop_clip();
|
||||
return;
|
||||
|
||||
switch (c) {
|
||||
case 0: snprintf(s, sizeof(s), "%s", chtlist[r].enabled ? "On" : "Off"); break;
|
||||
case 1: snprintf(s, sizeof(s), "%ls", chtlist[r].gg.c_str()); break;
|
||||
case 2: snprintf(s, sizeof(s), "%ls", chtlist[r].par.c_str()); break;
|
||||
case 3:
|
||||
if (chtlist[r].address) {
|
||||
snprintf(s, sizeof(s), "%04X %02X %02X", chtlist[r].address, chtlist[r].value, chtlist[r].compare);
|
||||
}
|
||||
else {
|
||||
s[0] = '\0';
|
||||
}
|
||||
break;
|
||||
case 4: snprintf(s, sizeof(s), "%ls", chtlist[r].description.c_str()); break;
|
||||
default: break;
|
||||
}
|
||||
case CONTEXT_CELL:
|
||||
fl_push_clip(X, Y, W, H);
|
||||
|
||||
// Background
|
||||
fl_color( row_selected(r) ? selection_color() : FL_WHITE);
|
||||
fl_rectf(X, Y, W, H);
|
||||
switch (c) {
|
||||
case 0: snprintf(s, sizeof(s), "%s", chtlist[r].enabled ? "On" : "Off"); break;
|
||||
case 1: snprintf(s, sizeof(s), "%s", chtlist[r].gg.c_str()); break;
|
||||
case 2: snprintf(s, sizeof(s), "%s", chtlist[r].par.c_str()); break;
|
||||
case 3:
|
||||
if (!chtlist[r].raw.empty()) {
|
||||
snprintf(s, sizeof(s), "%s", chtlist[r].raw.c_str());
|
||||
}
|
||||
else {
|
||||
s[0] = '\0';
|
||||
}
|
||||
break;
|
||||
case 4: snprintf(s, sizeof(s), "%ls", chtlist[r].description.c_str()); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Text
|
||||
fl_color(FL_BLACK);
|
||||
fl_draw(s, X, Y, W, H, c ? FL_ALIGN_LEFT : FL_ALIGN_CENTER);
|
||||
// Background
|
||||
fl_color( row_selected(r) ? selection_color() : FL_WHITE);
|
||||
fl_rectf(X, Y, W, H);
|
||||
|
||||
fl_pop_clip();
|
||||
// Text
|
||||
fl_color(row_selected(r) ? NstWhite : FL_BLACK);
|
||||
fl_draw(s, X, Y, W, H, c ? FL_ALIGN_LEFT : FL_ALIGN_CENTER);
|
||||
|
||||
return;
|
||||
fl_pop_clip();
|
||||
|
||||
default: return;
|
||||
}
|
||||
return;
|
||||
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void NstChtWindow::refresh() {
|
||||
ctable->rows(chtlist.size());
|
||||
ctable->row_header(0);
|
||||
std::vector<NstCheat>& chtlist = chtmgr.get_list();
|
||||
ctable->rows(chtlist.size());
|
||||
ctable->row_header(0);
|
||||
}
|
||||
|
||||
void NstChtWindow::populate() {
|
||||
ctable = new ChtTable(19, 20, 642, 270);
|
||||
ctable->selection_color(FL_YELLOW);
|
||||
ctable->cols(5);
|
||||
ctable->col_header(1); // enable col header
|
||||
ctable->col_width(0, 80);
|
||||
ctable->col_width(1, 100);
|
||||
ctable->col_width(2, 90);
|
||||
ctable->col_width(3, 90);
|
||||
ctable->col_width(4, 260);
|
||||
ctable = new ChtTable(19, 20, 682, 270, "", chtmgr);
|
||||
ctable->selection_color(NstGreen);
|
||||
ctable->cols(5);
|
||||
ctable->col_header(1); // enable col header
|
||||
ctable->col_width(0, 40);
|
||||
ctable->col_width(1, 100);
|
||||
ctable->col_width(2, 90);
|
||||
ctable->col_width(3, 150);
|
||||
ctable->col_width(4, 280);
|
||||
ctable->col_resize(1);
|
||||
|
||||
ctable->callback(cb_table, 0);
|
||||
ctable->when(FL_WHEN_CHANGED);
|
||||
ctable->end();
|
||||
ctable->callback(cb_table_s, 0);
|
||||
ctable->when(FL_WHEN_CHANGED);
|
||||
ctable->end();
|
||||
|
||||
input_desc = new Fl_Input(380, 310, 260, UI_ELEMHEIGHT, "Description:");
|
||||
input_gg = new Fl_Input(380, 340, 260, UI_ELEMHEIGHT, "Game Genie:");
|
||||
input_par = new Fl_Input(380, 370, 260, UI_ELEMHEIGHT, "Pro Action Rocky:");
|
||||
input_desc = new Fl_Input(400, 310, 300, UI_ELEMHEIGHT, "Description:");
|
||||
input_gg = new Fl_Input(400, 340, 300, UI_ELEMHEIGHT, "Game Genie:");
|
||||
input_par = new Fl_Input(400, 370, 300, UI_ELEMHEIGHT, "Pro Action Rocky:");
|
||||
|
||||
Fl_Button *btnadd = new Fl_Button(380, 400, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Add");
|
||||
btnadd->callback(cb_add, 0);
|
||||
Fl_Button *btnadd = new Fl_Button(400, 400, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Add");
|
||||
btnadd->callback(cb_add_s, 0);
|
||||
|
||||
Fl_Button *btntog = new Fl_Button(20, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Toggle");
|
||||
btntog->callback(cb_toggle, 0);
|
||||
Fl_Button *btntog = new Fl_Button(20, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Toggle");
|
||||
btntog->callback(cb_toggle_s, 0);
|
||||
|
||||
Fl_Button *btndel = new Fl_Button(110, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Delete");
|
||||
btndel->callback(cb_del, 0);
|
||||
Fl_Button *btndel = new Fl_Button(110, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Delete");
|
||||
btndel->callback(cb_del_s, 0);
|
||||
|
||||
Fl_Button *btnclr = new Fl_Button(200, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Clear");
|
||||
btnclr->callback(cb_clr, 0);
|
||||
Fl_Button *btnclr = new Fl_Button(200, 300, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Clear");
|
||||
btnclr->callback(cb_clear_s, 0);
|
||||
|
||||
Fl_Button *btnload = new Fl_Button(20, 350, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Load...");
|
||||
btnload->callback(cb_load, 0);
|
||||
Fl_Button *btnload = new Fl_Button(20, 350, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Load...");
|
||||
btnload->callback(cb_load_s, 0);
|
||||
|
||||
Fl_Button *btnsave = new Fl_Button(20, 380, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Save...");
|
||||
btnsave->callback(cb_save, 0);
|
||||
Fl_Button *btnsave = new Fl_Button(20, 380, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "Save...");
|
||||
btnsave->callback(cb_save_s, 0);
|
||||
|
||||
Fl_Button *btnok = new Fl_Button(560, 460, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "&OK");
|
||||
btnok->callback(cb_ok, 0);
|
||||
Fl_Button *btnok = new Fl_Button(620, 460, UI_ELEMWIDTH / 2, UI_ELEMHEIGHT, "OK");
|
||||
btnok->callback(cb_ok, 0);
|
||||
|
||||
this->end();
|
||||
this->end();
|
||||
}
|
||||
|
|
|
@ -1,14 +1,37 @@
|
|||
#ifndef _FLTKUI_CHEATS_H_
|
||||
#define _FLTKUI_CHEATS_H_
|
||||
#pragma once
|
||||
|
||||
#include "chtmanager.h"
|
||||
|
||||
class NstChtWindow : public Fl_Double_Window {
|
||||
|
||||
public:
|
||||
NstChtWindow(int w, int h, const char* t) : Fl_Double_Window(w, h, t) { }
|
||||
virtual ~NstChtWindow() { }
|
||||
NstChtWindow(int w, int h, const char* t, CheatManager& chtmgr);
|
||||
void refresh();
|
||||
void populate();
|
||||
|
||||
void refresh();
|
||||
void populate();
|
||||
private:
|
||||
void cb_del(Fl_Widget *w, void *data);
|
||||
static void cb_del_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_toggle(Fl_Widget *w, void *data);
|
||||
static void cb_toggle_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_add(Fl_Widget *w, void *data);
|
||||
static void cb_add_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_clear(Fl_Widget *w, void *data);
|
||||
static void cb_clear_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_load(Fl_Widget *w, void *data);
|
||||
static void cb_load_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_save(Fl_Widget *w, void *data);
|
||||
static void cb_save_s(Fl_Widget *w, void *data);
|
||||
|
||||
void cb_table(Fl_Widget *w, long rn);
|
||||
static void cb_table_s(Fl_Widget *w, long rn);
|
||||
|
||||
int rsel{0};
|
||||
|
||||
CheatManager& chtmgr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
void show_msgbox(bool show) { if (show) msgbox->show(); else msgbox->hide(); }
|
||||
|
||||
private:
|
||||
|
||||
void cb_chooser(Fl_Widget *w, void *data);
|
||||
static void cb_chooser_s(Fl_Widget *w, void *data);
|
||||
|
||||
|
|
|
@ -266,6 +266,14 @@ void JGManager::media_insert() {
|
|||
jg_media_insert();
|
||||
}
|
||||
|
||||
void JGManager::cheat_clear() {
|
||||
jg_cheat_clear();
|
||||
}
|
||||
|
||||
void JGManager::cheat_set(const char *code) {
|
||||
jg_cheat_set(code);
|
||||
}
|
||||
|
||||
int JGManager::get_frametime() {
|
||||
return frametime;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
void media_select();
|
||||
void media_insert();
|
||||
|
||||
void cheat_clear();
|
||||
void cheat_set(const char *code);
|
||||
|
||||
int get_frametime();
|
||||
|
||||
std::string& get_basepath();
|
||||
|
|
|
@ -95,10 +95,6 @@ SettingManager::SettingManager() {
|
|||
std::filesystem::create_directories(confpath);
|
||||
}
|
||||
|
||||
SettingManager::~SettingManager() {
|
||||
// Save frontend and emulator settings to the config file
|
||||
}
|
||||
|
||||
void SettingManager::read(JGManager& jgm) {
|
||||
// Read in any settings
|
||||
mINI::INIFile file(confpath + "/nestopia.conf");
|
||||
|
|
|
@ -12,7 +12,7 @@ constexpr unsigned FLAG_FRONTEND = 0x8000000;
|
|||
class SettingManager {
|
||||
public:
|
||||
SettingManager();
|
||||
~SettingManager();
|
||||
~SettingManager() {}
|
||||
|
||||
void read(JGManager& jgm);
|
||||
void write(JGManager& jgm);
|
||||
|
|
Loading…
Reference in a new issue