mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
603 lines
15 KiB
C++
603 lines
15 KiB
C++
#include "pch.h"
|
|
#include <random>
|
|
#include "Shared/EmuSettings.h"
|
|
#include "Shared/KeyManager.h"
|
|
#include "Shared/MessageManager.h"
|
|
#include "Shared/Emulator.h"
|
|
#include "Shared/DebuggerRequest.h"
|
|
#include "Shared/NotificationManager.h"
|
|
#include "Utilities/FolderUtilities.h"
|
|
#include "Utilities/Serializer.h"
|
|
|
|
EmuSettings::EmuSettings(Emulator* emu)
|
|
{
|
|
_emu = emu;
|
|
_flags = 0;
|
|
_debuggerFlags = 0;
|
|
|
|
std::random_device rd;
|
|
_mt = std::mt19937(rd());
|
|
}
|
|
|
|
void EmuSettings::CopySettings(EmuSettings& src)
|
|
{
|
|
SetVideoConfig(src._video);
|
|
SetAudioConfig(src._audio);
|
|
SetInputConfig(src._input);
|
|
SetEmulationConfig(src._emulation);
|
|
SetPreferences(src._preferences);
|
|
SetAudioPlayerConfig(src._audioPlayer);
|
|
SetDebugConfig(src._debug);
|
|
SetGameConfig(src._game);
|
|
SetSnesConfig(src._snes);
|
|
SetGameboyConfig(src._gameboy);
|
|
SetNesConfig(src._nes);
|
|
SetPcEngineConfig(src._pce);
|
|
SetSmsConfig(src._sms);
|
|
SetGbaConfig(src._gba);
|
|
}
|
|
|
|
void EmuSettings::Serialize(Serializer& s)
|
|
{
|
|
//Save/load settings that have an impact on emulation (for movies), netplay, etc.)
|
|
//TODOv2: These should probably not be loaded except for movie playback and netplay clients
|
|
//TODOv2: Desyncs are possible when random state options are turned on
|
|
SV(_video.IntegerFpsMode);
|
|
SV(_emulation.RunAheadFrames);
|
|
SV(_game.DipSwitches);
|
|
|
|
switch(_emu->GetConsoleType()) {
|
|
case ConsoleType::Nes:
|
|
SV(_nes.ConsoleType);
|
|
SV(_nes.RamPowerOnState);
|
|
SV(_nes.RandomizeMapperPowerOnState);
|
|
SV(_nes.RandomizeCpuPpuAlignment);
|
|
SV(_nes.DisableOamAddrBug); SV(_nes.DisablePaletteRead); SV(_nes.DisablePpu2004Reads);
|
|
SV(_nes.DisableGameGenieBusConflicts); SV(_nes.DisablePpuReset); SV(_nes.EnableOamDecay);
|
|
SV(_nes.EnablePpu2000ScrollGlitch); SV(_nes.EnablePpu2006ScrollGlitch); SV(_nes.EnablePpuOamRowCorruption);
|
|
SV(_nes.RestrictPpuAccessOnFirstFrame);
|
|
SV(_nes.EnableCpuTestMode);
|
|
SV(_nes.EnableDmcSampleDuplicationGlitch);
|
|
SV(_nes.EnablePpuSpriteEvalBug);
|
|
SV(_nes.PpuExtraScanlinesAfterNmi); SV(_nes.PpuExtraScanlinesBeforeNmi);
|
|
SV(_nes.Region);
|
|
SV(_nes.LightDetectionRadius);
|
|
SV(_nes.Port1.Type); SV(_nes.Port1SubPorts[0].Type); SV(_nes.Port1SubPorts[1].Type); SV(_nes.Port1SubPorts[2].Type); SV(_nes.Port1SubPorts[3].Type);
|
|
SV(_nes.Port2.Type);
|
|
SV(_nes.ExpPort.Type); SV(_nes.ExpPortSubPorts[0].Type); SV(_nes.ExpPortSubPorts[1].Type); SV(_nes.ExpPortSubPorts[2].Type); SV(_nes.ExpPortSubPorts[3].Type);
|
|
break;
|
|
|
|
case ConsoleType::Snes:
|
|
SV(_snes.RamPowerOnState);
|
|
SV(_snes.EnableRandomPowerOnState);
|
|
SV(_snes.GsuClockSpeed);
|
|
SV(_snes.PpuExtraScanlinesAfterNmi); SV(_snes.PpuExtraScanlinesBeforeNmi);
|
|
SV(_snes.Region);
|
|
SV(_snes.Port1.Type); SV(_snes.Port1SubPorts[0].Type); SV(_snes.Port1SubPorts[1].Type); SV(_snes.Port1SubPorts[2].Type); SV(_snes.Port1SubPorts[3].Type);
|
|
SV(_snes.Port2.Type); SV(_snes.Port2SubPorts[0].Type); SV(_snes.Port2SubPorts[1].Type); SV(_snes.Port2SubPorts[2].Type); SV(_snes.Port2SubPorts[3].Type);
|
|
SV(_snes.BsxCustomDate);
|
|
SV(_snes.SpcClockSpeedAdjustment);
|
|
|
|
if(_emu->GetRomInfo().Format == RomFormat::Gb) {
|
|
SV(_gameboy.RamPowerOnState);
|
|
SV(_gameboy.Controller.Type);
|
|
SV(_gameboy.Model);
|
|
SV(_gameboy.UseSgb2);
|
|
}
|
|
break;
|
|
|
|
case ConsoleType::Gameboy:
|
|
SV(_gameboy.RamPowerOnState);
|
|
SV(_gameboy.Controller.Type);
|
|
SV(_gameboy.Model);
|
|
SV(_gameboy.UseSgb2);
|
|
break;
|
|
|
|
case ConsoleType::PcEngine:
|
|
SV(_pce.RamPowerOnState);
|
|
SV(_pce.EnableRandomPowerOnState);
|
|
SV(_pce.CdRomType);
|
|
SV(_pce.ConsoleType);
|
|
SV(_pce.DisableCdRomSaveRamForHuCardGames);
|
|
SV(_pce.EnableCdRomForHuCardGames);
|
|
SV(_pce.Port1.Type);
|
|
SV(_pce.Port1SubPorts[0].Type);
|
|
SV(_pce.Port1SubPorts[1].Type);
|
|
SV(_pce.Port1SubPorts[2].Type);
|
|
SV(_pce.Port1SubPorts[3].Type);
|
|
SV(_pce.Port1SubPorts[4].Type);
|
|
break;
|
|
|
|
case ConsoleType::Sms:
|
|
SV(_sms.RamPowerOnState);
|
|
SV(_sms.Port1.Type);
|
|
SV(_sms.Port2.Type);
|
|
SV(_sms.Region);
|
|
SV(_sms.Revision);
|
|
SV(_sms.EnableFmAudio);
|
|
break;
|
|
|
|
case ConsoleType::Gba:
|
|
SV(_gba.RamPowerOnState);
|
|
SV(_gba.Controller.Type);
|
|
break;
|
|
|
|
case ConsoleType::Ws:
|
|
//TODOWS
|
|
break;
|
|
|
|
default:
|
|
throw std::runtime_error("unsupported console type");
|
|
}
|
|
}
|
|
|
|
uint32_t EmuSettings::GetVersion()
|
|
{
|
|
//Version 2.0.0
|
|
uint16_t major = 2;
|
|
uint8_t minor = 0;
|
|
uint8_t revision = 0;
|
|
return (major << 16) | (minor << 8) | revision;
|
|
}
|
|
|
|
string EmuSettings::GetVersionString()
|
|
{
|
|
uint32_t version = GetVersion();
|
|
return std::to_string(version >> 16) + "." + std::to_string((version >> 8) & 0xFF) + "." + std::to_string(version & 0xFF);
|
|
}
|
|
|
|
void EmuSettings::ProcessString(string & str, const char ** strPointer)
|
|
{
|
|
//Make a copy of the string and keep it (the original pointer will not be valid after the call is over)
|
|
if(*strPointer) {
|
|
str = *strPointer;
|
|
} else {
|
|
str.clear();
|
|
}
|
|
*strPointer = str.c_str();
|
|
}
|
|
|
|
void EmuSettings::SetVideoConfig(VideoConfig& config)
|
|
{
|
|
_video = config;
|
|
}
|
|
|
|
VideoConfig& EmuSettings::GetVideoConfig()
|
|
{
|
|
return _video;
|
|
}
|
|
|
|
void EmuSettings::SetAudioConfig(AudioConfig& config)
|
|
{
|
|
_audio = config;
|
|
ProcessString(_audioDevice, &_audio.AudioDevice);
|
|
}
|
|
|
|
AudioConfig& EmuSettings::GetAudioConfig()
|
|
{
|
|
return _audio;
|
|
}
|
|
|
|
void EmuSettings::SetInputConfig(InputConfig& config)
|
|
{
|
|
_input = config;
|
|
}
|
|
|
|
InputConfig& EmuSettings::GetInputConfig()
|
|
{
|
|
return _input;
|
|
}
|
|
|
|
void EmuSettings::SetEmulationConfig(EmulationConfig& config)
|
|
{
|
|
_emulation = config;
|
|
}
|
|
|
|
EmulationConfig& EmuSettings::GetEmulationConfig()
|
|
{
|
|
return _emulation;
|
|
}
|
|
|
|
void EmuSettings::SetSnesConfig(SnesConfig& config)
|
|
{
|
|
_snes = config;
|
|
}
|
|
|
|
SnesConfig& EmuSettings::GetSnesConfig()
|
|
{
|
|
return _snes;
|
|
}
|
|
|
|
void EmuSettings::SetNesConfig(NesConfig& config)
|
|
{
|
|
_nes = config;
|
|
}
|
|
|
|
NesConfig& EmuSettings::GetNesConfig()
|
|
{
|
|
return _nes;
|
|
}
|
|
|
|
void EmuSettings::SetGameboyConfig(GameboyConfig& config)
|
|
{
|
|
_gameboy = config;
|
|
}
|
|
|
|
GameboyConfig& EmuSettings::GetGameboyConfig()
|
|
{
|
|
return _gameboy;
|
|
}
|
|
|
|
void EmuSettings::SetGbaConfig(GbaConfig& config)
|
|
{
|
|
_gba = config;
|
|
}
|
|
|
|
GbaConfig& EmuSettings::GetGbaConfig()
|
|
{
|
|
return _gba;
|
|
}
|
|
|
|
void EmuSettings::SetPcEngineConfig(PcEngineConfig& config)
|
|
{
|
|
_pce = config;
|
|
}
|
|
|
|
PcEngineConfig& EmuSettings::GetPcEngineConfig()
|
|
{
|
|
return _pce;
|
|
}
|
|
|
|
void EmuSettings::SetSmsConfig(SmsConfig& config)
|
|
{
|
|
_sms = config;
|
|
}
|
|
|
|
SmsConfig& EmuSettings::GetSmsConfig()
|
|
{
|
|
return _sms;
|
|
}
|
|
|
|
void EmuSettings::SetCvConfig(CvConfig& config)
|
|
{
|
|
_cv = config;
|
|
}
|
|
|
|
CvConfig& EmuSettings::GetCvConfig()
|
|
{
|
|
return _cv;
|
|
}
|
|
|
|
void EmuSettings::SetWsConfig(WsConfig& config)
|
|
{
|
|
_ws = config;
|
|
}
|
|
|
|
WsConfig& EmuSettings::GetWsConfig()
|
|
{
|
|
return _ws;
|
|
}
|
|
|
|
void EmuSettings::SetGameConfig(GameConfig& config)
|
|
{
|
|
_game = config;
|
|
}
|
|
|
|
GameConfig& EmuSettings::GetGameConfig()
|
|
{
|
|
return _game;
|
|
}
|
|
|
|
void EmuSettings::SetPreferences(PreferencesConfig& config)
|
|
{
|
|
MessageManager::SetOsdState(!config.DisableOsd);
|
|
|
|
_preferences = config;
|
|
|
|
ProcessString(_saveFolder, &_preferences.SaveFolderOverride);
|
|
ProcessString(_saveStateFolder, &_preferences.SaveStateFolderOverride);
|
|
ProcessString(_screenshotFolder, &_preferences.ScreenshotFolderOverride);
|
|
|
|
FolderUtilities::SetFolderOverrides(
|
|
_saveFolder,
|
|
_saveStateFolder,
|
|
_screenshotFolder,
|
|
""
|
|
);
|
|
}
|
|
|
|
PreferencesConfig& EmuSettings::GetPreferences()
|
|
{
|
|
return _preferences;
|
|
}
|
|
|
|
void EmuSettings::SetAudioPlayerConfig(AudioPlayerConfig& config)
|
|
{
|
|
_audioPlayer = config;
|
|
}
|
|
|
|
AudioPlayerConfig& EmuSettings::GetAudioPlayerConfig()
|
|
{
|
|
return _audioPlayer;
|
|
}
|
|
|
|
void EmuSettings::SetDebugConfig(DebugConfig& config)
|
|
{
|
|
_debug = config;
|
|
|
|
DebuggerRequest req = _emu->GetDebugger(false);
|
|
Debugger* dbg = req.GetDebugger();
|
|
if(dbg) {
|
|
dbg->ProcessConfigChange();
|
|
}
|
|
}
|
|
|
|
DebugConfig& EmuSettings::GetDebugConfig()
|
|
{
|
|
return _debug;
|
|
}
|
|
|
|
void EmuSettings::ClearShortcutKeys()
|
|
{
|
|
_emulatorKeys[0].clear();
|
|
_emulatorKeys[1].clear();
|
|
_emulatorKeys[2].clear();
|
|
_shortcutSupersets[0].clear();
|
|
_shortcutSupersets[1].clear();
|
|
_shortcutSupersets[2].clear();
|
|
|
|
//Add Alt-F4 as a fake shortcut to prevent Alt-F4 from triggering Alt or F4 key bindings. (e.g load save state 4)
|
|
KeyCombination keyComb;
|
|
keyComb.Key1 = KeyManager::GetKeyCode("Left Alt");
|
|
keyComb.Key2 = KeyManager::GetKeyCode("F4");
|
|
SetShortcutKey(EmulatorShortcut::Exit, keyComb, 2);
|
|
}
|
|
|
|
void EmuSettings::SetShortcutKey(EmulatorShortcut shortcut, KeyCombination keyCombination, int keySetIndex)
|
|
{
|
|
_emulatorKeys[keySetIndex][(uint32_t)shortcut] = keyCombination;
|
|
|
|
for(int i = 0; i < 3; i++) {
|
|
for(std::pair<const uint32_t, KeyCombination> &kvp : _emulatorKeys[i]) {
|
|
if(keyCombination.IsSubsetOf(kvp.second)) {
|
|
_shortcutSupersets[keySetIndex][(uint32_t)shortcut].push_back(kvp.second);
|
|
} else if(kvp.second.IsSubsetOf(keyCombination)) {
|
|
_shortcutSupersets[i][kvp.first].push_back(keyCombination);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EmuSettings::SetShortcutKeys(vector<ShortcutKeyInfo> shortcuts)
|
|
{
|
|
auto lock = _updateShortcutsLock.AcquireSafe();
|
|
ClearShortcutKeys();
|
|
|
|
for(ShortcutKeyInfo &shortcut : shortcuts) {
|
|
if(_emulatorKeys[0][(uint32_t)shortcut.Shortcut].GetKeys().empty()) {
|
|
SetShortcutKey(shortcut.Shortcut, shortcut.Keys, 0);
|
|
} else {
|
|
SetShortcutKey(shortcut.Shortcut, shortcut.Keys, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
KeyCombination EmuSettings::GetShortcutKey(EmulatorShortcut shortcut, int keySetIndex)
|
|
{
|
|
auto lock = _updateShortcutsLock.AcquireSafe();
|
|
auto result = _emulatorKeys[keySetIndex].find((int)shortcut);
|
|
if(result != _emulatorKeys[keySetIndex].end()) {
|
|
return result->second;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
vector<KeyCombination> EmuSettings::GetShortcutSupersets(EmulatorShortcut shortcut, int keySetIndex)
|
|
{
|
|
auto lock = _updateShortcutsLock.AcquireSafe();
|
|
return _shortcutSupersets[keySetIndex][(uint32_t)shortcut];
|
|
}
|
|
|
|
OverscanDimensions EmuSettings::GetOverscan()
|
|
{
|
|
RomFormat romFormat = _emu->GetRomInfo().Format;
|
|
switch(romFormat) {
|
|
case RomFormat::Spc:
|
|
case RomFormat::Gbs:
|
|
case RomFormat::Nsf:
|
|
case RomFormat::PceHes:
|
|
//No overscan for music players
|
|
return OverscanDimensions {};
|
|
|
|
case RomFormat::Gb:
|
|
if(_emu->GetConsoleType() == ConsoleType::Snes && _emu->GetSettings()->GetGameboyConfig().HideSgbBorders) {
|
|
//Override overscan dimensions to hide SGB borders
|
|
OverscanDimensions overscan = {};
|
|
overscan.Top = 46;
|
|
overscan.Bottom = 49;
|
|
overscan.Left = 48;
|
|
overscan.Right = 48;
|
|
return overscan;
|
|
}
|
|
}
|
|
|
|
if(_game.OverrideOverscan) {
|
|
return _game.Overscan;
|
|
}
|
|
|
|
switch(_emu->GetConsoleType()) {
|
|
case ConsoleType::Snes: return _snes.Overscan;
|
|
case ConsoleType::Nes: return _emu->GetRegion() == ConsoleRegion::Ntsc ? _nes.NtscOverscan : _nes.PalOverscan;
|
|
case ConsoleType::PcEngine: return _pce.Overscan;
|
|
case ConsoleType::Sms:
|
|
if(romFormat == RomFormat::ColecoVision) {
|
|
return { 0, 0, 24, 24 };
|
|
} else if(romFormat == RomFormat::GameGear) {
|
|
return _sms.GameGearOverscan;
|
|
} else {
|
|
return _emu->GetRegion() == ConsoleRegion::Ntsc ? _sms.NtscOverscan : _sms.PalOverscan;
|
|
}
|
|
|
|
case ConsoleType::Gameboy:
|
|
case ConsoleType::Gba:
|
|
case ConsoleType::Ws:
|
|
break;
|
|
}
|
|
|
|
return OverscanDimensions {};
|
|
}
|
|
|
|
uint32_t EmuSettings::GetEmulationSpeed()
|
|
{
|
|
if(CheckFlag(EmulationFlags::MaximumSpeed)) {
|
|
return 0;
|
|
} else if(CheckFlag(EmulationFlags::Turbo)) {
|
|
return _emulation.TurboSpeed;
|
|
} else if(CheckFlag(EmulationFlags::Rewind)) {
|
|
return _emulation.RewindSpeed;
|
|
} else {
|
|
return _emulation.EmulationSpeed;
|
|
}
|
|
}
|
|
|
|
double EmuSettings::GetAspectRatio(ConsoleRegion region, FrameInfo baseFrameSize)
|
|
{
|
|
double screenAspectRatio = (double)baseFrameSize.Width / baseFrameSize.Height;
|
|
|
|
switch(_video.AspectRatio) {
|
|
case VideoAspectRatio::NoStretching: return screenAspectRatio;
|
|
|
|
//For auto, ntsc and pal, these are PAR ratios, so multiply them with the base screen's aspect ratio to get the expected screen aspect ratio
|
|
case VideoAspectRatio::Auto:
|
|
if(_emu->GetConsoleType() == ConsoleType::Gameboy || _emu->GetConsoleType() == ConsoleType::Gba || _emu->GetConsoleType() == ConsoleType::Ws) {
|
|
//GB/GBA/WS shouldn't use NTSC/PAL aspect ratio when in auto mode
|
|
return screenAspectRatio;
|
|
} else if(_emu->GetRomInfo().Format == RomFormat::GameGear) {
|
|
//GG has a 6:5 PAR
|
|
return screenAspectRatio * (6.0 / 5.0);
|
|
}
|
|
return screenAspectRatio * ((region == ConsoleRegion::Pal || region == ConsoleRegion::Dendy) ? (11.0 / 8.0) : (8.0 / 7.0));
|
|
|
|
case VideoAspectRatio::NTSC: return screenAspectRatio * 8.0 / 7.0;
|
|
case VideoAspectRatio::PAL: return screenAspectRatio * 11.0 / 8.0;
|
|
|
|
case VideoAspectRatio::Standard: return 4.0 / 3.0;
|
|
case VideoAspectRatio::Widescreen: return 16.0 / 9.0;
|
|
case VideoAspectRatio::Custom: return _video.CustomAspectRatio;
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
void EmuSettings::SetFlag(EmulationFlags flag)
|
|
{
|
|
if((_flags & (int)flag) == 0) {
|
|
_flags |= (int)flag;
|
|
}
|
|
}
|
|
|
|
void EmuSettings::SetFlagState(EmulationFlags flag, bool enabled)
|
|
{
|
|
if(enabled) {
|
|
SetFlag(flag);
|
|
} else {
|
|
ClearFlag(flag);
|
|
}
|
|
}
|
|
|
|
void EmuSettings::ClearFlag(EmulationFlags flag)
|
|
{
|
|
if((_flags & (int)flag) != 0) {
|
|
_flags &= ~(int)flag;
|
|
}
|
|
}
|
|
|
|
bool EmuSettings::CheckFlag(EmulationFlags flag)
|
|
{
|
|
return (_flags & (int)flag) != 0;
|
|
}
|
|
|
|
void EmuSettings::SetDebuggerFlag(DebuggerFlags flag, bool enabled)
|
|
{
|
|
if(enabled) {
|
|
if((_debuggerFlags & (uint64_t)flag) == 0) {
|
|
_debuggerFlags |= (uint64_t)flag;
|
|
}
|
|
} else {
|
|
if((_debuggerFlags & (uint64_t)flag) != 0) {
|
|
_debuggerFlags &= ~(uint64_t)flag;
|
|
}
|
|
}
|
|
|
|
DebuggerRequest req = _emu->GetDebugger(false);
|
|
Debugger* dbg = req.GetDebugger();
|
|
if(dbg) {
|
|
dbg->ProcessConfigChange();
|
|
}
|
|
}
|
|
|
|
bool EmuSettings::CheckDebuggerFlag(DebuggerFlags flag)
|
|
{
|
|
return (_debuggerFlags & (uint64_t)flag) != 0;
|
|
}
|
|
|
|
bool EmuSettings::HasRandomPowerOnState(ConsoleType consoleType)
|
|
{
|
|
switch(consoleType) {
|
|
case ConsoleType::Snes: return _snes.RamPowerOnState == RamState::Random || _snes.EnableRandomPowerOnState;
|
|
case ConsoleType::Gameboy: return _gameboy.RamPowerOnState == RamState::Random;
|
|
case ConsoleType::Nes: return _nes.RamPowerOnState == RamState::Random || _nes.RandomizeCpuPpuAlignment || _nes.RandomizeMapperPowerOnState;
|
|
case ConsoleType::PcEngine: return _pce.RamPowerOnState == RamState::Random || _pce.EnableRandomPowerOnState;
|
|
case ConsoleType::Sms: return _sms.RamPowerOnState == RamState::Random;
|
|
case ConsoleType::Gba: return _gba.RamPowerOnState == RamState::Random;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void EmuSettings::InitializeRam(RamState state, void* data, uint32_t length)
|
|
{
|
|
switch(state) {
|
|
default:
|
|
case RamState::AllZeros: memset(data, 0, length); break;
|
|
case RamState::AllOnes: memset(data, 0xFF, length); break;
|
|
case RamState::Random:
|
|
std::uniform_int_distribution<uint64_t> dist(0, std::numeric_limits<uint64_t>::max());
|
|
uint32_t i = 0;
|
|
while(i < length) {
|
|
uint64_t randomData = dist(_mt);
|
|
for(int j = 0; j < 8 && i < length; j++) {
|
|
((uint8_t*)data)[i] = (uint8_t)(randomData >> (8*j));
|
|
i++;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
int EmuSettings::GetRandomValue(int maxValue)
|
|
{
|
|
std::uniform_int_distribution<> dist(0, maxValue);
|
|
return dist(_mt);
|
|
}
|
|
|
|
bool EmuSettings::GetRandomBool()
|
|
{
|
|
return GetRandomValue(1) == 1;
|
|
}
|
|
|
|
bool EmuSettings::IsInputEnabled()
|
|
{
|
|
return !CheckFlag(EmulationFlags::InBackground) || _preferences.AllowBackgroundInput;
|
|
}
|
|
|
|
double EmuSettings::GetControllerDeadzoneRatio()
|
|
{
|
|
switch(_input.ControllerDeadzoneSize) {
|
|
case 0: return 0.5;
|
|
case 1: return 0.75;
|
|
case 2: return 1;
|
|
case 3: return 1.25;
|
|
case 4: return 1.5;
|
|
}
|
|
return 1;
|
|
}
|