1 #pragma once 2 3 #include <algorithm> 4 #include "stdafx.h" 5 #include "MessageManager.h" 6 #include "GameClient.h" 7 #include "KeyManager.h" 8 #include "../Utilities/SimpleLock.h" 9 10 class Console; 11 12 enum EmulationFlags : uint64_t 13 { 14 Paused = 0x01, 15 ShowFPS = 0x02, 16 VerticalSync = 0x04, 17 AllowInvalidInput = 0x08, 18 RemoveSpriteLimit = 0x10, 19 UseHdPacks = 0x20, 20 HasFourScore = 0x40, 21 22 DisableDynamicSampleRate = 0x80, 23 24 PauseOnMovieEnd = 0x0100, 25 26 DeveloperMode = 0x0200, 27 28 AllowBackgroundInput = 0x0400, 29 ReduceSoundInBackground = 0x0800, 30 MuteSoundInBackground = 0x1000, 31 32 FdsFastForwardOnLoad = 0x2000, 33 FdsAutoLoadDisk = 0x4000, 34 Mmc3IrqAltBehavior = 0x8000, 35 36 SwapDutyCycles = 0x10000, 37 38 AutoConfigureInput = 0x40000, 39 40 ShowLagCounter = 0x80000, 41 42 SilenceTriangleHighFreq = 0x100000, 43 ReduceDmcPopping = 0x200000, 44 45 DisableBackground = 0x400000, 46 DisableSprites = 0x800000, 47 ForceBackgroundFirstColumn = 0x1000000, 48 ForceSpritesFirstColumn = 0x2000000, 49 DisablePpu2004Reads = 0x4000000, 50 DisableNoiseModeFlag = 0x8000000, 51 DisablePaletteRead = 0x10000000, 52 DisableOamAddrBug = 0x20000000, 53 DisablePpuReset = 0x40000000, 54 EnableOamDecay = 0x80000000, 55 56 UseNes101Hvc101Behavior = 0x100000000, 57 ShowFrameCounter = 0x200000000, 58 ShowGameTimer = 0x400000000, 59 60 FdsAutoInsertDisk = 0x800000000, 61 62 Rewind = 0x1000000000, 63 Turbo = 0x2000000000, 64 InBackground = 0x4000000000, 65 NsfPlayerEnabled = 0x8000000000, 66 67 DisplayMovieIcons = 0x10000000000, 68 HidePauseOverlay = 0x20000000000, 69 70 UseCustomVsPalette = 0x40000000000, 71 72 AdaptiveSpriteLimit = 0x80000000000, 73 74 DisableGameSelectionScreen = 0x200000000000, 75 76 ConfirmExitResetPower = 0x400000000000, 77 78 NsfRepeat = 0x800000000000, 79 NsfShuffle = 0x1000000000000, 80 81 IntegerFpsMode = 0x2000000000000, 82 83 DebuggerWindowEnabled = 0x4000000000000, 84 BreakOnCrash = 0x8000000000000, 85 86 AllowMismatchingSaveState = 0x10000000000000, 87 88 RandomizeMapperPowerOnState = 0x20000000000000, 89 90 UseHighResolutionTimer = 0x40000000000000, 91 DisplayDebugInfo = 0x80000000000000, 92 93 ReduceSoundInFastForward = 0x100000000000000, 94 95 VsDualMuteMaster = 0x200000000000000, 96 VsDualMuteSlave = 0x400000000000000, 97 98 ForceMaxSpeed = 0x4000000000000000, 99 ConsoleMode = 0x8000000000000000, 100 }; 101 102 enum class AudioChannel 103 { 104 Square1 = 0, 105 Square2 = 1, 106 Triangle = 2, 107 Noise = 3, 108 DMC = 4, 109 FDS = 5, 110 MMC5 = 6, 111 VRC6 = 7, 112 VRC7 = 8, 113 Namco163 = 9, 114 Sunsoft5B = 10 115 }; 116 117 enum class EqualizerFilterType 118 { 119 None = 0, 120 Butterworth = 1, 121 Chebyshev1 = 2, 122 Chebyshev2 = 3 123 }; 124 125 enum class ScaleFilterType 126 { 127 xBRZ = 0, 128 HQX = 1, 129 Scale2x = 2, 130 _2xSai = 3, 131 Super2xSai = 4, 132 SuperEagle = 5, 133 Prescale = 6, 134 }; 135 136 enum class VideoFilterType 137 { 138 None = 0, 139 NTSC = 1, 140 BisqwitNtscQuarterRes = 2, 141 BisqwitNtscHalfRes = 3, 142 BisqwitNtsc = 4, 143 xBRZ2x = 5, 144 xBRZ3x = 6, 145 xBRZ4x = 7, 146 xBRZ5x = 8, 147 xBRZ6x = 9, 148 HQ2x = 10, 149 HQ3x = 11, 150 HQ4x = 12, 151 Scale2x = 13, 152 Scale3x = 14, 153 Scale4x = 15, 154 _2xSai = 16, 155 Super2xSai = 17, 156 SuperEagle = 18, 157 Prescale2x = 19, 158 Prescale3x = 20, 159 Prescale4x = 21, 160 Prescale6x = 22, 161 Prescale8x = 23, 162 Prescale10x = 24, 163 Raw = 25, 164 HdPack = 999 165 }; 166 167 enum class VideoResizeFilter 168 { 169 NearestNeighbor = 0, 170 Bilinear = 1 171 }; 172 173 enum class VideoAspectRatio 174 { 175 NoStretching = 0, 176 Auto = 1, 177 NTSC = 2, 178 PAL = 3, 179 Standard = 4, 180 Widescreen = 5, 181 Custom = 6 182 }; 183 184 struct OverscanDimensions 185 { 186 uint32_t Left = 0; 187 uint32_t Right = 0; 188 uint32_t Top = 0; 189 uint32_t Bottom = 0; 190 GetPixelCountOverscanDimensions191 uint32_t GetPixelCount() 192 { 193 return GetScreenWidth() * GetScreenHeight(); 194 } 195 GetScreenWidthOverscanDimensions196 uint32_t GetScreenWidth() 197 { 198 return 256 - Left - Right; 199 } 200 GetScreenHeightOverscanDimensions201 uint32_t GetScreenHeight() 202 { 203 return 240 - Top - Bottom; 204 } 205 }; 206 207 struct PictureSettings 208 { 209 double Brightness = 0; 210 double Contrast = 0; 211 double Saturation = 0; 212 double Hue = 0; 213 double ScanlineIntensity = 0; 214 }; 215 216 struct NtscFilterSettings 217 { 218 double Sharpness = 0; 219 double Gamma = 0; 220 double Resolution = 0; 221 double Artifacts = 0; 222 double Fringing = 0; 223 double Bleed = 0; 224 bool MergeFields = false; 225 bool VerticalBlend = false; 226 bool KeepVerticalResolution = false; 227 228 double YFilterLength = 0; 229 double IFilterLength = 0; 230 double QFilterLength = 0; 231 }; 232 233 enum class RamPowerOnState 234 { 235 AllZeros = 0, 236 AllOnes = 1, 237 Random = 2 238 }; 239 240 extern const vector<string> NesModelNames; 241 enum class NesModel 242 { 243 Auto = 0, 244 NTSC = 1, 245 PAL = 2, 246 Dendy = 3, 247 }; 248 249 extern const vector<string> ConsoleTypeNames; 250 enum class ConsoleType 251 { 252 Nes = 0, 253 Famicom = 1 254 }; 255 256 extern const vector<string> ControllerTypeNames; 257 enum class ControllerType 258 { 259 None = 0, 260 StandardController = 1, 261 Zapper = 2, 262 ArkanoidController = 3, 263 SnesController = 4, 264 PowerPad = 5, 265 SnesMouse = 6, 266 SuborMouse = 7, 267 VsZapper = 8 268 }; 269 270 extern const vector<string> ExpansionPortDeviceNames; 271 enum class ExpansionPortDevice 272 { 273 None = 0, 274 Zapper = 1, 275 FourPlayerAdapter = 2, 276 ArkanoidController = 3, 277 OekaKidsTablet = 4, 278 FamilyTrainerMat = 5, 279 KonamiHyperShot = 6, 280 FamilyBasicKeyboard = 7, 281 PartyTap = 8, 282 Pachinko = 9, 283 ExcitingBoxing = 10, 284 JissenMahjong = 11, 285 SuborKeyboard = 12, 286 BarcodeBattler = 13, 287 HoriTrack = 14, 288 BandaiHyperShot = 15, 289 AsciiTurboFile = 16, 290 BattleBox = 17, 291 }; 292 293 enum class VsInputType 294 { 295 Default = 0, 296 SwapControllers = 1, 297 SwapAB = 2 298 }; 299 300 struct KeyMapping 301 { 302 uint32_t A = 0; 303 uint32_t B = 0; 304 uint32_t Up = 0; 305 uint32_t Down = 0; 306 uint32_t Left = 0; 307 uint32_t Right = 0; 308 uint32_t Start = 0; 309 uint32_t Select = 0; 310 uint32_t TurboA = 0; 311 uint32_t TurboB = 0; 312 uint32_t TurboStart = 0; 313 uint32_t TurboSelect = 0; 314 uint32_t Microphone = 0; 315 uint32_t LButton = 0; 316 uint32_t RButton = 0; 317 318 uint32_t PowerPadButtons[12] = {}; 319 uint32_t FamilyBasicKeyboardButtons[72] = {}; 320 uint32_t PartyTapButtons[6] = {}; 321 uint32_t PachinkoButtons[2] = {}; 322 uint32_t ExcitingBoxingButtons[8] = {}; 323 uint32_t JissenMahjongButtons[21] = {}; 324 uint32_t SuborKeyboardButtons[99] = {}; 325 uint32_t BandaiMicrophoneButtons[3] = {}; 326 HasKeySetKeyMapping327 bool HasKeySet() 328 { 329 if(A || B || Up || Down || Left || Right || Start || Select || TurboA || TurboB || TurboStart || TurboSelect || Microphone || LButton || RButton) { 330 return true; 331 } 332 333 bool hasKeyBinding = false; 334 hasKeyBinding |= HasKeyBinding(PowerPadButtons, sizeof(PowerPadButtons) / sizeof(PowerPadButtons[0])); 335 hasKeyBinding |= HasKeyBinding(FamilyBasicKeyboardButtons, sizeof(FamilyBasicKeyboardButtons) / sizeof(FamilyBasicKeyboardButtons[0])); 336 hasKeyBinding |= HasKeyBinding(PartyTapButtons, sizeof(PartyTapButtons) / sizeof(PartyTapButtons[0])); 337 hasKeyBinding |= HasKeyBinding(PachinkoButtons, sizeof(PachinkoButtons) / sizeof(PachinkoButtons[0])); 338 hasKeyBinding |= HasKeyBinding(ExcitingBoxingButtons, sizeof(ExcitingBoxingButtons) / sizeof(ExcitingBoxingButtons[0])); 339 hasKeyBinding |= HasKeyBinding(JissenMahjongButtons, sizeof(JissenMahjongButtons) / sizeof(JissenMahjongButtons[0])); 340 hasKeyBinding |= HasKeyBinding(SuborKeyboardButtons, sizeof(SuborKeyboardButtons) / sizeof(SuborKeyboardButtons[0])); 341 hasKeyBinding |= HasKeyBinding(BandaiMicrophoneButtons, sizeof(BandaiMicrophoneButtons) / sizeof(BandaiMicrophoneButtons[0])); 342 return hasKeyBinding; 343 } 344 345 private: HasKeyBindingKeyMapping346 bool HasKeyBinding(uint32_t* buttons, uint32_t count) 347 { 348 for(uint32_t i = 0; i < count; i++) { 349 if(buttons[i] != 0) { 350 return true; 351 } 352 } 353 return false; 354 } 355 }; 356 357 struct KeyMappingSet 358 { 359 KeyMapping Mapping1; 360 KeyMapping Mapping2; 361 KeyMapping Mapping3; 362 KeyMapping Mapping4; 363 uint32_t TurboSpeed = 0; 364 bool PowerpadUseSideA = false; 365 GetKeyMappingArrayKeyMappingSet366 vector<KeyMapping> GetKeyMappingArray() 367 { 368 vector<KeyMapping> keyMappings; 369 if(Mapping1.HasKeySet()) { 370 keyMappings.push_back(Mapping1); 371 } 372 if(Mapping2.HasKeySet()) { 373 keyMappings.push_back(Mapping2); 374 } 375 if(Mapping3.HasKeySet()) { 376 keyMappings.push_back(Mapping3); 377 } 378 if(Mapping4.HasKeySet()) { 379 keyMappings.push_back(Mapping4); 380 } 381 return keyMappings; 382 } 383 }; 384 385 enum class EmulatorShortcut 386 { 387 FastForward, 388 Rewind, 389 RewindTenSecs, 390 RewindOneMin, 391 392 MoveToNextStateSlot, 393 MoveToPreviousStateSlot, 394 SaveState, 395 LoadState, 396 397 InsertNextDisk, 398 VsServiceButton, 399 VsServiceButton2, 400 401 ToggleCheats, 402 ToggleAudio, 403 ToggleFastForward, 404 ToggleRewind, 405 ToggleKeyboardMode, 406 407 RunSingleFrame, 408 409 // Everything below this is handled UI-side 410 SwitchDiskSide, 411 EjectDisk, 412 413 InsertCoin1, 414 InsertCoin2, 415 InsertCoin3, 416 InsertCoin4, 417 418 InputBarcode, 419 420 TakeScreenshot, 421 422 IncreaseSpeed, 423 DecreaseSpeed, 424 MaxSpeed, 425 426 Pause, 427 Reset, 428 PowerCycle, 429 PowerOff, 430 Exit, 431 432 SetScale1x, 433 SetScale2x, 434 SetScale3x, 435 SetScale4x, 436 SetScale5x, 437 SetScale6x, 438 ToggleFullscreen, 439 ToggleFps, 440 ToggleGameTimer, 441 ToggleFrameCounter, 442 ToggleLagCounter, 443 ToggleOsd, 444 ToggleAlwaysOnTop, 445 ToggleSprites, 446 ToggleBackground, 447 ToggleDebugInfo, 448 449 LoadRandomGame, 450 SaveStateSlot1, 451 SaveStateSlot2, 452 SaveStateSlot3, 453 SaveStateSlot4, 454 SaveStateSlot5, 455 SaveStateSlot6, 456 SaveStateSlot7, 457 SaveStateSlot8, 458 SaveStateSlot9, 459 SaveStateSlot10, 460 SaveStateToFile, 461 462 LoadStateSlot1, 463 LoadStateSlot2, 464 LoadStateSlot3, 465 LoadStateSlot4, 466 LoadStateSlot5, 467 LoadStateSlot6, 468 LoadStateSlot7, 469 LoadStateSlot8, 470 LoadStateSlot9, 471 LoadStateSlot10, 472 LoadStateSlotAuto, 473 LoadStateFromFile, 474 475 LoadLastSession, 476 477 OpenFile, 478 ShortcutCount 479 }; 480 481 struct KeyCombination 482 { 483 uint32_t Key1 = 0; 484 uint32_t Key2 = 0; 485 uint32_t Key3 = 0; 486 GetKeysKeyCombination487 vector<uint32_t> GetKeys() 488 { 489 vector<uint32_t> result; 490 if(Key1) { 491 result.push_back(Key1); 492 } 493 if(Key2) { 494 result.push_back(Key2); 495 } 496 if(Key3) { 497 result.push_back(Key3); 498 } 499 return result; 500 } 501 IsSubsetOfKeyCombination502 bool IsSubsetOf(KeyCombination keyCombination) 503 { 504 vector<uint32_t> myKeys = GetKeys(); 505 vector<uint32_t> otherKeys = keyCombination.GetKeys(); 506 507 if(otherKeys.size() > myKeys.size()) { 508 for(size_t i = 0; i < myKeys.size(); i++) { 509 if(std::find(otherKeys.begin(), otherKeys.end(), myKeys[i]) == otherKeys.end()) { 510 //Current key combination contains a key not found in the other combination, so it's not a subset 511 return false; 512 } 513 } 514 return true; 515 } 516 return false; 517 } 518 }; 519 520 enum class Language 521 { 522 //SystemDefault = 0, //This value is never used by the C++ core 523 English = 1, 524 French = 2, 525 Japanese = 3, 526 Russian = 4, 527 Spanish = 5, 528 Ukrainian = 6, 529 Portuguese = 7, 530 Catalan = 8, 531 Chinese = 9, 532 }; 533 534 enum class MouseDevice 535 { 536 Unknown = 0, 537 SnesMouse, 538 SuborMouse, 539 ArkanoidController, 540 HoriTrack 541 }; 542 543 enum class StereoFilter 544 { 545 None = 0, 546 Delay = 1, 547 Panning = 2, 548 CombFilter = 3, 549 }; 550 551 struct AudioFilterSettings 552 { 553 StereoFilter Filter = StereoFilter::None; 554 double Angle = 0; 555 int32_t Delay = 0; 556 int32_t Strength = 0; 557 558 double ReverbDelay = 0; 559 double ReverbStrength = 0; 560 561 int32_t CrossFadeRatio = 0; 562 }; 563 564 enum class InputDisplayPosition 565 { 566 TopLeft = 0, 567 TopRight = 1, 568 BottomLeft = 2, 569 BottomRight = 3 570 }; 571 572 struct InputDisplaySettings 573 { 574 uint8_t VisiblePorts; 575 InputDisplayPosition DisplayPosition; 576 bool DisplayHorizontally; 577 }; 578 579 class EmulationSettings 580 { 581 private: 582 static const vector<uint32_t> _speedValues; 583 584 static uint16_t _versionMajor; 585 static uint8_t _versionMinor; 586 static uint8_t _versionRevision; 587 static Language _displayLanguage; 588 589 static SimpleLock _shortcutLock; 590 static SimpleLock _equalizerLock; 591 static SimpleLock _lock; 592 593 uint32_t _ppuPaletteArgb[11][64] = { 594 /* 2C02 */ { 0xFF666666, 0xFF002A88, 0xFF1412A7, 0xFF3B00A4, 0xFF5C007E, 0xFF6E0040, 0xFF6C0600, 0xFF561D00, 0xFF333500, 0xFF0B4800, 0xFF005200, 0xFF004F08, 0xFF00404D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFADADAD, 0xFF155FD9, 0xFF4240FF, 0xFF7527FE, 0xFFA01ACC, 0xFFB71E7B, 0xFFB53120, 0xFF994E00, 0xFF6B6D00, 0xFF388700, 0xFF0C9300, 0xFF008F32, 0xFF007C8D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFF64B0FF, 0xFF9290FF, 0xFFC676FF, 0xFFF36AFF, 0xFFFE6ECC, 0xFFFE8170, 0xFFEA9E22, 0xFFBCBE00, 0xFF88D800, 0xFF5CE430, 0xFF45E082, 0xFF48CDDE, 0xFF4F4F4F, 0xFF000000, 0xFF000000, 0xFFFFFEFF, 0xFFC0DFFF, 0xFFD3D2FF, 0xFFE8C8FF, 0xFFFBC2FF, 0xFFFEC4EA, 0xFFFECCC5, 0xFFF7D8A5, 0xFFE4E594, 0xFFCFEF96, 0xFFBDF4AB, 0xFFB3F3CC, 0xFFB5EBF2, 0xFFB8B8B8, 0xFF000000, 0xFF000000 }, 595 /* 2C03 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, 596 /* 2C04-0001 */ { 0xFFFFB6B6, 0xFFDA6DFF, 0xFFFF0000, 0xFF9191FF, 0xFF009191, 0xFF244800, 0xFF484848, 0xFFFF0091, 0xFFFFFFFF, 0xFF6D6D6D, 0xFFFFB600, 0xFFB6006D, 0xFF91006D, 0xFFDADA00, 0xFF6D4800, 0xFFFFFFFF, 0xFF6DB6FF, 0xFFDAB66D, 0xFF6D2400, 0xFF6DDA00, 0xFF91DAFF, 0xFFDAB6FF, 0xFFFFDA91, 0xFF0048FF, 0xFFFFDA00, 0xFF48FFDA, 0xFF000000, 0xFF480000, 0xFFDADADA, 0xFF919191, 0xFFFF00FF, 0xFF002491, 0xFF00006D, 0xFFB6DAFF, 0xFFFFB6FF, 0xFF00FF00, 0xFF00FFFF, 0xFF004848, 0xFF00B66D, 0xFFB600FF, 0xFF000000, 0xFF914800, 0xFFFF91FF, 0xFFB62400, 0xFF9100FF, 0xFF0000DA, 0xFFFF9100, 0xFF000000, 0xFF000000, 0xFF249100, 0xFFB6B6B6, 0xFF006D24, 0xFFB6FF48, 0xFF6D48DA, 0xFFFFFF00, 0xFFDA6D00, 0xFF004800, 0xFF006DDA, 0xFF009100, 0xFF242424, 0xFFFFFF6D, 0xFFFF6DFF, 0xFF916D00, 0xFF91FF6D }, 597 /* 2C04-0002 */ { 0xFF000000, 0xFFFFB600, 0xFF916D00, 0xFFB6FF48, 0xFF91FF6D, 0xFFFF6DFF, 0xFF009191, 0xFFB6DAFF, 0xFFFF0000, 0xFF9100FF, 0xFFFFFF6D, 0xFFFF91FF, 0xFFFFFFFF, 0xFFDA6DFF, 0xFF91DAFF, 0xFF009100, 0xFF004800, 0xFF6DB6FF, 0xFFB62400, 0xFFDADADA, 0xFF00B66D, 0xFF6DDA00, 0xFF480000, 0xFF9191FF, 0xFF484848, 0xFFFF00FF, 0xFF00006D, 0xFF48FFDA, 0xFFDAB6FF, 0xFF6D4800, 0xFF000000, 0xFF6D48DA, 0xFF91006D, 0xFFFFDA91, 0xFFFF9100, 0xFFFFB6FF, 0xFF006DDA, 0xFF6D2400, 0xFFB6B6B6, 0xFF0000DA, 0xFFB600FF, 0xFFFFDA00, 0xFF6D6D6D, 0xFF244800, 0xFF0048FF, 0xFF000000, 0xFFDADA00, 0xFFFFFFFF, 0xFFDAB66D, 0xFF242424, 0xFF00FF00, 0xFFDA6D00, 0xFF004848, 0xFF002491, 0xFFFF0091, 0xFF249100, 0xFF000000, 0xFF00FFFF, 0xFF914800, 0xFFFFFF00, 0xFFFFB6B6, 0xFFB6006D, 0xFF006D24, 0xFF919191 }, 598 /* 2C04-0003 */ { 0xFFB600FF, 0xFFFF6DFF, 0xFF91FF6D, 0xFFB6B6B6, 0xFF009100, 0xFFFFFFFF, 0xFFB6DAFF, 0xFF244800, 0xFF002491, 0xFF000000, 0xFFFFDA91, 0xFF6D4800, 0xFFFF0091, 0xFFDADADA, 0xFFDAB66D, 0xFF91DAFF, 0xFF9191FF, 0xFF009191, 0xFFB6006D, 0xFF0048FF, 0xFF249100, 0xFF916D00, 0xFFDA6D00, 0xFF00B66D, 0xFF6D6D6D, 0xFF6D48DA, 0xFF000000, 0xFF0000DA, 0xFFFF0000, 0xFFB62400, 0xFFFF91FF, 0xFFFFB6B6, 0xFFDA6DFF, 0xFF004800, 0xFF00006D, 0xFFFFFF00, 0xFF242424, 0xFFFFB600, 0xFFFF9100, 0xFFFFFFFF, 0xFF6DDA00, 0xFF91006D, 0xFF6DB6FF, 0xFFFF00FF, 0xFF006DDA, 0xFF919191, 0xFF000000, 0xFF6D2400, 0xFF00FFFF, 0xFF480000, 0xFFB6FF48, 0xFFFFB6FF, 0xFF914800, 0xFF00FF00, 0xFFDADA00, 0xFF484848, 0xFF006D24, 0xFF000000, 0xFFDAB6FF, 0xFFFFFF6D, 0xFF9100FF, 0xFF48FFDA, 0xFFFFDA00, 0xFF004848 }, 599 /* 2C04-0004 */ { 0xFF916D00, 0xFF6D48DA, 0xFF009191, 0xFFDADA00, 0xFF000000, 0xFFFFB6B6, 0xFF002491, 0xFFDA6D00, 0xFFB6B6B6, 0xFF6D2400, 0xFF00FF00, 0xFF00006D, 0xFFFFDA91, 0xFFFFFF00, 0xFF009100, 0xFFB6FF48, 0xFFFF6DFF, 0xFF480000, 0xFF0048FF, 0xFFFF91FF, 0xFF000000, 0xFF484848, 0xFFB62400, 0xFFFF9100, 0xFFDAB66D, 0xFF00B66D, 0xFF9191FF, 0xFF249100, 0xFF91006D, 0xFF000000, 0xFF91FF6D, 0xFF6DB6FF, 0xFFB6006D, 0xFF006D24, 0xFF914800, 0xFF0000DA, 0xFF9100FF, 0xFFB600FF, 0xFF6D6D6D, 0xFFFF0091, 0xFF004848, 0xFFDADADA, 0xFF006DDA, 0xFF004800, 0xFF242424, 0xFFFFFF6D, 0xFF919191, 0xFFFF00FF, 0xFFFFB6FF, 0xFFFFFFFF, 0xFF6D4800, 0xFFFF0000, 0xFFFFDA00, 0xFF48FFDA, 0xFFFFFFFF, 0xFF91DAFF, 0xFF000000, 0xFFFFB600, 0xFFDA6DFF, 0xFFB6DAFF, 0xFF6DDA00, 0xFFDAB6FF, 0xFF00FFFF, 0xFF244800 }, 600 /* 2C05-01 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, 601 /* 2C05-02 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, 602 /* 2C05-03 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, 603 /* 2C05-04 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 }, 604 /* 2C05-05 */ { 0xFF6D6D6D, 0xFF002491, 0xFF0000DA, 0xFF6D48DA, 0xFF91006D, 0xFFB6006D, 0xFFB62400, 0xFF914800, 0xFF6D4800, 0xFF244800, 0xFF006D24, 0xFF009100, 0xFF004848, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB6B6B6, 0xFF006DDA, 0xFF0048FF, 0xFF9100FF, 0xFFB600FF, 0xFFFF0091, 0xFFFF0000, 0xFFDA6D00, 0xFF916D00, 0xFF249100, 0xFF009100, 0xFF00B66D, 0xFF009191, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFF6DB6FF, 0xFF9191FF, 0xFFDA6DFF, 0xFFFF00FF, 0xFFFF6DFF, 0xFFFF9100, 0xFFFFB600, 0xFFDADA00, 0xFF6DDA00, 0xFF00FF00, 0xFF48FFDA, 0xFF00FFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFB6DAFF, 0xFFDAB6FF, 0xFFFFB6FF, 0xFFFF91FF, 0xFFFFB6B6, 0xFFFFDA91, 0xFFFFFF48, 0xFFFFFF6D, 0xFFB6FF48, 0xFF91FF6D, 0xFF48FFDA, 0xFF91DAFF, 0xFF000000, 0xFF000000, 0xFF000000 } 605 }; 606 607 bool _isFullColorPalette = false; 608 uint32_t _userPalette[512] = { }; 609 uint32_t _currentPalette[512] = { }; 610 611 const uint8_t _paletteLut[11][64] = { 612 /* 2C02 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 }, 613 /* 2C03 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 614 /* 2C04-0001 */ { 53,35,22,34,28,9,29,21,32,0,39,5,4,40,8,32,33,62,31,41,60,50,54,18,63,43,46,30,61,45,36,1,14,49,51,42,44,12,27,20,46,7,52,6,19,2,38,46,46,25,16,10,57,3,55,23,15,17,11,13,56,37,24,58 }, 615 /* 2C04-0002 */ { 46,39,24,57,58,37,28,49,22,19,56,52,32,35,60,11,15,33,6,61,27,41,30,34,29,36,14,43,50,8,46,3,4,54,38,51,17,31,16,2,20,63,0,9,18,46,40,32,62,13,42,23,12,1,21,25,46,44,7,55,53,5,10,45 }, 616 /* 2C04-0003 */ { 20,37,58,16,11,32,49,9,1,46,54,8,21,61,62,60,34,28,5,18,25,24,23,27,0,3,46,2,22,6,52,53,35,15,14,55,13,39,38,32,41,4,33,36,17,45,46,31,44,30,57,51,7,42,40,29,10,46,50,56,19,43,63,12 }, 617 /* 2C04-0004 */ { 24,3,28,40,46,53,1,23,16,31,42,14,54,55,11,57,37,30,18,52,46,29,6,38,62,27,34,25,4,46,58,33,5,10,7,2,19,20,0,21,12,61,17,15,13,56,45,36,51,32,8,22,63,43,32,60,46,39,35,49,41,50,44,9 }, 618 /* 2C05-01 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 619 /* 2C05-02 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 620 /* 2C05-03 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 621 /* 2C05-04 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 622 /* 2C05-05 */ { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,15,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,15,62,63 }, 623 }; 624 625 string _pauseScreenMessage; 626 627 uint64_t _flags = 0; 628 629 bool _audioSettingsChanged = false; 630 uint32_t _audioLatency = 50; 631 double _channelVolume[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; 632 double _channelPanning[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; 633 EqualizerFilterType _equalizerFilterType = EqualizerFilterType::None; 634 vector<double> _bandGains = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; 635 vector<double> _bands = { { 40,56,80,113,160,225,320,450,600,750,1000,2000,3000,4000,5000,6000,7000,10000,12500,15000 } }; 636 double _masterVolume = 1.0; 637 double _volumeReduction = 0.75; 638 uint32_t _sampleRate = 48000; 639 AudioFilterSettings _audioFilterSettings; 640 641 NesModel _model = NesModel::Auto; 642 PpuModel _ppuModel = PpuModel::Ppu2C02; 643 644 uint32_t _emulationSpeed = 100; 645 uint32_t _turboSpeed = 300; 646 uint32_t _rewindSpeed = 100; 647 648 uint32_t _rewindBufferSize = 300; 649 650 bool _hasOverclock = false; 651 uint32_t _overclockRate = 100; 652 bool _overclockAdjustApu = true; 653 bool _disableOverclocking = false; 654 uint32_t _extraScanlinesBeforeNmi = 0; 655 uint32_t _extraScanlinesAfterNmi = 0; 656 double _effectiveOverclockRate = 100; 657 658 OverscanDimensions _overscan; 659 VideoFilterType _videoFilterType = VideoFilterType::None; 660 double _videoScale = 1; 661 VideoAspectRatio _aspectRatio = VideoAspectRatio::NoStretching; 662 double _customAspectRatio = 1.0; 663 VideoResizeFilter _resizeFilter = VideoResizeFilter::NearestNeighbor; 664 PictureSettings _pictureSettings; 665 NtscFilterSettings _ntscFilterSettings; 666 bool _backgroundEnabled = true; 667 bool _spritesEnabled = true; 668 uint32_t _screenRotation = 0; 669 uint32_t _exclusiveRefreshRate = 60; 670 671 ConsoleType _consoleType = ConsoleType::Nes; 672 ExpansionPortDevice _expansionDevice = ExpansionPortDevice::None; 673 ControllerType _controllerTypes[4] = { ControllerType::None, ControllerType::None, ControllerType::None, ControllerType::None }; 674 KeyMappingSet _controllerKeys[4] = { KeyMappingSet(), KeyMappingSet(), KeyMappingSet(), KeyMappingSet() }; 675 bool _needControllerUpdate = false; 676 uint32_t _zapperDetectionRadius = 0; 677 uint32_t _controllerDeadzoneSize = 2; 678 std::unordered_map<int, double> _mouseSensitivity; 679 int32_t _inputPollScanline = 241; 680 681 int32_t _nsfAutoDetectSilenceDelay = 3000; 682 int32_t _nsfMoveToNextTrackTime = 120; 683 bool _nsfDisableApuIrqs = true; 684 685 InputDisplaySettings _inputDisplaySettings = { 0, InputDisplayPosition::TopLeft, false }; 686 687 uint32_t _autoSaveDelay = 5; 688 bool _autoSaveNotify = false; 689 690 bool _keyboardModeEnabled = false; 691 692 std::unordered_map<uint32_t, KeyCombination> _emulatorKeys[3]; 693 std::unordered_map<uint32_t, vector<KeyCombination>> _shortcutSupersets[3]; 694 695 RamPowerOnState _ramPowerOnState = RamPowerOnState::AllZeros; 696 uint32_t _dipSwitches = 0; 697 698 public: EmulationSettings()699 EmulationSettings() 700 { 701 memcpy(_userPalette, _ppuPaletteArgb, sizeof(_userPalette)); 702 } 703 GetMesenVersion()704 static uint32_t GetMesenVersion() 705 { 706 return (_versionMajor << 16) | (_versionMinor << 8) | _versionRevision; 707 } 708 GetMesenVersionString()709 static string GetMesenVersionString() 710 { 711 return std::to_string(_versionMajor) + "." + std::to_string(_versionMinor) + "." + std::to_string(_versionRevision); 712 } 713 SetFlags(uint64_t flags)714 void SetFlags(uint64_t flags) 715 { 716 if((_flags & flags) != flags) { 717 //Need a lock to prevent flag changes from being ignored due to multithreaded access 718 LockHandler lock = _lock.AcquireSafe(); 719 _flags |= flags; 720 721 _backgroundEnabled = !CheckFlag(EmulationFlags::DisableBackground); 722 _spritesEnabled = !CheckFlag(EmulationFlags::DisableSprites); 723 if(flags & EmulationFlags::UseCustomVsPalette) { 724 UpdateCurrentPalette(); 725 } 726 } 727 } 728 SetFlagState(EmulationFlags flag,bool enabled)729 void SetFlagState(EmulationFlags flag, bool enabled) 730 { 731 if(enabled) { 732 SetFlags(flag); 733 } else { 734 ClearFlags(flag); 735 } 736 } 737 ClearFlags(uint64_t flags)738 void ClearFlags(uint64_t flags) 739 { 740 if((_flags & flags) != 0) { 741 //Need a lock to prevent flag changes from being ignored due to multithreaded access 742 LockHandler lock = _lock.AcquireSafe(); 743 _flags &= ~flags; 744 745 _backgroundEnabled = !CheckFlag(EmulationFlags::DisableBackground); 746 _spritesEnabled = !CheckFlag(EmulationFlags::DisableSprites); 747 if(flags & EmulationFlags::UseCustomVsPalette) { 748 UpdateCurrentPalette(); 749 } 750 } 751 } 752 CheckFlag(EmulationFlags flag)753 bool CheckFlag(EmulationFlags flag) 754 { 755 return (_flags & flag) == flag; 756 } 757 SetDisplayLanguage(Language lang)758 static void SetDisplayLanguage(Language lang) 759 { 760 _displayLanguage = lang; 761 } 762 GetDisplayLanguage()763 static Language GetDisplayLanguage() 764 { 765 return _displayLanguage; 766 } 767 NeedsPause()768 bool NeedsPause() 769 { 770 return CheckFlag(EmulationFlags::Paused) && !CheckFlag(EmulationFlags::DebuggerWindowEnabled); 771 } 772 InputEnabled()773 bool InputEnabled() 774 { 775 return !CheckFlag(EmulationFlags::InBackground) || CheckFlag(EmulationFlags::AllowBackgroundInput); 776 } 777 SetNesModel(NesModel model)778 void SetNesModel(NesModel model) 779 { 780 _model = model; 781 } 782 GetNesModel()783 NesModel GetNesModel() 784 { 785 return _model; 786 } 787 SetPpuModel(PpuModel ppuModel)788 void SetPpuModel(PpuModel ppuModel) 789 { 790 _ppuModel = ppuModel; 791 UpdateCurrentPalette(); 792 } 793 GetPpuModel()794 PpuModel GetPpuModel() 795 { 796 return _ppuModel; 797 } 798 UpdateCurrentPalette()799 void UpdateCurrentPalette() 800 { 801 if(CheckFlag(EmulationFlags::UseCustomVsPalette)) { 802 for(int i = 0; i < 64; i++) { 803 for(int j = 0; j < 8; j++) { 804 _currentPalette[(j << 6) | i] = _userPalette[(j << 6) | (_paletteLut[(int)_ppuModel][i])]; 805 } 806 } 807 } else if(_ppuModel == PpuModel::Ppu2C02) { 808 memcpy(_currentPalette, _userPalette, sizeof(_userPalette)); 809 } else { 810 memcpy(_currentPalette, _ppuPaletteArgb[(int)_ppuModel], sizeof(_ppuPaletteArgb[0])); 811 GenerateFullColorPalette(_currentPalette); 812 } 813 } 814 GetRgbPalette()815 uint32_t* GetRgbPalette() 816 { 817 return _currentPalette; 818 } 819 GetUserRgbPalette(uint32_t * paletteBuffer)820 void GetUserRgbPalette(uint32_t* paletteBuffer) 821 { 822 memcpy(paletteBuffer, _userPalette, sizeof(_userPalette)); 823 } 824 825 void SetUserRgbPalette(uint32_t* paletteBuffer, uint32_t size = 64) 826 { 827 if(size != 64 && size != 512) { 828 throw new std::runtime_error("Invalid palette buffer size"); 829 } 830 831 memcpy(_userPalette, paletteBuffer, size * sizeof(uint32_t)); 832 if(size == 64) { 833 GenerateFullColorPalette(_userPalette); 834 } 835 _isFullColorPalette = (size == 512); 836 UpdateCurrentPalette(); 837 } 838 IsFullColorPalette()839 bool IsFullColorPalette() 840 { 841 return _isFullColorPalette; 842 } 843 GenerateFullColorPalette(uint32_t * paletteBuffer)844 void GenerateFullColorPalette(uint32_t* paletteBuffer) 845 { 846 for(int i = 0; i < 64; i++) { 847 for(int j = 1; j < 8; j++) { 848 double redColor = (uint8_t)(paletteBuffer[i] >> 16); 849 double greenColor = (uint8_t)(paletteBuffer[i] >> 8); 850 double blueColor = (uint8_t)paletteBuffer[i]; 851 if(j & 0x01) { 852 //Intensify red 853 redColor *= 1.1; 854 greenColor *= 0.9; 855 blueColor *= 0.9; 856 } 857 if(j & 0x02) { 858 //Intensify green 859 greenColor *= 1.1; 860 redColor *= 0.9; 861 blueColor *= 0.9; 862 } 863 if(j & 0x04) { 864 //Intensify blue 865 blueColor *= 1.1; 866 redColor *= 0.9; 867 greenColor *= 0.9; 868 } 869 870 uint8_t r = (uint8_t)(redColor > 255 ? 255 : redColor); 871 uint8_t g = (uint8_t)(greenColor > 255 ? 255 : greenColor); 872 uint8_t b = (uint8_t)(blueColor > 255 ? 255 : blueColor); 873 874 uint32_t color = 0xFF000000 | (r << 16) | (g << 8) | b; 875 paletteBuffer[(j << 6) | i] = color; 876 } 877 } 878 } 879 880 //0: Muted, 0.5: Default, 1.0: Max volume SetChannelVolume(AudioChannel channel,double volume)881 void SetChannelVolume(AudioChannel channel, double volume) 882 { 883 _channelVolume[(int)channel] = volume; 884 _audioSettingsChanged = true; 885 } 886 887 void SetMasterVolume(double volume, double volumeReduction = -1.0) 888 { 889 _masterVolume = volume; 890 if(volumeReduction >= 0) { 891 _volumeReduction = volumeReduction; 892 } 893 _audioSettingsChanged = true; 894 } 895 SetChannelPanning(AudioChannel channel,double panning)896 void SetChannelPanning(AudioChannel channel, double panning) 897 { 898 _channelPanning[(int)channel] = panning; 899 _audioSettingsChanged = true; 900 } 901 GetBandGains()902 vector<double> GetBandGains() 903 { 904 auto lock = _equalizerLock.AcquireSafe(); 905 return _bandGains; 906 } 907 SetBandGain(int band,double gain)908 void SetBandGain(int band, double gain) 909 { 910 auto lock = _equalizerLock.AcquireSafe(); 911 if(band < (int)_bandGains.size()) { 912 _bandGains[band] = gain; 913 _audioSettingsChanged = true; 914 } 915 } 916 GetEqualizerBands()917 vector<double> GetEqualizerBands() 918 { 919 auto lock = _equalizerLock.AcquireSafe(); 920 return _bands; 921 } 922 SetEqualizerBands(double * bands,uint32_t bandCount)923 void SetEqualizerBands(double *bands, uint32_t bandCount) 924 { 925 auto lock = _equalizerLock.AcquireSafe(); 926 _bands.clear(); 927 _bandGains.clear(); 928 for(uint32_t i = 0; i < bandCount; i++) { 929 _bands.push_back(bands[i]); 930 _bandGains.push_back(0); 931 } 932 } 933 GetEqualizerFilterType()934 EqualizerFilterType GetEqualizerFilterType() 935 { 936 return _equalizerFilterType; 937 } 938 SetEqualizerFilterType(EqualizerFilterType filter)939 void SetEqualizerFilterType(EqualizerFilterType filter) 940 { 941 _equalizerFilterType = filter; 942 _audioSettingsChanged = true; 943 } 944 SetSampleRate(uint32_t sampleRate)945 void SetSampleRate(uint32_t sampleRate) 946 { 947 _sampleRate = sampleRate; 948 _audioSettingsChanged = true; 949 } 950 GetSampleRate()951 uint32_t GetSampleRate() 952 { 953 return _sampleRate; 954 } 955 SetAudioLatency(uint32_t msLatency)956 void SetAudioLatency(uint32_t msLatency) 957 { 958 _audioLatency = msLatency; 959 _audioSettingsChanged = true; 960 } 961 SetAudioFilterSettings(AudioFilterSettings settings)962 void SetAudioFilterSettings(AudioFilterSettings settings) 963 { 964 _audioFilterSettings = settings; 965 _audioSettingsChanged = true; 966 } 967 GetAudioFilterSettings()968 AudioFilterSettings GetAudioFilterSettings() 969 { 970 return _audioFilterSettings; 971 } 972 NeedAudioSettingsUpdate()973 bool NeedAudioSettingsUpdate() 974 { 975 bool value = _audioSettingsChanged; 976 if(value) { 977 _audioSettingsChanged = false; 978 } 979 return value; 980 } 981 982 //0: No limit, Number: % of default speed (50/60fps) 983 void SetEmulationSpeed(uint32_t emulationSpeed, bool displaySpeed = false) 984 { 985 if(_emulationSpeed != emulationSpeed) { 986 _emulationSpeed = emulationSpeed; 987 if(displaySpeed) { 988 MessageManager::DisplayMessage("EmulationSpeed", _emulationSpeed == 0 ? "EmulationMaximumSpeed" : "EmulationSpeedPercent", std::to_string(_emulationSpeed)); 989 } 990 } 991 } 992 IncreaseEmulationSpeed()993 void IncreaseEmulationSpeed() 994 { 995 if(_emulationSpeed == _speedValues.back()) { 996 SetEmulationSpeed(0, true); 997 } else if(_emulationSpeed != 0) { 998 for(size_t i = 0; i < _speedValues.size(); i++) { 999 if(_speedValues[i] > _emulationSpeed) { 1000 SetEmulationSpeed(_speedValues[i], true); 1001 break; 1002 } 1003 } 1004 } 1005 } 1006 DecreaseEmulationSpeed()1007 void DecreaseEmulationSpeed() 1008 { 1009 if(_emulationSpeed == 0) { 1010 SetEmulationSpeed(_speedValues.back(), true); 1011 } else if(_emulationSpeed > _speedValues.front()) { 1012 for(int i = (int)_speedValues.size() - 1; i >= 0; i--) { 1013 if(_speedValues[i] < _emulationSpeed) { 1014 SetEmulationSpeed(_speedValues[i], true); 1015 break; 1016 } 1017 } 1018 } 1019 } 1020 SetTurboRewindSpeed(uint32_t turboSpeed,uint32_t rewindSpeed)1021 void SetTurboRewindSpeed(uint32_t turboSpeed, uint32_t rewindSpeed) 1022 { 1023 _turboSpeed = turboSpeed; 1024 _rewindSpeed = rewindSpeed; 1025 } 1026 GetRewindSpeed()1027 uint32_t GetRewindSpeed() 1028 { 1029 return _rewindSpeed; 1030 } 1031 SetRewindBufferSize(uint32_t seconds)1032 void SetRewindBufferSize(uint32_t seconds) 1033 { 1034 _rewindBufferSize = seconds; 1035 } 1036 GetRewindBufferSize()1037 uint32_t GetRewindBufferSize() 1038 { 1039 return _rewindBufferSize; 1040 } 1041 1042 uint32_t GetEmulationSpeed(bool ignoreTurbo = false); 1043 UpdateEffectiveOverclockRate()1044 void UpdateEffectiveOverclockRate() 1045 { 1046 if(_disableOverclocking) { 1047 _effectiveOverclockRate = 100; 1048 } else { 1049 _effectiveOverclockRate = _overclockRate; 1050 } 1051 _hasOverclock = _effectiveOverclockRate != 100; 1052 _audioSettingsChanged = true; 1053 } 1054 DisableOverclocking(bool disabled)1055 void DisableOverclocking(bool disabled) 1056 { 1057 if(_disableOverclocking != disabled) { 1058 _disableOverclocking = disabled; 1059 UpdateEffectiveOverclockRate(); 1060 } 1061 } 1062 GetOverclockRateSetting()1063 uint32_t GetOverclockRateSetting() 1064 { 1065 return _overclockRate; 1066 } 1067 HasOverclock()1068 bool HasOverclock() 1069 { 1070 return _hasOverclock; 1071 } 1072 GetOverclockRate()1073 double GetOverclockRate() 1074 { 1075 return _effectiveOverclockRate; 1076 } 1077 GetOverclockAdjustApu()1078 bool GetOverclockAdjustApu() 1079 { 1080 return _overclockAdjustApu; 1081 } 1082 SetOverclockRate(uint32_t overclockRate,bool adjustApu)1083 void SetOverclockRate(uint32_t overclockRate, bool adjustApu) 1084 { 1085 if(_overclockRate != overclockRate || _overclockAdjustApu != adjustApu) { 1086 _overclockRate = overclockRate; 1087 _overclockAdjustApu = adjustApu; 1088 1089 UpdateEffectiveOverclockRate(); 1090 1091 MessageManager::DisplayMessage("ClockRate", std::to_string((uint32_t)GetOverclockRate()) + "%"); 1092 } 1093 } 1094 GetPpuExtraScanlinesBeforeNmi()1095 uint32_t GetPpuExtraScanlinesBeforeNmi() 1096 { 1097 return _disableOverclocking ? 0 : _extraScanlinesBeforeNmi; 1098 } 1099 GetPpuExtraScanlinesAfterNmi()1100 uint32_t GetPpuExtraScanlinesAfterNmi() 1101 { 1102 return _disableOverclocking ? 0 : _extraScanlinesAfterNmi; 1103 } 1104 SetPpuNmiConfig(uint32_t extraScanlinesBeforeNmi,uint32_t extraScanlinesAfterNmi)1105 void SetPpuNmiConfig(uint32_t extraScanlinesBeforeNmi, uint32_t extraScanlinesAfterNmi) 1106 { 1107 if(_extraScanlinesBeforeNmi != extraScanlinesBeforeNmi || _extraScanlinesAfterNmi != extraScanlinesAfterNmi) { 1108 if(extraScanlinesBeforeNmi > 0 || extraScanlinesAfterNmi > 0) { 1109 MessageManager::DisplayMessage("PPU", "ScanlineTimingWarning"); 1110 } 1111 1112 _extraScanlinesBeforeNmi = extraScanlinesBeforeNmi; 1113 _extraScanlinesAfterNmi = extraScanlinesAfterNmi; 1114 1115 UpdateEffectiveOverclockRate(); 1116 } 1117 } 1118 SetOverscanDimensions(uint8_t left,uint8_t right,uint8_t top,uint8_t bottom)1119 void SetOverscanDimensions(uint8_t left, uint8_t right, uint8_t top, uint8_t bottom) 1120 { 1121 if(_overscan.Left != left || _overscan.Right != right || _overscan.Top != top || _overscan.Bottom != bottom) { 1122 _overscan.Left = left; 1123 _overscan.Right = right; 1124 _overscan.Top = top; 1125 _overscan.Bottom = bottom; 1126 } 1127 } 1128 GetOverscanDimensions()1129 OverscanDimensions GetOverscanDimensions() 1130 { 1131 return _overscan; 1132 } 1133 GetChannelVolume(AudioChannel channel)1134 double GetChannelVolume(AudioChannel channel) 1135 { 1136 return _channelVolume[(int)channel]; 1137 } 1138 GetMasterVolume()1139 double GetMasterVolume() 1140 { 1141 return _masterVolume; 1142 } 1143 GetVolumeReduction()1144 double GetVolumeReduction() 1145 { 1146 return _volumeReduction; 1147 } 1148 GetChannelPanning(AudioChannel channel)1149 double GetChannelPanning(AudioChannel channel) 1150 { 1151 return _channelPanning[(int)channel]; 1152 } 1153 GetAudioLatency()1154 uint32_t GetAudioLatency() 1155 { 1156 return _audioLatency; 1157 } 1158 SetVideoFilterType(VideoFilterType videoFilterType)1159 void SetVideoFilterType(VideoFilterType videoFilterType) 1160 { 1161 _videoFilterType = videoFilterType; 1162 } 1163 GetVideoFilterType()1164 VideoFilterType GetVideoFilterType() 1165 { 1166 return _videoFilterType; 1167 } 1168 SetVideoResizeFilter(VideoResizeFilter videoResizeFilter)1169 void SetVideoResizeFilter(VideoResizeFilter videoResizeFilter) 1170 { 1171 _resizeFilter = videoResizeFilter; 1172 } 1173 GetVideoResizeFilter()1174 VideoResizeFilter GetVideoResizeFilter() 1175 { 1176 return _resizeFilter; 1177 } 1178 SetVideoAspectRatio(VideoAspectRatio aspectRatio,double customRatio)1179 void SetVideoAspectRatio(VideoAspectRatio aspectRatio, double customRatio) 1180 { 1181 _aspectRatio = aspectRatio; 1182 _customAspectRatio = customRatio; 1183 } 1184 GetBackgroundEnabled()1185 bool GetBackgroundEnabled() 1186 { 1187 return _backgroundEnabled; 1188 } 1189 GetSpritesEnabled()1190 bool GetSpritesEnabled() 1191 { 1192 return _spritesEnabled; 1193 } 1194 SetPictureSettings(double brightness,double contrast,double saturation,double hue,double scanlineIntensity)1195 void SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity) 1196 { 1197 _pictureSettings.Brightness = brightness; 1198 _pictureSettings.Contrast = contrast; 1199 _pictureSettings.Saturation = saturation; 1200 _pictureSettings.Hue = hue; 1201 _pictureSettings.ScanlineIntensity = scanlineIntensity; 1202 } 1203 GetPictureSettings()1204 PictureSettings GetPictureSettings() 1205 { 1206 return _pictureSettings; 1207 } 1208 SetNtscFilterSettings(double artifacts,double bleed,double fringing,double gamma,double resolution,double sharpness,bool mergeFields,double yFilterLength,double iFilterLength,double qFilterLength,bool verticalBlend,bool keepVerticalResolution)1209 void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, bool verticalBlend, bool keepVerticalResolution) 1210 { 1211 _ntscFilterSettings.Artifacts = artifacts; 1212 _ntscFilterSettings.Bleed = bleed; 1213 _ntscFilterSettings.Fringing = fringing; 1214 _ntscFilterSettings.Gamma = gamma; 1215 _ntscFilterSettings.Resolution = resolution; 1216 _ntscFilterSettings.Sharpness = sharpness; 1217 1218 _ntscFilterSettings.MergeFields = mergeFields; 1219 1220 _ntscFilterSettings.YFilterLength = yFilterLength; 1221 _ntscFilterSettings.IFilterLength = iFilterLength; 1222 _ntscFilterSettings.QFilterLength = qFilterLength; 1223 1224 _ntscFilterSettings.VerticalBlend = verticalBlend; 1225 _ntscFilterSettings.KeepVerticalResolution = keepVerticalResolution; 1226 } 1227 GetNtscFilterSettings()1228 NtscFilterSettings GetNtscFilterSettings() 1229 { 1230 return _ntscFilterSettings; 1231 } 1232 1233 double GetAspectRatio(shared_ptr<Console> console); 1234 void InitializeInputDevices(GameInputType inputType, GameSystem system, bool silent); 1235 SetVideoScale(double scale)1236 void SetVideoScale(double scale) 1237 { 1238 if(_videoScale != scale) { 1239 _videoScale = scale; 1240 } 1241 } 1242 GetVideoScale()1243 double GetVideoScale() 1244 { 1245 return _videoScale; 1246 } 1247 SetScreenRotation(uint32_t angle)1248 void SetScreenRotation(uint32_t angle) 1249 { 1250 _screenRotation = angle; 1251 } 1252 GetScreenRotation()1253 uint32_t GetScreenRotation() 1254 { 1255 return _screenRotation; 1256 } 1257 SetExclusiveRefreshRate(uint32_t refreshRate)1258 void SetExclusiveRefreshRate(uint32_t refreshRate) 1259 { 1260 _exclusiveRefreshRate = refreshRate; 1261 } 1262 GetExclusiveRefreshRate()1263 uint32_t GetExclusiveRefreshRate() 1264 { 1265 return _exclusiveRefreshRate; 1266 } 1267 SetExpansionDevice(ExpansionPortDevice expansionDevice)1268 void SetExpansionDevice(ExpansionPortDevice expansionDevice) 1269 { 1270 _expansionDevice = expansionDevice; 1271 _needControllerUpdate = true; 1272 } 1273 GetExpansionDevice()1274 ExpansionPortDevice GetExpansionDevice() 1275 { 1276 return _expansionDevice; 1277 } 1278 SetConsoleType(ConsoleType type)1279 void SetConsoleType(ConsoleType type) 1280 { 1281 _consoleType = type; 1282 _needControllerUpdate = true; 1283 } 1284 GetConsoleType()1285 ConsoleType GetConsoleType() 1286 { 1287 return _consoleType; 1288 } 1289 SetControllerType(uint8_t port,ControllerType type)1290 void SetControllerType(uint8_t port, ControllerType type) 1291 { 1292 _controllerTypes[port] = type; 1293 _needControllerUpdate = true; 1294 } 1295 GetControllerType(uint8_t port)1296 ControllerType GetControllerType(uint8_t port) 1297 { 1298 return _controllerTypes[port]; 1299 } 1300 SetControllerKeys(uint8_t port,KeyMappingSet keyMappings)1301 void SetControllerKeys(uint8_t port, KeyMappingSet keyMappings) 1302 { 1303 _controllerKeys[port] = keyMappings; 1304 _needControllerUpdate = true; 1305 } 1306 GetControllerKeys(uint8_t port)1307 KeyMappingSet GetControllerKeys(uint8_t port) 1308 { 1309 return _controllerKeys[port]; 1310 } 1311 ClearShortcutKeys()1312 void ClearShortcutKeys() 1313 { 1314 auto lock = _shortcutLock.AcquireSafe(); 1315 _emulatorKeys[0].clear(); 1316 _emulatorKeys[1].clear(); 1317 _emulatorKeys[2].clear(); 1318 _shortcutSupersets[0].clear(); 1319 _shortcutSupersets[1].clear(); 1320 _shortcutSupersets[2].clear(); 1321 1322 //Add Alt-F4 as a fake shortcut to prevent Alt-F4 from triggering Alt or F4 key bindings. (e.g load save state 4) 1323 KeyCombination keyComb; 1324 keyComb.Key1 = KeyManager::GetKeyCode("Alt"); 1325 keyComb.Key2 = KeyManager::GetKeyCode("F4"); 1326 SetShortcutKey(EmulatorShortcut::Exit, keyComb, 2); 1327 } 1328 SetShortcutKey(EmulatorShortcut shortcut,KeyCombination keyCombination,int keySetIndex)1329 void SetShortcutKey(EmulatorShortcut shortcut, KeyCombination keyCombination, int keySetIndex) 1330 { 1331 auto lock = _shortcutLock.AcquireSafe(); 1332 _emulatorKeys[keySetIndex][(uint32_t)shortcut] = keyCombination; 1333 1334 for(int i = 0; i < 3; i++) { 1335 for(std::pair<const uint32_t, KeyCombination> &kvp : _emulatorKeys[i]) { 1336 if(keyCombination.IsSubsetOf(kvp.second)) { 1337 _shortcutSupersets[keySetIndex][(uint32_t)shortcut].push_back(kvp.second); 1338 } else if(kvp.second.IsSubsetOf(keyCombination)) { 1339 _shortcutSupersets[i][kvp.first].push_back(keyCombination); 1340 } 1341 } 1342 } 1343 } 1344 GetShortcutKey(EmulatorShortcut shortcut,int keySetIndex)1345 KeyCombination GetShortcutKey(EmulatorShortcut shortcut, int keySetIndex) 1346 { 1347 auto lock = _shortcutLock.AcquireSafe(); 1348 auto result = _emulatorKeys[keySetIndex].find((int)shortcut); 1349 if(result != _emulatorKeys[keySetIndex].end()) { 1350 return result->second; 1351 } 1352 return {}; 1353 } 1354 GetShortcutSupersets(EmulatorShortcut shortcut,int keySetIndex)1355 vector<KeyCombination> GetShortcutSupersets(EmulatorShortcut shortcut, int keySetIndex) 1356 { 1357 auto lock = _shortcutLock.AcquireSafe(); 1358 return _shortcutSupersets[keySetIndex][(uint32_t)shortcut]; 1359 } 1360 NeedControllerUpdate()1361 bool NeedControllerUpdate() 1362 { 1363 if(_needControllerUpdate) { 1364 _needControllerUpdate = false; 1365 return true; 1366 } else { 1367 return false; 1368 } 1369 } 1370 SetMouseSensitivity(MouseDevice device,double sensitivity)1371 void SetMouseSensitivity(MouseDevice device, double sensitivity) 1372 { 1373 _mouseSensitivity[(int)device] = sensitivity; 1374 } 1375 GetMouseSensitivity(MouseDevice device)1376 double GetMouseSensitivity(MouseDevice device) 1377 { 1378 auto result = _mouseSensitivity.find((int)device); 1379 if(result != _mouseSensitivity.end()) { 1380 return result->second; 1381 } else { 1382 return 1.0; 1383 } 1384 } 1385 SetControllerDeadzoneSize(uint32_t deadzoneSize)1386 void SetControllerDeadzoneSize(uint32_t deadzoneSize) 1387 { 1388 _controllerDeadzoneSize = deadzoneSize; 1389 } 1390 GetControllerDeadzoneRatio()1391 double GetControllerDeadzoneRatio() 1392 { 1393 switch(_controllerDeadzoneSize) { 1394 case 0: return 0.5; 1395 case 1: return 0.75; 1396 case 2: return 1; 1397 case 3: return 1.25; 1398 case 4: return 1.5; 1399 } 1400 return 1; 1401 } 1402 SetZapperDetectionRadius(uint32_t detectionRadius)1403 void SetZapperDetectionRadius(uint32_t detectionRadius) 1404 { 1405 _zapperDetectionRadius = detectionRadius; 1406 } 1407 GetZapperDetectionRadius()1408 uint32_t GetZapperDetectionRadius() 1409 { 1410 return _zapperDetectionRadius; 1411 } 1412 SetInputPollScanline(int32_t scanline)1413 void SetInputPollScanline(int32_t scanline) 1414 { 1415 _inputPollScanline = scanline; 1416 } 1417 GetInputPollScanline()1418 int32_t GetInputPollScanline() 1419 { 1420 return _inputPollScanline; 1421 } 1422 HasZapper()1423 bool HasZapper() 1424 { 1425 return _controllerTypes[0] == ControllerType::Zapper || _controllerTypes[1] == ControllerType::Zapper || (_consoleType == ConsoleType::Famicom && _expansionDevice == ExpansionPortDevice::Zapper); 1426 } 1427 HasArkanoidPaddle()1428 bool HasArkanoidPaddle() 1429 { 1430 return _controllerTypes[0] == ControllerType::ArkanoidController || _controllerTypes[1] == ControllerType::ArkanoidController || (_consoleType == ConsoleType::Famicom && _expansionDevice == ExpansionPortDevice::ArkanoidController); 1431 } 1432 SetNsfConfig(int32_t autoDetectSilence,int32_t moveToNextTrackTime,bool disableApuIrqs)1433 void SetNsfConfig(int32_t autoDetectSilence, int32_t moveToNextTrackTime, bool disableApuIrqs) 1434 { 1435 _nsfAutoDetectSilenceDelay = autoDetectSilence; 1436 _nsfMoveToNextTrackTime = moveToNextTrackTime; 1437 _nsfDisableApuIrqs = disableApuIrqs; 1438 } 1439 GetNsfAutoDetectSilenceDelay()1440 int32_t GetNsfAutoDetectSilenceDelay() 1441 { 1442 return _nsfAutoDetectSilenceDelay; 1443 } 1444 GetNsfMoveToNextTrackTime()1445 int32_t GetNsfMoveToNextTrackTime() 1446 { 1447 return _nsfMoveToNextTrackTime; 1448 } 1449 GetNsfDisableApuIrqs()1450 bool GetNsfDisableApuIrqs() 1451 { 1452 return _nsfDisableApuIrqs; 1453 } 1454 SetInputDisplaySettings(uint8_t visiblePorts,InputDisplayPosition displayPosition,bool displayHorizontally)1455 void SetInputDisplaySettings(uint8_t visiblePorts, InputDisplayPosition displayPosition, bool displayHorizontally) 1456 { 1457 _inputDisplaySettings = { visiblePorts, displayPosition, displayHorizontally }; 1458 } 1459 GetInputDisplaySettings()1460 InputDisplaySettings GetInputDisplaySettings() 1461 { 1462 return _inputDisplaySettings; 1463 } 1464 SetRamPowerOnState(RamPowerOnState state)1465 void SetRamPowerOnState(RamPowerOnState state) 1466 { 1467 _ramPowerOnState = state; 1468 } 1469 GetRamPowerOnState()1470 RamPowerOnState GetRamPowerOnState() 1471 { 1472 return _ramPowerOnState; 1473 } 1474 SetAutoSaveOptions(uint32_t delayInMinutes,bool showMessage)1475 void SetAutoSaveOptions(uint32_t delayInMinutes, bool showMessage) 1476 { 1477 _autoSaveDelay = delayInMinutes; 1478 _autoSaveNotify = showMessage; 1479 } 1480 GetAutoSaveDelay(bool & showMessage)1481 uint32_t GetAutoSaveDelay(bool &showMessage) 1482 { 1483 showMessage = _autoSaveNotify; 1484 return _autoSaveDelay; 1485 } 1486 SetDipSwitches(uint32_t dipSwitches)1487 void SetDipSwitches(uint32_t dipSwitches) 1488 { 1489 _dipSwitches = dipSwitches; 1490 } 1491 GetDipSwitches()1492 uint32_t GetDipSwitches() 1493 { 1494 return _dipSwitches; 1495 } 1496 IsKeyboardMode()1497 bool IsKeyboardMode() 1498 { 1499 return _keyboardModeEnabled; 1500 } 1501 EnableKeyboardMode()1502 void EnableKeyboardMode() 1503 { 1504 if(!_keyboardModeEnabled) { 1505 _keyboardModeEnabled = true; 1506 MessageManager::DisplayMessage("Input", "KeyboardModeEnabled"); 1507 } 1508 } 1509 DisableKeyboardMode()1510 void DisableKeyboardMode() 1511 { 1512 if(_keyboardModeEnabled) { 1513 _keyboardModeEnabled = false; 1514 MessageManager::DisplayMessage("Input", "KeyboardModeDisabled"); 1515 } 1516 } 1517 SetPauseScreenMessage(string message)1518 void SetPauseScreenMessage(string message) 1519 { 1520 _pauseScreenMessage = message; 1521 } 1522 GetPauseScreenMessage()1523 string GetPauseScreenMessage() 1524 { 1525 return _pauseScreenMessage; 1526 } 1527 }; 1528