[config] Move VbamOption and wxGameControl to config namespace
This commit is contained in:
parent
297d7c06c4
commit
8c1bd84f40
1154
po/wxvbam/wxvbam.pot
1154
po/wxvbam/wxvbam.pot
File diff suppressed because it is too large
Load Diff
|
@ -736,14 +736,14 @@ set(
|
||||||
opts.cpp
|
opts.cpp
|
||||||
sys.cpp
|
sys.cpp
|
||||||
panel.cpp
|
panel.cpp
|
||||||
vbam-options.cpp
|
|
||||||
vbam-options-static.cpp
|
|
||||||
viewsupt.cpp
|
viewsupt.cpp
|
||||||
wayland.cpp
|
wayland.cpp
|
||||||
strutils.cpp
|
strutils.cpp
|
||||||
wxutil.cpp
|
wxutil.cpp
|
||||||
|
config/game-control.cpp
|
||||||
|
config/internal/option-internal.cpp
|
||||||
|
config/option.cpp
|
||||||
config/user-input.cpp
|
config/user-input.cpp
|
||||||
widgets/gamecontrol.cpp
|
|
||||||
widgets/keyedit.cpp
|
widgets/keyedit.cpp
|
||||||
widgets/joyedit.cpp
|
widgets/joyedit.cpp
|
||||||
widgets/sdljoy.cpp
|
widgets/sdljoy.cpp
|
||||||
|
@ -777,15 +777,15 @@ set(
|
||||||
filters.h
|
filters.h
|
||||||
ioregs.h
|
ioregs.h
|
||||||
opts.h
|
opts.h
|
||||||
vbam-options.h
|
|
||||||
vbam-options-internal.h
|
|
||||||
viewsupt.h
|
viewsupt.h
|
||||||
wxhead.h
|
wxhead.h
|
||||||
wayland.h
|
wayland.h
|
||||||
wxutil.h
|
wxutil.h
|
||||||
|
config/game-control.h
|
||||||
|
config/internal/option-internal.h
|
||||||
|
config/option.h
|
||||||
config/user-input.h
|
config/user-input.h
|
||||||
widgets/dpi-support.h
|
widgets/dpi-support.h
|
||||||
widgets/wx/gamecontrol.h
|
|
||||||
widgets/wx/keyedit.h
|
widgets/wx/keyedit.h
|
||||||
widgets/wx/joyedit.h
|
widgets/wx/joyedit.h
|
||||||
widgets/wx/sdljoy.h
|
widgets/wx/sdljoy.h
|
||||||
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
#include "config/game-control.h"
|
||||||
|
|
||||||
|
#include "../strutils.h"
|
||||||
|
#include "opts.h"
|
||||||
|
#include "wx/log.h"
|
||||||
|
#include "wxlogdebug.h"
|
||||||
|
|
||||||
|
namespace config {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr uint32_t kBitKeyA = (1 << 0);
|
||||||
|
constexpr uint32_t kBitKeyB = (1 << 1);
|
||||||
|
constexpr uint32_t kBitKeySelect = (1 << 2);
|
||||||
|
constexpr uint32_t kBitKeyStart = (1 << 3);
|
||||||
|
constexpr uint32_t kBitKeyRight = (1 << 4);
|
||||||
|
constexpr uint32_t kBitKeyLeft = (1 << 5);
|
||||||
|
constexpr uint32_t kBitKeyUp = (1 << 6);
|
||||||
|
constexpr uint32_t kBitKeyDown = (1 << 7);
|
||||||
|
constexpr uint32_t kBitKeyR = (1 << 8);
|
||||||
|
constexpr uint32_t kBitKeyL = (1 << 9);
|
||||||
|
constexpr uint32_t kBitKeySpeed = (1 << 10);
|
||||||
|
constexpr uint32_t kBitKeyCapture = (1 << 11);
|
||||||
|
constexpr uint32_t kBitKeyGameShark = (1 << 12);
|
||||||
|
constexpr uint32_t kBitKeyAutoA = (1 << 13);
|
||||||
|
constexpr uint32_t kBitKeyAutoB = (1 << 14);
|
||||||
|
constexpr uint32_t kBitKeyMotionUp = (1 << 15);
|
||||||
|
constexpr uint32_t kBitKeyMotionDown = (1 << 16);
|
||||||
|
constexpr uint32_t kBitKeyMotionLeft = (1 << 17);
|
||||||
|
constexpr uint32_t kBitKeyMotionRight = (1 << 18);
|
||||||
|
constexpr uint32_t kBitKeyMotionIn = (1 << 19);
|
||||||
|
constexpr uint32_t kBitKeyMotionOut = (1 << 20);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
constexpr std::array<uint32_t, kNbGameKeys> kBitMask = {
|
||||||
|
kBitKeyUp,
|
||||||
|
kBitKeyDown,
|
||||||
|
kBitKeyLeft,
|
||||||
|
kBitKeyRight,
|
||||||
|
kBitKeyA,
|
||||||
|
kBitKeyB,
|
||||||
|
kBitKeyL,
|
||||||
|
kBitKeyR,
|
||||||
|
kBitKeySelect,
|
||||||
|
kBitKeyStart,
|
||||||
|
kBitKeyMotionUp,
|
||||||
|
kBitKeyMotionDown,
|
||||||
|
kBitKeyMotionLeft,
|
||||||
|
kBitKeyMotionRight,
|
||||||
|
kBitKeyMotionIn,
|
||||||
|
kBitKeyMotionOut,
|
||||||
|
kBitKeyAutoA,
|
||||||
|
kBitKeyAutoB,
|
||||||
|
kBitKeySpeed,
|
||||||
|
kBitKeyCapture,
|
||||||
|
kBitKeyGameShark,
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
inline int GameKeyToInt(const GameKey& game_key) {
|
||||||
|
return static_cast<int>(game_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if `joypad` is in a valid joypad range.
|
||||||
|
inline bool JoypadInRange(const int& joypad) {
|
||||||
|
constexpr int kMinJoypadIndex = 0;
|
||||||
|
return joypad >= kMinJoypadIndex && joypad < kNbJoypads;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
wxString GameKeyToString(const GameKey& game_key) {
|
||||||
|
// Note: this must match GUI widget names or GUI won't work
|
||||||
|
// This array's order determines tab order as well
|
||||||
|
static const std::array<wxString, kNbGameKeys> kGameKeyStrings = {
|
||||||
|
"Up",
|
||||||
|
"Down",
|
||||||
|
"Left",
|
||||||
|
"Right",
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"L",
|
||||||
|
"R",
|
||||||
|
"Select",
|
||||||
|
"Start",
|
||||||
|
"MotionUp",
|
||||||
|
"MotionDown",
|
||||||
|
"MotionLeft",
|
||||||
|
"MotionRight",
|
||||||
|
"MotionIn",
|
||||||
|
"MotionOut",
|
||||||
|
"AutoA",
|
||||||
|
"AutoB",
|
||||||
|
"Speed",
|
||||||
|
"Capture",
|
||||||
|
"GS",
|
||||||
|
};
|
||||||
|
return kGameKeyStrings[GameKeyToInt(game_key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
nonstd::optional<GameKey> StringToGameKey(const wxString& input) {
|
||||||
|
static const std::map<wxString, GameKey> kStringToGameKey = {
|
||||||
|
{ "Up", GameKey::Up },
|
||||||
|
{ "Down", GameKey::Down },
|
||||||
|
{ "Left", GameKey::Left },
|
||||||
|
{ "Right", GameKey::Right },
|
||||||
|
{ "A", GameKey::A },
|
||||||
|
{ "B", GameKey::B },
|
||||||
|
{ "L", GameKey::L },
|
||||||
|
{ "R", GameKey::R },
|
||||||
|
{ "Select", GameKey::Select },
|
||||||
|
{ "Start", GameKey::Start },
|
||||||
|
{ "MotionUp", GameKey::MotionUp },
|
||||||
|
{ "MotionDown", GameKey::MotionDown },
|
||||||
|
{ "MotionLeft", GameKey::MotionLeft },
|
||||||
|
{ "MotionRight", GameKey::MotionRight },
|
||||||
|
{ "MotionIn", GameKey::MotionIn },
|
||||||
|
{ "MotionOut", GameKey::MotionOut },
|
||||||
|
{ "AutoA", GameKey::AutoA },
|
||||||
|
{ "AutoB", GameKey::AutoB },
|
||||||
|
{ "Speed", GameKey::Speed },
|
||||||
|
{ "Capture", GameKey::Capture },
|
||||||
|
{ "GS", GameKey::Gameshark },
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto iter = kStringToGameKey.find(input);
|
||||||
|
if (iter == kStringToGameKey.end()) {
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// static
|
||||||
|
nonstd::optional<GameControl> GameControl::FromString(const wxString& name) {
|
||||||
|
static const wxString kJoypad("Joypad");
|
||||||
|
if (!wxStrncmp(name, kJoypad, kJoypad.size())) {
|
||||||
|
wxLogDebug("Doesn't start with joypad");
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parts = strutils::split(name, "/");
|
||||||
|
if (parts.size() != 3) {
|
||||||
|
wxLogDebug("Wrong split size: %d", parts.size());
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int joypad = parts[1][0] - wxT('1');
|
||||||
|
if (!JoypadInRange(joypad)) {
|
||||||
|
wxLogDebug("Wrong joypad index: %d", joypad);
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
nonstd::optional<GameKey> game_key = StringToGameKey(parts[2]);
|
||||||
|
if (!game_key) {
|
||||||
|
wxLogDebug("Failed to parse game_key: %s", parts[2]);
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GameControl(joypad, game_key.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
GameControl::GameControl(int joypad, GameKey game_key)
|
||||||
|
: joypad_(joypad),
|
||||||
|
game_key_(game_key),
|
||||||
|
config_string_(wxString::Format("Joypad/%d/%s",
|
||||||
|
joypad_ + 1,
|
||||||
|
GameKeyToString(game_key_))) {
|
||||||
|
assert(JoypadInRange(joypad_));
|
||||||
|
}
|
||||||
|
GameControl::~GameControl() = default;
|
||||||
|
|
||||||
|
bool GameControl::operator==(const GameControl& other) const {
|
||||||
|
return joypad_ == other.joypad_ && game_key_ == other.game_key_;
|
||||||
|
}
|
||||||
|
bool GameControl::operator!=(const GameControl& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
bool GameControl::operator<(const GameControl& other) const {
|
||||||
|
if (joypad_ != other.joypad_) {
|
||||||
|
return joypad_ < other.joypad_;
|
||||||
|
}
|
||||||
|
if (game_key_ != other.game_key_) {
|
||||||
|
return game_key_ < other.game_key_;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool GameControl::operator<=(const GameControl& other) const {
|
||||||
|
return !(*this > other);
|
||||||
|
}
|
||||||
|
bool GameControl::operator>(const GameControl& other) const {
|
||||||
|
return other < *this;
|
||||||
|
}
|
||||||
|
bool GameControl::operator>=(const GameControl& other) const {
|
||||||
|
return !(*this < other);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameControlState& GameControlState::Instance() {
|
||||||
|
static GameControlState g_game_control_state;
|
||||||
|
return g_game_control_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameControlState::GameControlState() : joypads_({0, 0, 0, 0}) {}
|
||||||
|
GameControlState::~GameControlState() = default;
|
||||||
|
|
||||||
|
bool GameControlState::OnInputPressed(const config::UserInput& user_input) {
|
||||||
|
assert(user_input);
|
||||||
|
|
||||||
|
const auto& game_keys = input_bindings_.find(user_input);
|
||||||
|
if (game_keys == input_bindings_.end()) {
|
||||||
|
// No associated game control for `user_input`.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = keys_pressed_.find(user_input);
|
||||||
|
if (iter != keys_pressed_.end()) {
|
||||||
|
// Double press is noop.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember the key pressed.
|
||||||
|
keys_pressed_.emplace(user_input);
|
||||||
|
|
||||||
|
// Update all corresponding controls.
|
||||||
|
for (const GameControl& game_control : game_keys->second) {
|
||||||
|
active_controls_[game_control].emplace(user_input);
|
||||||
|
joypads_[game_control.joypad_] |=
|
||||||
|
kBitMask[GameKeyToInt(game_control.game_key_)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameControlState::OnInputReleased(const config::UserInput& user_input) {
|
||||||
|
assert(user_input);
|
||||||
|
|
||||||
|
const auto& game_keys = input_bindings_.find(user_input);
|
||||||
|
if (game_keys == input_bindings_.end()) {
|
||||||
|
// No associated game control for `user_input`.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = keys_pressed_.find(user_input);
|
||||||
|
if (iter == keys_pressed_.end()) {
|
||||||
|
// Double release is noop.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the key pressed.
|
||||||
|
keys_pressed_.erase(iter);
|
||||||
|
|
||||||
|
// Update all corresponding controls.
|
||||||
|
for (const GameControl& game_control : game_keys->second) {
|
||||||
|
auto active_controls = active_controls_.find(game_control);
|
||||||
|
if (active_controls == active_controls_.end()) {
|
||||||
|
// This should never happen.
|
||||||
|
assert(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
active_controls->second.erase(user_input);
|
||||||
|
if (active_controls->second.empty()) {
|
||||||
|
// Actually release control.
|
||||||
|
active_controls_.erase(active_controls);
|
||||||
|
joypads_[game_control.joypad_] &=
|
||||||
|
~kBitMask[GameKeyToInt(game_control.game_key_)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameControlState::Reset() {
|
||||||
|
active_controls_.clear();
|
||||||
|
keys_pressed_.clear();
|
||||||
|
joypads_.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameControlState::OnGameBindingsChanged() {
|
||||||
|
// We should reset to ensure no key remains accidentally pressed following a
|
||||||
|
// configuration change.
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
input_bindings_.clear();
|
||||||
|
for (const auto& iter : gopts.game_control_bindings) {
|
||||||
|
for (const auto& user_input : iter.second) {
|
||||||
|
input_bindings_[user_input].emplace(iter.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GameControlState::GetJoypad(int joypad) const {
|
||||||
|
assert(JoypadInRange(joypad));
|
||||||
|
return joypads_[joypad];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace config
|
|
@ -0,0 +1,144 @@
|
||||||
|
#ifndef VBAM_WX_CONFIG_GAME_CONTROL_H_
|
||||||
|
#define VBAM_WX_CONFIG_GAME_CONTROL_H_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include "nonstd/optional.hpp"
|
||||||
|
#include <set>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include "config/user-input.h"
|
||||||
|
|
||||||
|
namespace config {
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
class GameControlState;
|
||||||
|
|
||||||
|
//clang-format off
|
||||||
|
// Represents an in-game input.
|
||||||
|
enum class GameKey {
|
||||||
|
Up = 0,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
L,
|
||||||
|
R,
|
||||||
|
Select,
|
||||||
|
Start,
|
||||||
|
MotionUp,
|
||||||
|
MotionDown,
|
||||||
|
MotionLeft,
|
||||||
|
MotionRight,
|
||||||
|
MotionIn,
|
||||||
|
MotionOut,
|
||||||
|
AutoA,
|
||||||
|
AutoB,
|
||||||
|
Speed,
|
||||||
|
Capture,
|
||||||
|
Gameshark,
|
||||||
|
Last = Gameshark
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr int kNbGameKeys = static_cast<size_t>(GameKey::Last) + 1;
|
||||||
|
inline constexpr int kNbJoypads = 4;
|
||||||
|
|
||||||
|
inline constexpr std::array<GameKey, kNbGameKeys> kAllGameKeys = {
|
||||||
|
GameKey::Up,
|
||||||
|
GameKey::Down,
|
||||||
|
GameKey::Left,
|
||||||
|
GameKey::Right,
|
||||||
|
GameKey::A,
|
||||||
|
GameKey::B,
|
||||||
|
GameKey::L,
|
||||||
|
GameKey::R,
|
||||||
|
GameKey::Select,
|
||||||
|
GameKey::Start,
|
||||||
|
GameKey::MotionUp,
|
||||||
|
GameKey::MotionDown,
|
||||||
|
GameKey::MotionLeft,
|
||||||
|
GameKey::MotionRight,
|
||||||
|
GameKey::MotionIn,
|
||||||
|
GameKey::MotionOut,
|
||||||
|
GameKey::AutoA,
|
||||||
|
GameKey::AutoB,
|
||||||
|
GameKey::Speed,
|
||||||
|
GameKey::Capture,
|
||||||
|
GameKey::Gameshark,
|
||||||
|
};
|
||||||
|
//clang-format on
|
||||||
|
|
||||||
|
// Conversion utility method. Returns empty string on failure.
|
||||||
|
// This is O(1).
|
||||||
|
wxString GameKeyToString(const GameKey& game_key);
|
||||||
|
|
||||||
|
// Conversion utility method. Returns std::nullopt on failure.
|
||||||
|
// This is O(log(kNbGameKeys)).
|
||||||
|
nonstd::optional<GameKey> StringToGameKey(const wxString& input);
|
||||||
|
|
||||||
|
// Abstraction for an in-game control, wich is made of a player index (from 0
|
||||||
|
// to 3), and a GameKey.
|
||||||
|
class GameControl {
|
||||||
|
public:
|
||||||
|
// Converts a string to a GameControl. Returns std::nullopt on failure.
|
||||||
|
static nonstd::optional<GameControl> FromString(const wxString& name);
|
||||||
|
|
||||||
|
GameControl(int joypad, GameKey game_key);
|
||||||
|
~GameControl();
|
||||||
|
|
||||||
|
wxString ToString() const { return config_string_; };
|
||||||
|
|
||||||
|
bool operator==(const GameControl& other) const;
|
||||||
|
bool operator!=(const GameControl& other) const;
|
||||||
|
bool operator<(const GameControl& other) const;
|
||||||
|
bool operator<=(const GameControl& other) const;
|
||||||
|
bool operator>(const GameControl& other) const;
|
||||||
|
bool operator>=(const GameControl& other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int joypad_;
|
||||||
|
const GameKey game_key_;
|
||||||
|
const wxString config_string_;
|
||||||
|
|
||||||
|
friend class GameControlState;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tracks in-game input and computes the joypad value used to send control input
|
||||||
|
// data to the emulator.
|
||||||
|
class GameControlState {
|
||||||
|
public:
|
||||||
|
// This is a global singleton.
|
||||||
|
static GameControlState& Instance();
|
||||||
|
|
||||||
|
// Disable copy constructor and assignment operator.
|
||||||
|
GameControlState(const GameControlState&) = delete;
|
||||||
|
GameControlState& operator=(const GameControlState&) = delete;
|
||||||
|
|
||||||
|
// Processes `user_input` and updates the internal tracking state.
|
||||||
|
// Returns true if `user_input` corresponds to a game input.
|
||||||
|
bool OnInputPressed(const config::UserInput& user_input);
|
||||||
|
bool OnInputReleased(const config::UserInput& user_input);
|
||||||
|
|
||||||
|
// Clears all input.
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
// Recomputes internal bindinds. This is a potentially slow operation and
|
||||||
|
// should only be called when the game input configuration has been changed.
|
||||||
|
void OnGameBindingsChanged();
|
||||||
|
|
||||||
|
uint32_t GetJoypad(int joypad) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameControlState();
|
||||||
|
~GameControlState();
|
||||||
|
|
||||||
|
std::map<config::UserInput, std::set<GameControl>> input_bindings_;
|
||||||
|
std::map<GameControl, std::set<config::UserInput>> active_controls_;
|
||||||
|
std::set<config::UserInput> keys_pressed_;
|
||||||
|
std::array<uint32_t, kNbJoypads> joypads_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace config
|
||||||
|
|
||||||
|
#endif // VBAM_WX_CONFIG_GAME_CONTROL_H_
|
|
@ -0,0 +1,873 @@
|
||||||
|
#include "config/option.h"
|
||||||
|
|
||||||
|
// Helper implementation file to define and compile all of these huge constants
|
||||||
|
// separately. These should not be updated very often, so having these in a
|
||||||
|
// separate file improves incremental build time.
|
||||||
|
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "../common/ConfigManager.h"
|
||||||
|
#include "../gb/gbGlobals.h"
|
||||||
|
#include "opts.h"
|
||||||
|
|
||||||
|
#define VBAM_OPTION_INTERNAL_INCLUDE
|
||||||
|
#include "config/internal/option-internal.h"
|
||||||
|
#undef VBAM_OPTION_INTERNAL_INCLUDE
|
||||||
|
|
||||||
|
namespace config {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
// This enum must be kept in sync with the one in wxvbam.h
|
||||||
|
// TODO: These 2 enums should be unified and a validator created for this enum.
|
||||||
|
enum class FilterFunction {
|
||||||
|
kNone,
|
||||||
|
k2xsai,
|
||||||
|
kSuper2xsai,
|
||||||
|
kSupereagle,
|
||||||
|
kPixelate,
|
||||||
|
kAdvmame,
|
||||||
|
kBilinear,
|
||||||
|
kBilinearplus,
|
||||||
|
kScanlines,
|
||||||
|
kTvmode,
|
||||||
|
kHQ2x,
|
||||||
|
kLQ2x,
|
||||||
|
kSimple2x,
|
||||||
|
kSimple3x,
|
||||||
|
kHQ3x,
|
||||||
|
kSimple4x,
|
||||||
|
kHQ4x,
|
||||||
|
kXbrz2x,
|
||||||
|
kXbrz3x,
|
||||||
|
kXbrz4x,
|
||||||
|
kXbrz5x,
|
||||||
|
kXbrz6x,
|
||||||
|
kPlugin, // This must always be last.
|
||||||
|
|
||||||
|
// Do not add anything under here.
|
||||||
|
kLast,
|
||||||
|
};
|
||||||
|
constexpr size_t kNbFilterFunctions = static_cast<size_t>(FilterFunction::kLast);
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions of the enum above.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbFilterFunctions is automatically updated.
|
||||||
|
static const std::array<wxString, kNbFilterFunctions> kFilterStrings = {
|
||||||
|
"none",
|
||||||
|
"2xsai",
|
||||||
|
"super2xsai",
|
||||||
|
"supereagle",
|
||||||
|
"pixelate",
|
||||||
|
"advmame",
|
||||||
|
"bilinear",
|
||||||
|
"bilinearplus",
|
||||||
|
"scanlines",
|
||||||
|
"tvmode",
|
||||||
|
"hq2x",
|
||||||
|
"lq2x",
|
||||||
|
"simple2x",
|
||||||
|
"simple3x",
|
||||||
|
"hq3x",
|
||||||
|
"simple4x",
|
||||||
|
"hq4x",
|
||||||
|
"xbrz2x",
|
||||||
|
"xbrz3x",
|
||||||
|
"xbrz4x",
|
||||||
|
"xbrz5x",
|
||||||
|
"xbrz6x",
|
||||||
|
"plugin",
|
||||||
|
};
|
||||||
|
|
||||||
|
// This enum must be kept in sync with the one in wxvbam.h
|
||||||
|
// TODO: These 2 enums should be unified and a validator created for this enum.
|
||||||
|
enum class Interframe {
|
||||||
|
kNone = 0,
|
||||||
|
kSmart,
|
||||||
|
kMotionBlur,
|
||||||
|
|
||||||
|
// Do not add anything under here.
|
||||||
|
kLast,
|
||||||
|
};
|
||||||
|
constexpr size_t kNbInterframes = static_cast<size_t>(Interframe::kLast);
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions of the enum above.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbInterframes is automatically updated.
|
||||||
|
static const std::array<wxString, kNbInterframes> kInterframeStrings = {
|
||||||
|
"none",
|
||||||
|
"smart",
|
||||||
|
"motionblur",
|
||||||
|
};
|
||||||
|
|
||||||
|
// This enum must be kept in sync with the one in wxvbam.h
|
||||||
|
// TODO: These 2 enums should be unified and a validator created for this enum.
|
||||||
|
enum class RenderMethod {
|
||||||
|
kSimple = 0,
|
||||||
|
kOpenGL,
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
kDirect3d,
|
||||||
|
#elif defined(__WXMAC__)
|
||||||
|
kQuartz2d,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Do not add anything under here.
|
||||||
|
kLast,
|
||||||
|
};
|
||||||
|
constexpr size_t kNbRenderMethods = static_cast<size_t>(RenderMethod::kLast);
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions of the enum above.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbRenderMethods is automatically updated.
|
||||||
|
static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
||||||
|
"simple",
|
||||||
|
"opengl",
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
"direct3d",
|
||||||
|
#elif defined(__WXMAC__)
|
||||||
|
"quartz2d",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// This enum must be kept in sync with the one in wxvbam.h
|
||||||
|
// TODO: These 2 enums should be unified and a validator created for this enum.
|
||||||
|
// TODO: DirectSound and XAudio2 should only be used on Windows.
|
||||||
|
enum class AudioApi {
|
||||||
|
kSdl = 0,
|
||||||
|
kOpenAL,
|
||||||
|
kDirectSound,
|
||||||
|
kXAudio2,
|
||||||
|
kFaudio,
|
||||||
|
|
||||||
|
// Do not add anything under here.
|
||||||
|
kLast,
|
||||||
|
};
|
||||||
|
constexpr size_t kNbAudioApis = static_cast<size_t>(AudioApi::kLast);
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions of the enum above.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbAudioApis is automatically updated.
|
||||||
|
static const std::array<wxString, kNbAudioApis> kAudioApiStrings = {
|
||||||
|
"sdl",
|
||||||
|
"openal",
|
||||||
|
"directsound",
|
||||||
|
"xaudio2",
|
||||||
|
"faudio",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SoundQuality {
|
||||||
|
k48kHz = 0,
|
||||||
|
k44kHz,
|
||||||
|
k22kHz,
|
||||||
|
k11kHz,
|
||||||
|
|
||||||
|
// Do not add anything under here.
|
||||||
|
kLast,
|
||||||
|
};
|
||||||
|
constexpr size_t kNbSoundQualities = static_cast<size_t>(SoundQuality::kLast);
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions of the enum above.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbSoundQualities is automatically updated.
|
||||||
|
static const std::array<wxString, kNbSoundQualities> kSoundQualityStrings = {
|
||||||
|
"48",
|
||||||
|
"44",
|
||||||
|
"22",
|
||||||
|
"11",
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Builds the "all enum values" string for a given array defined above.
|
||||||
|
template <std::size_t SIZE>
|
||||||
|
wxString AllEnumValuesForArray(const std::array<wxString, SIZE>& input) {
|
||||||
|
// 15 characters per option is a reasonable higher bound. Probably.
|
||||||
|
static constexpr size_t kMaxOptionLength = 15u;
|
||||||
|
|
||||||
|
wxString all_options;
|
||||||
|
all_options.reserve(kMaxOptionLength * SIZE);
|
||||||
|
|
||||||
|
std::for_each(input.cbegin(), input.cend(),
|
||||||
|
[&all_options](const auto& elt) {
|
||||||
|
all_options.append(elt);
|
||||||
|
all_options.append('|');
|
||||||
|
});
|
||||||
|
// Remove last value
|
||||||
|
all_options.RemoveLast(1u);
|
||||||
|
return all_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::array<Option, kNbOptions>& Option::AllOptions() {
|
||||||
|
// These MUST follow the same order as the definitions in OptionID.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbOptions is automatically updated.
|
||||||
|
// This will be initialized on the first call, in load_opts(), ensuring the
|
||||||
|
// translation initialization has already happened.
|
||||||
|
static std::array<Option, kNbOptions> g_all_opts = {
|
||||||
|
/// Display
|
||||||
|
Option(OptionID::kDisplayBilinear, &gopts.bilinear),
|
||||||
|
Option(OptionID::kDisplayFilter, &gopts.filter),
|
||||||
|
Option(OptionID::kDisplayFilterPlugin, &gopts.filter_plugin),
|
||||||
|
Option(OptionID::kDisplayIFB, &gopts.ifb),
|
||||||
|
Option(OptionID::kDisplayKeepOnTop, &gopts.keep_on_top),
|
||||||
|
Option(OptionID::kDisplayMaxThreads, &gopts.max_threads, 1, 256),
|
||||||
|
Option(OptionID::kDisplayRenderMethod, &gopts.render_method),
|
||||||
|
Option(OptionID::kDisplayScale, &gopts.video_scale, 1, 6),
|
||||||
|
Option(OptionID::kDisplayStretch, &gopts.retain_aspect),
|
||||||
|
|
||||||
|
/// GB
|
||||||
|
Option(OptionID::kGBBiosFile, &gopts.gb_bios),
|
||||||
|
Option(OptionID::kGBColorOption, &gbColorOption, 0, 1),
|
||||||
|
Option(OptionID::kGBColorizerHack, &colorizerHack, 0, 1),
|
||||||
|
Option(OptionID::kGBLCDFilter, &gbLcdFilter),
|
||||||
|
Option(OptionID::kGBGBCBiosFile, &gopts.gbc_bios),
|
||||||
|
Option(OptionID::kGBPalette0, systemGbPalette),
|
||||||
|
Option(OptionID::kGBPalette1, systemGbPalette + 8),
|
||||||
|
Option(OptionID::kGBPalette2, systemGbPalette + 16),
|
||||||
|
Option(OptionID::kGBPrintAutoPage, &gopts.print_auto_page),
|
||||||
|
Option(OptionID::kGBPrintScreenCap, &gopts.print_screen_cap),
|
||||||
|
Option(OptionID::kGBROMDir, &gopts.gb_rom_dir),
|
||||||
|
Option(OptionID::kGBGBCROMDir, &gopts.gbc_rom_dir),
|
||||||
|
|
||||||
|
/// GBA
|
||||||
|
Option(OptionID::kGBABiosFile, &gopts.gba_bios),
|
||||||
|
Option(OptionID::kGBALCDFilter, &gbaLcdFilter),
|
||||||
|
#ifndef NO_LINK
|
||||||
|
Option(OptionID::kGBALinkAuto, &gopts.link_auto),
|
||||||
|
Option(OptionID::kGBALinkFast, &linkHacks, 0, 1),
|
||||||
|
Option(OptionID::kGBALinkHost, &gopts.link_host),
|
||||||
|
Option(OptionID::kGBAServerIP, &gopts.server_ip),
|
||||||
|
Option(OptionID::kGBALinkPort, &gopts.link_port, 0, 65535),
|
||||||
|
Option(OptionID::kGBALinkProto, &gopts.link_proto, 0, 1),
|
||||||
|
Option(OptionID::kGBALinkTimeout, &linkTimeout, 0, 9999999),
|
||||||
|
Option(OptionID::kGBALinkType, &gopts.gba_link_type, 0, 5),
|
||||||
|
#endif
|
||||||
|
Option(OptionID::kGBAROMDir, &gopts.gba_rom_dir),
|
||||||
|
|
||||||
|
/// General
|
||||||
|
Option(OptionID::kGeneralAutoLoadLastState, &gopts.autoload_state),
|
||||||
|
Option(OptionID::kGeneralBatteryDir, &gopts.battery_dir),
|
||||||
|
Option(OptionID::kGeneralFreezeRecent, &gopts.recent_freeze),
|
||||||
|
Option(OptionID::kGeneralRecordingDir, &gopts.recording_dir),
|
||||||
|
Option(OptionID::kGeneralRewindInterval, &gopts.rewind_interval, 0,
|
||||||
|
600),
|
||||||
|
Option(OptionID::kGeneralScreenshotDir, &gopts.scrshot_dir),
|
||||||
|
Option(OptionID::kGeneralStateDir, &gopts.state_dir),
|
||||||
|
Option(OptionID::kGeneralStatusBar, &gopts.statusbar, 0, 1),
|
||||||
|
|
||||||
|
/// Joypad
|
||||||
|
Option(OptionID::kJoypad),
|
||||||
|
Option(OptionID::kJoypadAutofireThrottle, &gopts.autofire_rate, 1,
|
||||||
|
1000),
|
||||||
|
Option(OptionID::kJoypadDefault, &gopts.default_stick, 1, 4),
|
||||||
|
|
||||||
|
/// Keyboard
|
||||||
|
Option(OptionID::kKeyboard),
|
||||||
|
|
||||||
|
// Core
|
||||||
|
Option(OptionID::kpreferencesagbPrint, &agbPrint, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesautoFrameSkip, &autoFrameSkip, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesautoPatch, &autoPatch, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesautoSaveLoadCheatList,
|
||||||
|
&gopts.autoload_cheats),
|
||||||
|
Option(OptionID::kpreferencesborderAutomatic, &gbBorderAutomatic, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesborderOn, &gbBorderOn, 0, 1),
|
||||||
|
Option(OptionID::kpreferencescaptureFormat, &captureFormat, 0, 1),
|
||||||
|
Option(OptionID::kpreferencescheatsEnabled, &cheatsEnabled, 0, 1),
|
||||||
|
#ifdef MMX
|
||||||
|
Option(OptionID::kpreferencesenableMMX, &enableMMX, 0, 1),
|
||||||
|
#endif
|
||||||
|
Option(OptionID::kpreferencesdisableStatus, &disableStatusMessages, 0,
|
||||||
|
1),
|
||||||
|
Option(OptionID::kpreferencesemulatorType, &gbEmulatorType, 0, 5),
|
||||||
|
Option(OptionID::kpreferencesflashSize, &optFlashSize, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesframeSkip, &frameSkip, -1, 9),
|
||||||
|
Option(OptionID::kpreferencesfsColorDepth, &fsColorDepth, 0, 999),
|
||||||
|
Option(OptionID::kpreferencesfsFrequency, &fsFrequency, 0, 999),
|
||||||
|
Option(OptionID::kpreferencesfsHeight, &fsHeight, 0, 99999),
|
||||||
|
Option(OptionID::kpreferencesfsWidth, &fsWidth, 0, 99999),
|
||||||
|
Option(OptionID::kpreferencesgbPaletteOption, &gbPaletteOption, 0, 2),
|
||||||
|
Option(OptionID::kpreferencesgbPrinter, &winGbPrinterEnabled, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesgdbBreakOnLoad, &gdbBreakOnLoad, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesgdbPort, &gdbPort, 0, 65535),
|
||||||
|
#ifndef NO_LINK
|
||||||
|
Option(OptionID::kpreferencesLinkNumPlayers, &linkNumPlayers, 2, 4),
|
||||||
|
#endif
|
||||||
|
Option(OptionID::kpreferencesmaxScale, &maxScale, 0, 100),
|
||||||
|
Option(OptionID::kpreferencespauseWhenInactive, &pauseWhenInactive, 0,
|
||||||
|
1),
|
||||||
|
Option(OptionID::kpreferencesrtcEnabled, &rtcEnabled, 0, 1),
|
||||||
|
Option(OptionID::kpreferencessaveType, &cpuSaveType, 0, 5),
|
||||||
|
Option(OptionID::kpreferencesshowSpeed, &showSpeed, 0, 2),
|
||||||
|
Option(OptionID::kpreferencesshowSpeedTransparent,
|
||||||
|
&showSpeedTransparent, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesskipBios, &skipBios, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesskipSaveGameCheats, &skipSaveGameCheats, 0,
|
||||||
|
1),
|
||||||
|
Option(OptionID::kpreferencesskipSaveGameBattery, &skipSaveGameBattery,
|
||||||
|
0, 1),
|
||||||
|
Option(OptionID::kpreferencesthrottle, &throttle, 0, 450),
|
||||||
|
Option(OptionID::kpreferencesspeedupThrottle, &speedup_throttle, 0,
|
||||||
|
3000),
|
||||||
|
Option(OptionID::kpreferencesspeedupFrameSkip, &speedup_frame_skip, 0,
|
||||||
|
300),
|
||||||
|
Option(OptionID::kpreferencesspeedupThrottleFrameSkip,
|
||||||
|
&speedup_throttle_frame_skip),
|
||||||
|
Option(OptionID::kpreferencesuseBiosGB, &useBiosFileGB, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesuseBiosGBA, &useBiosFileGBA, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesuseBiosGBC, &useBiosFileGBC, 0, 1),
|
||||||
|
Option(OptionID::kpreferencesvsync, &vsync, 0, 1),
|
||||||
|
|
||||||
|
/// Geometry
|
||||||
|
Option(OptionID::kgeometryfullScreen, &fullScreen, 0, 1),
|
||||||
|
Option(OptionID::kgeometryisMaximized, &windowMaximized, 0, 1),
|
||||||
|
Option(OptionID::kgeometrywindowHeight, &windowHeight, 0, 99999),
|
||||||
|
Option(OptionID::kgeometrywindowWidth, &windowWidth, 0, 99999),
|
||||||
|
Option(OptionID::kgeometrywindowX, &windowPositionX, -1, 99999),
|
||||||
|
Option(OptionID::kgeometrywindowY, &windowPositionY, -1, 99999),
|
||||||
|
|
||||||
|
/// UI
|
||||||
|
Option(OptionID::kuiallowKeyboardBackgroundInput,
|
||||||
|
&allowKeyboardBackgroundInput),
|
||||||
|
Option(OptionID::kuiallowJoystickBackgroundInput,
|
||||||
|
&allowJoystickBackgroundInput),
|
||||||
|
Option(OptionID::kuihideMenuBar, &gopts.hide_menu_bar),
|
||||||
|
|
||||||
|
/// Sound
|
||||||
|
Option(OptionID::kSoundAudioAPI, &gopts.audio_api),
|
||||||
|
Option(OptionID::kSoundAudioDevice, &gopts.audio_dev),
|
||||||
|
Option(OptionID::kSoundBuffers, &gopts.audio_buffers, 2, 10),
|
||||||
|
Option(OptionID::kSoundEnable, &gopts.sound_en, 0, 0x30f),
|
||||||
|
Option(OptionID::kSoundGBAFiltering, &gopts.gba_sound_filter, 0, 100),
|
||||||
|
Option(OptionID::kSoundGBAInterpolation, &gopts.soundInterpolation),
|
||||||
|
Option(OptionID::kSoundGBDeclicking, &gopts.gb_declick),
|
||||||
|
Option(OptionID::kSoundGBEcho, &gopts.gb_echo, 0, 100),
|
||||||
|
Option(OptionID::kSoundGBEnableEffects,
|
||||||
|
&gopts.gb_effects_config_enabled),
|
||||||
|
Option(OptionID::kSoundGBStereo, &gopts.gb_stereo, 0, 100),
|
||||||
|
Option(OptionID::kSoundGBSurround, &gopts.gb_effects_config_surround),
|
||||||
|
Option(OptionID::kSoundQuality, &gopts.sound_qual),
|
||||||
|
Option(OptionID::kSoundVolume, &gopts.sound_vol, 0, 200),
|
||||||
|
};
|
||||||
|
return g_all_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// These MUST follow the same order as the definitions in OptionID.
|
||||||
|
// Adding an option without adding to this array will result in a compiler
|
||||||
|
// error since kNbOptions is automatically updated.
|
||||||
|
const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||||
|
/// Display
|
||||||
|
OptionData{"Display/Bilinear", "Bilinear",
|
||||||
|
_("Use bilinear filter with 3d renderer"), Option::Type::kBool},
|
||||||
|
OptionData{"Display/Filter", "", _("Full-screen filter to apply"),
|
||||||
|
Option::Type::kFilter},
|
||||||
|
OptionData{"Display/FilterPlugin", "", _("Filter plugin library"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"Display/IFB", "", _("Interframe blending function"),
|
||||||
|
Option::Type::kInterframe},
|
||||||
|
OptionData{"Display/KeepOnTop", "KeepOnTop", _("Keep window on top"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"Display/MaxThreads", "Multithread",
|
||||||
|
_("Maximum number of threads to run filters in"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Display/RenderMethod", "",
|
||||||
|
_("Render method; if unsupported, simple method will be used"),
|
||||||
|
Option::Type::kRenderMethod},
|
||||||
|
OptionData{"Display/Scale", "", _("Default scale factor"),
|
||||||
|
Option::Type::kDouble},
|
||||||
|
OptionData{"Display/Stretch", "RetainAspect",
|
||||||
|
_("Retain aspect ratio when resizing"), Option::Type::kBool},
|
||||||
|
|
||||||
|
/// GB
|
||||||
|
OptionData{"GB/BiosFile", "", _("BIOS file to use for GB, if enabled"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GB/ColorOption", "GBColorOption",
|
||||||
|
_("GB color enhancement, if enabled"), Option::Type::kInt},
|
||||||
|
OptionData{"GB/ColorizerHack", "ColorizerHack",
|
||||||
|
_("Enable DX Colorization Hacks"), Option::Type::kInt},
|
||||||
|
OptionData{"GB/LCDFilter", "GBLcdFilter", _("Apply LCD filter, if enabled"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"GB/GBCBiosFile", "", _("BIOS file to use for GBC, if enabled"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GB/Palette0", "",
|
||||||
|
_("The default palette, as 8 comma-separated 4-digit hex "
|
||||||
|
"integers (rgb555)."),
|
||||||
|
Option::Type::kGbPalette},
|
||||||
|
OptionData{"GB/Palette1", "",
|
||||||
|
_("The first user palette, as 8 comma-separated 4-digit hex "
|
||||||
|
"integers (rgb555)."),
|
||||||
|
Option::Type::kGbPalette},
|
||||||
|
OptionData{"GB/Palette2", "",
|
||||||
|
_("The second user palette, as 8 comma-separated 4-digit hex "
|
||||||
|
"integers (rgb555)."),
|
||||||
|
Option::Type::kGbPalette},
|
||||||
|
OptionData{"GB/PrintAutoPage", "PrintGather",
|
||||||
|
_("Automatically gather a full page before printing"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{
|
||||||
|
"GB/PrintScreenCap", "PrintSnap",
|
||||||
|
_("Automatically save printouts as screen captures with -print suffix"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"GB/ROMDir", "", _("Directory to look for ROM files"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GB/GBCROMDir", "", _("Directory to look for GBC ROM files"),
|
||||||
|
Option::Type::kString},
|
||||||
|
|
||||||
|
/// GBA
|
||||||
|
OptionData{"GBA/BiosFile", "", _("BIOS file to use, if enabled"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GBA/LCDFilter", "GBALcdFilter",
|
||||||
|
_("Apply LCD filter, if enabled"), Option::Type::kBool},
|
||||||
|
#ifndef NO_LINK
|
||||||
|
OptionData{"GBA/LinkAuto", "LinkAuto", _("Enable link at boot"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"GBA/LinkFast", "SpeedOn",
|
||||||
|
_("Enable faster network protocol by default"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"GBA/LinkHost", "", _("Default network link client host"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GBA/ServerIP", "", _("Default network link server IP to bind"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"GBA/LinkPort", "",
|
||||||
|
_("Default network link port (server and client)"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"GBA/LinkProto", "LinkProto", _("Default network protocol"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"GBA/LinkTimeout", "LinkTimeout", _("Link timeout (ms)"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"GBA/LinkType", "LinkType", _("Link cable type"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
#endif
|
||||||
|
OptionData{"GBA/ROMDir", "", _("Directory to look for ROM files"),
|
||||||
|
Option::Type::kString},
|
||||||
|
|
||||||
|
/// General
|
||||||
|
OptionData{"General/AutoLoadLastState", "",
|
||||||
|
_("Automatically load last saved state"), Option::Type::kBool},
|
||||||
|
OptionData{"General/BatteryDir", "",
|
||||||
|
_("Directory to store game save files (relative paths are "
|
||||||
|
"relative to ROM; blank is config dir)"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"General/FreezeRecent", "", _("Freeze recent load list"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"General/RecordingDir", "",
|
||||||
|
_("Directory to store A/V and game recordings (relative paths "
|
||||||
|
"are relative to ROM)"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"General/RewindInterval", "",
|
||||||
|
_("Number of seconds between rewind snapshots (0 to disable)"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"General/ScreenshotDir", "",
|
||||||
|
_("Directory to store screenshots (relative paths are relative "
|
||||||
|
"to ROM)"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"General/StateDir", "",
|
||||||
|
_("Directory to store saved state files (relative paths are "
|
||||||
|
"relative to BatteryDir)"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"General/StatusBar", "StatusBar", _("Enable status bar"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
|
||||||
|
/// Joypad
|
||||||
|
OptionData{"Joypad/*/*", "",
|
||||||
|
_("The parameter Joypad/<n>/<button> contains a comma-separated "
|
||||||
|
"list of key names which map to joypad #<n> button <button>. "
|
||||||
|
"Button is one of Up, Down, Left, Right, A, B, L, R, Select, "
|
||||||
|
"Start, MotionUp, MotionDown, MotionLeft, MotionRight, AutoA, "
|
||||||
|
"AutoB, Speed, Capture, GS"),
|
||||||
|
Option::Type::kNone},
|
||||||
|
OptionData{"Joypad/AutofireThrottle", "",
|
||||||
|
_("The autofire toggle period, in frames (1/60 s)"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Joypad/Default", "",
|
||||||
|
_("The number of the stick to use in single-player mode"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
|
||||||
|
/// Keyboard
|
||||||
|
OptionData{"Keyboard/*", "",
|
||||||
|
_("The parameter Keyboard/<cmd> contains a comma-separated list "
|
||||||
|
"of key names (e.g. Alt-Shift-F1). When the named key is "
|
||||||
|
"pressed, the command <cmd> is executed."),
|
||||||
|
Option::Type::kNone},
|
||||||
|
|
||||||
|
// Core
|
||||||
|
OptionData{"preferences/agbPrint", "AGBPrinter",
|
||||||
|
_("Enable AGB debug print"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/autoFrameSkip", "FrameSkipAuto",
|
||||||
|
_("Auto skip frames."), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/autoPatch", "ApplyPatches",
|
||||||
|
_("Apply IPS/UPS/IPF patches if found"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/autoSaveLoadCheatList", "",
|
||||||
|
_("Automatically save and load cheat list"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"preferences/borderAutomatic", "",
|
||||||
|
_("Automatically enable border for Super GameBoy games"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/borderOn", "", _("Always enable border"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/captureFormat", "", _("Screen capture file format"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/cheatsEnabled", "", _("Enable cheats"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
#ifdef MMX
|
||||||
|
OptionData{"preferences/enableMMX", "MMX", _("Enable MMX"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
#endif
|
||||||
|
OptionData{"preferences/disableStatus", "NoStatusMsg",
|
||||||
|
_("Disable on-screen status messages"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/emulatorType", "", _("Type of system to emulate"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/flashSize", "", _("Flash size 0 = 64KB 1 = 128KB"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/frameSkip", "FrameSkip",
|
||||||
|
_("Skip frames. Values are 0-9 or -1 to skip automatically "
|
||||||
|
"based on time."),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/fsColorDepth", "",
|
||||||
|
_("Fullscreen mode color depth (0 = any)"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/fsFrequency", "",
|
||||||
|
_("Fullscreen mode frequency (0 = any)"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/fsHeight", "",
|
||||||
|
_("Fullscreen mode height (0 = desktop)"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/fsWidth", "",
|
||||||
|
_("Fullscreen mode width (0 = desktop)"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/gbPaletteOption", "", _("The palette to use"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/gbPrinter", "Printer",
|
||||||
|
_("Enable printer emulation"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/gdbBreakOnLoad", "DebugGDBBreakOnLoad",
|
||||||
|
_("Break into GDB after loading the game."), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/gdbPort", "DebugGDBPort",
|
||||||
|
_("Port to connect GDB to."), Option::Type::kInt},
|
||||||
|
#ifndef NO_LINK
|
||||||
|
OptionData{"preferences/LinkNumPlayers", "",
|
||||||
|
_("Number of players in network"), Option::Type::kInt},
|
||||||
|
#endif
|
||||||
|
OptionData{"preferences/maxScale", "",
|
||||||
|
_("Maximum scale factor (0 = no limit)"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/pauseWhenInactive", "PauseWhenInactive",
|
||||||
|
_("Pause game when main window loses focus"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/rtcEnabled", "RTC",
|
||||||
|
_("Enable RTC (vba-over.ini override is rtcEnabled"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/saveType", "",
|
||||||
|
_("Native save (\"battery\") hardware type"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/showSpeed", "", _("Show speed indicator"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/showSpeedTransparent", "Transparent",
|
||||||
|
_("Draw on-screen messages transparently"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/skipBios", "SkipIntro",
|
||||||
|
_("Skip BIOS initialization"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/skipSaveGameCheats", "",
|
||||||
|
_("Do not overwrite cheat list when loading state"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/skipSaveGameBattery", "",
|
||||||
|
_("Do not overwrite native (battery) save when loading state"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"preferences/throttle", "",
|
||||||
|
_("Throttle game speed, even when accelerated (0-450%, 0 = no "
|
||||||
|
"throttle)"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"preferences/speedupThrottle", "",
|
||||||
|
_("Set throttle for speedup key (0-3000%, 0 = no throttle)"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"preferences/speedupFrameSkip", "",
|
||||||
|
_("Number of frames to skip with speedup (instead of speedup "
|
||||||
|
"throttle)"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"preferences/speedupThrottleFrameSkip", "",
|
||||||
|
_("Use frame skip for speedup throttle"), Option::Type::kBool},
|
||||||
|
OptionData{"preferences/useBiosGB", "BootRomGB",
|
||||||
|
_("Use the specified BIOS file for GB"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/useBiosGBA", "BootRomEn",
|
||||||
|
_("Use the specified BIOS file"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/useBiosGBC", "BootRomGBC",
|
||||||
|
_("Use the specified BIOS file for GBC"), Option::Type::kInt},
|
||||||
|
OptionData{"preferences/vsync", "VSync", _("Wait for vertical sync"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
|
||||||
|
/// Geometry
|
||||||
|
OptionData{"geometry/fullScreen", "Fullscreen",
|
||||||
|
_("Enter fullscreen mode at startup"), Option::Type::kInt},
|
||||||
|
OptionData{"geometry/isMaximized", "Maximized", _("Window maximized"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"geometry/windowHeight", "Height", _("Window height at startup"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"geometry/windowWidth", "Width", _("Window width at startup"),
|
||||||
|
Option::Type::kUnsigned},
|
||||||
|
OptionData{"geometry/windowX", "X", _("Window axis X position at startup"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"geometry/windowY", "Y", _("Window axis Y position at startup"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
|
||||||
|
/// UI
|
||||||
|
OptionData{
|
||||||
|
"ui/allowKeyboardBackgroundInput", "AllowKeyboardBackgroundInput",
|
||||||
|
_("Capture key events while on background"), Option::Type::kBool},
|
||||||
|
OptionData{
|
||||||
|
"ui/allowJoystickBackgroundInput", "AllowJoystickBackgroundInput",
|
||||||
|
_("Capture joy events while on background"), Option::Type::kBool},
|
||||||
|
OptionData{"ui/hideMenuBar", "", _("Hide menu bar when mouse is inactive"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
|
||||||
|
/// Sound
|
||||||
|
OptionData{"Sound/AudioAPI", "",
|
||||||
|
_("Sound API; if unsupported, default API will be used"),
|
||||||
|
Option::Type::kAudioApi},
|
||||||
|
OptionData{"Sound/AudioDevice", "",
|
||||||
|
_("Device ID of chosen audio device for chosen driver"),
|
||||||
|
Option::Type::kString},
|
||||||
|
OptionData{"Sound/Buffers", "", _("Number of sound buffers"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Sound/Enable", "", _("Bit mask of sound channels to enable"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Sound/GBAFiltering", "", _("GBA sound filtering (%)"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Sound/GBAInterpolation", "GBASoundInterpolation",
|
||||||
|
_("GBA sound interpolation"), Option::Type::kBool},
|
||||||
|
OptionData{"Sound/GBDeclicking", "GBDeclicking", _("GB sound declicking"),
|
||||||
|
Option::Type::kBool},
|
||||||
|
OptionData{"Sound/GBEcho", "", _("GB echo effect (%)"), Option::Type::kInt},
|
||||||
|
OptionData{"Sound/GBEnableEffects", "GBEnhanceSound",
|
||||||
|
_("Enable GB sound effects"), Option::Type::kBool},
|
||||||
|
OptionData{"Sound/GBStereo", "", _("GB stereo effect (%)"),
|
||||||
|
Option::Type::kInt},
|
||||||
|
OptionData{"Sound/GBSurround", "GBSurround",
|
||||||
|
_("GB surround sound effect (%)"), Option::Type::kBool},
|
||||||
|
OptionData{"Sound/Quality", "", _("Sound sample rate (kHz)"),
|
||||||
|
Option::Type::kSoundQuality},
|
||||||
|
OptionData{"Sound/Volume", "", _("Sound volume (%)"), Option::Type::kInt},
|
||||||
|
|
||||||
|
// Last. This should never be used, it actually maps to OptionID::kLast.
|
||||||
|
// This is to prevent a memory access violation error in case something
|
||||||
|
// attempts to instantiate a OptionID::kLast. It will trigger a check
|
||||||
|
// in the Option constructor, but that is after the constructor has
|
||||||
|
// accessed this entry.
|
||||||
|
OptionData{"", "", "", Option::Type::kNone},
|
||||||
|
};
|
||||||
|
|
||||||
|
nonstd::optional<OptionID> StringToOptionId(const wxString& input) {
|
||||||
|
static std::map<wxString, OptionID> kStringToOptionId;
|
||||||
|
if (kStringToOptionId.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbOptions; i++) {
|
||||||
|
kStringToOptionId.emplace(kAllOptionsData[i].config_name,
|
||||||
|
static_cast<OptionID>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToOptionId.size() == kNbOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToOptionId.find(input);
|
||||||
|
if (iter == kStringToOptionId.end()) {
|
||||||
|
return nonstd::nullopt;
|
||||||
|
}
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString FilterToString(int value) {
|
||||||
|
assert(value >= 0 && static_cast<size_t>(value) < kNbFilterFunctions);
|
||||||
|
return kFilterStrings[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString InterframeToString(int value) {
|
||||||
|
assert(value >= 0 && static_cast<size_t>(value) < kNbInterframes);
|
||||||
|
return kInterframeStrings[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString RenderMethodToString(int value) {
|
||||||
|
assert(value >= 0 && static_cast<size_t>(value) < kNbRenderMethods);
|
||||||
|
return kRenderMethodStrings[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString AudioApiToString(int value) {
|
||||||
|
assert(value >= 0 && static_cast<size_t>(value) < kNbAudioApis);
|
||||||
|
return kAudioApiStrings[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString SoundQualityToString(int value) {
|
||||||
|
assert(value >= 0 && static_cast<size_t>(value) < kNbSoundQualities);
|
||||||
|
return kSoundQualityStrings[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringToFilter(const wxString& config_name, const wxString& input) {
|
||||||
|
static std::map<wxString, FilterFunction> kStringToFilter;
|
||||||
|
if (kStringToFilter.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbFilterFunctions; i++) {
|
||||||
|
kStringToFilter.emplace(kFilterStrings[i],
|
||||||
|
static_cast<FilterFunction>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToFilter.size() == kNbFilterFunctions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToFilter.find(input);
|
||||||
|
if (iter == kStringToFilter.end()) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||||
|
input, config_name,
|
||||||
|
AllEnumValuesForType(Option::Type::kFilter));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringToInterframe(const wxString& config_name, const wxString& input) {
|
||||||
|
static std::map<wxString, Interframe> kStringToInterframe;
|
||||||
|
if (kStringToInterframe.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbInterframes; i++) {
|
||||||
|
kStringToInterframe.emplace(kInterframeStrings[i],
|
||||||
|
static_cast<Interframe>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToInterframe.size() == kNbInterframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToInterframe.find(input);
|
||||||
|
if (iter == kStringToInterframe.end()) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||||
|
input, config_name,
|
||||||
|
AllEnumValuesForType(Option::Type::kInterframe));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringToRenderMethod(const wxString& config_name, const wxString& input) {
|
||||||
|
static std::map<wxString, RenderMethod> kStringToRenderMethod;
|
||||||
|
if (kStringToRenderMethod.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbRenderMethods; i++) {
|
||||||
|
kStringToRenderMethod.emplace(kRenderMethodStrings[i],
|
||||||
|
static_cast<RenderMethod>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToRenderMethod.size() == kNbRenderMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToRenderMethod.find(input);
|
||||||
|
if (iter == kStringToRenderMethod.end()) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||||
|
input, config_name,
|
||||||
|
AllEnumValuesForType(Option::Type::kRenderMethod));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringToAudioApi(const wxString& config_name, const wxString& input) {
|
||||||
|
static std::map<wxString, AudioApi> kStringToAudioApi;
|
||||||
|
if (kStringToAudioApi.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbAudioApis; i++) {
|
||||||
|
kStringToAudioApi.emplace(kAudioApiStrings[i],
|
||||||
|
static_cast<AudioApi>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToAudioApi.size() == kNbAudioApis);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToAudioApi.find(input);
|
||||||
|
if (iter == kStringToAudioApi.end()) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||||
|
input, config_name,
|
||||||
|
AllEnumValuesForType(Option::Type::kAudioApi));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StringToSoundQuality(const wxString& config_name, const wxString& input) {
|
||||||
|
static std::map<wxString, SoundQuality> kStringToSoundQuality;
|
||||||
|
if (kStringToSoundQuality.empty()) {
|
||||||
|
for (size_t i = 0; i < kNbSoundQualities; i++) {
|
||||||
|
kStringToSoundQuality.emplace(kSoundQualityStrings[i],
|
||||||
|
static_cast<SoundQuality>(i));
|
||||||
|
}
|
||||||
|
assert(kStringToSoundQuality.size() == kNbSoundQualities);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = kStringToSoundQuality.find(input);
|
||||||
|
if (iter == kStringToSoundQuality.end()) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||||
|
input, config_name,
|
||||||
|
AllEnumValuesForType(Option::Type::kSoundQuality));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<int>(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString AllEnumValuesForType(Option::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case Option::Type::kFilter: {
|
||||||
|
static const wxString kAllFilterValues =
|
||||||
|
AllEnumValuesForArray(kFilterStrings);
|
||||||
|
return kAllFilterValues;
|
||||||
|
}
|
||||||
|
case Option::Type::kInterframe: {
|
||||||
|
static const wxString kAllInterframeValues =
|
||||||
|
AllEnumValuesForArray(kInterframeStrings);
|
||||||
|
return kAllInterframeValues;
|
||||||
|
}
|
||||||
|
case Option::Type::kRenderMethod: {
|
||||||
|
static const wxString kAllRenderValues =
|
||||||
|
AllEnumValuesForArray(kRenderMethodStrings);
|
||||||
|
return kAllRenderValues;
|
||||||
|
}
|
||||||
|
case Option::Type::kAudioApi: {
|
||||||
|
static const wxString kAllAudioApiValues =
|
||||||
|
AllEnumValuesForArray(kAudioApiStrings);
|
||||||
|
return kAllAudioApiValues;
|
||||||
|
}
|
||||||
|
case Option::Type::kSoundQuality: {
|
||||||
|
static const wxString kAllSoundQualityValues =
|
||||||
|
AllEnumValuesForArray(kSoundQualityStrings);
|
||||||
|
return kAllSoundQualityValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't use default here to explicitly trigger a compiler warning
|
||||||
|
// when adding a new value.
|
||||||
|
case Option::Type::kNone:
|
||||||
|
case Option::Type::kBool:
|
||||||
|
case Option::Type::kDouble:
|
||||||
|
case Option::Type::kInt:
|
||||||
|
case Option::Type::kUnsigned:
|
||||||
|
case Option::Type::kString:
|
||||||
|
case Option::Type::kGbPalette:
|
||||||
|
assert(false);
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MaxForType(Option::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case Option::Type::kFilter:
|
||||||
|
return kNbFilterFunctions;
|
||||||
|
case Option::Type::kInterframe:
|
||||||
|
return kNbInterframes;
|
||||||
|
case Option::Type::kRenderMethod:
|
||||||
|
return kNbRenderMethods;
|
||||||
|
case Option::Type::kAudioApi:
|
||||||
|
return kNbAudioApis;
|
||||||
|
case Option::Type::kSoundQuality:
|
||||||
|
return kNbSoundQualities;
|
||||||
|
|
||||||
|
// We don't use default here to explicitly trigger a compiler warning
|
||||||
|
// when adding a new value.
|
||||||
|
case Option::Type::kNone:
|
||||||
|
case Option::Type::kBool:
|
||||||
|
case Option::Type::kDouble:
|
||||||
|
case Option::Type::kInt:
|
||||||
|
case Option::Type::kUnsigned:
|
||||||
|
case Option::Type::kString:
|
||||||
|
case Option::Type::kGbPalette:
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace config
|
|
@ -1,28 +1,29 @@
|
||||||
#ifndef VBAM_OPTIONS_INTERNAL_INCLUDE
|
#ifndef VBAM_OPTION_INTERNAL_INCLUDE
|
||||||
#error "Do not include "vbam-options-internal.h" outside of the implementation."
|
#error "Do not include "config/internal/option-internal.h" outside of the implementation."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <wx/string.h>
|
|
||||||
|
|
||||||
|
#include "config/option.h"
|
||||||
#include "nonstd/optional.hpp"
|
#include "nonstd/optional.hpp"
|
||||||
#include "vbam-options.h"
|
|
||||||
|
|
||||||
|
namespace config {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
struct VbamOptionData {
|
struct OptionData {
|
||||||
const wxString config_name;
|
const wxString config_name;
|
||||||
const wxString command;
|
const wxString command;
|
||||||
const wxString ux_helper;
|
const wxString ux_helper;
|
||||||
const VbamOption::Type type;
|
const Option::Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static data to initialize global values.
|
// Static data to initialize global values.
|
||||||
extern const std::array<VbamOptionData, kNbOptions + 1> kAllOptionsData;
|
extern const std::array<OptionData, kNbOptions + 1> kAllOptionsData;
|
||||||
|
|
||||||
// Conversion utilities.
|
// Conversion utilities.
|
||||||
nonstd::optional<VbamOptionID> StringToOptionId(const wxString& input);
|
nonstd::optional<OptionID> StringToOptionId(const wxString& input);
|
||||||
wxString FilterToString(int value);
|
wxString FilterToString(int value);
|
||||||
wxString InterframeToString(int value);
|
wxString InterframeToString(int value);
|
||||||
wxString RenderMethodToString(int value);
|
wxString RenderMethodToString(int value);
|
||||||
|
@ -34,9 +35,10 @@ int StringToRenderMethod(const wxString& config_name, const wxString& input);
|
||||||
int StringToAudioApi(const wxString& config_name, const wxString& input);
|
int StringToAudioApi(const wxString& config_name, const wxString& input);
|
||||||
int StringToSoundQuality(const wxString& config_name, const wxString& input);
|
int StringToSoundQuality(const wxString& config_name, const wxString& input);
|
||||||
|
|
||||||
wxString AllEnumValuesForType(VbamOption::Type type);
|
wxString AllEnumValuesForType(Option::Type type);
|
||||||
|
|
||||||
// Max value for enum types.
|
// Max value for enum types.
|
||||||
int MaxForType(VbamOption::Type type);
|
int MaxForType(Option::Type type);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
} // namespace config
|
|
@ -0,0 +1,389 @@
|
||||||
|
#include "config/option.h"
|
||||||
|
|
||||||
|
#include "nonstd/variant.hpp"
|
||||||
|
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <wx/translation.h>
|
||||||
|
|
||||||
|
#define VBAM_OPTION_INTERNAL_INCLUDE
|
||||||
|
#include "config/internal/option-internal.h"
|
||||||
|
#undef VBAM_OPTION_INTERNAL_INCLUDE
|
||||||
|
|
||||||
|
namespace config {
|
||||||
|
|
||||||
|
// static
|
||||||
|
Option const* Option::FindByName(const wxString& config_name) {
|
||||||
|
nonstd::optional<OptionID> option_id =
|
||||||
|
internal::StringToOptionId(config_name);
|
||||||
|
if (!option_id) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &FindByID(option_id.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
Option& Option::FindByID(OptionID id) {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
return AllOptions()[static_cast<size_t>(id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::~Option() = default;
|
||||||
|
|
||||||
|
Option::Option(OptionID id)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(),
|
||||||
|
min_(),
|
||||||
|
max_() {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, bool* option)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(),
|
||||||
|
max_() {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_bool());
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, double* option, double min, double max)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(min),
|
||||||
|
max_(max) {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_double());
|
||||||
|
|
||||||
|
// Validate the initial value.
|
||||||
|
SetDouble(*option);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, int32_t* option, int32_t min, int32_t max)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(min),
|
||||||
|
max_(max) {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_int());
|
||||||
|
|
||||||
|
// Validate the initial value.
|
||||||
|
SetInt(*option);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, uint32_t* option, uint32_t min, uint32_t max)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(min),
|
||||||
|
max_(max) {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_unsigned());
|
||||||
|
|
||||||
|
// Validate the initial value.
|
||||||
|
SetUnsigned(*option);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, wxString* option)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(),
|
||||||
|
max_() {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, int* option)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(0),
|
||||||
|
max_(internal::MaxForType(type_)) {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_filter() || is_interframe() || is_render_method() ||
|
||||||
|
is_audio_api() || is_sound_quality());
|
||||||
|
|
||||||
|
// Validate the initial value.
|
||||||
|
SetEnumInt(*option);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option::Option(OptionID id, uint16_t* option)
|
||||||
|
: id_(id),
|
||||||
|
config_name_(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||||
|
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||||
|
ux_helper_(wxGetTranslation(
|
||||||
|
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||||
|
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
||||||
|
value_(option),
|
||||||
|
min_(),
|
||||||
|
max_() {
|
||||||
|
assert(id != OptionID::Last);
|
||||||
|
assert(is_gb_palette());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Option::GetBool() const {
|
||||||
|
assert(is_bool());
|
||||||
|
return *(nonstd::get<bool*>(value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
double Option::GetDouble() const {
|
||||||
|
assert(is_double());
|
||||||
|
return *(nonstd::get<double*>(value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Option::GetInt() const {
|
||||||
|
assert(is_int());
|
||||||
|
return *(nonstd::get<int32_t*>(value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Option::GetUnsigned() const {
|
||||||
|
assert(is_unsigned());
|
||||||
|
return *(nonstd::get<uint32_t*>(value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxString Option::GetString() const {
|
||||||
|
assert(is_string());
|
||||||
|
return *(nonstd::get<wxString*>(value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Option::GetEnumString() const {
|
||||||
|
switch (type_) {
|
||||||
|
case Option::Type::kFilter:
|
||||||
|
return internal::FilterToString(*(nonstd::get<int32_t*>(value_)));
|
||||||
|
case Option::Type::kInterframe:
|
||||||
|
return internal::InterframeToString(
|
||||||
|
*(nonstd::get<int32_t*>(value_)));
|
||||||
|
case Option::Type::kRenderMethod:
|
||||||
|
return internal::RenderMethodToString(
|
||||||
|
*(nonstd::get<int32_t*>(value_)));
|
||||||
|
case Option::Type::kAudioApi:
|
||||||
|
return internal::AudioApiToString(*(nonstd::get<int32_t*>(value_)));
|
||||||
|
case Option::Type::kSoundQuality:
|
||||||
|
return internal::SoundQualityToString(
|
||||||
|
*(nonstd::get<int32_t*>(value_)));
|
||||||
|
|
||||||
|
// We don't use default here to explicitly trigger a compiler warning
|
||||||
|
// when adding a new value.
|
||||||
|
case Option::Type::kNone:
|
||||||
|
case Option::Type::kBool:
|
||||||
|
case Option::Type::kDouble:
|
||||||
|
case Option::Type::kInt:
|
||||||
|
case Option::Type::kUnsigned:
|
||||||
|
case Option::Type::kString:
|
||||||
|
case Option::Type::kGbPalette:
|
||||||
|
assert(false);
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Option::GetGbPaletteString() const {
|
||||||
|
assert(is_gb_palette());
|
||||||
|
|
||||||
|
wxString palette_string;
|
||||||
|
uint16_t const* value = nonstd::get<uint16_t*>(value_);
|
||||||
|
palette_string.Printf("%04X,%04X,%04X,%04X,%04X,%04X,%04X,%04X", value[0],
|
||||||
|
value[1], value[2], value[3], value[4], value[5],
|
||||||
|
value[6], value[7]);
|
||||||
|
return palette_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetBool(bool value) const {
|
||||||
|
assert(is_bool());
|
||||||
|
*nonstd::get<bool*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetDouble(double value) const {
|
||||||
|
assert(is_double());
|
||||||
|
if (value < nonstd::get<double>(min_) ||
|
||||||
|
value > nonstd::get<double>(max_)) {
|
||||||
|
wxLogWarning(
|
||||||
|
_("Invalid value %f for option %s; valid values are %f - %f"),
|
||||||
|
value, config_name_, nonstd::get<double>(min_),
|
||||||
|
nonstd::get<double>(max_));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*nonstd::get<double*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetInt(int32_t value) const {
|
||||||
|
assert(is_int());
|
||||||
|
if (value < nonstd::get<int32_t>(min_) ||
|
||||||
|
value > nonstd::get<int32_t>(max_)) {
|
||||||
|
wxLogWarning(
|
||||||
|
_("Invalid value %d for option %s; valid values are %d - %d"),
|
||||||
|
value, config_name_, nonstd::get<int32_t>(min_),
|
||||||
|
nonstd::get<int32_t>(max_));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*nonstd::get<int32_t*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetUnsigned(uint32_t value) const {
|
||||||
|
assert(is_unsigned());
|
||||||
|
if (value < nonstd::get<uint32_t>(min_) ||
|
||||||
|
value > nonstd::get<uint32_t>(max_)) {
|
||||||
|
wxLogWarning(
|
||||||
|
_("Invalid value %d for option %s; valid values are %d - %d"),
|
||||||
|
value, config_name_, nonstd::get<uint32_t>(min_),
|
||||||
|
nonstd::get<uint32_t>(max_));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*nonstd::get<uint32_t*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetString(const wxString& value) const {
|
||||||
|
assert(is_string());
|
||||||
|
*nonstd::get<wxString*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetEnumString(const wxString& value) const {
|
||||||
|
switch (type_) {
|
||||||
|
case Option::Type::kFilter:
|
||||||
|
SetEnumInt(internal::StringToFilter(config_name_, value));
|
||||||
|
return;
|
||||||
|
case Option::Type::kInterframe:
|
||||||
|
SetEnumInt(internal::StringToInterframe(config_name_, value));
|
||||||
|
return;
|
||||||
|
case Option::Type::kRenderMethod:
|
||||||
|
SetEnumInt(internal::StringToRenderMethod(config_name_, value));
|
||||||
|
return;
|
||||||
|
case Option::Type::kAudioApi:
|
||||||
|
SetEnumInt(internal::StringToAudioApi(config_name_, value));
|
||||||
|
return;
|
||||||
|
case Option::Type::kSoundQuality:
|
||||||
|
SetEnumInt(internal::StringToSoundQuality(config_name_, value));
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We don't use default here to explicitly trigger a compiler warning
|
||||||
|
// when adding a new value.
|
||||||
|
case Option::Type::kNone:
|
||||||
|
case Option::Type::kBool:
|
||||||
|
case Option::Type::kDouble:
|
||||||
|
case Option::Type::kInt:
|
||||||
|
case Option::Type::kUnsigned:
|
||||||
|
case Option::Type::kString:
|
||||||
|
case Option::Type::kGbPalette:
|
||||||
|
assert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetEnumInt(int value) const {
|
||||||
|
assert(is_filter() || is_interframe() || is_render_method() ||
|
||||||
|
is_audio_api() || is_sound_quality());
|
||||||
|
if (value < nonstd::get<int32_t>(min_) ||
|
||||||
|
value > nonstd::get<int32_t>(max_)) {
|
||||||
|
wxLogWarning(_("Invalid value %d for option %s; valid values are %s"),
|
||||||
|
value, config_name_,
|
||||||
|
internal::AllEnumValuesForType(type_));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*nonstd::get<int32_t*>(value_) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Option::SetGbPalette(const wxString& value) const {
|
||||||
|
assert(is_gb_palette());
|
||||||
|
|
||||||
|
// 8 values of 4 chars and 7 commas.
|
||||||
|
static constexpr size_t kPaletteStringSize = 8 * 4 + 7;
|
||||||
|
|
||||||
|
if (value.size() != kPaletteStringSize) {
|
||||||
|
wxLogWarning(_("Invalid value %s for option %s"), value, config_name_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint16_t* dest = nonstd::get<uint16_t*>(value_);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 8; i++) {
|
||||||
|
wxString number = value.substr(i * 5, 4);
|
||||||
|
long temp = 0;
|
||||||
|
if (number.ToLong(&temp, 16)) {
|
||||||
|
dest[i] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Option::ToHelperString() const {
|
||||||
|
wxString helper_string = config_name_;
|
||||||
|
|
||||||
|
switch (type_) {
|
||||||
|
case Option::Type::kNone:
|
||||||
|
break;
|
||||||
|
case Option::Type::kBool:
|
||||||
|
helper_string.Append(" (flag)");
|
||||||
|
break;
|
||||||
|
case Option::Type::kDouble:
|
||||||
|
helper_string.Append(" (decimal)");
|
||||||
|
break;
|
||||||
|
case Option::Type::kInt:
|
||||||
|
helper_string.Append(" (int)");
|
||||||
|
break;
|
||||||
|
case Option::Type::kUnsigned:
|
||||||
|
helper_string.Append(" (unsigned)");
|
||||||
|
break;
|
||||||
|
case Option::Type::kString:
|
||||||
|
helper_string.Append(" (string)");
|
||||||
|
break;
|
||||||
|
case Option::Type::kFilter:
|
||||||
|
case Option::Type::kInterframe:
|
||||||
|
case Option::Type::kRenderMethod:
|
||||||
|
case Option::Type::kAudioApi:
|
||||||
|
case Option::Type::kSoundQuality:
|
||||||
|
helper_string.Append(" (");
|
||||||
|
helper_string.Append(internal::AllEnumValuesForType(type_));
|
||||||
|
helper_string.Append(")");
|
||||||
|
break;
|
||||||
|
case Option::Type::kGbPalette:
|
||||||
|
helper_string.Append(" (XXXX,XXXX,XXXX,XXXX,XXXX,XXXX,XXXX,XXXX)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
helper_string.Append("\n\t");
|
||||||
|
helper_string.Append(ux_helper_);
|
||||||
|
helper_string.Append("\n");
|
||||||
|
|
||||||
|
return helper_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace config
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef VBAM_OPTIONS_H
|
#ifndef VBAM_WX_CONFIG_OPTIONS_H_
|
||||||
#define VBAM_OPTIONS_H
|
#define VBAM_WX_CONFIG_OPTIONS_H_
|
||||||
|
|
||||||
#include "nonstd/variant.hpp"
|
#include "nonstd/variant.hpp"
|
||||||
|
|
||||||
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
enum class VbamOptionID {
|
namespace config {
|
||||||
|
|
||||||
|
enum class OptionID {
|
||||||
// Display
|
// Display
|
||||||
kDisplayBilinear = 0,
|
kDisplayBilinear = 0,
|
||||||
kDisplayFilter,
|
kDisplayFilter,
|
||||||
|
@ -144,23 +146,23 @@ enum class VbamOptionID {
|
||||||
Last,
|
Last,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t kNbOptions = static_cast<size_t>(VbamOptionID::Last);
|
constexpr size_t kNbOptions = static_cast<size_t>(OptionID::Last);
|
||||||
|
|
||||||
// Represents a single option saved in the INI file. VbamOption does not own the
|
// Represents a single option saved in the INI file. Option does not own the
|
||||||
// individual option, but keeps a pointer to where the data is actually saved.
|
// individual option, but keeps a pointer to where the data is actually saved.
|
||||||
//
|
//
|
||||||
// Ideally, options in the UI code should only be accessed and set via this
|
// Ideally, options in the UI code should only be accessed and set via this
|
||||||
// class, which should also take care of updating the INI file when
|
// class, which should also take care of updating the INI file when
|
||||||
// VbamOption::Set*() is called. This should also handle keyboard and joystick
|
// Option::Set*() is called. This should also handle keyboard and joystick
|
||||||
// configuration so option parsing can be done in a uniform manner. If we ever
|
// configuration so option parsing can be done in a uniform manner. If we ever
|
||||||
// get to that point, we would be able to remove most update_opts() calls and
|
// get to that point, we would be able to remove most update_opts() calls and
|
||||||
// have individual UI elements access the option via
|
// have individual UI elements access the option via
|
||||||
// VbamOption::FindOptionByID().
|
// Option::FindByID().
|
||||||
//
|
//
|
||||||
// The implementation for this class is largely inspired by base::Value in
|
// The implementation for this class is largely inspired by base::Value in
|
||||||
// Chromium.
|
// Chromium.
|
||||||
// https://source.chromium.org/chromium/chromium/src/+/main:base/values.h
|
// https://source.chromium.org/chromium/chromium/src/+/main:base/values.h
|
||||||
class VbamOption {
|
class Option {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
kNone = 0,
|
kNone = 0,
|
||||||
|
@ -177,15 +179,15 @@ public:
|
||||||
kGbPalette,
|
kGbPalette,
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::array<VbamOption, kNbOptions>& AllOptions();
|
static std::array<Option, kNbOptions>& AllOptions();
|
||||||
|
|
||||||
// O(log(kNbOptions))
|
// O(log(kNbOptions))
|
||||||
static VbamOption const* FindOptionByName(const wxString& config_name);
|
static Option const* FindByName(const wxString& config_name);
|
||||||
|
|
||||||
// O(1)
|
// O(1)
|
||||||
static VbamOption& FindOptionByID(VbamOptionID id);
|
static Option& FindByID(OptionID id);
|
||||||
|
|
||||||
~VbamOption();
|
~Option();
|
||||||
|
|
||||||
// Accessors.
|
// Accessors.
|
||||||
const wxString& config_name() const { return config_name_; }
|
const wxString& config_name() const { return config_name_; }
|
||||||
|
@ -235,37 +237,38 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Disable copy and assignment. Every individual option is unique.
|
// Disable copy and assignment. Every individual option is unique.
|
||||||
VbamOption(const VbamOption&) = delete;
|
Option(const Option&) = delete;
|
||||||
VbamOption& operator=(const VbamOption&) = delete;
|
Option& operator=(const Option&) = delete;
|
||||||
|
|
||||||
VbamOption(VbamOptionID id);
|
Option(OptionID id);
|
||||||
VbamOption(VbamOptionID id, bool* option);
|
Option(OptionID id, bool* option);
|
||||||
VbamOption(VbamOptionID id, double* option, double min, double max);
|
Option(OptionID id, double* option, double min, double max);
|
||||||
VbamOption(VbamOptionID id, int32_t* option, int32_t min, int32_t max);
|
Option(OptionID id, int32_t* option, int32_t min, int32_t max);
|
||||||
VbamOption(VbamOptionID id, uint32_t* option, uint32_t min, uint32_t max);
|
Option(OptionID id, uint32_t* option, uint32_t min, uint32_t max);
|
||||||
VbamOption(VbamOptionID id, wxString* option);
|
Option(OptionID id, wxString* option);
|
||||||
VbamOption(VbamOptionID id, int* option);
|
Option(OptionID id, int* option);
|
||||||
VbamOption(VbamOptionID id, uint16_t* option);
|
Option(OptionID id, uint16_t* option);
|
||||||
|
|
||||||
const VbamOptionID id_;
|
const OptionID id_;
|
||||||
|
|
||||||
const wxString config_name_;
|
const wxString config_name_;
|
||||||
const wxString command_;
|
const wxString command_;
|
||||||
const wxString ux_helper_;
|
const wxString ux_helper_;
|
||||||
|
|
||||||
const Type type_;
|
const Type type_;
|
||||||
const nonstd::variant<
|
const nonstd::variant<nonstd::monostate,
|
||||||
nonstd::monostate,
|
bool*,
|
||||||
bool*,
|
double*,
|
||||||
double*,
|
int32_t*,
|
||||||
int32_t*,
|
uint32_t*,
|
||||||
uint32_t*,
|
wxString*,
|
||||||
wxString*,
|
uint16_t*>
|
||||||
uint16_t*>
|
|
||||||
value_;
|
value_;
|
||||||
|
|
||||||
const nonstd::variant<nonstd::monostate, double, int32_t, uint32_t> min_;
|
const nonstd::variant<nonstd::monostate, double, int32_t, uint32_t> min_;
|
||||||
const nonstd::variant<nonstd::monostate, double, int32_t, uint32_t> max_;
|
const nonstd::variant<nonstd::monostate, double, int32_t, uint32_t> max_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* VBAM_OPTIONS_H */
|
} // namespace config
|
||||||
|
|
||||||
|
#endif // VBAM_WX_CONFIG_OPTIONS_H_
|
|
@ -23,11 +23,11 @@
|
||||||
#include <wx/txtstrm.h>
|
#include <wx/txtstrm.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
|
|
||||||
|
#include "../gba/CheatSearch.h"
|
||||||
|
#include "config/game-control.h"
|
||||||
|
#include "config/option.h"
|
||||||
#include "config/user-input.h"
|
#include "config/user-input.h"
|
||||||
#include "opts.h"
|
#include "opts.h"
|
||||||
#include "vbam-options.h"
|
|
||||||
#include "wx/gamecontrol.h"
|
|
||||||
#include "../gba/CheatSearch.h"
|
|
||||||
|
|
||||||
#if defined(__WXGTK__)
|
#if defined(__WXGTK__)
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
@ -1673,8 +1673,8 @@ public:
|
||||||
// For the individual clear buttons, we assume their name is
|
// For the individual clear buttons, we assume their name is
|
||||||
// "Clear" + control_name
|
// "Clear" + control_name
|
||||||
// ClearUp for Up; ClearR for R etc
|
// ClearUp for Up; ClearR for R etc
|
||||||
for (const wxGameKey& game_key : kAllGameKeys) {
|
for (const config::GameKey& game_key : config::kAllGameKeys) {
|
||||||
const wxString control_name = GameKeyToString(game_key);
|
const wxString control_name = config::GameKeyToString(game_key);
|
||||||
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*p, control_name, wxJoyKeyTextCtrl);
|
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*p, control_name, wxJoyKeyTextCtrl);
|
||||||
wxString singleClearButton("Clear" + control_name);
|
wxString singleClearButton("Clear" + control_name);
|
||||||
if (ev.GetId() == XRCID(singleClearButton.c_str())) {
|
if (ev.GetId() == XRCID(singleClearButton.c_str())) {
|
||||||
|
@ -1683,17 +1683,16 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const wxGameKey& game_key : kAllGameKeys) {
|
for (const config::GameKey& game_key : config::kAllGameKeys) {
|
||||||
wxJoyKeyTextCtrl* tc =
|
wxJoyKeyTextCtrl* tc = XRCCTRL_D(
|
||||||
XRCCTRL_D(*p, GameKeyToString(game_key), wxJoyKeyTextCtrl);
|
*p, config::GameKeyToString(game_key), wxJoyKeyTextCtrl);
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
tc->SetValue(wxEmptyString);
|
tc->SetValue(wxEmptyString);
|
||||||
} else {
|
} else {
|
||||||
tc->SetValue(
|
tc->SetValue(config::UserInput::SpanToString(
|
||||||
config::UserInput::SpanToString(
|
kDefaultBindings.find(config::GameControl(0, game_key))
|
||||||
kDefaultBindings.find(
|
->second));
|
||||||
wxGameControl(0, game_key))->second));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2977,7 +2976,8 @@ bool MainFrame::BindControls()
|
||||||
checkable_mi_t cmi = { cmdtab[i].cmd_id, mi, 0, 0 };
|
checkable_mi_t cmi = { cmdtab[i].cmd_id, mi, 0, 0 };
|
||||||
checkable_mi.push_back(cmi);
|
checkable_mi.push_back(cmi);
|
||||||
|
|
||||||
for (const VbamOption& option : VbamOption::AllOptions()) {
|
for (const config::Option& option :
|
||||||
|
config::Option::AllOptions()) {
|
||||||
if (cmdtab[i].cmd == option.command()) {
|
if (cmdtab[i].cmd == option.command()) {
|
||||||
if (option.is_int()) {
|
if (option.is_int()) {
|
||||||
MenuOptionIntMask(
|
MenuOptionIntMask(
|
||||||
|
@ -3861,8 +3861,8 @@ bool MainFrame::BindControls()
|
||||||
cb->SetValidator(wxBoolIntValidator(&gopts.default_stick, i + 1));
|
cb->SetValidator(wxBoolIntValidator(&gopts.default_stick, i + 1));
|
||||||
wxWindow *prev = NULL, *prevp = NULL;
|
wxWindow *prev = NULL, *prevp = NULL;
|
||||||
|
|
||||||
for (const wxGameKey& game_key : kAllGameKeys) {
|
for (const config::GameKey& game_key : config::kAllGameKeys) {
|
||||||
const wxString control_name = GameKeyToString(game_key);
|
const wxString control_name = config::GameKeyToString(game_key);
|
||||||
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*w, control_name, wxJoyKeyTextCtrl);
|
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*w, control_name, wxJoyKeyTextCtrl);
|
||||||
CheckThrowXRCError(tc, control_name);
|
CheckThrowXRCError(tc, control_name);
|
||||||
wxWindow* p = tc->GetParent();
|
wxWindow* p = tc->GetParent();
|
||||||
|
@ -3872,7 +3872,8 @@ bool MainFrame::BindControls()
|
||||||
|
|
||||||
prev = tc;
|
prev = tc;
|
||||||
prevp = p;
|
prevp = p;
|
||||||
tc->SetValidator(wxJoyKeyValidator(wxGameControl(i, game_key)));
|
tc->SetValidator(
|
||||||
|
wxJoyKeyValidator(config::GameControl(i, game_key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JoyPadConfigHandler[i].p = w;
|
JoyPadConfigHandler[i].p = w;
|
||||||
|
@ -3882,8 +3883,8 @@ bool MainFrame::BindControls()
|
||||||
w->Connect(XRCID("Clear"), wxEVT_COMMAND_BUTTON_CLICKED,
|
w->Connect(XRCID("Clear"), wxEVT_COMMAND_BUTTON_CLICKED,
|
||||||
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
||||||
NULL, &JoyPadConfigHandler[i]);
|
NULL, &JoyPadConfigHandler[i]);
|
||||||
for (const wxGameKey& game_key : kAllGameKeys) {
|
for (const config::GameKey& game_key : config::kAllGameKeys) {
|
||||||
const wxString control_name = GameKeyToString(game_key);
|
const wxString control_name = config::GameKeyToString(game_key);
|
||||||
w->Connect(XRCID(wxString("Clear" + control_name).c_str()),
|
w->Connect(XRCID(wxString("Clear" + control_name).c_str()),
|
||||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||||
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
||||||
|
|
260
src/wx/opts.cpp
260
src/wx/opts.cpp
|
@ -6,7 +6,7 @@
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#include <wx/display.h>
|
#include <wx/display.h>
|
||||||
|
|
||||||
#include "vbam-options.h"
|
#include "config/option.h"
|
||||||
#include "wxvbam.h"
|
#include "wxvbam.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
|
|
||||||
|
@ -115,138 +115,138 @@ const wxAcceleratorEntryUnicode default_accels[] = {
|
||||||
};
|
};
|
||||||
const int num_def_accels = sizeof(default_accels) / sizeof(default_accels[0]);
|
const int num_def_accels = sizeof(default_accels) / sizeof(default_accels[0]);
|
||||||
|
|
||||||
const std::map<wxGameControl, std::set<config::UserInput>> kDefaultBindings = {
|
const std::map<config::GameControl, std::set<config::UserInput>> kDefaultBindings = {
|
||||||
{ wxGameControl(0, wxGameKey::Up), {
|
{ config::GameControl(0, config::GameKey::Up), {
|
||||||
WJKB(wxT('W')),
|
WJKB(wxT('W')),
|
||||||
WJKB(11, wxJoyControl::Button, 1),
|
WJKB(11, wxJoyControl::Button, 1),
|
||||||
WJKB(1, wxJoyControl::AxisMinus, 1),
|
WJKB(1, wxJoyControl::AxisMinus, 1),
|
||||||
WJKB(3, wxJoyControl::AxisMinus, 1),
|
WJKB(3, wxJoyControl::AxisMinus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Down), {
|
{ config::GameControl(0, config::GameKey::Down), {
|
||||||
WJKB(wxT('S')),
|
WJKB(wxT('S')),
|
||||||
WJKB(12, wxJoyControl::Button, 1),
|
WJKB(12, wxJoyControl::Button, 1),
|
||||||
WJKB(1, wxJoyControl::AxisPlus, 1),
|
WJKB(1, wxJoyControl::AxisPlus, 1),
|
||||||
WJKB(3, wxJoyControl::AxisPlus, 1),
|
WJKB(3, wxJoyControl::AxisPlus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Left), {
|
{ config::GameControl(0, config::GameKey::Left), {
|
||||||
WJKB(wxT('A')),
|
WJKB(wxT('A')),
|
||||||
WJKB(13, wxJoyControl::Button, 1),
|
WJKB(13, wxJoyControl::Button, 1),
|
||||||
WJKB(0, wxJoyControl::AxisMinus, 1),
|
WJKB(0, wxJoyControl::AxisMinus, 1),
|
||||||
WJKB(2, wxJoyControl::AxisMinus, 1),
|
WJKB(2, wxJoyControl::AxisMinus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Right), {
|
{ config::GameControl(0, config::GameKey::Right), {
|
||||||
WJKB(wxT('D')),
|
WJKB(wxT('D')),
|
||||||
WJKB(14, wxJoyControl::Button, 1),
|
WJKB(14, wxJoyControl::Button, 1),
|
||||||
WJKB(0, wxJoyControl::AxisPlus, 1),
|
WJKB(0, wxJoyControl::AxisPlus, 1),
|
||||||
WJKB(2, wxJoyControl::AxisPlus, 1),
|
WJKB(2, wxJoyControl::AxisPlus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::A), {
|
{ config::GameControl(0, config::GameKey::A), {
|
||||||
WJKB(wxT('L')),
|
WJKB(wxT('L')),
|
||||||
WJKB(0, wxJoyControl::Button, 1),
|
WJKB(0, wxJoyControl::Button, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::B), {
|
{ config::GameControl(0, config::GameKey::B), {
|
||||||
WJKB(wxT('K')),
|
WJKB(wxT('K')),
|
||||||
WJKB(1, wxJoyControl::Button, 1),
|
WJKB(1, wxJoyControl::Button, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::L), {
|
{ config::GameControl(0, config::GameKey::L), {
|
||||||
WJKB(wxT('I')),
|
WJKB(wxT('I')),
|
||||||
WJKB(2, wxJoyControl::Button, 1),
|
WJKB(2, wxJoyControl::Button, 1),
|
||||||
WJKB(9, wxJoyControl::Button, 1),
|
WJKB(9, wxJoyControl::Button, 1),
|
||||||
WJKB(4, wxJoyControl::AxisPlus, 1),
|
WJKB(4, wxJoyControl::AxisPlus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::R), {
|
{ config::GameControl(0, config::GameKey::R), {
|
||||||
WJKB(wxT('O')),
|
WJKB(wxT('O')),
|
||||||
WJKB(3, wxJoyControl::Button, 1),
|
WJKB(3, wxJoyControl::Button, 1),
|
||||||
WJKB(10, wxJoyControl::Button, 1),
|
WJKB(10, wxJoyControl::Button, 1),
|
||||||
WJKB(5, wxJoyControl::AxisPlus, 1),
|
WJKB(5, wxJoyControl::AxisPlus, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Select), {
|
{ config::GameControl(0, config::GameKey::Select), {
|
||||||
WJKB(WXK_BACK),
|
WJKB(WXK_BACK),
|
||||||
WJKB(4, wxJoyControl::Button, 1),
|
WJKB(4, wxJoyControl::Button, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Start), {
|
{ config::GameControl(0, config::GameKey::Start), {
|
||||||
WJKB(WXK_RETURN),
|
WJKB(WXK_RETURN),
|
||||||
WJKB(6, wxJoyControl::Button, 1),
|
WJKB(6, wxJoyControl::Button, 1),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionUp), {}},
|
{ config::GameControl(0, config::GameKey::MotionUp), {}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionDown), {}},
|
{ config::GameControl(0, config::GameKey::MotionDown), {}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionLeft), {}},
|
{ config::GameControl(0, config::GameKey::MotionLeft), {}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionRight), {}},
|
{ config::GameControl(0, config::GameKey::MotionRight), {}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionIn), {}},
|
{ config::GameControl(0, config::GameKey::MotionIn), {}},
|
||||||
{ wxGameControl(0, wxGameKey::MotionOut), {}},
|
{ config::GameControl(0, config::GameKey::MotionOut), {}},
|
||||||
{ wxGameControl(0, wxGameKey::AutoA), {}},
|
{ config::GameControl(0, config::GameKey::AutoA), {}},
|
||||||
{ wxGameControl(0, wxGameKey::AutoB), {}},
|
{ config::GameControl(0, config::GameKey::AutoB), {}},
|
||||||
{ wxGameControl(0, wxGameKey::Speed), {
|
{ config::GameControl(0, config::GameKey::Speed), {
|
||||||
WJKB(WXK_SPACE),
|
WJKB(WXK_SPACE),
|
||||||
}},
|
}},
|
||||||
{ wxGameControl(0, wxGameKey::Capture), {}},
|
{ config::GameControl(0, config::GameKey::Capture), {}},
|
||||||
{ wxGameControl(0, wxGameKey::Gameshark), {}},
|
{ config::GameControl(0, config::GameKey::Gameshark), {}},
|
||||||
|
|
||||||
{ wxGameControl(1, wxGameKey::Up), {}},
|
{ config::GameControl(1, config::GameKey::Up), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Down), {}},
|
{ config::GameControl(1, config::GameKey::Down), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Left), {}},
|
{ config::GameControl(1, config::GameKey::Left), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Right), {}},
|
{ config::GameControl(1, config::GameKey::Right), {}},
|
||||||
{ wxGameControl(1, wxGameKey::A), {}},
|
{ config::GameControl(1, config::GameKey::A), {}},
|
||||||
{ wxGameControl(1, wxGameKey::B), {}},
|
{ config::GameControl(1, config::GameKey::B), {}},
|
||||||
{ wxGameControl(1, wxGameKey::L), {}},
|
{ config::GameControl(1, config::GameKey::L), {}},
|
||||||
{ wxGameControl(1, wxGameKey::R), {}},
|
{ config::GameControl(1, config::GameKey::R), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Select), {}},
|
{ config::GameControl(1, config::GameKey::Select), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Start), {}},
|
{ config::GameControl(1, config::GameKey::Start), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionUp), {}},
|
{ config::GameControl(1, config::GameKey::MotionUp), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionDown), {}},
|
{ config::GameControl(1, config::GameKey::MotionDown), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionLeft), {}},
|
{ config::GameControl(1, config::GameKey::MotionLeft), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionRight), {}},
|
{ config::GameControl(1, config::GameKey::MotionRight), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionIn), {}},
|
{ config::GameControl(1, config::GameKey::MotionIn), {}},
|
||||||
{ wxGameControl(1, wxGameKey::MotionOut), {}},
|
{ config::GameControl(1, config::GameKey::MotionOut), {}},
|
||||||
{ wxGameControl(1, wxGameKey::AutoA), {}},
|
{ config::GameControl(1, config::GameKey::AutoA), {}},
|
||||||
{ wxGameControl(1, wxGameKey::AutoB), {}},
|
{ config::GameControl(1, config::GameKey::AutoB), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Speed), {}},
|
{ config::GameControl(1, config::GameKey::Speed), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Capture), {}},
|
{ config::GameControl(1, config::GameKey::Capture), {}},
|
||||||
{ wxGameControl(1, wxGameKey::Gameshark), {}},
|
{ config::GameControl(1, config::GameKey::Gameshark), {}},
|
||||||
|
|
||||||
{ wxGameControl(2, wxGameKey::Up), {}},
|
{ config::GameControl(2, config::GameKey::Up), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Down), {}},
|
{ config::GameControl(2, config::GameKey::Down), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Left), {}},
|
{ config::GameControl(2, config::GameKey::Left), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Right), {}},
|
{ config::GameControl(2, config::GameKey::Right), {}},
|
||||||
{ wxGameControl(2, wxGameKey::A), {}},
|
{ config::GameControl(2, config::GameKey::A), {}},
|
||||||
{ wxGameControl(2, wxGameKey::B), {}},
|
{ config::GameControl(2, config::GameKey::B), {}},
|
||||||
{ wxGameControl(2, wxGameKey::L), {}},
|
{ config::GameControl(2, config::GameKey::L), {}},
|
||||||
{ wxGameControl(2, wxGameKey::R), {}},
|
{ config::GameControl(2, config::GameKey::R), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Select), {}},
|
{ config::GameControl(2, config::GameKey::Select), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Start), {}},
|
{ config::GameControl(2, config::GameKey::Start), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionUp), {}},
|
{ config::GameControl(2, config::GameKey::MotionUp), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionDown), {}},
|
{ config::GameControl(2, config::GameKey::MotionDown), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionLeft), {}},
|
{ config::GameControl(2, config::GameKey::MotionLeft), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionRight), {}},
|
{ config::GameControl(2, config::GameKey::MotionRight), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionIn), {}},
|
{ config::GameControl(2, config::GameKey::MotionIn), {}},
|
||||||
{ wxGameControl(2, wxGameKey::MotionOut), {}},
|
{ config::GameControl(2, config::GameKey::MotionOut), {}},
|
||||||
{ wxGameControl(2, wxGameKey::AutoA), {}},
|
{ config::GameControl(2, config::GameKey::AutoA), {}},
|
||||||
{ wxGameControl(2, wxGameKey::AutoB), {}},
|
{ config::GameControl(2, config::GameKey::AutoB), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Speed), {}},
|
{ config::GameControl(2, config::GameKey::Speed), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Capture), {}},
|
{ config::GameControl(2, config::GameKey::Capture), {}},
|
||||||
{ wxGameControl(2, wxGameKey::Gameshark), {}},
|
{ config::GameControl(2, config::GameKey::Gameshark), {}},
|
||||||
|
|
||||||
{ wxGameControl(3, wxGameKey::Up), {}},
|
{ config::GameControl(3, config::GameKey::Up), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Down), {}},
|
{ config::GameControl(3, config::GameKey::Down), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Left), {}},
|
{ config::GameControl(3, config::GameKey::Left), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Right), {}},
|
{ config::GameControl(3, config::GameKey::Right), {}},
|
||||||
{ wxGameControl(3, wxGameKey::A), {}},
|
{ config::GameControl(3, config::GameKey::A), {}},
|
||||||
{ wxGameControl(3, wxGameKey::B), {}},
|
{ config::GameControl(3, config::GameKey::B), {}},
|
||||||
{ wxGameControl(3, wxGameKey::L), {}},
|
{ config::GameControl(3, config::GameKey::L), {}},
|
||||||
{ wxGameControl(3, wxGameKey::R), {}},
|
{ config::GameControl(3, config::GameKey::R), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Select), {}},
|
{ config::GameControl(3, config::GameKey::Select), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Start), {}},
|
{ config::GameControl(3, config::GameKey::Start), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionUp), {}},
|
{ config::GameControl(3, config::GameKey::MotionUp), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionDown), {}},
|
{ config::GameControl(3, config::GameKey::MotionDown), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionLeft), {}},
|
{ config::GameControl(3, config::GameKey::MotionLeft), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionRight), {}},
|
{ config::GameControl(3, config::GameKey::MotionRight), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionIn), {}},
|
{ config::GameControl(3, config::GameKey::MotionIn), {}},
|
||||||
{ wxGameControl(3, wxGameKey::MotionOut), {}},
|
{ config::GameControl(3, config::GameKey::MotionOut), {}},
|
||||||
{ wxGameControl(3, wxGameKey::AutoA), {}},
|
{ config::GameControl(3, config::GameKey::AutoA), {}},
|
||||||
{ wxGameControl(3, wxGameKey::AutoB), {}},
|
{ config::GameControl(3, config::GameKey::AutoB), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Speed), {}},
|
{ config::GameControl(3, config::GameKey::Speed), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Capture), {}},
|
{ config::GameControl(3, config::GameKey::Capture), {}},
|
||||||
{ wxGameControl(3, wxGameKey::Gameshark), {}},
|
{ config::GameControl(3, config::GameKey::Gameshark), {}},
|
||||||
};
|
};
|
||||||
|
|
||||||
wxAcceleratorEntry_v sys_accels;
|
wxAcceleratorEntry_v sys_accels;
|
||||||
|
@ -367,7 +367,7 @@ void load_opts()
|
||||||
|
|
||||||
for (cont = cfg->GetFirstEntry(e, key_idx); cont;
|
for (cont = cfg->GetFirstEntry(e, key_idx); cont;
|
||||||
cont = cfg->GetNextEntry(e, key_idx)) {
|
cont = cfg->GetNextEntry(e, key_idx)) {
|
||||||
if (!StringToGameKey(e)) {
|
if (!config::StringToGameKey(e)) {
|
||||||
s.append(e);
|
s.append(e);
|
||||||
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
||||||
item_del.push_back(s);
|
item_del.push_back(s);
|
||||||
|
@ -403,7 +403,7 @@ void load_opts()
|
||||||
} else {
|
} else {
|
||||||
s.append(wxT('/'));
|
s.append(wxT('/'));
|
||||||
s.append(e);
|
s.append(e);
|
||||||
if (!VbamOption::FindOptionByName(s) && s != wxT("General/LastUpdated") && s != wxT("General/LastUpdatedFileName")) {
|
if (!config::Option::FindByName(s) && s != wxT("General/LastUpdated") && s != wxT("General/LastUpdatedFileName")) {
|
||||||
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
||||||
item_del.push_back(s);
|
item_del.push_back(s);
|
||||||
}
|
}
|
||||||
|
@ -425,46 +425,46 @@ void load_opts()
|
||||||
cfg->SetRecordDefaults();
|
cfg->SetRecordDefaults();
|
||||||
|
|
||||||
// First access here will also initialize translations.
|
// First access here will also initialize translations.
|
||||||
for (const VbamOption& opt : VbamOption::AllOptions()) {
|
for (const config::Option& opt : config::Option::AllOptions()) {
|
||||||
switch (opt.type()) {
|
switch (opt.type()) {
|
||||||
case VbamOption::Type::kNone:
|
case config::Option::Type::kNone:
|
||||||
// Keyboard or Joystick. Handled separately for now.
|
// Keyboard or Joystick. Handled separately for now.
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kBool: {
|
case config::Option::Type::kBool: {
|
||||||
bool temp;
|
bool temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetBool());
|
cfg->Read(opt.config_name(), &temp, opt.GetBool());
|
||||||
opt.SetBool(temp);
|
opt.SetBool(temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kDouble: {
|
case config::Option::Type::kDouble: {
|
||||||
double temp;
|
double temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetDouble());
|
cfg->Read(opt.config_name(), &temp, opt.GetDouble());
|
||||||
opt.SetDouble(temp);
|
opt.SetDouble(temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kInt: {
|
case config::Option::Type::kInt: {
|
||||||
int32_t temp;
|
int32_t temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetInt());
|
cfg->Read(opt.config_name(), &temp, opt.GetInt());
|
||||||
opt.SetInt(temp);
|
opt.SetInt(temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kUnsigned: {
|
case config::Option::Type::kUnsigned: {
|
||||||
int temp;
|
int temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetUnsigned());
|
cfg->Read(opt.config_name(), &temp, opt.GetUnsigned());
|
||||||
opt.SetUnsigned(temp);
|
opt.SetUnsigned(temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kString: {
|
case config::Option::Type::kString: {
|
||||||
wxString temp;
|
wxString temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetString());
|
cfg->Read(opt.config_name(), &temp, opt.GetString());
|
||||||
opt.SetString(temp);
|
opt.SetString(temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kFilter:
|
case config::Option::Type::kFilter:
|
||||||
case VbamOption::Type::kInterframe:
|
case config::Option::Type::kInterframe:
|
||||||
case VbamOption::Type::kRenderMethod:
|
case config::Option::Type::kRenderMethod:
|
||||||
case VbamOption::Type::kAudioApi:
|
case config::Option::Type::kAudioApi:
|
||||||
case VbamOption::Type::kSoundQuality: {
|
case config::Option::Type::kSoundQuality: {
|
||||||
wxString temp;
|
wxString temp;
|
||||||
if (cfg->Read(opt.config_name(), &temp) && !temp.empty()) {
|
if (cfg->Read(opt.config_name(), &temp) && !temp.empty()) {
|
||||||
opt.SetEnumString(temp.MakeLower());
|
opt.SetEnumString(temp.MakeLower());
|
||||||
|
@ -473,7 +473,7 @@ void load_opts()
|
||||||
cfg->Write(opt.config_name(), opt.GetEnumString());
|
cfg->Write(opt.config_name(), opt.GetEnumString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kGbPalette: {
|
case config::Option::Type::kGbPalette: {
|
||||||
wxString temp;
|
wxString temp;
|
||||||
cfg->Read(opt.config_name(), &temp, opt.GetGbPaletteString());
|
cfg->Read(opt.config_name(), &temp, opt.GetGbPaletteString());
|
||||||
opt.SetGbPalette(temp);
|
opt.SetGbPalette(temp);
|
||||||
|
@ -539,34 +539,34 @@ void update_opts()
|
||||||
{
|
{
|
||||||
wxFileConfig* cfg = wxGetApp().cfg;
|
wxFileConfig* cfg = wxGetApp().cfg;
|
||||||
|
|
||||||
for (const VbamOption& opt : VbamOption::AllOptions()) {
|
for (const config::Option& opt : config::Option::AllOptions()) {
|
||||||
switch (opt.type()) {
|
switch (opt.type()) {
|
||||||
case VbamOption::Type::kNone:
|
case config::Option::Type::kNone:
|
||||||
// Keyboard and Joypad are handled separately.
|
// Keyboard and Joypad are handled separately.
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kBool:
|
case config::Option::Type::kBool:
|
||||||
cfg->Write(opt.config_name(), opt.GetBool());
|
cfg->Write(opt.config_name(), opt.GetBool());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kDouble:
|
case config::Option::Type::kDouble:
|
||||||
cfg->Write(opt.config_name(), opt.GetDouble());
|
cfg->Write(opt.config_name(), opt.GetDouble());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kInt:
|
case config::Option::Type::kInt:
|
||||||
cfg->Write(opt.config_name(), opt.GetInt());
|
cfg->Write(opt.config_name(), opt.GetInt());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kUnsigned:
|
case config::Option::Type::kUnsigned:
|
||||||
cfg->Write(opt.config_name(), opt.GetUnsigned());
|
cfg->Write(opt.config_name(), opt.GetUnsigned());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kString:
|
case config::Option::Type::kString:
|
||||||
cfg->Write(opt.config_name(), opt.GetString());
|
cfg->Write(opt.config_name(), opt.GetString());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kFilter:
|
case config::Option::Type::kFilter:
|
||||||
case VbamOption::Type::kInterframe:
|
case config::Option::Type::kInterframe:
|
||||||
case VbamOption::Type::kRenderMethod:
|
case config::Option::Type::kRenderMethod:
|
||||||
case VbamOption::Type::kAudioApi:
|
case config::Option::Type::kAudioApi:
|
||||||
case VbamOption::Type::kSoundQuality:
|
case config::Option::Type::kSoundQuality:
|
||||||
cfg->Write(opt.config_name(), opt.GetEnumString());
|
cfg->Write(opt.config_name(), opt.GetEnumString());
|
||||||
break;
|
break;
|
||||||
case VbamOption::Type::kGbPalette:
|
case config::Option::Type::kGbPalette:
|
||||||
cfg->Write(opt.config_name(), opt.GetGbPaletteString());
|
cfg->Write(opt.config_name(), opt.GetGbPaletteString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,7 @@ void update_opts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (game_bindings_changed) {
|
if (game_bindings_changed) {
|
||||||
wxGameControlState::Instance().OnGameBindingsChanged();
|
config::GameControlState::Instance().OnGameBindingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// for keyboard, first remove any commands that aren't bound at all
|
// for keyboard, first remove any commands that aren't bound at all
|
||||||
|
@ -656,16 +656,16 @@ void update_opts()
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_set(const wxString& name, const wxString& val) {
|
void opt_set(const wxString& name, const wxString& val) {
|
||||||
VbamOption const* opt = VbamOption::FindOptionByName(name);
|
config::Option const* opt = config::Option::FindByName(name);
|
||||||
|
|
||||||
// opt->is_none() means it is Keyboard or Joypad.
|
// opt->is_none() means it is Keyboard or Joypad.
|
||||||
if (opt && !opt->is_none()) {
|
if (opt && !opt->is_none()) {
|
||||||
switch (opt->type()) {
|
switch (opt->type()) {
|
||||||
case VbamOption::Type::kNone:
|
case config::Option::Type::kNone:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
case VbamOption::Type::kBool:
|
case config::Option::Type::kBool:
|
||||||
if (val != '0' && val != '1') {
|
if (val != '0' && val != '1') {
|
||||||
wxLogWarning(_("Invalid value %s for option %s"),
|
wxLogWarning(_("Invalid value %s for option %s"),
|
||||||
name.c_str(), val.c_str());
|
name.c_str(), val.c_str());
|
||||||
|
@ -673,7 +673,7 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||||
}
|
}
|
||||||
opt->SetBool(val == '1');
|
opt->SetBool(val == '1');
|
||||||
return;
|
return;
|
||||||
case VbamOption::Type::kDouble: {
|
case config::Option::Type::kDouble: {
|
||||||
double value;
|
double value;
|
||||||
if (!val.ToDouble(&value)) {
|
if (!val.ToDouble(&value)) {
|
||||||
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
||||||
|
@ -682,7 +682,7 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||||
opt->SetDouble(value);
|
opt->SetDouble(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kInt: {
|
case config::Option::Type::kInt: {
|
||||||
long value;
|
long value;
|
||||||
if (!val.ToLong(&value)) {
|
if (!val.ToLong(&value)) {
|
||||||
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
||||||
|
@ -691,7 +691,7 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||||
opt->SetInt(static_cast<int32_t>(value));
|
opt->SetInt(static_cast<int32_t>(value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kUnsigned: {
|
case config::Option::Type::kUnsigned: {
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
if (!val.ToULong(&value)) {
|
if (!val.ToULong(&value)) {
|
||||||
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
wxLogWarning(_("Invalid value %s for option %s"), val, name.c_str());
|
||||||
|
@ -700,17 +700,17 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||||
opt->SetUnsigned(static_cast<uint32_t>(value));
|
opt->SetUnsigned(static_cast<uint32_t>(value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case VbamOption::Type::kString:
|
case config::Option::Type::kString:
|
||||||
opt->SetString(val);
|
opt->SetString(val);
|
||||||
return;
|
return;
|
||||||
case VbamOption::Type::kFilter:
|
case config::Option::Type::kFilter:
|
||||||
case VbamOption::Type::kInterframe:
|
case config::Option::Type::kInterframe:
|
||||||
case VbamOption::Type::kRenderMethod:
|
case config::Option::Type::kRenderMethod:
|
||||||
case VbamOption::Type::kAudioApi:
|
case config::Option::Type::kAudioApi:
|
||||||
case VbamOption::Type::kSoundQuality:
|
case config::Option::Type::kSoundQuality:
|
||||||
opt->SetEnumString(val);
|
opt->SetEnumString(val);
|
||||||
return;
|
return;
|
||||||
case VbamOption::Type::kGbPalette:
|
case config::Option::Type::kGbPalette:
|
||||||
opt->SetGbPalette(val);
|
opt->SetGbPalette(val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -754,8 +754,8 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nonstd::optional<wxGameControl> game_control =
|
const nonstd::optional<config::GameControl> game_control =
|
||||||
wxGameControl::FromString(name);
|
config::GameControl::FromString(name);
|
||||||
if (game_control) {
|
if (game_control) {
|
||||||
if (val.empty()) {
|
if (val.empty()) {
|
||||||
gopts.game_control_bindings[game_control.value()].clear();
|
gopts.game_control_bindings[game_control.value()].clear();
|
||||||
|
|
|
@ -6,15 +6,16 @@
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <wx/vidmode.h>
|
#include <wx/vidmode.h>
|
||||||
|
|
||||||
#include "wx/gamecontrol.h"
|
#include "config/game-control.h"
|
||||||
#include "wx/keyedit.h"
|
|
||||||
#include "config/user-input.h"
|
#include "config/user-input.h"
|
||||||
|
#include "wx/keyedit.h"
|
||||||
|
|
||||||
// Forward declaration.
|
// Forward declaration.
|
||||||
class wxFileHistory;
|
class wxFileHistory;
|
||||||
|
|
||||||
// Default joystick bindings.
|
// Default joystick bindings.
|
||||||
extern const std::map<wxGameControl, std::set<config::UserInput>> kDefaultBindings;
|
extern const std::map<config::GameControl, std::set<config::UserInput>>
|
||||||
|
kDefaultBindings;
|
||||||
|
|
||||||
extern struct opts_t {
|
extern struct opts_t {
|
||||||
opts_t();
|
opts_t();
|
||||||
|
@ -64,7 +65,8 @@ extern struct opts_t {
|
||||||
int statusbar;
|
int statusbar;
|
||||||
|
|
||||||
/// Joypad
|
/// Joypad
|
||||||
std::map<wxGameControl, std::set<config::UserInput>> game_control_bindings;
|
std::map<config::GameControl, std::set<config::UserInput>>
|
||||||
|
game_control_bindings;
|
||||||
int autofire_rate;
|
int autofire_rate;
|
||||||
int default_stick;
|
int default_stick;
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,21 @@
|
||||||
#include <wx/menu.h>
|
#include <wx/menu.h>
|
||||||
#include <SDL_joystick.h>
|
#include <SDL_joystick.h>
|
||||||
|
|
||||||
#include "../common/version_cpp.h"
|
|
||||||
#include "../common/Patch.h"
|
#include "../common/Patch.h"
|
||||||
|
#include "../common/version_cpp.h"
|
||||||
#include "../gb/gbPrinter.h"
|
#include "../gb/gbPrinter.h"
|
||||||
#include "../gba/RTC.h"
|
#include "../gba/RTC.h"
|
||||||
#include "../gba/agbprint.h"
|
#include "../gba/agbprint.h"
|
||||||
#include "../sdl/text.h"
|
#include "../sdl/text.h"
|
||||||
|
#include "background-input.h"
|
||||||
|
#include "config/game-control.h"
|
||||||
#include "config/user-input.h"
|
#include "config/user-input.h"
|
||||||
#include "drawing.h"
|
#include "drawing.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
#include "wx/joyedit.h"
|
|
||||||
#include "wx/gamecontrol.h"
|
|
||||||
#include "wxvbam.h"
|
|
||||||
#include "wxutil.h"
|
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
#include "background-input.h"
|
#include "wx/joyedit.h"
|
||||||
|
#include "wxutil.h"
|
||||||
|
#include "wxvbam.h"
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -958,7 +958,7 @@ GameArea::~GameArea()
|
||||||
|
|
||||||
void GameArea::OnKillFocus(wxFocusEvent& ev)
|
void GameArea::OnKillFocus(wxFocusEvent& ev)
|
||||||
{
|
{
|
||||||
wxGameControlState::Instance().Reset();
|
config::GameControlState::Instance().Reset();
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,7 +978,7 @@ void GameArea::Pause()
|
||||||
// when the game is paused like this, we should not allow any
|
// when the game is paused like this, we should not allow any
|
||||||
// input to remain pressed, because they could be released
|
// input to remain pressed, because they could be released
|
||||||
// outside of the game zone and we would not know about it.
|
// outside of the game zone and we would not know about it.
|
||||||
wxGameControlState::Instance().Reset();
|
config::GameControlState::Instance().Reset();
|
||||||
|
|
||||||
if (loaded != IMAGE_UNKNOWN)
|
if (loaded != IMAGE_UNKNOWN)
|
||||||
soundPause();
|
soundPause();
|
||||||
|
@ -1212,9 +1212,9 @@ void GameArea::OnIdle(wxIdleEvent& event)
|
||||||
static bool process_user_input(bool down, const config::UserInput& user_input)
|
static bool process_user_input(bool down, const config::UserInput& user_input)
|
||||||
{
|
{
|
||||||
if (down)
|
if (down)
|
||||||
return wxGameControlState::Instance().OnInputPressed(user_input);
|
return config::GameControlState::Instance().OnInputPressed(user_input);
|
||||||
else
|
else
|
||||||
return wxGameControlState::Instance().OnInputReleased(user_input);
|
return config::GameControlState::Instance().OnInputReleased(user_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_black_background(wxWindow* win) {
|
static void draw_black_background(wxWindow* win) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "../common/SoundSDL.h"
|
#include "../common/SoundSDL.h"
|
||||||
#include "wx/gamecontrol.h"
|
#include "config/game-control.h"
|
||||||
#include "wxvbam.h"
|
#include "wxvbam.h"
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include <wx/ffile.h>
|
#include <wx/ffile.h>
|
||||||
|
@ -331,7 +331,7 @@ uint32_t systemReadJoypad(int joy)
|
||||||
if (joy < 0 || joy > 3)
|
if (joy < 0 || joy > 3)
|
||||||
joy = gopts.default_stick - 1;
|
joy = gopts.default_stick - 1;
|
||||||
|
|
||||||
uint32_t ret = wxGameControlState::Instance().GetJoypad(joy);
|
uint32_t ret = config::GameControlState::Instance().GetJoypad(joy);
|
||||||
|
|
||||||
if (turbo)
|
if (turbo)
|
||||||
ret |= KEYM_SPEED;
|
ret |= KEYM_SPEED;
|
||||||
|
@ -641,7 +641,9 @@ void systemUpdateSolarSensor()
|
||||||
void systemUpdateMotionSensor()
|
void systemUpdateMotionSensor()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
const uint32_t joy_value = wxGameControlState::Instance().GetJoypad(i);
|
const uint32_t joy_value =
|
||||||
|
config::GameControlState::Instance().GetJoypad(i);
|
||||||
|
|
||||||
if (!sensorx[i])
|
if (!sensorx[i])
|
||||||
sensorx[i] = 2047;
|
sensorx[i] = 2047;
|
||||||
|
|
||||||
|
|
|
@ -1,698 +0,0 @@
|
||||||
#include "vbam-options.h"
|
|
||||||
|
|
||||||
// Helper implementation file to define and compile all of these huge constants
|
|
||||||
// separately. These should not be updated very often, so having these in a
|
|
||||||
// separate file improves incremental build time.
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <wx/log.h>
|
|
||||||
|
|
||||||
#include "../common/ConfigManager.h"
|
|
||||||
#include "../gb/gbGlobals.h"
|
|
||||||
#include "opts.h"
|
|
||||||
|
|
||||||
#define VBAM_OPTIONS_INTERNAL_INCLUDE
|
|
||||||
#include "vbam-options-internal.h"
|
|
||||||
#undef VBAM_OPTIONS_INTERNAL_INCLUDE
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// This enum must be kept in sync with the one in wxvbam.h
|
|
||||||
// TODO: These 2 enums should be unified and a validator created for this enum.
|
|
||||||
enum class FilterFunction {
|
|
||||||
kNone,
|
|
||||||
k2xsai,
|
|
||||||
kSuper2xsai,
|
|
||||||
kSupereagle,
|
|
||||||
kPixelate,
|
|
||||||
kAdvmame,
|
|
||||||
kBilinear,
|
|
||||||
kBilinearplus,
|
|
||||||
kScanlines,
|
|
||||||
kTvmode,
|
|
||||||
kHQ2x,
|
|
||||||
kLQ2x,
|
|
||||||
kSimple2x,
|
|
||||||
kSimple3x,
|
|
||||||
kHQ3x,
|
|
||||||
kSimple4x,
|
|
||||||
kHQ4x,
|
|
||||||
kXbrz2x,
|
|
||||||
kXbrz3x,
|
|
||||||
kXbrz4x,
|
|
||||||
kXbrz5x,
|
|
||||||
kXbrz6x,
|
|
||||||
kPlugin, // This must always be last.
|
|
||||||
|
|
||||||
// Do not add anything under here.
|
|
||||||
kLast,
|
|
||||||
};
|
|
||||||
constexpr size_t kNbFilterFunctions = static_cast<size_t>(FilterFunction::kLast);
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions of the enum above.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbFilterFunctions is automatically updated.
|
|
||||||
static const std::array<wxString, kNbFilterFunctions> kFilterStrings = {
|
|
||||||
"none",
|
|
||||||
"2xsai",
|
|
||||||
"super2xsai",
|
|
||||||
"supereagle",
|
|
||||||
"pixelate",
|
|
||||||
"advmame",
|
|
||||||
"bilinear",
|
|
||||||
"bilinearplus",
|
|
||||||
"scanlines",
|
|
||||||
"tvmode",
|
|
||||||
"hq2x",
|
|
||||||
"lq2x",
|
|
||||||
"simple2x",
|
|
||||||
"simple3x",
|
|
||||||
"hq3x",
|
|
||||||
"simple4x",
|
|
||||||
"hq4x",
|
|
||||||
"xbrz2x",
|
|
||||||
"xbrz3x",
|
|
||||||
"xbrz4x",
|
|
||||||
"xbrz5x",
|
|
||||||
"xbrz6x",
|
|
||||||
"plugin",
|
|
||||||
};
|
|
||||||
|
|
||||||
// This enum must be kept in sync with the one in wxvbam.h
|
|
||||||
// TODO: These 2 enums should be unified and a validator created for this enum.
|
|
||||||
enum class Interframe {
|
|
||||||
kNone = 0,
|
|
||||||
kSmart,
|
|
||||||
kMotionBlur,
|
|
||||||
|
|
||||||
// Do not add anything under here.
|
|
||||||
kLast,
|
|
||||||
};
|
|
||||||
constexpr size_t kNbInterframes = static_cast<size_t>(Interframe::kLast);
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions of the enum above.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbInterframes is automatically updated.
|
|
||||||
static const std::array<wxString, kNbInterframes> kInterframeStrings = {
|
|
||||||
"none",
|
|
||||||
"smart",
|
|
||||||
"motionblur",
|
|
||||||
};
|
|
||||||
|
|
||||||
// This enum must be kept in sync with the one in wxvbam.h
|
|
||||||
// TODO: These 2 enums should be unified and a validator created for this enum.
|
|
||||||
enum class RenderMethod {
|
|
||||||
kSimple = 0,
|
|
||||||
kOpenGL,
|
|
||||||
#ifdef __WXMSW__
|
|
||||||
kDirect3d,
|
|
||||||
#elif defined(__WXMAC__)
|
|
||||||
kQuartz2d,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Do not add anything under here.
|
|
||||||
kLast,
|
|
||||||
};
|
|
||||||
constexpr size_t kNbRenderMethods = static_cast<size_t>(RenderMethod::kLast);
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions of the enum above.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbRenderMethods is automatically updated.
|
|
||||||
static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
|
||||||
"simple",
|
|
||||||
"opengl",
|
|
||||||
#ifdef __WXMSW__
|
|
||||||
"direct3d",
|
|
||||||
#elif defined(__WXMAC__)
|
|
||||||
"quartz2d",
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// This enum must be kept in sync with the one in wxvbam.h
|
|
||||||
// TODO: These 2 enums should be unified and a validator created for this enum.
|
|
||||||
// TODO: DirectSound and XAudio2 should only be used on Windows.
|
|
||||||
enum class AudioApi {
|
|
||||||
kSdl = 0,
|
|
||||||
kOpenAL,
|
|
||||||
kDirectSound,
|
|
||||||
kXAudio2,
|
|
||||||
kFaudio,
|
|
||||||
|
|
||||||
// Do not add anything under here.
|
|
||||||
kLast,
|
|
||||||
};
|
|
||||||
constexpr size_t kNbAudioApis = static_cast<size_t>(AudioApi::kLast);
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions of the enum above.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbAudioApis is automatically updated.
|
|
||||||
static const std::array<wxString, kNbAudioApis> kAudioApiStrings = {
|
|
||||||
"sdl",
|
|
||||||
"openal",
|
|
||||||
"directsound",
|
|
||||||
"xaudio2",
|
|
||||||
"faudio",
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SoundQuality {
|
|
||||||
k48kHz = 0,
|
|
||||||
k44kHz,
|
|
||||||
k22kHz,
|
|
||||||
k11kHz,
|
|
||||||
|
|
||||||
// Do not add anything under here.
|
|
||||||
kLast,
|
|
||||||
};
|
|
||||||
constexpr size_t kNbSoundQualities = static_cast<size_t>(SoundQuality::kLast);
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions of the enum above.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbSoundQualities is automatically updated.
|
|
||||||
static const std::array<wxString, kNbSoundQualities> kSoundQualityStrings = {
|
|
||||||
"48",
|
|
||||||
"44",
|
|
||||||
"22",
|
|
||||||
"11",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Builds the "all enum values" string for a given array defined above.
|
|
||||||
template<std::size_t SIZE>
|
|
||||||
wxString AllEnumValuesForArray(const std::array<wxString, SIZE>& input) {
|
|
||||||
// 15 characters per option is a reasonable higher bound. Probably.
|
|
||||||
static constexpr size_t kMaxOptionLength = 15u;
|
|
||||||
|
|
||||||
wxString all_options;
|
|
||||||
all_options.reserve(kMaxOptionLength * SIZE);
|
|
||||||
|
|
||||||
std::for_each(input.cbegin(), input.cend(), [&all_options](const auto& elt) {
|
|
||||||
all_options.append(elt);
|
|
||||||
all_options.append('|');
|
|
||||||
});
|
|
||||||
// Remove last value
|
|
||||||
all_options.RemoveLast(1u);
|
|
||||||
return all_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::array<VbamOption, kNbOptions>& VbamOption::AllOptions() {
|
|
||||||
// These MUST follow the same order as the definitions in VbamOptionID.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbOptions is automatically updated.
|
|
||||||
// This will be initialized on the first call, in load_opts(), ensuring the
|
|
||||||
// translation initialization has already happened.
|
|
||||||
static std::array<VbamOption, kNbOptions> g_all_opts = {
|
|
||||||
/// Display
|
|
||||||
VbamOption(VbamOptionID::kDisplayBilinear, &gopts.bilinear),
|
|
||||||
VbamOption(VbamOptionID::kDisplayFilter, &gopts.filter),
|
|
||||||
VbamOption(VbamOptionID::kDisplayFilterPlugin, &gopts.filter_plugin),
|
|
||||||
VbamOption(VbamOptionID::kDisplayIFB, &gopts.ifb),
|
|
||||||
VbamOption(VbamOptionID::kDisplayKeepOnTop, &gopts.keep_on_top),
|
|
||||||
VbamOption(VbamOptionID::kDisplayMaxThreads, &gopts.max_threads, 1, 256),
|
|
||||||
VbamOption(VbamOptionID::kDisplayRenderMethod, &gopts.render_method),
|
|
||||||
VbamOption(VbamOptionID::kDisplayScale, &gopts.video_scale, 1, 6),
|
|
||||||
VbamOption(VbamOptionID::kDisplayStretch, &gopts.retain_aspect),
|
|
||||||
|
|
||||||
/// GB
|
|
||||||
VbamOption(VbamOptionID::kGBBiosFile, &gopts.gb_bios),
|
|
||||||
VbamOption(VbamOptionID::kGBColorOption, &gbColorOption, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kGBColorizerHack, &colorizerHack, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kGBLCDFilter, &gbLcdFilter),
|
|
||||||
VbamOption(VbamOptionID::kGBGBCBiosFile, &gopts.gbc_bios),
|
|
||||||
VbamOption(VbamOptionID::kGBPalette0, systemGbPalette),
|
|
||||||
VbamOption(VbamOptionID::kGBPalette1, systemGbPalette + 8),
|
|
||||||
VbamOption(VbamOptionID::kGBPalette2, systemGbPalette + 16),
|
|
||||||
VbamOption(VbamOptionID::kGBPrintAutoPage, &gopts.print_auto_page),
|
|
||||||
VbamOption(VbamOptionID::kGBPrintScreenCap, &gopts.print_screen_cap),
|
|
||||||
VbamOption(VbamOptionID::kGBROMDir, &gopts.gb_rom_dir),
|
|
||||||
VbamOption(VbamOptionID::kGBGBCROMDir, &gopts.gbc_rom_dir),
|
|
||||||
|
|
||||||
/// GBA
|
|
||||||
VbamOption(VbamOptionID::kGBABiosFile, &gopts.gba_bios),
|
|
||||||
VbamOption(VbamOptionID::kGBALCDFilter, &gbaLcdFilter),
|
|
||||||
#ifndef NO_LINK
|
|
||||||
VbamOption(VbamOptionID::kGBALinkAuto, &gopts.link_auto),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkFast, &linkHacks, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkHost, &gopts.link_host),
|
|
||||||
VbamOption(VbamOptionID::kGBAServerIP, &gopts.server_ip),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkPort, &gopts.link_port, 0, 65535),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkProto, &gopts.link_proto, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkTimeout, &linkTimeout, 0, 9999999),
|
|
||||||
VbamOption(VbamOptionID::kGBALinkType, &gopts.gba_link_type, 0, 5),
|
|
||||||
#endif
|
|
||||||
VbamOption(VbamOptionID::kGBAROMDir, &gopts.gba_rom_dir),
|
|
||||||
|
|
||||||
/// General
|
|
||||||
VbamOption(VbamOptionID::kGeneralAutoLoadLastState, &gopts.autoload_state),
|
|
||||||
VbamOption(VbamOptionID::kGeneralBatteryDir, &gopts.battery_dir),
|
|
||||||
VbamOption(VbamOptionID::kGeneralFreezeRecent, &gopts.recent_freeze),
|
|
||||||
VbamOption(VbamOptionID::kGeneralRecordingDir, &gopts.recording_dir),
|
|
||||||
VbamOption(VbamOptionID::kGeneralRewindInterval, &gopts.rewind_interval, 0, 600),
|
|
||||||
VbamOption(VbamOptionID::kGeneralScreenshotDir, &gopts.scrshot_dir),
|
|
||||||
VbamOption(VbamOptionID::kGeneralStateDir, &gopts.state_dir),
|
|
||||||
VbamOption(VbamOptionID::kGeneralStatusBar, &gopts.statusbar, 0, 1),
|
|
||||||
|
|
||||||
/// Joypad
|
|
||||||
VbamOption(VbamOptionID::kJoypad),
|
|
||||||
VbamOption(VbamOptionID::kJoypadAutofireThrottle, &gopts.autofire_rate, 1, 1000),
|
|
||||||
VbamOption(VbamOptionID::kJoypadDefault, &gopts.default_stick, 1, 4),
|
|
||||||
|
|
||||||
/// Keyboard
|
|
||||||
VbamOption(VbamOptionID::kKeyboard),
|
|
||||||
|
|
||||||
// Core
|
|
||||||
VbamOption(VbamOptionID::kpreferencesagbPrint, &agbPrint, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesautoFrameSkip, &autoFrameSkip, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesautoPatch, &autoPatch, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesautoSaveLoadCheatList, &gopts.autoload_cheats),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesborderAutomatic, &gbBorderAutomatic, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesborderOn, &gbBorderOn, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencescaptureFormat, &captureFormat, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencescheatsEnabled, &cheatsEnabled, 0, 1),
|
|
||||||
#ifdef MMX
|
|
||||||
VbamOption(VbamOptionID::kpreferencesenableMMX, &enableMMX, 0, 1),
|
|
||||||
#endif
|
|
||||||
VbamOption(VbamOptionID::kpreferencesdisableStatus, &disableStatusMessages, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesemulatorType, &gbEmulatorType, 0, 5),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesflashSize, &optFlashSize, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesframeSkip, &frameSkip, -1, 9),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesfsColorDepth, &fsColorDepth, 0, 999),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesfsFrequency, &fsFrequency, 0, 999),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesfsHeight, &fsHeight, 0, 99999),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesfsWidth, &fsWidth, 0, 99999),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesgbPaletteOption, &gbPaletteOption, 0, 2),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesgbPrinter, &winGbPrinterEnabled, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesgdbBreakOnLoad, &gdbBreakOnLoad, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesgdbPort, &gdbPort, 0, 65535),
|
|
||||||
#ifndef NO_LINK
|
|
||||||
VbamOption(VbamOptionID::kpreferencesLinkNumPlayers, &linkNumPlayers, 2, 4),
|
|
||||||
#endif
|
|
||||||
VbamOption(VbamOptionID::kpreferencesmaxScale, &maxScale, 0, 100),
|
|
||||||
VbamOption(VbamOptionID::kpreferencespauseWhenInactive, &pauseWhenInactive, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesrtcEnabled, &rtcEnabled, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencessaveType, &cpuSaveType, 0, 5),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesshowSpeed, &showSpeed, 0, 2),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesshowSpeedTransparent, &showSpeedTransparent, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesskipBios, &skipBios, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesskipSaveGameCheats, &skipSaveGameCheats, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesskipSaveGameBattery, &skipSaveGameBattery, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesthrottle, &throttle, 0, 450),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesspeedupThrottle, &speedup_throttle, 0, 3000),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesspeedupFrameSkip, &speedup_frame_skip, 0, 300),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesspeedupThrottleFrameSkip, &speedup_throttle_frame_skip),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesuseBiosGB, &useBiosFileGB, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesuseBiosGBA, &useBiosFileGBA, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesuseBiosGBC, &useBiosFileGBC, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kpreferencesvsync, &vsync, 0, 1),
|
|
||||||
|
|
||||||
/// Geometry
|
|
||||||
VbamOption(VbamOptionID::kgeometryfullScreen, &fullScreen, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kgeometryisMaximized, &windowMaximized, 0, 1),
|
|
||||||
VbamOption(VbamOptionID::kgeometrywindowHeight, &windowHeight, 0, 99999),
|
|
||||||
VbamOption(VbamOptionID::kgeometrywindowWidth, &windowWidth, 0, 99999),
|
|
||||||
VbamOption(VbamOptionID::kgeometrywindowX, &windowPositionX, -1, 99999),
|
|
||||||
VbamOption(VbamOptionID::kgeometrywindowY, &windowPositionY, -1, 99999),
|
|
||||||
|
|
||||||
/// UI
|
|
||||||
VbamOption(VbamOptionID::kuiallowKeyboardBackgroundInput, &allowKeyboardBackgroundInput),
|
|
||||||
VbamOption(VbamOptionID::kuiallowJoystickBackgroundInput, &allowJoystickBackgroundInput),
|
|
||||||
VbamOption(VbamOptionID::kuihideMenuBar, &gopts.hide_menu_bar),
|
|
||||||
|
|
||||||
/// Sound
|
|
||||||
VbamOption(VbamOptionID::kSoundAudioAPI, &gopts.audio_api),
|
|
||||||
VbamOption(VbamOptionID::kSoundAudioDevice, &gopts.audio_dev),
|
|
||||||
VbamOption(VbamOptionID::kSoundBuffers, &gopts.audio_buffers, 2, 10),
|
|
||||||
VbamOption(VbamOptionID::kSoundEnable, &gopts.sound_en, 0, 0x30f),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBAFiltering, &gopts.gba_sound_filter, 0, 100),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBAInterpolation, &gopts.soundInterpolation),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBDeclicking, &gopts.gb_declick),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBEcho, &gopts.gb_echo, 0, 100),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBEnableEffects, &gopts.gb_effects_config_enabled),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBStereo, &gopts.gb_stereo, 0, 100),
|
|
||||||
VbamOption(VbamOptionID::kSoundGBSurround, &gopts.gb_effects_config_surround),
|
|
||||||
VbamOption(VbamOptionID::kSoundQuality, &gopts.sound_qual),
|
|
||||||
VbamOption(VbamOptionID::kSoundVolume, &gopts.sound_vol, 0, 200),
|
|
||||||
};
|
|
||||||
return g_all_opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// These MUST follow the same order as the definitions in VbamOptionID.
|
|
||||||
// Adding an option without adding to this array will result in a compiler
|
|
||||||
// error since kNbOptions is automatically updated.
|
|
||||||
const std::array<VbamOptionData, kNbOptions + 1> kAllOptionsData = {
|
|
||||||
/// Display
|
|
||||||
VbamOptionData { "Display/Bilinear", "Bilinear", _("Use bilinear filter with 3d renderer"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Display/Filter", "", _("Full-screen filter to apply"), VbamOption::Type::kFilter },
|
|
||||||
VbamOptionData { "Display/FilterPlugin", "", _("Filter plugin library"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "Display/IFB", "", _("Interframe blending function"), VbamOption::Type::kInterframe },
|
|
||||||
VbamOptionData { "Display/KeepOnTop", "KeepOnTop", _("Keep window on top"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Display/MaxThreads", "Multithread", _("Maximum number of threads to run filters in"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Display/RenderMethod", "", _("Render method; if unsupported, simple method will be used"), VbamOption::Type::kRenderMethod },
|
|
||||||
VbamOptionData { "Display/Scale", "", _("Default scale factor"), VbamOption::Type::kDouble },
|
|
||||||
VbamOptionData { "Display/Stretch", "RetainAspect", _("Retain aspect ratio when resizing"), VbamOption::Type::kBool },
|
|
||||||
|
|
||||||
/// GB
|
|
||||||
VbamOptionData { "GB/BiosFile", "", _("BIOS file to use for GB, if enabled"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GB/ColorOption", "GBColorOption", _("GB color enhancement, if enabled"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "GB/ColorizerHack", "ColorizerHack", _("Enable DX Colorization Hacks"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "GB/LCDFilter", "GBLcdFilter", _("Apply LCD filter, if enabled"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "GB/GBCBiosFile", "", _("BIOS file to use for GBC, if enabled"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GB/Palette0", "", _("The default palette, as 8 comma-separated 4-digit hex integers (rgb555)."), VbamOption::Type::kGbPalette },
|
|
||||||
VbamOptionData { "GB/Palette1", "", _("The first user palette, as 8 comma-separated 4-digit hex integers (rgb555)."), VbamOption::Type::kGbPalette },
|
|
||||||
VbamOptionData { "GB/Palette2", "", _("The second user palette, as 8 comma-separated 4-digit hex integers (rgb555)."), VbamOption::Type::kGbPalette },
|
|
||||||
VbamOptionData { "GB/PrintAutoPage", "PrintGather", _("Automatically gather a full page before printing"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "GB/PrintScreenCap", "PrintSnap", _("Automatically save printouts as screen captures with -print suffix"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "GB/ROMDir", "", _("Directory to look for ROM files"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GB/GBCROMDir", "", _("Directory to look for GBC ROM files"), VbamOption::Type::kString },
|
|
||||||
|
|
||||||
/// GBA
|
|
||||||
VbamOptionData { "GBA/BiosFile", "", _("BIOS file to use, if enabled"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GBA/LCDFilter", "GBALcdFilter", _("Apply LCD filter, if enabled"), VbamOption::Type::kBool },
|
|
||||||
#ifndef NO_LINK
|
|
||||||
VbamOptionData { "GBA/LinkAuto", "LinkAuto", _("Enable link at boot"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "GBA/LinkFast", "SpeedOn", _("Enable faster network protocol by default"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "GBA/LinkHost", "", _("Default network link client host"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GBA/ServerIP", "", _("Default network link server IP to bind"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "GBA/LinkPort", "", _("Default network link port (server and client)"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "GBA/LinkProto", "LinkProto", _("Default network protocol"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "GBA/LinkTimeout", "LinkTimeout", _("Link timeout (ms)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "GBA/LinkType", "LinkType", _("Link cable type"), VbamOption::Type::kInt },
|
|
||||||
#endif
|
|
||||||
VbamOptionData { "GBA/ROMDir", "", _("Directory to look for ROM files"), VbamOption::Type::kString },
|
|
||||||
|
|
||||||
/// General
|
|
||||||
VbamOptionData { "General/AutoLoadLastState", "", _("Automatically load last saved state"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "General/BatteryDir", "", _("Directory to store game save files (relative paths are relative to ROM; blank is config dir)"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "General/FreezeRecent", "", _("Freeze recent load list"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "General/RecordingDir", "", _("Directory to store A/V and game recordings (relative paths are relative to ROM)"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "General/RewindInterval", "", _("Number of seconds between rewind snapshots (0 to disable)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "General/ScreenshotDir", "", _("Directory to store screenshots (relative paths are relative to ROM)"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "General/StateDir", "", _("Directory to store saved state files (relative paths are relative to BatteryDir)"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "General/StatusBar", "StatusBar", _("Enable status bar"), VbamOption::Type::kInt },
|
|
||||||
|
|
||||||
/// Joypad
|
|
||||||
VbamOptionData { "Joypad/*/*", "", _("The parameter Joypad/<n>/<button> contains a comma-separated list of key names which map to joypad #<n> button <button>. Button is one of Up, Down, Left, Right, A, B, L, R, Select, Start, MotionUp, MotionDown, MotionLeft, MotionRight, AutoA, AutoB, Speed, Capture, GS"), VbamOption::Type::kNone },
|
|
||||||
VbamOptionData { "Joypad/AutofireThrottle", "", _("The autofire toggle period, in frames (1/60 s)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Joypad/Default", "", _("The number of the stick to use in single-player mode"), VbamOption::Type::kInt },
|
|
||||||
|
|
||||||
/// Keyboard
|
|
||||||
VbamOptionData { "Keyboard/*", "", _("The parameter Keyboard/<cmd> contains a comma-separated list of key names (e.g. Alt-Shift-F1). When the named key is pressed, the command <cmd> is executed."), VbamOption::Type::kNone },
|
|
||||||
|
|
||||||
// Core
|
|
||||||
VbamOptionData { "preferences/agbPrint", "AGBPrinter", _("Enable AGB debug print"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/autoFrameSkip", "FrameSkipAuto", _("Auto skip frames."), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/autoPatch", "ApplyPatches", _("Apply IPS/UPS/IPF patches if found"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/autoSaveLoadCheatList", "", _("Automatically save and load cheat list"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "preferences/borderAutomatic", "", _("Automatically enable border for Super GameBoy games"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/borderOn", "", _("Always enable border"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/captureFormat", "", _("Screen capture file format"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/cheatsEnabled", "", _("Enable cheats"), VbamOption::Type::kInt },
|
|
||||||
#ifdef MMX
|
|
||||||
VbamOptionData { "preferences/enableMMX", "MMX", _("Enable MMX"), VbamOption::Type::kInt },
|
|
||||||
#endif
|
|
||||||
VbamOptionData { "preferences/disableStatus", "NoStatusMsg", _("Disable on-screen status messages"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/emulatorType", "", _("Type of system to emulate"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/flashSize", "", _("Flash size 0 = 64KB 1 = 128KB"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/frameSkip", "FrameSkip", _("Skip frames. Values are 0-9 or -1 to skip automatically based on time."), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/fsColorDepth", "", _("Fullscreen mode color depth (0 = any)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/fsFrequency", "", _("Fullscreen mode frequency (0 = any)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/fsHeight", "", _("Fullscreen mode height (0 = desktop)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/fsWidth", "", _("Fullscreen mode width (0 = desktop)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/gbPaletteOption", "", _("The palette to use"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/gbPrinter", "Printer", _("Enable printer emulation"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/gdbBreakOnLoad", "DebugGDBBreakOnLoad", _("Break into GDB after loading the game."), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/gdbPort", "DebugGDBPort", _("Port to connect GDB to."), VbamOption::Type::kInt },
|
|
||||||
#ifndef NO_LINK
|
|
||||||
VbamOptionData { "preferences/LinkNumPlayers", "", _("Number of players in network"), VbamOption::Type::kInt },
|
|
||||||
#endif
|
|
||||||
VbamOptionData { "preferences/maxScale", "", _("Maximum scale factor (0 = no limit)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/pauseWhenInactive", "PauseWhenInactive", _("Pause game when main window loses focus"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/rtcEnabled", "RTC", _("Enable RTC (vba-over.ini override is rtcEnabled"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/saveType", "", _("Native save (\"battery\") hardware type"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/showSpeed", "", _("Show speed indicator"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/showSpeedTransparent", "Transparent", _("Draw on-screen messages transparently"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/skipBios", "SkipIntro", _("Skip BIOS initialization"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/skipSaveGameCheats", "", _("Do not overwrite cheat list when loading state"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/skipSaveGameBattery", "", _("Do not overwrite native (battery) save when loading state"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/throttle", "", _("Throttle game speed, even when accelerated (0-450%, 0 = no throttle)"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "preferences/speedupThrottle", "", _("Set throttle for speedup key (0-3000%, 0 = no throttle)"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "preferences/speedupFrameSkip", "", _("Number of frames to skip with speedup (instead of speedup throttle)"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "preferences/speedupThrottleFrameSkip", "", _("Use frame skip for speedup throttle"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "preferences/useBiosGB", "BootRomGB", _("Use the specified BIOS file for GB"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/useBiosGBA", "BootRomEn", _("Use the specified BIOS file"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/useBiosGBC", "BootRomGBC", _("Use the specified BIOS file for GBC"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "preferences/vsync", "VSync", _("Wait for vertical sync"), VbamOption::Type::kInt },
|
|
||||||
|
|
||||||
/// Geometry
|
|
||||||
VbamOptionData { "geometry/fullScreen", "Fullscreen", _("Enter fullscreen mode at startup"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "geometry/isMaximized", "Maximized", _("Window maximized"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "geometry/windowHeight", "Height", _("Window height at startup"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "geometry/windowWidth", "Width", _("Window width at startup"), VbamOption::Type::kUnsigned },
|
|
||||||
VbamOptionData { "geometry/windowX", "X", _("Window axis X position at startup"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "geometry/windowY", "Y", _("Window axis Y position at startup"), VbamOption::Type::kInt },
|
|
||||||
|
|
||||||
/// UI
|
|
||||||
VbamOptionData { "ui/allowKeyboardBackgroundInput", "AllowKeyboardBackgroundInput", _("Capture key events while on background"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "ui/allowJoystickBackgroundInput", "AllowJoystickBackgroundInput", _("Capture joy events while on background"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "ui/hideMenuBar", "", _("Hide menu bar when mouse is inactive"), VbamOption::Type::kBool },
|
|
||||||
|
|
||||||
/// Sound
|
|
||||||
VbamOptionData { "Sound/AudioAPI", "", _("Sound API; if unsupported, default API will be used"), VbamOption::Type::kAudioApi },
|
|
||||||
VbamOptionData { "Sound/AudioDevice", "", _("Device ID of chosen audio device for chosen driver"), VbamOption::Type::kString },
|
|
||||||
VbamOptionData { "Sound/Buffers", "", _("Number of sound buffers"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Sound/Enable", "", _("Bit mask of sound channels to enable"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Sound/GBAFiltering", "", _("GBA sound filtering (%)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Sound/GBAInterpolation", "GBASoundInterpolation", _("GBA sound interpolation"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Sound/GBDeclicking", "GBDeclicking", _("GB sound declicking"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Sound/GBEcho", "", _("GB echo effect (%)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Sound/GBEnableEffects", "GBEnhanceSound", _("Enable GB sound effects"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Sound/GBStereo", "", _("GB stereo effect (%)"), VbamOption::Type::kInt },
|
|
||||||
VbamOptionData { "Sound/GBSurround", "GBSurround", _("GB surround sound effect (%)"), VbamOption::Type::kBool },
|
|
||||||
VbamOptionData { "Sound/Quality", "", _("Sound sample rate (kHz)"), VbamOption::Type::kSoundQuality },
|
|
||||||
VbamOptionData { "Sound/Volume", "", _("Sound volume (%)"), VbamOption::Type::kInt },
|
|
||||||
|
|
||||||
// Last. This should never be used, it actually maps to VbamOptionID::kLast.
|
|
||||||
// This is to prevent a memory access violation error in case something
|
|
||||||
// attempts to instantiate a VbamOptionID::kLast. It will trigger a check
|
|
||||||
// in the VbamOption constructor, but that is after the constructor has
|
|
||||||
// accessed this entry.
|
|
||||||
VbamOptionData { "", "", "", VbamOption::Type::kNone },
|
|
||||||
};
|
|
||||||
|
|
||||||
nonstd::optional<VbamOptionID> StringToOptionId(const wxString& input) {
|
|
||||||
static std::map<wxString, VbamOptionID> kStringToOptionId;
|
|
||||||
if (kStringToOptionId.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbOptions; i++) {
|
|
||||||
kStringToOptionId.emplace(
|
|
||||||
kAllOptionsData[i].config_name, static_cast<VbamOptionID>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToOptionId.size() == kNbOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToOptionId.find(input);
|
|
||||||
if (iter == kStringToOptionId.end()) {
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString FilterToString(int value) {
|
|
||||||
assert(value >= 0 && static_cast<size_t>(value) < kNbFilterFunctions);
|
|
||||||
return kFilterStrings[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString InterframeToString(int value) {
|
|
||||||
assert(value >= 0 && static_cast<size_t>(value) < kNbInterframes);
|
|
||||||
return kInterframeStrings[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString RenderMethodToString(int value) {
|
|
||||||
assert(value >= 0 && static_cast<size_t>(value) < kNbRenderMethods);
|
|
||||||
return kRenderMethodStrings[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString AudioApiToString(int value) {
|
|
||||||
assert(value >= 0 && static_cast<size_t>(value) < kNbAudioApis);
|
|
||||||
return kAudioApiStrings[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString SoundQualityToString(int value) {
|
|
||||||
assert(value >= 0 && static_cast<size_t>(value) < kNbSoundQualities);
|
|
||||||
return kSoundQualityStrings[value];
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringToFilter(const wxString& config_name, const wxString& input) {
|
|
||||||
static std::map<wxString, FilterFunction> kStringToFilter;
|
|
||||||
if (kStringToFilter.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbFilterFunctions; i++) {
|
|
||||||
kStringToFilter.emplace(
|
|
||||||
kFilterStrings[i], static_cast<FilterFunction>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToFilter.size() == kNbFilterFunctions);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToFilter.find(input);
|
|
||||||
if (iter == kStringToFilter.end()) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
|
||||||
input,
|
|
||||||
config_name,
|
|
||||||
AllEnumValuesForType(VbamOption::Type::kFilter));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<int>(iter->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringToInterframe(const wxString& config_name, const wxString& input) {
|
|
||||||
static std::map<wxString, Interframe> kStringToInterframe;
|
|
||||||
if (kStringToInterframe.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbInterframes; i++) {
|
|
||||||
kStringToInterframe.emplace(
|
|
||||||
kInterframeStrings[i], static_cast<Interframe>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToInterframe.size() == kNbInterframes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToInterframe.find(input);
|
|
||||||
if (iter == kStringToInterframe.end()) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
|
||||||
input,
|
|
||||||
config_name,
|
|
||||||
AllEnumValuesForType(VbamOption::Type::kInterframe));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<int>(iter->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringToRenderMethod(const wxString& config_name, const wxString& input) {
|
|
||||||
static std::map<wxString, RenderMethod> kStringToRenderMethod;
|
|
||||||
if (kStringToRenderMethod.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbRenderMethods; i++) {
|
|
||||||
kStringToRenderMethod.emplace(kRenderMethodStrings[i], static_cast<RenderMethod>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToRenderMethod.size() == kNbRenderMethods);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToRenderMethod.find(input);
|
|
||||||
if (iter == kStringToRenderMethod.end()) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
|
||||||
input,
|
|
||||||
config_name,
|
|
||||||
AllEnumValuesForType(VbamOption::Type::kRenderMethod));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<int>(iter->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringToAudioApi(const wxString& config_name, const wxString& input) {
|
|
||||||
static std::map<wxString, AudioApi> kStringToAudioApi;
|
|
||||||
if (kStringToAudioApi.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbAudioApis; i++) {
|
|
||||||
kStringToAudioApi.emplace(kAudioApiStrings[i], static_cast<AudioApi>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToAudioApi.size() == kNbAudioApis);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToAudioApi.find(input);
|
|
||||||
if (iter == kStringToAudioApi.end()) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
|
||||||
input,
|
|
||||||
config_name,
|
|
||||||
AllEnumValuesForType(VbamOption::Type::kAudioApi));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<int>(iter->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StringToSoundQuality(const wxString& config_name, const wxString& input) {
|
|
||||||
static std::map<wxString, SoundQuality> kStringToSoundQuality;
|
|
||||||
if (kStringToSoundQuality.empty()) {
|
|
||||||
for (size_t i = 0; i < kNbSoundQualities; i++) {
|
|
||||||
kStringToSoundQuality.emplace(kSoundQualityStrings[i], static_cast<SoundQuality>(i));
|
|
||||||
}
|
|
||||||
assert(kStringToSoundQuality.size() == kNbSoundQualities);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto iter = kStringToSoundQuality.find(input);
|
|
||||||
if (iter == kStringToSoundQuality.end()) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
|
||||||
input,
|
|
||||||
config_name,
|
|
||||||
AllEnumValuesForType(VbamOption::Type::kSoundQuality));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<int>(iter->second);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString AllEnumValuesForType(VbamOption::Type type) {
|
|
||||||
switch (type) {
|
|
||||||
case VbamOption::Type::kFilter: {
|
|
||||||
static const wxString kAllFilterValues = AllEnumValuesForArray(kFilterStrings);
|
|
||||||
return kAllFilterValues;
|
|
||||||
}
|
|
||||||
case VbamOption::Type::kInterframe: {
|
|
||||||
static const wxString kAllInterframeValues = AllEnumValuesForArray(kInterframeStrings);
|
|
||||||
return kAllInterframeValues;
|
|
||||||
}
|
|
||||||
case VbamOption::Type::kRenderMethod: {
|
|
||||||
static const wxString kAllRenderValues = AllEnumValuesForArray(kRenderMethodStrings);
|
|
||||||
return kAllRenderValues;
|
|
||||||
}
|
|
||||||
case VbamOption::Type::kAudioApi: {
|
|
||||||
static const wxString kAllAudioApiValues = AllEnumValuesForArray(kAudioApiStrings);
|
|
||||||
return kAllAudioApiValues;
|
|
||||||
}
|
|
||||||
case VbamOption::Type::kSoundQuality: {
|
|
||||||
static const wxString kAllSoundQualityValues = AllEnumValuesForArray(kSoundQualityStrings);
|
|
||||||
return kAllSoundQualityValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't use default here to explicitly trigger a compiler warning when
|
|
||||||
// adding a new value.
|
|
||||||
case VbamOption::Type::kNone:
|
|
||||||
case VbamOption::Type::kBool:
|
|
||||||
case VbamOption::Type::kDouble:
|
|
||||||
case VbamOption::Type::kInt:
|
|
||||||
case VbamOption::Type::kUnsigned:
|
|
||||||
case VbamOption::Type::kString:
|
|
||||||
case VbamOption::Type::kGbPalette:
|
|
||||||
assert(false);
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MaxForType(VbamOption::Type type) {
|
|
||||||
switch (type) {
|
|
||||||
case VbamOption::Type::kFilter:
|
|
||||||
return kNbFilterFunctions;
|
|
||||||
case VbamOption::Type::kInterframe:
|
|
||||||
return kNbInterframes;
|
|
||||||
case VbamOption::Type::kRenderMethod:
|
|
||||||
return kNbRenderMethods;
|
|
||||||
case VbamOption::Type::kAudioApi:
|
|
||||||
return kNbAudioApis;
|
|
||||||
case VbamOption::Type::kSoundQuality:
|
|
||||||
return kNbSoundQualities;
|
|
||||||
|
|
||||||
// We don't use default here to explicitly trigger a compiler warning when
|
|
||||||
// adding a new value.
|
|
||||||
case VbamOption::Type::kNone:
|
|
||||||
case VbamOption::Type::kBool:
|
|
||||||
case VbamOption::Type::kDouble:
|
|
||||||
case VbamOption::Type::kInt:
|
|
||||||
case VbamOption::Type::kUnsigned:
|
|
||||||
case VbamOption::Type::kString:
|
|
||||||
case VbamOption::Type::kGbPalette:
|
|
||||||
assert(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
|
@ -1,369 +0,0 @@
|
||||||
#include "vbam-options.h"
|
|
||||||
|
|
||||||
#include "nonstd/variant.hpp"
|
|
||||||
|
|
||||||
#include <wx/log.h>
|
|
||||||
#include <wx/translation.h>
|
|
||||||
|
|
||||||
#define VBAM_OPTIONS_INTERNAL_INCLUDE
|
|
||||||
#include "vbam-options-internal.h"
|
|
||||||
#undef VBAM_OPTIONS_INTERNAL_INCLUDE
|
|
||||||
|
|
||||||
// static
|
|
||||||
VbamOption const* VbamOption::FindOptionByName(const wxString &config_name) {
|
|
||||||
nonstd::optional<VbamOptionID> option_id = internal::StringToOptionId(config_name);
|
|
||||||
if (!option_id) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return &FindOptionByID(option_id.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
VbamOption& VbamOption::FindOptionByID(VbamOptionID id) {
|
|
||||||
assert (id != VbamOptionID::Last);
|
|
||||||
return AllOptions()[static_cast<size_t>(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::~VbamOption() = default;
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(),
|
|
||||||
min_(),
|
|
||||||
max_() {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, bool* option) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(),
|
|
||||||
max_() {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_bool());
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, double* option, double min, double max) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(min),
|
|
||||||
max_(max) {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_double());
|
|
||||||
|
|
||||||
// Validate the initial value.
|
|
||||||
SetDouble(*option);
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, int32_t* option, int32_t min, int32_t max) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(min),
|
|
||||||
max_(max) {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_int());
|
|
||||||
|
|
||||||
// Validate the initial value.
|
|
||||||
SetInt(*option);
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, uint32_t* option, uint32_t min, uint32_t max) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(min),
|
|
||||||
max_(max) {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_unsigned());
|
|
||||||
|
|
||||||
// Validate the initial value.
|
|
||||||
SetUnsigned(*option);
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, wxString* option) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(),
|
|
||||||
max_() {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, int* option) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(0),
|
|
||||||
max_(internal::MaxForType(type_)) {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_filter() || is_interframe() || is_render_method() || is_audio_api() || is_sound_quality());
|
|
||||||
|
|
||||||
// Validate the initial value.
|
|
||||||
SetEnumInt(*option);
|
|
||||||
}
|
|
||||||
|
|
||||||
VbamOption::VbamOption(VbamOptionID id, uint16_t* option) :
|
|
||||||
id_(id),
|
|
||||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
|
||||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
|
||||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
|
||||||
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
|
|
||||||
value_(option),
|
|
||||||
min_(),
|
|
||||||
max_() {
|
|
||||||
assert(id != VbamOptionID::Last);
|
|
||||||
assert(is_gb_palette());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VbamOption::GetBool() const {
|
|
||||||
assert(is_bool());
|
|
||||||
return *(nonstd::get<bool*>(value_));
|
|
||||||
}
|
|
||||||
|
|
||||||
double VbamOption::GetDouble() const {
|
|
||||||
assert(is_double());
|
|
||||||
return *(nonstd::get<double*>(value_));
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VbamOption::GetInt() const {
|
|
||||||
assert(is_int());
|
|
||||||
return *(nonstd::get<int32_t*>(value_));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t VbamOption::GetUnsigned() const {
|
|
||||||
assert(is_unsigned());
|
|
||||||
return *(nonstd::get<uint32_t*>(value_));
|
|
||||||
}
|
|
||||||
|
|
||||||
const wxString VbamOption::GetString() const {
|
|
||||||
assert(is_string());
|
|
||||||
return *(nonstd::get<wxString*>(value_));
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString VbamOption::GetEnumString() const {
|
|
||||||
switch (type_) {
|
|
||||||
case VbamOption::Type::kFilter:
|
|
||||||
return internal::FilterToString(*(nonstd::get<int32_t*>(value_)));
|
|
||||||
case VbamOption::Type::kInterframe:
|
|
||||||
return internal::InterframeToString(*(nonstd::get<int32_t*>(value_)));
|
|
||||||
case VbamOption::Type::kRenderMethod:
|
|
||||||
return internal::RenderMethodToString(*(nonstd::get<int32_t*>(value_)));
|
|
||||||
case VbamOption::Type::kAudioApi:
|
|
||||||
return internal::AudioApiToString(*(nonstd::get<int32_t*>(value_)));
|
|
||||||
case VbamOption::Type::kSoundQuality:
|
|
||||||
return internal::SoundQualityToString(*(nonstd::get<int32_t*>(value_)));
|
|
||||||
|
|
||||||
// We don't use default here to explicitly trigger a compiler warning when
|
|
||||||
// adding a new value.
|
|
||||||
case VbamOption::Type::kNone:
|
|
||||||
case VbamOption::Type::kBool:
|
|
||||||
case VbamOption::Type::kDouble:
|
|
||||||
case VbamOption::Type::kInt:
|
|
||||||
case VbamOption::Type::kUnsigned:
|
|
||||||
case VbamOption::Type::kString:
|
|
||||||
case VbamOption::Type::kGbPalette:
|
|
||||||
assert(false);
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString VbamOption::GetGbPaletteString() const {
|
|
||||||
assert(is_gb_palette());
|
|
||||||
|
|
||||||
wxString palette_string;
|
|
||||||
uint16_t const* value = nonstd::get<uint16_t*>(value_);
|
|
||||||
palette_string.Printf("%04X,%04X,%04X,%04X,%04X,%04X,%04X,%04X",
|
|
||||||
value[0], value[1], value[2], value[3],
|
|
||||||
value[4], value[5], value[6], value[7]);
|
|
||||||
return palette_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetBool(bool value) const {
|
|
||||||
assert(is_bool());
|
|
||||||
*nonstd::get<bool*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetDouble(double value) const {
|
|
||||||
assert(is_double());
|
|
||||||
if (value < nonstd::get<double>(min_) || value > nonstd::get<double>(max_)) {
|
|
||||||
wxLogWarning(
|
|
||||||
_("Invalid value %f for option %s; valid values are %f - %f"),
|
|
||||||
value,
|
|
||||||
config_name_,
|
|
||||||
nonstd::get<double>(min_),
|
|
||||||
nonstd::get<double>(max_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*nonstd::get<double*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetInt(int32_t value) const {
|
|
||||||
assert(is_int());
|
|
||||||
if (value < nonstd::get<int32_t>(min_) || value > nonstd::get<int32_t>(max_)) {
|
|
||||||
wxLogWarning(
|
|
||||||
_("Invalid value %d for option %s; valid values are %d - %d"),
|
|
||||||
value,
|
|
||||||
config_name_,
|
|
||||||
nonstd::get<int32_t>(min_),
|
|
||||||
nonstd::get<int32_t>(max_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*nonstd::get<int32_t*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetUnsigned(uint32_t value) const {
|
|
||||||
assert(is_unsigned());
|
|
||||||
if (value < nonstd::get<uint32_t>(min_) || value > nonstd::get<uint32_t>(max_)) {
|
|
||||||
wxLogWarning(
|
|
||||||
_("Invalid value %d for option %s; valid values are %d - %d"),
|
|
||||||
value,
|
|
||||||
config_name_,
|
|
||||||
nonstd::get<uint32_t>(min_),
|
|
||||||
nonstd::get<uint32_t>(max_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*nonstd::get<uint32_t*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetString(const wxString& value) const {
|
|
||||||
assert(is_string());
|
|
||||||
*nonstd::get<wxString*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetEnumString(const wxString& value) const {
|
|
||||||
switch (type_) {
|
|
||||||
case VbamOption::Type::kFilter:
|
|
||||||
SetEnumInt(internal::StringToFilter(config_name_, value));
|
|
||||||
return;
|
|
||||||
case VbamOption::Type::kInterframe:
|
|
||||||
SetEnumInt(internal::StringToInterframe(config_name_, value));
|
|
||||||
return;
|
|
||||||
case VbamOption::Type::kRenderMethod:
|
|
||||||
SetEnumInt(internal::StringToRenderMethod(config_name_, value));
|
|
||||||
return;
|
|
||||||
case VbamOption::Type::kAudioApi:
|
|
||||||
SetEnumInt(internal::StringToAudioApi(config_name_, value));
|
|
||||||
return;
|
|
||||||
case VbamOption::Type::kSoundQuality:
|
|
||||||
SetEnumInt(internal::StringToSoundQuality(config_name_, value));
|
|
||||||
return;
|
|
||||||
|
|
||||||
// We don't use default here to explicitly trigger a compiler warning when
|
|
||||||
// adding a new value.
|
|
||||||
case VbamOption::Type::kNone:
|
|
||||||
case VbamOption::Type::kBool:
|
|
||||||
case VbamOption::Type::kDouble:
|
|
||||||
case VbamOption::Type::kInt:
|
|
||||||
case VbamOption::Type::kUnsigned:
|
|
||||||
case VbamOption::Type::kString:
|
|
||||||
case VbamOption::Type::kGbPalette:
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetEnumInt(int value) const {
|
|
||||||
assert(is_filter() || is_interframe() || is_render_method() || is_audio_api() || is_sound_quality());
|
|
||||||
if (value < nonstd::get<int32_t>(min_) || value > nonstd::get<int32_t>(max_)) {
|
|
||||||
wxLogWarning(
|
|
||||||
_("Invalid value %d for option %s; valid values are %s"),
|
|
||||||
value,
|
|
||||||
config_name_,
|
|
||||||
internal::AllEnumValuesForType(type_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*nonstd::get<int32_t*>(value_) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VbamOption::SetGbPalette(const wxString& value) const {
|
|
||||||
assert(is_gb_palette());
|
|
||||||
|
|
||||||
// 8 values of 4 chars and 7 commas.
|
|
||||||
static constexpr size_t kPaletteStringSize = 8 * 4 + 7;
|
|
||||||
|
|
||||||
if (value.size() != kPaletteStringSize) {
|
|
||||||
wxLogWarning(_("Invalid value %s for option %s"),
|
|
||||||
value,
|
|
||||||
config_name_);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint16_t* dest = nonstd::get<uint16_t*>(value_);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++) {
|
|
||||||
wxString number = value.substr(i * 5, 4);
|
|
||||||
long temp = 0;
|
|
||||||
if (number.ToLong(&temp, 16)) {
|
|
||||||
dest[i] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString VbamOption::ToHelperString() const {
|
|
||||||
wxString helper_string = config_name_;
|
|
||||||
|
|
||||||
switch (type_) {
|
|
||||||
case VbamOption::Type::kNone:
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kBool:
|
|
||||||
helper_string.Append(" (flag)");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kDouble:
|
|
||||||
helper_string.Append(" (decimal)");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kInt:
|
|
||||||
helper_string.Append(" (int)");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kUnsigned:
|
|
||||||
helper_string.Append(" (unsigned)");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kString:
|
|
||||||
helper_string.Append(" (string)");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kFilter:
|
|
||||||
case VbamOption::Type::kInterframe:
|
|
||||||
case VbamOption::Type::kRenderMethod:
|
|
||||||
case VbamOption::Type::kAudioApi:
|
|
||||||
case VbamOption::Type::kSoundQuality:
|
|
||||||
helper_string.Append(" (");
|
|
||||||
helper_string.Append(internal::AllEnumValuesForType(type_));
|
|
||||||
helper_string.Append(")");
|
|
||||||
break;
|
|
||||||
case VbamOption::Type::kGbPalette:
|
|
||||||
helper_string.Append(" (XXXX,XXXX,XXXX,XXXX,XXXX,XXXX,XXXX,XXXX)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
helper_string.Append("\n\t");
|
|
||||||
helper_string.Append(ux_helper_);
|
|
||||||
helper_string.Append("\n");
|
|
||||||
|
|
||||||
return helper_string;
|
|
||||||
}
|
|
|
@ -1,291 +0,0 @@
|
||||||
#include "wx/gamecontrol.h"
|
|
||||||
|
|
||||||
#include "../strutils.h"
|
|
||||||
#include "opts.h"
|
|
||||||
#include "wx/log.h"
|
|
||||||
#include "wxlogdebug.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
constexpr uint32_t kBitKeyA = (1 << 0);
|
|
||||||
constexpr uint32_t kBitKeyB = (1 << 1);
|
|
||||||
constexpr uint32_t kBitKeySelect = (1 << 2);
|
|
||||||
constexpr uint32_t kBitKeyStart = (1 << 3);
|
|
||||||
constexpr uint32_t kBitKeyRight = (1 << 4);
|
|
||||||
constexpr uint32_t kBitKeyLeft = (1 << 5);
|
|
||||||
constexpr uint32_t kBitKeyUp = (1 << 6);
|
|
||||||
constexpr uint32_t kBitKeyDown = (1 << 7);
|
|
||||||
constexpr uint32_t kBitKeyR = (1 << 8);
|
|
||||||
constexpr uint32_t kBitKeyL = (1 << 9);
|
|
||||||
constexpr uint32_t kBitKeySpeed = (1 << 10);
|
|
||||||
constexpr uint32_t kBitKeyCapture = (1 << 11);
|
|
||||||
constexpr uint32_t kBitKeyGameShark = (1 << 12);
|
|
||||||
constexpr uint32_t kBitKeyAutoA = (1 << 13);
|
|
||||||
constexpr uint32_t kBitKeyAutoB = (1 << 14);
|
|
||||||
constexpr uint32_t kBitKeyMotionUp = (1 << 15);
|
|
||||||
constexpr uint32_t kBitKeyMotionDown = (1 << 16);
|
|
||||||
constexpr uint32_t kBitKeyMotionLeft = (1 << 17);
|
|
||||||
constexpr uint32_t kBitKeyMotionRight = (1 << 18);
|
|
||||||
constexpr uint32_t kBitKeyMotionIn = (1 << 19);
|
|
||||||
constexpr uint32_t kBitKeyMotionOut = (1 << 20);
|
|
||||||
|
|
||||||
constexpr std::array<uint32_t, kNbGameKeys> kBitMask = {
|
|
||||||
kBitKeyUp,
|
|
||||||
kBitKeyDown,
|
|
||||||
kBitKeyLeft,
|
|
||||||
kBitKeyRight,
|
|
||||||
kBitKeyA,
|
|
||||||
kBitKeyB,
|
|
||||||
kBitKeyL,
|
|
||||||
kBitKeyR,
|
|
||||||
kBitKeySelect,
|
|
||||||
kBitKeyStart,
|
|
||||||
kBitKeyMotionUp,
|
|
||||||
kBitKeyMotionDown,
|
|
||||||
kBitKeyMotionLeft,
|
|
||||||
kBitKeyMotionRight,
|
|
||||||
kBitKeyMotionIn,
|
|
||||||
kBitKeyMotionOut,
|
|
||||||
kBitKeyAutoA,
|
|
||||||
kBitKeyAutoB,
|
|
||||||
kBitKeySpeed,
|
|
||||||
kBitKeyCapture,
|
|
||||||
kBitKeyGameShark,
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int GameKeyToInt(const wxGameKey& game_key) {
|
|
||||||
return static_cast<std::underlying_type<wxGameKey>::type>(
|
|
||||||
game_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if `joypad` is in a valid joypad range.
|
|
||||||
inline bool JoypadInRange(const int& joypad) {
|
|
||||||
constexpr int kMinJoypadIndex = 0;
|
|
||||||
return joypad >= kMinJoypadIndex && joypad < kNbJoypads;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
wxString GameKeyToString(const wxGameKey& game_key) {
|
|
||||||
// Note: this must match GUI widget names or GUI won't work
|
|
||||||
// This array's order determines tab order as well
|
|
||||||
static const std::array<wxString, kNbGameKeys> kGameKeyStrings = {
|
|
||||||
wxT("Up"),
|
|
||||||
wxT("Down"),
|
|
||||||
wxT("Left"),
|
|
||||||
wxT("Right"),
|
|
||||||
wxT("A"),
|
|
||||||
wxT("B"),
|
|
||||||
wxT("L"),
|
|
||||||
wxT("R"),
|
|
||||||
wxT("Select"),
|
|
||||||
wxT("Start"),
|
|
||||||
wxT("MotionUp"),
|
|
||||||
wxT("MotionDown"),
|
|
||||||
wxT("MotionLeft"),
|
|
||||||
wxT("MotionRight"),
|
|
||||||
wxT("MotionIn"),
|
|
||||||
wxT("MotionOut"),
|
|
||||||
wxT("AutoA"),
|
|
||||||
wxT("AutoB"),
|
|
||||||
wxT("Speed"),
|
|
||||||
wxT("Capture"),
|
|
||||||
wxT("GS"),
|
|
||||||
};
|
|
||||||
return kGameKeyStrings[GameKeyToInt(game_key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional<wxGameKey> StringToGameKey(const wxString& input) {
|
|
||||||
static const std::map<wxString, wxGameKey> kStringToGameKey = {
|
|
||||||
{ wxT("Up"), wxGameKey::Up },
|
|
||||||
{ wxT("Down"), wxGameKey::Down },
|
|
||||||
{ wxT("Left"), wxGameKey::Left },
|
|
||||||
{ wxT("Right"), wxGameKey::Right },
|
|
||||||
{ wxT("A"), wxGameKey::A },
|
|
||||||
{ wxT("B"), wxGameKey::B },
|
|
||||||
{ wxT("L"), wxGameKey::L },
|
|
||||||
{ wxT("R"), wxGameKey::R },
|
|
||||||
{ wxT("Select"), wxGameKey::Select },
|
|
||||||
{ wxT("Start"), wxGameKey::Start },
|
|
||||||
{ wxT("MotionUp"), wxGameKey::MotionUp },
|
|
||||||
{ wxT("MotionDown"), wxGameKey::MotionDown },
|
|
||||||
{ wxT("MotionLeft"), wxGameKey::MotionLeft },
|
|
||||||
{ wxT("MotionRight"), wxGameKey::MotionRight },
|
|
||||||
{ wxT("MotionIn"), wxGameKey::MotionIn },
|
|
||||||
{ wxT("MotionOut"), wxGameKey::MotionOut },
|
|
||||||
{ wxT("AutoA"), wxGameKey::AutoA },
|
|
||||||
{ wxT("AutoB"), wxGameKey::AutoB },
|
|
||||||
{ wxT("Speed"), wxGameKey::Speed },
|
|
||||||
{ wxT("Capture"), wxGameKey::Capture },
|
|
||||||
{ wxT("GS"), wxGameKey::Gameshark },
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto iter = kStringToGameKey.find(input);
|
|
||||||
if (iter == kStringToGameKey.end()) {
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
nonstd::optional<wxGameControl> wxGameControl::FromString(const wxString &name) {
|
|
||||||
static const wxString kJoypad(wxT("Joypad"));
|
|
||||||
if (!wxStrncmp(name, kJoypad, kJoypad.size())) {
|
|
||||||
wxLogDebug("Doesn't start with joypad");
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto parts = strutils::split(name, wxT("/"));
|
|
||||||
if (parts.size() != 3) {
|
|
||||||
wxLogDebug("Wrong split size: %d", parts.size());
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int joypad = parts[1][0] - wxT('1');
|
|
||||||
if (!JoypadInRange(joypad)) {
|
|
||||||
wxLogDebug("Wrong joypad index: %d", joypad);
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional<wxGameKey> game_key = StringToGameKey(parts[2]);
|
|
||||||
if (!game_key) {
|
|
||||||
wxLogDebug("Failed to parse game_key: %s", parts[2]);
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxGameControl(joypad, game_key.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
wxGameControl::wxGameControl(int joypad, wxGameKey game_key) :
|
|
||||||
joypad_(joypad),
|
|
||||||
game_key_(game_key),
|
|
||||||
config_string_(wxString::Format(
|
|
||||||
wxT("Joypad/%d/%s"), joypad_ + 1, GameKeyToString(game_key_))) {
|
|
||||||
assert(JoypadInRange(joypad_));
|
|
||||||
}
|
|
||||||
wxGameControl::~wxGameControl() = default;
|
|
||||||
|
|
||||||
bool wxGameControl::operator==(const wxGameControl& other) const {
|
|
||||||
return joypad_ == other.joypad_ && game_key_ == other.game_key_;
|
|
||||||
}
|
|
||||||
bool wxGameControl::operator!=(const wxGameControl& other) const {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
bool wxGameControl::operator<(const wxGameControl& other) const {
|
|
||||||
if (joypad_ != other.joypad_) {
|
|
||||||
return joypad_ < other.joypad_;
|
|
||||||
}
|
|
||||||
if (game_key_ != other.game_key_) {
|
|
||||||
return game_key_ < other.game_key_;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool wxGameControl::operator<=(const wxGameControl& other) const {
|
|
||||||
return !(*this > other);
|
|
||||||
}
|
|
||||||
bool wxGameControl::operator>(const wxGameControl& other) const {
|
|
||||||
return other < *this;
|
|
||||||
}
|
|
||||||
bool wxGameControl::operator>=(const wxGameControl& other) const {
|
|
||||||
return !(*this < other);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxGameControlState& wxGameControlState::Instance() {
|
|
||||||
static wxGameControlState g_game_control_state;
|
|
||||||
return g_game_control_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxGameControlState::wxGameControlState() : joypads_({0, 0, 0, 0}) {}
|
|
||||||
wxGameControlState::~wxGameControlState() = default;
|
|
||||||
|
|
||||||
bool wxGameControlState::OnInputPressed(const config::UserInput& user_input) {
|
|
||||||
assert(user_input);
|
|
||||||
|
|
||||||
const auto& game_keys = input_bindings_.find(user_input);
|
|
||||||
if (game_keys == input_bindings_.end()) {
|
|
||||||
// No associated game control for `user_input`.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto iter = keys_pressed_.find(user_input);
|
|
||||||
if (iter != keys_pressed_.end()) {
|
|
||||||
// Double press is noop.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember the key pressed.
|
|
||||||
keys_pressed_.emplace(user_input);
|
|
||||||
|
|
||||||
// Update all corresponding controls.
|
|
||||||
for (const wxGameControl& game_control : game_keys->second) {
|
|
||||||
active_controls_[game_control].emplace(user_input);
|
|
||||||
joypads_[game_control.joypad_] |=
|
|
||||||
kBitMask[GameKeyToInt(game_control.game_key_)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxGameControlState::OnInputReleased(const config::UserInput& user_input) {
|
|
||||||
assert(user_input);
|
|
||||||
|
|
||||||
const auto& game_keys = input_bindings_.find(user_input);
|
|
||||||
if (game_keys == input_bindings_.end()) {
|
|
||||||
// No associated game control for `user_input`.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto iter = keys_pressed_.find(user_input);
|
|
||||||
if (iter == keys_pressed_.end()) {
|
|
||||||
// Double release is noop.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the key pressed.
|
|
||||||
keys_pressed_.erase(iter);
|
|
||||||
|
|
||||||
// Update all corresponding controls.
|
|
||||||
for (const wxGameControl& game_control : game_keys->second) {
|
|
||||||
auto active_controls = active_controls_.find(game_control);
|
|
||||||
if (active_controls == active_controls_.end()) {
|
|
||||||
// This should never happen.
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
active_controls->second.erase(user_input);
|
|
||||||
if (active_controls->second.empty()) {
|
|
||||||
// Actually release control.
|
|
||||||
active_controls_.erase(active_controls);
|
|
||||||
joypads_[game_control.joypad_] &=
|
|
||||||
~kBitMask[GameKeyToInt(game_control.game_key_)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxGameControlState::Reset() {
|
|
||||||
active_controls_.clear();
|
|
||||||
keys_pressed_.clear();
|
|
||||||
joypads_.fill(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxGameControlState::OnGameBindingsChanged() {
|
|
||||||
// We should reset to ensure no key remains accidentally pressed following a
|
|
||||||
// configuration change.
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
input_bindings_.clear();
|
|
||||||
for (const auto& iter : gopts.game_control_bindings) {
|
|
||||||
for (const auto& user_input : iter.second) {
|
|
||||||
input_bindings_[user_input].emplace(iter.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t wxGameControlState::GetJoypad(int joypad) const {
|
|
||||||
assert(JoypadInRange(joypad));
|
|
||||||
return joypads_[joypad];
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
#ifndef _WX_GAME_CONTROL_H_
|
|
||||||
#define _WX_GAME_CONTROL_H_
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <map>
|
|
||||||
#include "nonstd/optional.hpp"
|
|
||||||
#include <set>
|
|
||||||
#include <wx/string.h>
|
|
||||||
|
|
||||||
#include "config/user-input.h"
|
|
||||||
|
|
||||||
// Forward declaration.
|
|
||||||
class wxGameControlState;
|
|
||||||
|
|
||||||
// Represents an in-game input.
|
|
||||||
enum class wxGameKey {
|
|
||||||
Up = 0,
|
|
||||||
Down,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
L,
|
|
||||||
R,
|
|
||||||
Select,
|
|
||||||
Start,
|
|
||||||
MotionUp,
|
|
||||||
MotionDown,
|
|
||||||
MotionLeft,
|
|
||||||
MotionRight,
|
|
||||||
MotionIn,
|
|
||||||
MotionOut,
|
|
||||||
AutoA,
|
|
||||||
AutoB,
|
|
||||||
Speed,
|
|
||||||
Capture,
|
|
||||||
Gameshark,
|
|
||||||
Last = Gameshark
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr int kNbGameKeys =
|
|
||||||
static_cast<std::underlying_type<wxGameKey>::type>(wxGameKey::Last) + 1;
|
|
||||||
inline constexpr int kNbJoypads = 4;
|
|
||||||
|
|
||||||
inline constexpr std::array<wxGameKey, kNbGameKeys> kAllGameKeys = {
|
|
||||||
wxGameKey::Up,
|
|
||||||
wxGameKey::Down,
|
|
||||||
wxGameKey::Left,
|
|
||||||
wxGameKey::Right,
|
|
||||||
wxGameKey::A,
|
|
||||||
wxGameKey::B,
|
|
||||||
wxGameKey::L,
|
|
||||||
wxGameKey::R,
|
|
||||||
wxGameKey::Select,
|
|
||||||
wxGameKey::Start,
|
|
||||||
wxGameKey::MotionUp,
|
|
||||||
wxGameKey::MotionDown,
|
|
||||||
wxGameKey::MotionLeft,
|
|
||||||
wxGameKey::MotionRight,
|
|
||||||
wxGameKey::MotionIn,
|
|
||||||
wxGameKey::MotionOut,
|
|
||||||
wxGameKey::AutoA,
|
|
||||||
wxGameKey::AutoB,
|
|
||||||
wxGameKey::Speed,
|
|
||||||
wxGameKey::Capture,
|
|
||||||
wxGameKey::Gameshark,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Conversion utility method. Returns empty string on failure.
|
|
||||||
// This is O(1).
|
|
||||||
wxString GameKeyToString(const wxGameKey& game_key);
|
|
||||||
|
|
||||||
// Conversion utility method. Returns std::nullopt on failure.
|
|
||||||
// This is O(log(kNbGameKeys)).
|
|
||||||
nonstd::optional<wxGameKey> StringToGameKey(const wxString& input);
|
|
||||||
|
|
||||||
// Abstraction for an in-game control, wich is made of a player index (from 0
|
|
||||||
// to 3), and a wxGameKey.
|
|
||||||
class wxGameControl {
|
|
||||||
public:
|
|
||||||
// Converts a string to a wxGameControl. Returns std::nullopt on failure.
|
|
||||||
static nonstd::optional<wxGameControl> FromString(const wxString& name);
|
|
||||||
|
|
||||||
wxGameControl(int joypad, wxGameKey game_key);
|
|
||||||
~wxGameControl();
|
|
||||||
|
|
||||||
wxString ToString() const { return config_string_; };
|
|
||||||
|
|
||||||
bool operator==(const wxGameControl& other) const;
|
|
||||||
bool operator!=(const wxGameControl& other) const;
|
|
||||||
bool operator<(const wxGameControl& other) const;
|
|
||||||
bool operator<=(const wxGameControl& other) const;
|
|
||||||
bool operator>(const wxGameControl& other) const;
|
|
||||||
bool operator>=(const wxGameControl& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const int joypad_;
|
|
||||||
const wxGameKey game_key_;
|
|
||||||
const wxString config_string_;
|
|
||||||
|
|
||||||
friend class wxGameControlState;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tracks in-game input and computes the joypad value used to send control input
|
|
||||||
// data to the emulator.
|
|
||||||
class wxGameControlState {
|
|
||||||
public:
|
|
||||||
// This is a global singleton.
|
|
||||||
static wxGameControlState& Instance();
|
|
||||||
|
|
||||||
// Disable copy constructor and assignment operator.
|
|
||||||
wxGameControlState(const wxGameControlState&) = delete;
|
|
||||||
wxGameControlState& operator=(const wxGameControlState&) = delete;
|
|
||||||
|
|
||||||
// Processes `user_input` and updates the internal tracking state.
|
|
||||||
// Returns true if `user_input` corresponds to a game input.
|
|
||||||
bool OnInputPressed(const config::UserInput& user_input);
|
|
||||||
bool OnInputReleased(const config::UserInput& user_input);
|
|
||||||
|
|
||||||
// Clears all input.
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
// Recomputes internal bindinds. This is a potentially slow operation and
|
|
||||||
// should only be called when the game input configuration has been changed.
|
|
||||||
void OnGameBindingsChanged();
|
|
||||||
|
|
||||||
uint32_t GetJoypad(int joypad) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
wxGameControlState();
|
|
||||||
~wxGameControlState();
|
|
||||||
|
|
||||||
std::map<config::UserInput, std::set<wxGameControl>> input_bindings_;
|
|
||||||
std::map<wxGameControl, std::set<config::UserInput>> active_controls_;
|
|
||||||
std::set<config::UserInput> keys_pressed_;
|
|
||||||
std::array<uint32_t, kNbJoypads> joypads_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _WX_GAME_CONTROL_H_
|
|
|
@ -5,7 +5,7 @@
|
||||||
// The value is the symbolic name of the key pressed
|
// The value is the symbolic name of the key pressed
|
||||||
// Supports manual clearing (bs), multiple keys in widget, automatic tab on key
|
// Supports manual clearing (bs), multiple keys in widget, automatic tab on key
|
||||||
|
|
||||||
#include "wx/gamecontrol.h"
|
#include "config/game-control.h"
|
||||||
#include "wx/keyedit.h"
|
#include "wx/keyedit.h"
|
||||||
#include "wx/sdljoy.h"
|
#include "wx/sdljoy.h"
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ protected:
|
||||||
// A simple copy-only validator
|
// A simple copy-only validator
|
||||||
class wxJoyKeyValidator : public wxValidator {
|
class wxJoyKeyValidator : public wxValidator {
|
||||||
public:
|
public:
|
||||||
wxJoyKeyValidator(const wxGameControl v)
|
wxJoyKeyValidator(const config::GameControl v)
|
||||||
: wxValidator()
|
: wxValidator()
|
||||||
, val_(v)
|
, val_(v)
|
||||||
{
|
{
|
||||||
|
@ -64,7 +64,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const wxGameControl val_;
|
const config::GameControl val_;
|
||||||
|
|
||||||
DECLARE_CLASS(wxJoyKeyValidator)
|
DECLARE_CLASS(wxJoyKeyValidator)
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,9 +32,9 @@
|
||||||
#include "builtin-over.h"
|
#include "builtin-over.h"
|
||||||
#include "config/user-input.h"
|
#include "config/user-input.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
#include "vbam-options.h"
|
#include "config/game-control.h"
|
||||||
|
#include "config/option.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
#include "wx/gamecontrol.h"
|
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ bool wxvbamApp::OnInit() {
|
||||||
|
|
||||||
// Initialize game bindings here, after defaults bindings, vbam.ini bindings
|
// Initialize game bindings here, after defaults bindings, vbam.ini bindings
|
||||||
// and command line overrides have been applied.
|
// and command line overrides have been applied.
|
||||||
wxGameControlState::Instance().OnGameBindingsChanged();
|
config::GameControlState::Instance().OnGameBindingsChanged();
|
||||||
|
|
||||||
// create the main window
|
// create the main window
|
||||||
int x = windowPositionX;
|
int x = windowPositionX;
|
||||||
|
@ -669,7 +669,7 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl)
|
||||||
" configuration changes are made in the user interface.\n\n"
|
" configuration changes are made in the user interface.\n\n"
|
||||||
"For flag options, true and false are specified as 1 and 0, respectively.\n\n"));
|
"For flag options, true and false are specified as 1 and 0, respectively.\n\n"));
|
||||||
|
|
||||||
for (const VbamOption& opt : VbamOption::AllOptions()) {
|
for (const config::Option& opt : config::Option::AllOptions()) {
|
||||||
wxPrintf("%s\n", opt.ToHelperString());
|
wxPrintf("%s\n", opt.ToHelperString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue