#include // MT. #include "../bsnes.hpp" #include "bsnes-mt/strings.h" // MT. #include "bsnes-mt/utils.h" // MT. #include "_video.cpp" #include "_audio.cpp" #include "_input.cpp" #include "_hotkeys.cpp" #include "_builtin-hotkeys.cpp" // MT. #include "_paths.cpp" #include "_emulator.cpp" #include "_enhancements.cpp" #include "_compatibility.cpp" #include "_drivers.cpp" /* MT. */ #include "bsnes-mt/translations.h" namespace bmt = bsnesMt::translations; /* /MT. */ Settings settings; VideoSettings videoSettings; AudioSettings audioSettings; InputSettings inputSettings; HotkeySettings hotkeySettings; BuiltinHotkeysSettings builtinHotkeysSettings; // MT. PathSettings pathSettings; EmulatorSettings emulatorSettings; EnhancementSettings enhancementSettings; CompatibilitySettings compatibilitySettings; DriverSettings driverSettings; namespace Instances { Instance settingsWindow; } SettingsWindow& settingsWindow = Instances::settingsWindow(); auto Settings::load() -> void { Markup::Node::operator=(BML::unserialize(string::read(location), " ")); process(true); save(); } auto Settings::save() -> void { process(false); file::write(location ? location : locate("bsnes-mt-settings.bml"), BML::serialize(*this, " ")); } auto Settings::process(bool load) -> void { if (load) { //initialize non-static default settings video.driver = ruby::Video::safestDriver(); audio.driver = ruby::Audio::safestDriver(); input.driver = ruby::Input::safestDriver(); } #define bind(type, path, name) \ if (load) { \ if (auto node = operator[](path)) name = node.type(); \ } \ else { \ operator()(path).setValue(name); \ } \ bind(text, "Video/Driver", video.driver); bind(boolean, "Video/Exclusive", video.exclusive); bind(boolean, "Video/Blocking", video.blocking); bind(boolean, "Video/Flush", video.flush); bind(text, "Video/Monitor", video.monitor); bind(text, "Video/Format", video.format); bind(text, "Video/Shader", video.shader); bind(natural, "Video/Luminance", video.luminance); bind(natural, "Video/Saturation", video.saturation); bind(natural, "Video/Gamma", video.gamma); bind(boolean, "Video/Dimming", video.dimming); bind(boolean, "Video/Snow", video.snow); bind(text, "Video/Output", video.output); bind(natural, "Video/Multiplier", video.multiplier); bind(boolean, "Video/AspectCorrection", video.aspectCorrection); bind(boolean, "Video/ParInsteadOfAr", video.parInsteadOfAr); // MT. bind(boolean, "Video/Overscan", video.overscan); bind(boolean, "Video/ScalingInfo", video.scalingInfo); // MT. bind(boolean, "Video/Blur", video.blur); bind(text, "Video/Filter", video.filter); bind(text, "Audio/Driver", audio.driver); bind(boolean, "Audio/Exclusive", audio.exclusive); bind(text, "Audio/Device", audio.device); bind(boolean, "Audio/Blocking", audio.blocking); bind(boolean, "Audio/Dynamic", audio.dynamic); bind(natural, "Audio/Frequency", audio.frequency); bind(natural, "Audio/Latency", audio.latency); bind(boolean, "Audio/Mute", audio.mute); bind(boolean, "Audio/MuteUnfocused", audio.muteUnfocused); bind(integer, "Audio/Skew", audio.skew); bind(natural, "Audio/Volume", audio.volume); bind(natural, "Audio/Balance", audio.balance); bind(text, "Input/Driver", input.driver); bind(natural, "Input/Frequency", input.frequency); bind(text, "Input/Defocus", input.defocus); bind(natural, "Input/Turbo/Frequency", input.turbo.frequency); bind(text, "Input/Hotkey/Logic", input.hotkey.logic); /* MT. */ // Underscores cannot be used in settings paths (2nd `bind()` parameter) -- settings are not saved. bind(boolean, "BuiltinHotkeys/openGame/CtrlO", builtinHotkeys.openGame_CtrlO); bind(boolean, "BuiltinHotkeys/closeGame/CtrlW", builtinHotkeys.closeGame_CtrlW); bind(boolean, "BuiltinHotkeys/closeGame/CtrlF4", builtinHotkeys.closeGame_CtrlF4); bind(boolean, "BuiltinHotkeys/fullScreen/F11", builtinHotkeys.fullScreen_F11); bind(boolean, "BuiltinHotkeys/fullScreen/AltEnter", builtinHotkeys.fullScreen_AltEnter); bind(boolean, "BuiltinHotkeys/pseudoFullScreen/ShiftEnter", builtinHotkeys.pseudoFullScreen_ShiftEnter); bind(boolean, "BuiltinHotkeys/takeScreenshot/PrintScreen", builtinHotkeys.takeScreenshot_PrintScreen); bind(boolean, "BuiltinHotkeys/takeScreenshot/F9", builtinHotkeys.takeScreenshot_F9); bind(boolean, "BuiltinHotkeys/resetEmulation/F5", builtinHotkeys.resetEmulation_F5); bind(boolean, "BuiltinHotkeys/pauseEmulation/PauseBreak", builtinHotkeys.pauseEmulation_PauseBreak); /* /MT. */ bind(text, "Path/Games", path.games); bind(text, "Path/Patches", path.patches); bind(text, "Path/Saves", path.saves); bind(text, "Path/Cheats", path.cheats); bind(text, "Path/States", path.states); bind(text, "Path/Screenshots", path.screenshots); bind(text, "Path/Recent/SuperFamicom", path.recent.superFamicom); bind(text, "Path/Recent/GameBoy", path.recent.gameBoy); bind(text, "Path/Recent/BSMemory", path.recent.bsMemory); bind(text, "Path/Recent/SufamiTurboA", path.recent.sufamiTurboA); bind(text, "Path/Recent/SufamiTurboB", path.recent.sufamiTurboB); bind(natural, "FastForward/FrameSkip", fastForward.frameSkip); bind(natural, "FastForward/Limiter", fastForward.limiter); bind(boolean, "FastForward/Mute", fastForward.mute); bind(natural, "Rewind/Frequency", rewind.frequency); bind(natural, "Rewind/Length", rewind.length); bind(boolean, "Rewind/Mute", rewind.mute); bind(boolean, "Emulator/WarnOnUnverifiedGames", emulator.warnOnUnverifiedGames); bind(boolean, "Emulator/AutoSaveMemory/Enable", emulator.autoSaveMemory.enable); bind(natural, "Emulator/AutoSaveMemory/Interval", emulator.autoSaveMemory.interval); bind(boolean, "Emulator/AutoSaveStateOnUnload", emulator.autoSaveStateOnUnload); bind(boolean, "Emulator/AutoLoadStateOnLoad", emulator.autoLoadStateOnLoad); bind(text, "Emulator/Serialization/Method", emulator.serialization.method); bind(natural, "Emulator/RunAhead/Frames", emulator.runAhead.frames); bind(boolean, "Emulator/Hack/Hotfixes", emulator.hack.hotfixes); bind(text, "Emulator/Hack/Entropy", emulator.hack.entropy); bind(natural, "Emulator/Hack/CPU/Overclock", emulator.hack.cpu.overclock); bind(boolean, "Emulator/Hack/CPU/FastMath", emulator.hack.cpu.fastMath); bind(boolean, "Emulator/Hack/PPU/Fast", emulator.hack.ppu.fast); bind(boolean, "Emulator/Hack/PPU/Deinterlace", emulator.hack.ppu.deinterlace); bind(boolean, "Emulator/Hack/PPU/NoSpriteLimit", emulator.hack.ppu.noSpriteLimit); bind(boolean, "Emulator/Hack/PPU/NoVRAMBlocking", emulator.hack.ppu.noVRAMBlocking); bind(natural, "Emulator/Hack/PPU/Mode7/Scale", emulator.hack.ppu.mode7.scale); bind(boolean, "Emulator/Hack/PPU/Mode7/Perspective", emulator.hack.ppu.mode7.perspective); bind(boolean, "Emulator/Hack/PPU/Mode7/Supersample", emulator.hack.ppu.mode7.supersample); bind(boolean, "Emulator/Hack/PPU/Mode7/Mosaic", emulator.hack.ppu.mode7.mosaic); bind(boolean, "Emulator/Hack/DSP/Fast", emulator.hack.dsp.fast); bind(boolean, "Emulator/Hack/DSP/Cubic", emulator.hack.dsp.cubic); bind(boolean, "Emulator/Hack/DSP/EchoShadow", emulator.hack.dsp.echoShadow); bind(boolean, "Emulator/Hack/Coprocessor/DelayedSync", emulator.hack.coprocessor.delayedSync); bind(boolean, "Emulator/Hack/Coprocessor/PreferHLE", emulator.hack.coprocessor.preferHLE); bind(natural, "Emulator/Hack/SA1/Overclock", emulator.hack.sa1.overclock); bind(natural, "Emulator/Hack/SuperFX/Overclock", emulator.hack.superfx.overclock); bind(boolean, "Emulator/Cheats/Enable", emulator.cheats.enable); bind(boolean, "General/StatusBar", general.statusBar); bind(boolean, "General/ScreenSaver", general.screenSaver); bind(boolean, "General/ToolTips", general.toolTips); bind(boolean, "General/Crashed", general.crashed); bind(boolean, "General/NativeFileDialogs", general.nativeFileDialogs); #undef bind } struct SettingsHome : VerticalLayout { SettingsHome() { setCollapsible(); setVisible(false); image icon{Resource::Icon}; auto data = icon.data(); for (uint y : range(icon.height())) { for (uint x : range(icon.width())) { auto pixel = icon.read(data); auto a = pixel >> 24 & 255; auto r = pixel >> 16 & 255; auto g = pixel >> 8 & 255; auto b = pixel >> 0 & 255; a = a * 0.25; icon.write(data, a << 24 | r << 16 | g << 8 | b << 0); data += icon.stride(); } } canvas.setIcon(icon); } public: Canvas canvas{this, Size{~0, ~0}}; } settingsHome; auto SettingsWindow::create() -> void { layout.setPadding(5_sx); panelList.append(ListViewItem().setText(bmt::get("Common.Video").data()).setIcon(Icon::Device::Display)); panelList.append(ListViewItem().setText(bmt::get("Common.Audio").data()).setIcon(Icon::Device::Speaker)); panelList.append(ListViewItem().setText(bmt::get("Settings.Input").data()).setIcon(Icon::Device::Joypad)); panelList.append(ListViewItem().setText(bmt::get("Settings.Hotkeys").data()).setIcon(Icon::Device::Keyboard)); panelList.append(ListViewItem().setText(bmt::get("Settings.BuiltinHotkeys").data()).setIcon(Icon::Device::Keyboard)); // MT. panelList.append(ListViewItem().setText(bmt::get("Settings.Paths").data()).setIcon(Icon::Emblem::Folder)); panelList.append(ListViewItem().setText(bmt::get("Settings.Emulator").data()).setIcon(Icon::Action::Settings)); panelList.append(ListViewItem().setText(bmt::get("Settings.Enhancements").data()).setIcon(Icon::Action::Add)); panelList.append(ListViewItem().setText(bmt::get("Settings.Compatibility").data()).setIcon(Icon::Action::Remove)); panelList.append(ListViewItem().setText(bmt::get("Settings.Drivers").data()).setIcon(Icon::Place::Settings)); panelList.onChange([&] { if (auto item = panelList.selected()) { show(item.offset()); } else { show(-1); } }); panelContainer.append(settingsHome, Size{~0, ~0}); panelContainer.append(videoSettings, Size{~0, ~0}); panelContainer.append(audioSettings, Size{~0, ~0}); panelContainer.append(inputSettings, Size{~0, ~0}); panelContainer.append(hotkeySettings, Size{~0, ~0}); panelContainer.append(builtinHotkeysSettings, Size{~0, ~0}); // MT. panelContainer.append(pathSettings, Size{~0, ~0}); panelContainer.append(emulatorSettings, Size{~0, ~0}); panelContainer.append(enhancementSettings, Size{~0, ~0}); panelContainer.append(compatibilitySettings, Size{~0, ~0}); panelContainer.append(driverSettings, Size{~0, ~0}); statusBar.setFont(Font().setBold()); setTitle(bmt::get("Settings").data()); setSize({750_sx, 400_sy}); // `680_sx` => `750_sx` by MT. setAlignment({0.0, 1.0}); setDismissable(); onClose([&] { if (inputSettings.activeMapping) { inputSettings.cancelMapping(); } if (hotkeySettings.activeMapping) { hotkeySettings.cancelMapping(); } setVisible(false); }); } auto SettingsWindow::setVisible(bool visible) -> SettingsWindow& { if (visible) { inputSettings.refreshMappings(); hotkeySettings.refreshMappings(); Application::processEvents(); } return Window::setVisible(visible), *this; } /* MT. */ auto setSettingsWindowTitle(std::string id) -> void { static string title = bmt::get("Settings").data(); static string postfix = {u8" ← ", title}; // MT. settingsWindow.setTitle("" == id ? title : string({bmt::get(id).data(), postfix})); } /* /MT. */ auto SettingsWindow::show(int index) -> void { settingsHome.setVisible(false); videoSettings.setVisible(false); audioSettings.setVisible(false); inputSettings.setVisible(false); hotkeySettings.setVisible(false); builtinHotkeysSettings.setVisible(false); // MT. pathSettings.setVisible(false); emulatorSettings.setVisible(false); enhancementSettings.setVisible(false); compatibilitySettings.setVisible(false); driverSettings.setVisible(false); panelList.item(index).setSelected(); if (index == -1) { setSettingsWindowTitle(""); // MT. settingsHome.setVisible(true); } else if (index == 0) { setSettingsWindowTitle("Common.Video"); // MT. videoSettings.setVisible(true); } else if (index == 1) { setSettingsWindowTitle("Common.Audio"); // MT. audioSettings.setVisible(true); } else if (index == 2) { setSettingsWindowTitle("Settings.Input"); // MT. inputSettings.setVisible(true); } else if (index == 3) { setSettingsWindowTitle("Settings.Hotkeys"); // MT. hotkeySettings.setVisible(true); } /* MT. */ else if (index == 4) { setSettingsWindowTitle("Settings.BuiltinHotkeys"); // MT. builtinHotkeysSettings.setVisible(true); } /* /MT. */ else if (index == 5) { setSettingsWindowTitle("Settings.Paths"); // MT. pathSettings.setVisible(true); } else if (index == 6) { setSettingsWindowTitle("Settings.Emulator"); // MT. emulatorSettings.setVisible(true); } else if (index == 7) { setSettingsWindowTitle("Settings.Enhancements"); // MT. enhancementSettings.setVisible(true); } else if (index == 8) { setSettingsWindowTitle("Settings.Compatibility"); // MT. compatibilitySettings.setVisible(true); } else if (index == 9) { setSettingsWindowTitle("Settings.Drivers"); // MT. driverSettings.setVisible(true); } panelContainer.resize(); setVisible(); setFocused(); panelList.setFocused(); }