diff --git a/Core/BaseControlDevice.cpp b/Core/BaseControlDevice.cpp new file mode 100644 index 00000000..55b9b0dd --- /dev/null +++ b/Core/BaseControlDevice.cpp @@ -0,0 +1,80 @@ +#include "stdafx.h" +#include "BaseControlDevice.h" +#include "ControlManager.h" +#include "Movie.h" +#include "EmulationSettings.h" +#include "GameClient.h" +#include "GameServerConnection.h" + +BaseControlDevice::BaseControlDevice(uint8_t port) +{ + _port = port; + _famiconDevice = EmulationSettings::GetConsoleType() == ConsoleType::Famicom; + if(EmulationSettings::GetControllerType(port) == ControllerType::StandardController) { + AddKeyMappings(EmulationSettings::GetControllerKeys(port)); + } +} + +BaseControlDevice::~BaseControlDevice() +{ +} + +void BaseControlDevice::StreamState(bool saving) +{ + Stream(_currentState); +} + +uint8_t BaseControlDevice::GetPort() +{ + return _port; +} + +void BaseControlDevice::AddKeyMappings(KeyMappingSet keyMappings) +{ + if(keyMappings.Mapping1.HasKeySet()) { + _keyMappings.push_back(keyMappings.Mapping1); + } + if(keyMappings.Mapping2.HasKeySet()) { + _keyMappings.push_back(keyMappings.Mapping2); + } + if(keyMappings.Mapping3.HasKeySet()) { + _keyMappings.push_back(keyMappings.Mapping3); + } + if(keyMappings.Mapping4.HasKeySet()) { + _keyMappings.push_back(keyMappings.Mapping4); + } + _turboSpeed = keyMappings.TurboSpeed; +} + +void BaseControlDevice::RefreshStateBuffer() +{ + //Do nothing by default - used by standard controllers and some others +} + +uint8_t BaseControlDevice::ProcessNetPlayState(uint32_t netplayState) +{ + return netplayState; +} + +uint8_t BaseControlDevice::GetControlState() +{ + GameServerConnection* netPlayDevice = nullptr; + if(Movie::Playing()) { + _currentState = Movie::GetInstance()->GetState(_port); + } else if(GameClient::Connected()) { + _currentState = GameClient::GetControllerState(_port); + } else if(netPlayDevice = GameServerConnection::GetNetPlayDevice(_port)) { + _currentState = ProcessNetPlayState(netPlayDevice->GetState()); + } else { + _currentState = RefreshState(); + } + + if(Movie::Recording()) { + Movie::GetInstance()->RecordState(_port, _currentState); + } + + //For NetPlay + ControlManager::BroadcastInput(_port, _currentState); + + return _currentState; +} \ No newline at end of file diff --git a/Core/BaseControlDevice.h b/Core/BaseControlDevice.h new file mode 100644 index 00000000..45a604a9 --- /dev/null +++ b/Core/BaseControlDevice.h @@ -0,0 +1,58 @@ +#pragma once + +#include "stdafx.h" +#include "EmulationSettings.h" +#include "Snapshotable.h" + +struct ButtonState +{ + bool Up = false; + bool Down = false; + bool Left = false; + bool Right = false; + + bool A = false; + bool B = false; + + bool Select = false; + bool Start = false; + + uint8_t ToByte() + { + //"Button status for each controller is returned as an 8-bit report in the following order: A, B, Select, Start, Up, Down, Left, Right." + return (uint8_t)A | ((uint8_t)B << 1) | ((uint8_t)Select << 2) | ((uint8_t)Start << 3) | + ((uint8_t)Up << 4) | ((uint8_t)Down << 5) | ((uint8_t)Left << 6) | ((uint8_t)Right << 7); + } +}; + +class BaseControlDevice : public Snapshotable +{ +protected: + uint8_t _port; + uint8_t _currentState; + vector _keyMappings; + uint32_t _turboSpeed = 0; + bool _famiconDevice = false; + + uint8_t GetPort(); + void AddKeyMappings(KeyMappingSet keyMappings); + + //Defined in controller-specific code and called when we need to read a device's state + virtual uint8_t RefreshState() = 0; + virtual uint8_t ProcessNetPlayState(uint32_t netplayState); + + virtual void StreamState(bool saving); + +public: + //Used by controller-specific code to get the current state (buttons, position, etc) + uint8_t GetControlState(); + + BaseControlDevice(uint8_t port); + virtual ~BaseControlDevice(); + + //Called when reading $4016/7 + virtual uint8_t GetPortOutput() = 0; + + //Used by standard controllers when $4017.1 is set + virtual void RefreshStateBuffer(); +}; \ No newline at end of file diff --git a/Core/Console.cpp b/Core/Console.cpp index 9168af1a..b983274a 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -230,7 +230,7 @@ void Console::Run() _runLock.Acquire(); } - bool paused = EmulationSettings::CheckFlag(EmulationFlags::Paused) || (EmulationSettings::CheckFlag(EmulationFlags::InBackground) && EmulationSettings::CheckFlag(EmulationFlags::PauseWhenInBackground)); + bool paused = EmulationSettings::IsPaused(); if(paused && !_stop) { MessageManager::SendNotification(ConsoleNotificationType::GamePaused); _runLock.Release(); @@ -241,7 +241,7 @@ void Console::Run() while(paused) { //Sleep until emulation is resumed std::this_thread::sleep_for(std::chrono::duration(100)); - paused = EmulationSettings::CheckFlag(EmulationFlags::Paused) || (EmulationSettings::CheckFlag(EmulationFlags::InBackground) && EmulationSettings::CheckFlag(EmulationFlags::PauseWhenInBackground)); + paused = EmulationSettings::IsPaused(); } _runLock.Acquire(); MessageManager::SendNotification(ConsoleNotificationType::GameResumed); @@ -276,11 +276,21 @@ void Console::Run() double Console::UpdateNesModel() { + bool configChanged = false; + if(EmulationSettings::NeedControllerUpdate()) { + _controlManager->UpdateControlDevices(); + configChanged = true; + } + NesModel model = EmulationSettings::GetNesModel(); uint32_t emulationSpeed = EmulationSettings::GetEmulationSpeed(); if(model == NesModel::Auto) { model = _mapper->IsPalRom() ? NesModel::PAL : NesModel::NTSC; } + if(_model != model) { + _model = model; + configChanged = true; + } double frameDelay; if(emulationSpeed == 0) { @@ -298,6 +308,10 @@ double Console::UpdateNesModel() _ppu->SetNesModel(model); _apu->SetNesModel(model); + if(configChanged) { + MessageManager::SendNotification(ConsoleNotificationType::ConfigChanged); + } + return frameDelay; } @@ -346,4 +360,9 @@ std::weak_ptr Console::GetDebugger() void Console::StopDebugger() { _debugger.reset(); +} + +NesModel Console::GetNesModel() +{ + return Instance->_model; } \ No newline at end of file diff --git a/Core/Console.h b/Core/Console.h index 3dd61887..79926b7d 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -27,6 +27,8 @@ class Console unique_ptr _controlManager; shared_ptr _memoryManager; + NesModel _model; + string _romFilepath; bool _stop = false; @@ -54,6 +56,7 @@ class Console std::weak_ptr GetDebugger(); void StopDebugger(); + static NesModel GetNesModel(); static void SaveState(ostream &saveStream); static void LoadState(istream &loadStream); static void LoadState(uint8_t *buffer, uint32_t bufferSize); diff --git a/Core/ControlManager.cpp b/Core/ControlManager.cpp index 0990a5f7..319905e2 100644 --- a/Core/ControlManager.cpp +++ b/Core/ControlManager.cpp @@ -1,12 +1,14 @@ #include "stdafx.h" #include "ControlManager.h" +#include "StandardController.h" +#include "Zapper.h" +#include "EmulationSettings.h" +#include "Console.h" +#include "GameServerConnection.h" unique_ptr ControlManager::_keyManager = nullptr; - -IControlDevice* ControlManager::ControlDevices[] = { nullptr, nullptr, nullptr, nullptr }; -IControlDevice* ControlManager::OriginalControlDevices[] = { nullptr, nullptr, nullptr, nullptr }; -IGameBroadcaster* ControlManager::GameBroadcaster = nullptr; -SimpleLock ControlManager::ControllerLock[4]; +shared_ptr ControlManager::_controlDevices[2]; +IGameBroadcaster* ControlManager::_gameBroadcaster = nullptr; ControlManager::ControlManager() { @@ -52,154 +54,110 @@ uint32_t ControlManager::GetKeyCode(string keyName) void ControlManager::RegisterBroadcaster(IGameBroadcaster* gameBroadcaster) { - ControlManager::GameBroadcaster = gameBroadcaster; + ControlManager::_gameBroadcaster = gameBroadcaster; } void ControlManager::UnregisterBroadcaster(IGameBroadcaster* gameBroadcaster) { - if(ControlManager::GameBroadcaster == gameBroadcaster) { - ControlManager::GameBroadcaster = nullptr; + if(ControlManager::_gameBroadcaster == gameBroadcaster) { + ControlManager::_gameBroadcaster = nullptr; } } -void ControlManager::BackupControlDevices() +void ControlManager::BroadcastInput(uint8_t port, uint8_t state) { - for(int i = 0; i < 4; i++) { - OriginalControlDevices[i] = ControlDevices[i]; + if(ControlManager::_gameBroadcaster) { + //Used when acting as a game server + ControlManager::_gameBroadcaster->BroadcastInput(state, port); } } -void ControlManager::RestoreControlDevices() +shared_ptr ControlManager::GetControlDevice(uint8_t port) { - for(int i = 0; i < 4; i++) { - ControlManager::ControllerLock[i].Acquire(); - ControlDevices[i] = OriginalControlDevices[i]; - ControlManager::ControllerLock[i].Release(); - } + return ControlManager::_controlDevices[port]; } -IControlDevice* ControlManager::GetControlDevice(uint8_t port) +void ControlManager::RegisterControlDevice(shared_ptr controlDevice, uint8_t port) { - return ControlManager::ControlDevices[port]; + ControlManager::_controlDevices[port] = controlDevice; } -void ControlManager::RegisterControlDevice(IControlDevice* controlDevice, uint8_t port) +void ControlManager::UnregisterControlDevice(uint8_t port) { - ControlManager::ControllerLock[port].Acquire(); - ControlManager::ControlDevices[port] = controlDevice; - ControlManager::ControllerLock[port].Release(); -} - -void ControlManager::UnregisterControlDevice(IControlDevice* controlDevice) -{ - for(int i = 0; i < 4; i++) { - if(ControlManager::ControlDevices[i] == controlDevice) { - ControlManager::ControllerLock[i].Acquire(); - ControlManager::ControlDevices[i] = nullptr; - ControlManager::ControllerLock[i].Release(); - break; - } - } - + ControlManager::_controlDevices[port].reset(); } void ControlManager::RefreshAllPorts() { - RefreshStateBuffer(0); - RefreshStateBuffer(1); -} + if(_refreshState) { + if(_keyManager) { + _keyManager->RefreshState(); + } -uint8_t ControlManager::GetControllerState(uint8_t controllerID) -{ - ControlManager::ControllerLock[controllerID].Acquire(); - IControlDevice* controlDevice = ControlManager::ControlDevices[controllerID]; - - uint8_t state; - if(Movie::Playing()) { - state = Movie::Instance->GetState(controllerID); - } else { - if(controlDevice) { - if(_keyManager) { - _keyManager->RefreshState(); + for(int i = 0; i < 2; i++) { + if(ControlManager::_controlDevices[i]) { + ControlManager::_controlDevices[i]->RefreshStateBuffer(); } - state = controlDevice->GetButtonState().ToByte(); - } else { - state = 0x00; } } - ControlManager::ControllerLock[controllerID].Release(); - - //Used when recording movies - Movie::Instance->RecordState(controllerID, state); - - if(ControlManager::GameBroadcaster) { - //Used when acting as a game server - ControlManager::GameBroadcaster->BroadcastInput(state, controllerID); - } - - return state; } -bool ControlManager::HasFourScoreAdapter() +void ControlManager::UpdateControlDevices() { - //When a movie is playing, always assume 4 controllers are plugged in (TODO: Change this so movies know how many controllers were plugged when recording) - return ControlManager::ControlDevices[2] != nullptr || ControlManager::ControlDevices[3] != nullptr || Movie::Playing(); -} - -void ControlManager::RefreshStateBuffer(uint8_t port) -{ - if(port >= 2) { - throw std::runtime_error("Invalid port"); + bool fourScore = EmulationSettings::CheckFlag(EmulationFlags::HasFourScore); + if(EmulationSettings::GetConsoleType() == ConsoleType::Famicom && EmulationSettings::GetExpansionDevice() != ExpansionPortDevice::FourPlayerAdapter) { + fourScore = false; } - //First 8 bits : Gamepad 1/2 - uint32_t state = GetControllerState(port); - if(HasFourScoreAdapter()) { - //Next 8 bits = Gamepad 3/4 - state |= GetControllerState(port + 2) << 8; + for(int i = 0; i < 2; i++) { + shared_ptr device; + if(fourScore) { + //Need to set standard controller in all slots if four score (to allow emulation to work correctly) + device.reset(new StandardController(i)); + } else { + switch(EmulationSettings::GetControllerType(i)) { + case ControllerType::StandardController: device.reset(new StandardController(i)); break; + case ControllerType::Zapper: device.reset(new Zapper(i)); break; + } + } - //Last 8 bits = signature - //Signature for port 0 = 0x10, reversed bit order => 0x08 - //Signature for port 1 = 0x20, reversed bit order => 0x04 - state |= (port == 0 ? 0x08 : 0x04) << 16; - } else { - //"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers." - state |= 0xFFFF00; + if(device) { + ControlManager::RegisterControlDevice(device, i); + + if(fourScore) { + std::dynamic_pointer_cast(device)->AddAdditionalController(shared_ptr(new StandardController(i + 2))); + } else if(i == 1 && EmulationSettings::GetConsoleType() == ConsoleType::Famicom && EmulationSettings::GetExpansionDevice() == ExpansionPortDevice::Zapper) { + std::dynamic_pointer_cast(device)->AddAdditionalController(shared_ptr(new Zapper(2))); + } + } else { + //Remove current device if it's no longer in use + ControlManager::UnregisterControlDevice(i); + } } - - _stateBuffer[port] = state; } uint8_t ControlManager::GetPortValue(uint8_t port) { - if(port >= 2) { - throw std::runtime_error("Invalid port"); - } - if(_refreshState) { - RefreshStateBuffer(port); + RefreshAllPorts(); } - uint8_t returnValue = _stateBuffer[port] & 0x01; - _stateBuffer[port] >>= 1; - - //"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers." - _stateBuffer[port] |= 0x800000; - //"In the NES and Famicom, the top three (or five) bits are not driven, and so retain the bits of the previous byte on the bus. //Usually this is the most significant byte of the address of the controller port - 0x40. //Paperboy relies on this behavior and requires that reads from the controller ports return exactly $40 or $41 as appropriate." - return 0x40 | returnValue; + shared_ptr device = GetControlDevice(port); + if(device) { + return 0x40 | device->GetPortOutput(); + } else { + return 0x40; + } } uint8_t ControlManager::ReadRAM(uint16_t addr) { switch(addr) { - case 0x4016: - return GetPortValue(0); - - case 0x4017: - return GetPortValue(1); + case 0x4016: return GetPortValue(0); + case 0x4017: return GetPortValue(1); } return 0; @@ -207,19 +165,90 @@ uint8_t ControlManager::ReadRAM(uint16_t addr) void ControlManager::WriteRAM(uint16_t addr, uint8_t value) { - switch(addr) { - case 0x4016: - _refreshState = (value & 0x01) == 0x01; - if(_refreshState) { - RefreshAllPorts(); - } - break; + //$4016 writes + _refreshState = (value & 0x01) == 0x01; + if(_refreshState) { + RefreshAllPorts(); } - } void ControlManager::StreamState(bool saving) { - StreamArray(_stateBuffer, 2); Stream(_refreshState); + + //Restore controllers that were being used at the time the snapshot was made + //This is particularely important to ensure proper sync during NetPlay + ControllerType controllerTypes[4]; + NesModel nesModel; + ExpansionPortDevice expansionDevice; + ConsoleType consoleType; + if(saving) { + nesModel = Console::GetNesModel(); + expansionDevice = EmulationSettings::GetExpansionDevice(); + consoleType = EmulationSettings::GetConsoleType(); + for(int i = 0; i < 4; i++) { + controllerTypes[i] = EmulationSettings::GetControllerType(i); + } + } + + Stream(nesModel); + Stream(expansionDevice); + Stream(consoleType); + for(int i = 0; i < 4; i++) { + Stream(controllerTypes[i]); + } + + if(!saving) { + EmulationSettings::SetNesModel(nesModel); + EmulationSettings::SetExpansionDevice(expansionDevice); + EmulationSettings::SetConsoleType(consoleType); + for(int i = 0; i < 4; i++) { + EmulationSettings::SetControllerType(i, controllerTypes[i]); + } + + UpdateControlDevices(); + + if(GetControlDevice(0)) { + Stream(GetControlDevice(0)); + } + if(GetControlDevice(1)) { + Stream(GetControlDevice(1)); + } + } +} + +shared_ptr ControlManager::GetZapper(uint8_t port) +{ + shared_ptr zapper = std::dynamic_pointer_cast(GetControlDevice(port)); + if(zapper) { + return zapper; + } else { + shared_ptr controller = std::dynamic_pointer_cast(GetControlDevice(port)); + if(controller) { + return controller->GetZapper(); + } + } + + return nullptr; +} + +bool ControlManager::HasZapper() +{ + return GetZapper(0) != nullptr || GetZapper(1) != nullptr; +} + +void ControlManager::ZapperSetPosition(uint8_t port, int32_t x, int32_t y) +{ + shared_ptr zapper = GetZapper(port); + if(zapper) { + zapper->SetPosition(x, y); + } +} + +void ControlManager::ZapperSetTriggerState(uint8_t port, bool pulled) +{ + shared_ptr zapper = GetZapper(port); + if(zapper) { + zapper->SetTriggerState(pulled); + } } \ No newline at end of file diff --git a/Core/ControlManager.h b/Core/ControlManager.h index 66776072..ddf3229f 100644 --- a/Core/ControlManager.h +++ b/Core/ControlManager.h @@ -1,7 +1,7 @@ #pragma once #include "stdafx.h" -#include "IControlDevice.h" +#include "BaseControlDevice.h" #include "IMemoryHandler.h" #include "Movie.h" #include "IGameBroadcaster.h" @@ -9,30 +9,33 @@ #include "../Utilities/SimpleLock.h" #include "IKeyManager.h" +class BaseControlDevice; +class Zapper; + class ControlManager : public Snapshotable, public IMemoryHandler { private: static unique_ptr _keyManager; - static IControlDevice* ControlDevices[4]; - static IControlDevice* OriginalControlDevices[4]; - static IGameBroadcaster* GameBroadcaster; - static SimpleLock ControllerLock[4]; + static shared_ptr _controlDevices[2]; + static IGameBroadcaster* _gameBroadcaster; bool _refreshState = false; - uint32_t _stateBuffer[2]; void RefreshAllPorts(); - uint8_t GetControllerState(uint8_t port); - bool HasFourScoreAdapter(); - void RefreshStateBuffer(uint8_t port); uint8_t GetPortValue(uint8_t port); + static shared_ptr GetZapper(uint8_t port); + static void RegisterControlDevice(shared_ptr controlDevice, uint8_t port); + void UnregisterControlDevice(uint8_t port); + protected: virtual void StreamState(bool saving); public: ControlManager(); + void UpdateControlDevices(); + static void RegisterBroadcaster(IGameBroadcaster* gameBroadcaster); static void UnregisterBroadcaster(IGameBroadcaster* gameBroadcaster); @@ -41,12 +44,14 @@ class ControlManager : public Snapshotable, public IMemoryHandler static uint32_t GetPressedKey(); static string GetKeyName(uint32_t keyCode); static uint32_t GetKeyCode(string keyName); + + static shared_ptr GetControlDevice(uint8_t port); - static void BackupControlDevices(); - static void RestoreControlDevices(); - static IControlDevice* GetControlDevice(uint8_t port); - static void RegisterControlDevice(IControlDevice* controlDevice, uint8_t port); - static void UnregisterControlDevice(IControlDevice* controlDevice); + static bool HasZapper(); + static void ZapperSetPosition(uint8_t port, int32_t x, int32_t y); + static void ZapperSetTriggerState(uint8_t port, bool pulled); + + static void BroadcastInput(uint8_t port, uint8_t state); void GetMemoryRanges(MemoryRanges &ranges) { diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 2d4def72..50ad943f 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -447,7 +447,7 @@ - + @@ -506,18 +506,19 @@ - + + @@ -563,7 +564,7 @@ - + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 99be1b6c..6ebbbd91 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -63,6 +63,9 @@ {4a7af167-f6cb-4173-b7ca-04ed7c5858b1} + + {acd315c2-48ad-4243-a997-bb9a970c24bd} + @@ -71,9 +74,6 @@ Nes\Interfaces - - Nes\Interfaces - Nes\Interfaces @@ -263,9 +263,6 @@ NetPlay - - NetPlay - Nes @@ -281,9 +278,6 @@ Nes - - Nes - Nes @@ -536,6 +530,15 @@ VideoDecoder + + Nes\Controllers + + + Nes\Controllers + + + Nes\Controllers + @@ -598,9 +601,6 @@ NetPlay - - NetPlay - Nes @@ -619,9 +619,6 @@ Nes - - Nes - Nes @@ -658,5 +655,14 @@ VideoDecoder + + Nes\Controllers + + + Nes\Controllers + + + Nes\Controllers + \ No newline at end of file diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index 6c6072e6..d84a9b28 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -30,4 +30,10 @@ uint32_t EmulationSettings::_emulationSpeed = 100; OverscanDimensions EmulationSettings::_overscan; VideoFilterType EmulationSettings::_videoFilterType = VideoFilterType::None; -uint32_t EmulationSettings::_videoScale = 1; \ No newline at end of file +uint32_t EmulationSettings::_videoScale = 1; + +ConsoleType EmulationSettings::_consoleType = ConsoleType::Nes; +ExpansionPortDevice EmulationSettings::_expansionDevice = ExpansionPortDevice::None; +ControllerType EmulationSettings::_controllerTypes[4] = { ControllerType::None, ControllerType::None, ControllerType::None, ControllerType::None }; +KeyMappingSet EmulationSettings::_controllerKeys[4] = { KeyMappingSet(), KeyMappingSet(), KeyMappingSet(), KeyMappingSet() }; +bool EmulationSettings::_needControllerUpdate = false; \ No newline at end of file diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 57cfc58e..6332703c 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -2,6 +2,7 @@ #include "stdafx.h" #include "MessageManager.h" +#include "GameClient.h" enum EmulationFlags { @@ -11,6 +12,7 @@ enum EmulationFlags AllowInvalidInput = 0x08, RemoveSpriteLimit = 0x10, UseHdPacks = 0x20, + HasFourScore = 0x40, PauseOnMovieEnd = 0x0100, PauseWhenInBackground = 0x0200, @@ -78,6 +80,57 @@ struct OverscanDimensions } }; +enum class ConsoleType +{ + Nes = 0, + Famicom = 1, + VsSystem = 2, +}; + +enum class ControllerType +{ + None = 0, + StandardController = 1, + Zapper = 2, +}; + +enum class ExpansionPortDevice +{ + None = 0, + Zapper = 1, + FourPlayerAdapter = 2, +}; + +struct KeyMapping +{ + uint32_t A = 0; + uint32_t B = 0; + uint32_t Up = 0; + uint32_t Down = 0; + uint32_t Left = 0; + uint32_t Right = 0; + uint32_t Start = 0; + uint32_t Select = 0; + uint32_t TurboA = 0; + uint32_t TurboB = 0; + uint32_t TurboStart = 0; + uint32_t TurboSelect = 0; + + bool HasKeySet() + { + return A || B || Up || Down || Left || Right || Start || Select || TurboA || TurboB || TurboStart || TurboSelect; + } +}; + +struct KeyMappingSet +{ + KeyMapping Mapping1; + KeyMapping Mapping2; + KeyMapping Mapping3; + KeyMapping Mapping4; + uint32_t TurboSpeed; +}; + class EmulationSettings { private: @@ -98,6 +151,12 @@ private: static VideoFilterType _videoFilterType; static uint32_t _videoScale; + static ConsoleType _consoleType; + static ExpansionPortDevice _expansionDevice; + static ControllerType _controllerTypes[4]; + static KeyMappingSet _controllerKeys[4]; + static bool _needControllerUpdate; + public: static uint32_t GetMesenVersion() { @@ -124,6 +183,11 @@ public: return (_flags & flag) == flag; } + static bool IsPaused() + { + return CheckFlag(EmulationFlags::Paused) || (CheckFlag(EmulationFlags::InBackground) && CheckFlag(EmulationFlags::PauseWhenInBackground) && !GameClient::Connected()); + } + static void SetNesModel(NesModel model) { _model = model; @@ -234,4 +298,58 @@ public: { memcpy(PpuPaletteArgb, paletteBuffer, sizeof(PpuPaletteArgb)); } + + static void SetExpansionDevice(ExpansionPortDevice expansionDevice) + { + _expansionDevice = expansionDevice; + _needControllerUpdate = true; + } + + static ExpansionPortDevice GetExpansionDevice() + { + return _expansionDevice; + } + + static void SetConsoleType(ConsoleType type) + { + _consoleType = type; + _needControllerUpdate = true; + } + + static ConsoleType GetConsoleType() + { + return _consoleType; + } + + static void SetControllerType(uint8_t port, ControllerType type) + { + _controllerTypes[port] = type; + _needControllerUpdate = true; + } + + static ControllerType GetControllerType(uint8_t port) + { + return _controllerTypes[port]; + } + + static void SetControllerKeys(uint8_t port, KeyMappingSet keyMappings) + { + _controllerKeys[port] = keyMappings; + _needControllerUpdate = true; + } + + static KeyMappingSet GetControllerKeys(uint8_t port) + { + return _controllerKeys[port]; + } + + static bool NeedControllerUpdate() + { + if(_needControllerUpdate) { + _needControllerUpdate = false; + return true; + } else { + return false; + } + } }; diff --git a/Core/GameClient.cpp b/Core/GameClient.cpp index d244758b..e487491c 100644 --- a/Core/GameClient.cpp +++ b/Core/GameClient.cpp @@ -7,6 +7,7 @@ using std::thread; #include "Console.h" #include "../Utilities/Socket.h" #include "ClientConnectionData.h" +#include "GameClientConnection.h" unique_ptr GameClient::Instance; @@ -57,15 +58,6 @@ void GameClient::PrivateConnect(shared_ptr connectionData) } } -void GameClient::PrivateDisconnect() -{ - if(_connected) { - _connected = false; - _socket.reset(); - _connection.reset(); - } -} - void GameClient::Exec() { if(_connected) { @@ -89,4 +81,9 @@ void GameClient::ProcessNotification(ConsoleNotificationType type, void* paramet if(type == ConsoleNotificationType::GameLoaded && std::this_thread::get_id() != _clientThread->get_id()) { GameClient::Disconnect(); } +} + +uint8_t GameClient::GetControllerState(uint8_t port) +{ + return Instance->_connection->GetControllerState(port); } \ No newline at end of file diff --git a/Core/GameClient.h b/Core/GameClient.h index 2e3845d2..d1b3ccc2 100644 --- a/Core/GameClient.h +++ b/Core/GameClient.h @@ -1,11 +1,11 @@ #pragma once - #include "stdafx.h" -#include "GameClientConnection.h" +#include #include "INotificationListener.h" - +using std::thread; +class Socket; +class GameClientConnection; class ClientConnectionData; -class thread; class GameClient : public INotificationListener { @@ -20,7 +20,6 @@ private: void PrivateConnect(shared_ptr connectionData); void Exec(); - void PrivateDisconnect(); public: GameClient(); @@ -30,5 +29,7 @@ public: static void Connect(shared_ptr connectionData); static void Disconnect(); + static uint8_t GetControllerState(uint8_t port); + void ProcessNotification(ConsoleNotificationType type, void* parameter); }; \ No newline at end of file diff --git a/Core/GameClientConnection.cpp b/Core/GameClientConnection.cpp index d415ac6d..3db40125 100644 --- a/Core/GameClientConnection.cpp +++ b/Core/GameClientConnection.cpp @@ -8,23 +8,21 @@ #include "Console.h" #include "EmulationSettings.h" #include "ControlManager.h" -#include "VirtualController.h" #include "ClientConnectionData.h" +#include "StandardController.h" GameClientConnection::GameClientConnection(shared_ptr socket, shared_ptr connectionData) : GameConnection(socket, connectionData) { - _controlDevice = ControlManager::GetControlDevice(0); - ControlManager::BackupControlDevices(); - MessageManager::DisplayMessage("Net Play", "Connected to server."); - SendHandshake(); } GameClientConnection::~GameClientConnection() { - _virtualControllers.clear(); - ControlManager::RestoreControlDevices(); + _shutdown = true; + DisableControllers(); + + MessageManager::SendNotification(ConsoleNotificationType::DisconnectedFromServer); MessageManager::DisplayMessage("Net Play", "Connection to server lost."); } @@ -34,54 +32,49 @@ void GameClientConnection::SendHandshake() SendNetMessage(message); } -void GameClientConnection::InitializeVirtualControllers() +void GameClientConnection::ClearInputData() { for(int i = 0; i < 4; i++) { - _virtualControllers.push_back(unique_ptr(new VirtualController(i))); + _inputSize[i] = 0; + _inputData[i].clear(); } } -void GameClientConnection::DisposeVirtualControllers() -{ - _virtualControllers.clear(); -} - void GameClientConnection::ProcessMessage(NetMessage* message) { - uint8_t port; - uint8_t state; GameInformationMessage* gameInfo; switch(message->GetType()) { case MessageType::SaveState: if(_gameLoaded) { - DisposeVirtualControllers(); - + DisableControllers(); Console::Pause(); - + ClearInputData(); ((SaveStateMessage*)message)->LoadState(); - + _enableControllers = true; + switch(EmulationSettings::GetControllerType(_controllerPort)) { + case ControllerType::StandardController: _controlDevice.reset(new StandardController(0)); break; + case ControllerType::Zapper: _controlDevice = ControlManager::GetControlDevice(_controllerPort); break; + } Console::Resume(); - InitializeVirtualControllers(); } break; case MessageType::MovieData: if(_gameLoaded) { - port = ((MovieDataMessage*)message)->GetPortNumber(); - state = ((MovieDataMessage*)message)->GetInputState(); - - _virtualControllers[port]->PushState(state); + PushControllerState(((MovieDataMessage*)message)->GetPortNumber(), ((MovieDataMessage*)message)->GetInputState()); } break; case MessageType::GameInformation: + DisableControllers(); + Console::Pause(); gameInfo = (GameInformationMessage*)message; if(gameInfo->GetPort() != _controllerPort) { _controllerPort = gameInfo->GetPort(); MessageManager::DisplayMessage("Net Play", string("Connected as player ") + std::to_string(_controllerPort + 1)); } - DisposeVirtualControllers(); + ClearInputData(); _gameLoaded = gameInfo->AttemptLoadGame(); if(gameInfo->IsPaused()) { @@ -89,17 +82,78 @@ void GameClientConnection::ProcessMessage(NetMessage* message) } else { EmulationSettings::ClearFlags(EmulationFlags::Paused); } - + Console::Resume(); break; default: break; } } + +void GameClientConnection::PushControllerState(uint8_t port, uint8_t state) +{ + LockHandler lock = _writeLock.AcquireSafe(); + _inputData[port].push_back(state); + _inputSize[port]++; + + if(_inputData[port].size() >= _minimumQueueSize) { + _waitForInput[port].Signal(); + } +} + +void GameClientConnection::DisableControllers() +{ + //Used to prevent deadlocks when client is trying to fill its buffer while the host changes the current game/settings/etc. (i.e situations where we need to call Console::Pause()) + ClearInputData(); + _enableControllers = false; + for(int i = 0; i < 4; i++) { + _waitForInput[i].Signal(); + } +} + +uint8_t GameClientConnection::GetControllerState(uint8_t port) +{ + if(_enableControllers) { + while(_inputSize[port] == 0) { + _waitForInput[port].Wait(); + + if(port == 0 && _minimumQueueSize < 10) { + //Increase buffer size - reduces freezes at the cost of additional lag + _minimumQueueSize++; + } + + if(_shutdown || !_enableControllers) { + return 0; + } + } + + LockHandler lock = _writeLock.AcquireSafe(); + uint8_t state = _inputData[port].front(); + _inputData[port].pop_front(); + _inputSize[port]--; + + if(_inputData[port].size() > _minimumQueueSize) { + //Too much data, catch up + EmulationSettings::SetEmulationSpeed(0); + } else { + EmulationSettings::SetEmulationSpeed(100); + } + return state; + } + return 0; +} void GameClientConnection::SendInput() { if(_gameLoaded) { - uint8_t inputState = _controlDevice->GetButtonState().ToByte(); + uint32_t inputState = 0; + if(std::dynamic_pointer_cast(_controlDevice)) { + shared_ptr zapper = std::dynamic_pointer_cast(_controlDevice); + inputState = zapper->GetZapperState(); + } else if(std::dynamic_pointer_cast(_controlDevice)) { + shared_ptr controller = std::dynamic_pointer_cast(_controlDevice); + inputState = controller->GetButtonState(); + } + if(_lastInputSent != inputState) { InputDataMessage message(inputState); SendNetMessage(message); diff --git a/Core/GameClientConnection.h b/Core/GameClientConnection.h index c6b41941..2cbf474a 100644 --- a/Core/GameClientConnection.h +++ b/Core/GameClientConnection.h @@ -1,24 +1,34 @@ #pragma once #include "stdafx.h" +#include #include "GameConnection.h" -#include "IControlDevice.h" +#include "../Utilities/AutoResetEvent.h" +#include "../Utilities/SimpleLock.h" +#include "StandardController.h" class ClientConnectionData; -class VirtualController; class GameClientConnection : public GameConnection { private: - vector> _virtualControllers; - IControlDevice* _controlDevice; - uint8_t _lastInputSent = 0x00; + std::deque _inputData[4]; + atomic _inputSize[4]; + AutoResetEvent _waitForInput[4]; + SimpleLock _writeLock; + atomic _shutdown; + atomic _enableControllers = false; + atomic _minimumQueueSize = 3; + + shared_ptr _controlDevice; + uint32_t _lastInputSent = 0x00; bool _gameLoaded = false; uint8_t _controllerPort = 255; private: void SendHandshake(); - void InitializeVirtualControllers(); - void DisposeVirtualControllers(); + void ClearInputData(); + void PushControllerState(uint8_t port, uint8_t state); + void DisableControllers(); protected: void ProcessMessage(NetMessage* message); @@ -26,6 +36,7 @@ protected: public: GameClientConnection(shared_ptr socket, shared_ptr connectionData); ~GameClientConnection(); - + + uint8_t GetControllerState(uint8_t port); void SendInput(); }; \ No newline at end of file diff --git a/Core/GameServer.cpp b/Core/GameServer.cpp index 1ab9fad9..34c902e7 100644 --- a/Core/GameServer.cpp +++ b/Core/GameServer.cpp @@ -29,8 +29,7 @@ void GameServer::AcceptConnections() while(true) { shared_ptr socket = _listener->Accept(); if(!socket->ConnectionError()) { - _openConnections.push_back(shared_ptr(new GameServerConnection(socket, 1, this))); - std::cout << "Client connected." << std::endl; + _openConnections.push_back(shared_ptr(new GameServerConnection(socket, 1))); } else { break; } diff --git a/Core/GameServerConnection.cpp b/Core/GameServerConnection.cpp index 69c56bc4..d7a7dde1 100644 --- a/Core/GameServerConnection.cpp +++ b/Core/GameServerConnection.cpp @@ -10,15 +10,14 @@ #include "ControlManager.h" #include "ClientConnectionData.h" #include "EmulationSettings.h" +#include "StandardController.h" -GameServerConnection::GameServerConnection(shared_ptr socket, int controllerPort, IGameBroadcaster* gameBroadcaster) : GameConnection(socket, nullptr) +GameServerConnection* GameServerConnection::_netPlayDevices[4] = { nullptr,nullptr,nullptr, nullptr }; + +GameServerConnection::GameServerConnection(shared_ptr socket, int controllerPort) : GameConnection(socket, nullptr) { //Server-side connection - _gameBroadcaster = gameBroadcaster; _controllerPort = controllerPort; - - ControlManager::BackupControlDevices(); - MessageManager::RegisterNotificationListener(this); } @@ -30,8 +29,7 @@ GameServerConnection::~GameServerConnection() MessageManager::DisplayMessage("Net Play", "Player " + std::to_string(_controllerPort + 1) + " disconnected."); } - ControlManager::RestoreControlDevices(); - + UnregisterNetPlayDevice(this); MessageManager::UnregisterNotificationListener(this); } @@ -53,11 +51,17 @@ void GameServerConnection::SendMovieData(uint8_t state, uint8_t port) } } -ButtonState GameServerConnection::GetButtonState() +void GameServerConnection::PushState(uint32_t state) +{ + if(_inputData.size() == 0 || state != _inputData.back()) { + _inputData.push_back(state); + } +} + +uint32_t GameServerConnection::GetState() { - ButtonState state; size_t inputBufferSize = _inputData.size(); - uint8_t stateData = 0; + uint32_t stateData = 0; if(inputBufferSize > 0) { stateData = _inputData.front(); if(inputBufferSize > 1) { @@ -65,8 +69,7 @@ ButtonState GameServerConnection::GetButtonState() _inputData.pop_front(); } } - state.FromByte(stateData); - return state; + return stateData; } void GameServerConnection::ProcessMessage(NetMessage* message) @@ -85,18 +88,13 @@ void GameServerConnection::ProcessMessage(NetMessage* message) } _handshakeCompleted = true; - ControlManager::RegisterControlDevice(this, _controllerPort); + RegisterNetPlayDevice(this, _controllerPort); Console::Resume(); } break; case MessageType::InputData: - { - uint8_t state = ((InputDataMessage*)message)->GetInputState(); - if(_inputData.size() == 0 || state != _inputData.back()) { - _inputData.push_back(state); - } + PushState(((InputDataMessage*)message)->GetInputState()); break; - } default: break; } @@ -112,9 +110,32 @@ void GameServerConnection::ProcessNotification(ConsoleNotificationType type, voi case ConsoleNotificationType::StateLoaded: case ConsoleNotificationType::CheatAdded: case ConsoleNotificationType::FdsDiskChanged: + case ConsoleNotificationType::ConfigChanged: SendGameInformation(); break; default: break; } +} + +void GameServerConnection::RegisterNetPlayDevice(GameServerConnection* device, uint8_t port) +{ + GameServerConnection::_netPlayDevices[port] = device; +} + +void GameServerConnection::UnregisterNetPlayDevice(GameServerConnection* device) +{ + if(device != nullptr) { + for(int i = 0; i < 4; i++) { + if(GameServerConnection::_netPlayDevices[i] == device) { + GameServerConnection::_netPlayDevices[i] = nullptr; + break; + } + } + } +} + +GameServerConnection* GameServerConnection::GetNetPlayDevice(uint8_t port) +{ + return GameServerConnection::_netPlayDevices[port]; } \ No newline at end of file diff --git a/Core/GameServerConnection.h b/Core/GameServerConnection.h index 1d5eb84c..2e6e602a 100644 --- a/Core/GameServerConnection.h +++ b/Core/GameServerConnection.h @@ -1,29 +1,35 @@ #pragma once #include "stdafx.h" +#include #include "GameConnection.h" -#include "IControlDevice.h" +#include "StandardController.h" #include "IGameBroadcaster.h" #include "INotificationListener.h" -class GameServerConnection : public GameConnection, public IControlDevice, public INotificationListener +class GameServerConnection : public GameConnection, public INotificationListener { private: - int _controllerPort; - list _inputData; - IGameBroadcaster* _gameBroadcaster; + static GameServerConnection* _netPlayDevices[4]; + list _inputData; + int _controllerPort; bool _handshakeCompleted = false; + void PushState(uint32_t state); + void SendGameInformation(); + + static void RegisterNetPlayDevice(GameServerConnection* connection, uint8_t port); + static void UnregisterNetPlayDevice(GameServerConnection* device); protected: void ProcessMessage(NetMessage* message); public: - GameServerConnection(shared_ptr socket, int controllerPort, IGameBroadcaster* gameBroadcaster); + GameServerConnection(shared_ptr socket, int controllerPort); ~GameServerConnection(); - void SendGameInformation(); + uint32_t GetState(); void SendMovieData(uint8_t state, uint8_t port); - ButtonState GetButtonState(); - virtual void ProcessNotification(ConsoleNotificationType type, void* parameter); + + static GameServerConnection* GetNetPlayDevice(uint8_t port); }; diff --git a/Core/IControlDevice.h b/Core/IControlDevice.h deleted file mode 100644 index 7970e495..00000000 --- a/Core/IControlDevice.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "stdafx.h" - -struct ButtonState -{ - bool Up = false; - bool Down = false; - bool Left = false; - bool Right = false; - - bool A = false; - bool B = false; - - bool Select = false; - bool Start = false; - - uint8_t ToByte() - { - //"Button status for each controller is returned as an 8-bit report in the following order: A, B, Select, Start, Up, Down, Left, Right." - return (uint8_t)A | ((uint8_t)B << 1) | ((uint8_t)Select << 2) | ((uint8_t)Start << 3) | - ((uint8_t)Up << 4) | ((uint8_t)Down << 5) | ((uint8_t)Left << 6) | ((uint8_t)Right << 7); - } - - void FromByte(uint8_t stateData) - { - A = (stateData & 0x01) == 0x01; - B = (stateData & 0x02) == 0x02; - Select = (stateData & 0x04) == 0x04; - Start = (stateData & 0x08) == 0x08; - Up = (stateData & 0x10) == 0x10; - Down = (stateData & 0x20) == 0x20; - Left = (stateData & 0x40) == 0x40; - Right = (stateData & 0x80) == 0x80; - } -}; - -class IControlDevice -{ - public: - virtual ButtonState GetButtonState() = 0; -}; \ No newline at end of file diff --git a/Core/INotificationListener.h b/Core/INotificationListener.h index 28691f81..1c4c59ff 100644 --- a/Core/INotificationListener.h +++ b/Core/INotificationListener.h @@ -17,6 +17,8 @@ enum class ConsoleNotificationType ResolutionChanged = 11, FdsDiskChanged = 12, FdsBiosNotFound = 13, + ConfigChanged = 14, + DisconnectedFromServer = 15 }; class INotificationListener diff --git a/Core/InputDataMessage.h b/Core/InputDataMessage.h index c36e09a9..7ef415a4 100644 --- a/Core/InputDataMessage.h +++ b/Core/InputDataMessage.h @@ -5,22 +5,23 @@ class InputDataMessage : public NetMessage { private: - uint8_t _inputState; + uint32_t _inputState; + protected: virtual void ProtectedStreamState() { - Stream(_inputState); + Stream(_inputState); } public: InputDataMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { } - InputDataMessage(uint8_t inputState) : NetMessage(MessageType::InputData) + InputDataMessage(uint32_t inputState) : NetMessage(MessageType::InputData) { _inputState = inputState; } - uint8_t GetInputState() + uint32_t GetInputState() { return _inputState; } diff --git a/Core/Movie.cpp b/Core/Movie.cpp index a3149a1f..6b938cf7 100644 --- a/Core/Movie.cpp +++ b/Core/Movie.cpp @@ -5,7 +5,17 @@ #include "../Utilities/FolderUtilities.h" #include "RomLoader.h" -Movie* Movie::Instance = new Movie(); +shared_ptr Movie::_instance(new Movie()); + +Movie::~Movie() +{ + _instance = nullptr; +} + +shared_ptr Movie::GetInstance() +{ + return _instance; +} void Movie::PushState(uint8_t port) { @@ -137,57 +147,101 @@ void Movie::PlayMovie(stringstream &filestream, bool autoLoadRom, string filenam void Movie::Record(string filename, bool reset) { - Instance->StartRecording(filename, reset); + if(_instance) { + _instance->StartRecording(filename, reset); + } } void Movie::Play(string filename) { - ifstream file(filename, ios::in | ios::binary); - std::stringstream ss; + if(_instance) { + ifstream file(filename, ios::in | ios::binary); + std::stringstream ss; - if(file) { - ss << file.rdbuf(); - file.close(); - - Instance->PlayMovie(ss, true, filename); + if(file) { + ss << file.rdbuf(); + file.close(); + + _instance->PlayMovie(ss, true, filename); + } } } void Movie::Play(std::stringstream &filestream, bool autoLoadRom) { - Instance->PlayMovie(filestream, autoLoadRom); + if(_instance) { + _instance->PlayMovie(filestream, autoLoadRom); + } } void Movie::Stop() { - Instance->StopAll(); + if(_instance) { + _instance->StopAll(); + } } bool Movie::Playing() { - return Instance->_playing; + if(_instance) { + return _instance->_playing; + } else { + return false; + } } bool Movie::Recording() { - return Instance->_recording; + if(_instance) { + return _instance->_recording; + } else { + return false; + } } +struct MovieHeader +{ + char Header[3] = { 'M', 'M', 'O' }; + uint32_t MesenVersion; + uint32_t MovieFormatVersion; + uint32_t RomCrc32; + uint32_t Region; + uint32_t ConsoleType; + uint8_t ControllerTypes[4]; + uint32_t ExpansionDevice; + uint32_t FilenameLength; +}; + bool Movie::Save() { - _file.write("MMO", 3); - _data.SaveStateSize = (uint32_t)_startState.tellp(); - string romFilepath = Console::GetROMPath(); string romFilename = FolderUtilities::GetFilename(romFilepath, true); - uint32_t romCrc32 = RomLoader::GetCRC32(romFilepath); - _file.write((char*)&romCrc32, sizeof(romCrc32)); + MovieHeader header = {}; + header.MesenVersion = EmulationSettings::GetMesenVersion(); + header.MovieFormatVersion = 1; + header.RomCrc32 = RomLoader::GetCRC32(romFilepath); + header.Region = (uint32_t)Console::GetNesModel(); + header.ConsoleType = (uint32_t)EmulationSettings::GetConsoleType(); + header.ExpansionDevice = (uint32_t)EmulationSettings::GetExpansionDevice(); + for(int port = 0; port < 4; port++) { + header.ControllerTypes[port] = (uint32_t)EmulationSettings::GetControllerType(port); + } + header.FilenameLength = (uint32_t)romFilename.size(); - uint32_t romNameSize = (uint32_t)romFilename.size(); - _file.write((char*)&romNameSize, sizeof(uint32_t)); - _file.write((char*)romFilename.c_str(), romNameSize); + _file.write((char*)header.Header, sizeof(header.Header)); + _file.write((char*)&header.MesenVersion, sizeof(header.MesenVersion)); + _file.write((char*)&header.MovieFormatVersion, sizeof(header.MovieFormatVersion)); + _file.write((char*)&header.RomCrc32, sizeof(header.RomCrc32)); + _file.write((char*)&header.Region, sizeof(header.Region)); + _file.write((char*)&header.ConsoleType, sizeof(header.ConsoleType)); + _file.write((char*)&header.ControllerTypes, sizeof(header.ControllerTypes)); + _file.write((char*)&header.ExpansionDevice, sizeof(header.ExpansionDevice)); + _file.write((char*)&header.FilenameLength, sizeof(header.FilenameLength)); + _file.write((char*)romFilename.c_str(), header.FilenameLength); + + _data.SaveStateSize = (uint32_t)_startState.tellp(); _file.write((char*)&_data.SaveStateSize, sizeof(uint32_t)); if(_data.SaveStateSize > 0) { @@ -215,30 +269,39 @@ bool Movie::Save() bool Movie::Load(std::stringstream &file, bool autoLoadRom) { - char header[3]; - file.read((char*)&header, 3); + MovieHeader header = {}; + file.read((char*)header.Header, sizeof(header.Header)); - if(memcmp((char*)&header, "MMO", 3) != 0) { + if(memcmp(header.Header, "MMO", 3) != 0) { //Invalid movie file return false; } - uint32_t romCrc32; - file.read((char*)&romCrc32, sizeof(romCrc32)); + file.read((char*)&header.MesenVersion, sizeof(header.MesenVersion)); + file.read((char*)&header.MovieFormatVersion, sizeof(header.MovieFormatVersion)); + file.read((char*)&header.RomCrc32, sizeof(header.RomCrc32)); + file.read((char*)&header.Region, sizeof(header.Region)); + file.read((char*)&header.ConsoleType, sizeof(header.ConsoleType)); + file.read((char*)&header.ControllerTypes, sizeof(header.ControllerTypes)); + file.read((char*)&header.ExpansionDevice, sizeof(header.ExpansionDevice)); + file.read((char*)&header.FilenameLength, sizeof(header.FilenameLength)); - uint32_t romNameSize; - file.read((char*)&romNameSize, sizeof(uint32_t)); + EmulationSettings::SetConsoleType((ConsoleType)header.ConsoleType); + EmulationSettings::SetExpansionDevice((ExpansionPortDevice)header.ExpansionDevice); + for(int port = 0; port < 4; port++) { + EmulationSettings::SetControllerType(port, (ControllerType)header.ControllerTypes[port]); + } - char* romFilename = new char[romNameSize + 1]; - memset(romFilename, 0, (romNameSize + 1)); - file.read((char*)romFilename, romNameSize); + char* romFilename = new char[header.FilenameLength + 1]; + memset(romFilename, 0, header.FilenameLength + 1); + file.read((char*)romFilename, header.FilenameLength); bool loadedGame = true; if(autoLoadRom) { string currentRom = Console::GetROMPath(); - if(currentRom.empty() || romCrc32 != RomLoader::GetCRC32(currentRom)) { + if(currentRom.empty() || header.RomCrc32 != RomLoader::GetCRC32(currentRom)) { //Loaded game isn't the same as the game used for the movie, attempt to load the correct game - loadedGame = Console::LoadROM(romFilename, romCrc32); + loadedGame = Console::LoadROM(romFilename, header.RomCrc32); } } diff --git a/Core/Movie.h b/Core/Movie.h index db14c0ed..879f34f7 100644 --- a/Core/Movie.h +++ b/Core/Movie.h @@ -11,10 +11,8 @@ struct MovieData class Movie { - friend class ControlManager; - private: - static Movie* Instance; + static shared_ptr _instance; bool _recording = false; bool _playing = false; uint8_t _counter[4]; @@ -33,13 +31,16 @@ class Movie void StopAll(); void Reset(); - void RecordState(uint8_t port, uint8_t state); - uint8_t GetState(uint8_t port); - bool Save(); bool Load(std::stringstream &file, bool autoLoadRom); public: + ~Movie(); + + void RecordState(uint8_t port, uint8_t state); + uint8_t GetState(uint8_t port); + + static shared_ptr GetInstance(); static void Record(string filename, bool reset); static void Play(string filename); static void Play(std::stringstream &filestream, bool autoLoadRom); diff --git a/Core/PPU.h b/Core/PPU.h index 6b96b688..7943ad29 100644 --- a/Core/PPU.h +++ b/Core/PPU.h @@ -3,6 +3,7 @@ #include "stdafx.h" #include "Snapshotable.h" #include "MemoryManager.h" +#include "EmulationSettings.h" enum class NesModel; @@ -266,4 +267,12 @@ class PPU : public IMemoryHandler, public Snapshotable { return _secondarySpriteRAM; } + + static uint32_t GetPixelBrightness(uint8_t x, uint8_t y) + { + //Used by Zapper, gives a rough approximation of the brightness level of the specific pixel + uint16_t pixelData = PPU::Instance->_currentOutputBuffer[y << 8 | x]; + uint32_t argbColor = EmulationSettings::GetRgbPalette()[pixelData & 0x3F]; + return (argbColor & 0xFF) + ((argbColor >> 8) & 0xFF) + ((argbColor >> 16) & 0xFF); + } }; diff --git a/Core/SaveStateMessage.h b/Core/SaveStateMessage.h index 14180b08..d5e38a2c 100644 --- a/Core/SaveStateMessage.h +++ b/Core/SaveStateMessage.h @@ -16,11 +16,10 @@ private: protected: virtual void ProtectedStreamState() { - vector cheats; - StreamArray((void**)&_stateData, _dataSize); if(_sending) { + vector cheats; cheats = CheatManager::GetCheats(); _cheats = cheats.size() > 0 ? &cheats[0] : nullptr; _cheatArraySize = (uint32_t)cheats.size() * sizeof(CodeInfo); @@ -28,11 +27,6 @@ protected: delete[] _stateData; } else { StreamArray((void**)&_cheats, _cheatArraySize); - for(uint32_t i = 0; i < _cheatArraySize / sizeof(CodeInfo); i++) { - cheats.push_back(((CodeInfo*)_cheats)[i]); - } - - CheatManager::SetCheats(cheats); } } @@ -55,5 +49,11 @@ public: void LoadState() { Console::LoadState((uint8_t*)_stateData, _dataSize); + + vector cheats; + for(uint32_t i = 0; i < _cheatArraySize / sizeof(CodeInfo); i++) { + cheats.push_back(((CodeInfo*)_cheats)[i]); + } + CheatManager::SetCheats(cheats); } }; \ No newline at end of file diff --git a/Core/StandardController.cpp b/Core/StandardController.cpp index 99117ca6..0ec12ff0 100644 --- a/Core/StandardController.cpp +++ b/Core/StandardController.cpp @@ -4,27 +4,18 @@ #include "PPU.h" #include "EmulationSettings.h" -StandardController::StandardController(uint8_t port) +void StandardController::StreamState(bool saving) { - ControlManager::RegisterControlDevice(this, port); + BaseControlDevice::StreamState(saving); + Stream(_stateBuffer); + Stream(_stateBufferFamicom); + + if(_additionalController) { + Stream(_additionalController); + } } -StandardController::~StandardController() -{ - ControlManager::UnregisterControlDevice(this); -} - -void StandardController::AddKeyMappings(KeyMapping keyMapping) -{ - _keyMappings.push_back(keyMapping); -} - -void StandardController::ClearKeyMappings() -{ - _keyMappings.clear(); -} - -ButtonState StandardController::GetButtonState() +uint8_t StandardController::GetButtonState() { ButtonState state; @@ -42,7 +33,7 @@ ButtonState StandardController::GetButtonState() state.Right |= ControlManager::IsKeyPressed(keyMapping.Right); //Turbo buttons - need to be applied for at least 2 reads in a row (some games require this) - uint8_t turboFreq = 1 << (4 - keyMapping.TurboSpeed); + uint8_t turboFreq = 1 << (4 - _turboSpeed); bool turboOn = (uint8_t)(PPU::GetFrameCount() % turboFreq) < turboFreq / 2; if(turboOn) { state.A |= ControlManager::IsKeyPressed(keyMapping.TurboA); @@ -62,5 +53,72 @@ ButtonState StandardController::GetButtonState() } } - return state; + return state.ToByte(); } + +uint8_t StandardController::GetPortOutput() +{ + uint8_t returnValue = _stateBuffer & 0x01; + _stateBuffer >>= 1; + + if(_famiconDevice && _additionalController) { + if(_hasZapper) { + returnValue |= _additionalController->GetPortOutput(); + } else { + returnValue |= (_stateBufferFamicom & 0x01) << 1; + _stateBufferFamicom >>= 1; + _stateBuffer |= 0x800000; + } + } + + //"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers." + _stateBuffer |= 0x800000; + + return returnValue; +} + +void StandardController::RefreshStateBuffer() +{ + _stateBuffer = GetControlState(); + if(_additionalController) { + //Next 8 bits = Gamepad 3/4 + if(_famiconDevice) { + //Four player adapter (Famicom) + _stateBufferFamicom = _additionalController->GetControlState(); + _stateBufferFamicom |= 0xFFFF00; + } else { + //Four-score adapter (NES) + _stateBuffer |= _additionalController->GetControlState() << 8; + + //Last 8 bits = signature + //Signature for port 0 = 0x10, reversed bit order => 0x08 + //Signature for port 1 = 0x20, reversed bit order => 0x04 + _stateBuffer |= (GetPort() == 0 ? 0x08 : 0x04) << 16; + } + } else { + //"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers." + _stateBuffer |= 0xFFFF00; + } +} + +uint8_t StandardController::RefreshState() +{ + return GetButtonState(); +} + +void StandardController::AddAdditionalController(shared_ptr controller) +{ + if(std::dynamic_pointer_cast(controller)) { + _hasZapper = true; + } + _additionalController = controller; +} + +shared_ptr StandardController::GetZapper() +{ + if(_hasZapper) { + return std::dynamic_pointer_cast(_additionalController); + } else { + return nullptr; + } +} \ No newline at end of file diff --git a/Core/StandardController.h b/Core/StandardController.h index f2a4f0bc..9efbc7d1 100644 --- a/Core/StandardController.h +++ b/Core/StandardController.h @@ -1,37 +1,29 @@ #pragma once - #include "stdafx.h" +#include "BaseControlDevice.h" +#include "Zapper.h" -#include "IControlDevice.h" - -struct KeyMapping -{ - uint32_t A; - uint32_t B; - uint32_t Up; - uint32_t Down; - uint32_t Left; - uint32_t Right; - uint32_t Start; - uint32_t Select; - uint32_t TurboA; - uint32_t TurboB; - uint32_t TurboStart; - uint32_t TurboSelect; - uint32_t TurboSpeed; -}; - -class StandardController : public IControlDevice +class StandardController : public BaseControlDevice { private: - vector _keyMappings; + uint32_t _stateBuffer; + uint32_t _stateBufferFamicom; + + bool _hasZapper; + shared_ptr _additionalController; + +protected: + uint8_t RefreshState(); + virtual void StreamState(bool saving); public: - StandardController(uint8_t port); - ~StandardController(); + using BaseControlDevice::BaseControlDevice; - void AddKeyMappings(KeyMapping keyMapping); - void ClearKeyMappings(); + virtual uint8_t GetButtonState(); + uint8_t GetPortOutput(); + void RefreshStateBuffer(); - ButtonState GetButtonState(); + shared_ptr GetZapper(); + + void AddAdditionalController(shared_ptr controller); }; \ No newline at end of file diff --git a/Core/VirtualController.cpp b/Core/VirtualController.cpp deleted file mode 100644 index 1c808820..00000000 --- a/Core/VirtualController.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "stdafx.h" -#include "VirtualController.h" -#include "ControlManager.h" -#include "Console.h" -#include "EmulationSettings.h" - -VirtualController::VirtualController(uint8_t port) -{ - _port = port; - _queueSize = 0; - _waiting = false; - _shutdown = false; - ControlManager::RegisterControlDevice(this, _port); -} - -VirtualController::~VirtualController() -{ - _shutdown = true; - while(_waiting.load()); - - ControlManager::UnregisterControlDevice(this); -} - -ButtonState VirtualController::GetButtonState() -{ - ButtonState state; - if(_queueSize.load() == 0) { - _waiting = true; - while(_queueSize.load() <= _minimumBuffer) { - if(_minimumBuffer < 10) { - _minimumBuffer++; - } - if(_shutdown.load()) { - _waiting = false; - return state; - } - } - _waiting = false; - } - - _writeLock.Acquire(); - state.FromByte(_inputData.front()); - _inputData.pop_front(); - _queueSize--; - - if(_queueSize.load() > _minimumBuffer) { - EmulationSettings::SetEmulationSpeed(0); - } else { - EmulationSettings::SetEmulationSpeed(100); - } - - _writeLock.Release(); - - return state; -} - -void VirtualController::PushState(uint8_t state) -{ - _writeLock.Acquire(); - _inputData.push_back(state); - _queueSize++; - _writeLock.Release(); -} \ No newline at end of file diff --git a/Core/VirtualController.h b/Core/VirtualController.h deleted file mode 100644 index ebf9e5d8..00000000 --- a/Core/VirtualController.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include -using std::atomic; - -#include "IControlDevice.h" -#include "../Utilities/SimpleLock.h" - -class VirtualController : public IControlDevice -{ - list _inputData; - bool _paused = false; - atomic _queueSize; - atomic _waiting; - atomic _shutdown; - SimpleLock _writeLock; - uint8_t _port; - uint32_t _minimumBuffer = 3; - -public: - VirtualController(uint8_t port); - ~VirtualController(); - - ButtonState GetButtonState(); - void PushState(uint8_t state); -}; diff --git a/Core/Zapper.cpp b/Core/Zapper.cpp new file mode 100644 index 00000000..9d5558bc --- /dev/null +++ b/Core/Zapper.cpp @@ -0,0 +1,86 @@ +#include "stdafx.h" +#include "Zapper.h" +#include "CPU.h" +#include "PPU.h" + +struct ZapperButtonState +{ + bool TriggerPressed = false; + bool LightNotDetected = false; + + uint8_t ToByte() + { + return (LightNotDetected ? 0x08 : 0x00) | (TriggerPressed ? 0x10 : 0x00); + } +}; + +void Zapper::StreamState(bool saving) +{ + BaseControlDevice::StreamState(saving); + Stream(_xPosition); + Stream(_yPosition); + Stream(_pulled); +} + +void Zapper::SetPosition(int32_t x, int32_t y) +{ + _xPosition = x; + _yPosition = y; +} + +void Zapper::SetTriggerState(bool pulled) +{ + _pulled = pulled; +} + +uint32_t Zapper::GetZapperState() +{ + //Used by netplay + uint32_t state; + if(_yPosition == -1 || _xPosition == -1) { + state = 0x80000000; + } else { + state = _xPosition | (_yPosition << 8); + } + + if(_pulled) { + state |= 0x40000000; + } + + return state; +} + +uint8_t Zapper::ProcessNetPlayState(uint32_t netplayState) +{ + if(netplayState >> 31) { + _xPosition = -1; + _yPosition = -1; + } else { + _xPosition = netplayState & 0xFF; + _yPosition = (netplayState >> 8) & 0xFF; + } + _pulled = ((netplayState >> 30) & 0x01) == 0x01; + + return RefreshState(); +} + +uint8_t Zapper::RefreshState() +{ + ZapperButtonState state; + state.TriggerPressed = _pulled; + + int32_t scanline = PPU::GetCurrentScanline(); + int32_t cycle = PPU::GetCurrentCycle(); + if(_xPosition == -1 || _yPosition == -1 || scanline > 240 || scanline < _yPosition || (scanline == _yPosition && cycle < _xPosition) || PPU::GetPixelBrightness(_xPosition, _yPosition) < 50) { + //Light cannot be detected if the Y/X position is further ahead than the PPU, or if the PPU drew a dark color + state.LightNotDetected = true; + } + + return state.ToByte(); +} + +uint8_t Zapper::GetPortOutput() +{ + return GetControlState(); +} + diff --git a/Core/Zapper.h b/Core/Zapper.h new file mode 100644 index 00000000..a60fbcd2 --- /dev/null +++ b/Core/Zapper.h @@ -0,0 +1,25 @@ +#pragma once +#include "stdafx.h" +#include "BaseControlDevice.h" + +class Zapper : public BaseControlDevice +{ +private: + bool _pulled; + int32_t _xPosition; + int32_t _yPosition; + +protected: + uint8_t RefreshState(); + uint8_t ProcessNetPlayState(uint32_t netplayState); + void StreamState(bool saving); + +public: + using BaseControlDevice::BaseControlDevice; + + uint8_t GetPortOutput(); + + uint32_t GetZapperState(); + void SetPosition(int32_t x, int32_t y); + void SetTriggerState(bool pulled); +}; \ No newline at end of file diff --git a/GUI.NET/Config/Configuration.cs b/GUI.NET/Config/Configuration.cs index 0a7c4e85..835e7a18 100644 --- a/GUI.NET/Config/Configuration.cs +++ b/GUI.NET/Config/Configuration.cs @@ -15,9 +15,9 @@ namespace Mesen.GUI.Config public PreferenceInfo PreferenceInfo; public AudioInfo AudioInfo; public VideoInfo VideoInfo; + public InputInfo InputInfo; public List RecentFiles; public List Cheats; - public List Controllers; public bool ShowOnlyCheatsForCurrentGame; public bool AutoLoadIpsPatches; public NesModel Region; @@ -34,13 +34,13 @@ namespace Mesen.GUI.Config VideoInfo = new VideoInfo(); PreferenceInfo = new PreferenceInfo(); RecentFiles = new List(); - Controllers = new List(); + InputInfo = new InputInfo(); Cheats = new List(); } public void ApplyConfig() { - ControllerInfo.ApplyConfig(); + InputInfo.ApplyConfig(); VideoInfo.ApplyConfig(); AudioInfo.ApplyConfig(); PreferenceInfo.ApplyConfig(); @@ -50,11 +50,7 @@ namespace Mesen.GUI.Config public void InitializeDefaults() { - while(Controllers.Count < 4) { - var controllerInfo = new ControllerInfo(); - controllerInfo.ControllerType = Controllers.Count < 2 ? ControllerType.StandardController : ControllerType.None; - Controllers.Add(controllerInfo); - } + InputInfo.InitializeDefaults(); } public void AddRecentFile(string filepath) diff --git a/GUI.NET/Config/ControllerInfo.cs b/GUI.NET/Config/ControllerInfo.cs deleted file mode 100644 index 71999180..00000000 --- a/GUI.NET/Config/ControllerInfo.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Mesen.GUI.Config -{ - public enum ControllerType - { - None = 0, - StandardController = 1, - } - - public class KeyMappings - { - public string A = "A"; - public string B = "S"; - public string Select = "W"; - public string Start = "Q"; - public string Up = "Up Arrow"; - public string Down = "Down Arrow"; - public string Left = "Left Arrow"; - public string Right = "Right Arrow"; - - public string TurboA = "Z"; - public string TurboB = "X"; - public string TurboStart = ""; - public string TurboSelect = ""; - public UInt32 TurboSpeed; - - public InteropEmu.KeyMapping ToInteropMapping() - { - InteropEmu.KeyMapping mapping = new InteropEmu.KeyMapping(); - - mapping.A = InteropEmu.GetKeyCode(A); - mapping.B = InteropEmu.GetKeyCode(B); - mapping.Start = InteropEmu.GetKeyCode(Start); - mapping.Select = InteropEmu.GetKeyCode(Select); - mapping.Up = InteropEmu.GetKeyCode(Up); - mapping.Down = InteropEmu.GetKeyCode(Down); - mapping.Left = InteropEmu.GetKeyCode(Left); - mapping.Right = InteropEmu.GetKeyCode(Right); - mapping.TurboA = InteropEmu.GetKeyCode(TurboA); - mapping.TurboB = InteropEmu.GetKeyCode(TurboB); - mapping.TurboStart = InteropEmu.GetKeyCode(TurboStart); - mapping.TurboSelect = InteropEmu.GetKeyCode(TurboSelect); - mapping.TurboSpeed = TurboSpeed; - - return mapping; - } - } - - public class ControllerInfo - { - public ControllerType ControllerType = ControllerType.StandardController; - public KeyMappings Keys = new KeyMappings(); - - public static void ApplyConfig() - { - for(int i = 0; i < 4; i++) { - InteropEmu.ClearKeyMappings(i); - - if(ConfigManager.Config.Controllers[i].ControllerType != ControllerType.None) { - InteropEmu.AddKeyMappings(i, ConfigManager.Config.Controllers[i].Keys.ToInteropMapping()); - } - } - } - } -} diff --git a/GUI.NET/Config/InputInfo.cs b/GUI.NET/Config/InputInfo.cs new file mode 100644 index 00000000..0b756971 --- /dev/null +++ b/GUI.NET/Config/InputInfo.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mesen.GUI.Config +{ + public class KeyMappings + { + public string A; + public string B; + public string Select; + public string Start; + public string Up; + public string Down; + public string Left; + public string Right; + + public string TurboA; + public string TurboB; + public string TurboStart; + public string TurboSelect; + + public KeyMappings() + { + } + + public KeyMappings(int controllerIndex, int keySetIndex) + { + if(controllerIndex == 0) { + if(keySetIndex == 0) { + A = "A"; + B = "S"; + Select = "W"; + Start = "Q"; + Up = "Up Arrow"; + Down = "Down Arrow"; + Left = "Left Arrow"; + Right = "Right Arrow"; + + TurboA = "Z"; + TurboB = "X"; + } else if(keySetIndex == 1) { + A = "Pad1 A"; + B = "Pad1 X"; + Select = "Pad1 Back"; + Start = "Pad1 Start"; + Up = "Pad1 Up"; + Down = "Pad1 Down"; + Left = "Pad1 Left"; + Right = "Pad1 Right"; + + TurboA = "Pad1 B"; + TurboB = "Pad1 Y"; + } + } + } + + public InteropEmu.KeyMapping ToInteropMapping() + { + InteropEmu.KeyMapping mapping = new InteropEmu.KeyMapping(); + + mapping.A = InteropEmu.GetKeyCode(A); + mapping.B = InteropEmu.GetKeyCode(B); + mapping.Start = InteropEmu.GetKeyCode(Start); + mapping.Select = InteropEmu.GetKeyCode(Select); + mapping.Up = InteropEmu.GetKeyCode(Up); + mapping.Down = InteropEmu.GetKeyCode(Down); + mapping.Left = InteropEmu.GetKeyCode(Left); + mapping.Right = InteropEmu.GetKeyCode(Right); + mapping.TurboA = InteropEmu.GetKeyCode(TurboA); + mapping.TurboB = InteropEmu.GetKeyCode(TurboB); + mapping.TurboStart = InteropEmu.GetKeyCode(TurboStart); + mapping.TurboSelect = InteropEmu.GetKeyCode(TurboSelect); + + return mapping; + } + } + + public class ControllerInfo + { + public InteropEmu.ControllerType ControllerType = InteropEmu.ControllerType.StandardController; + public List Keys = new List(); + public UInt32 TurboSpeed = 2; + + public InteropEmu.KeyMappingSet GetKeyMappingSet() + { + while(Keys.Count < 4) { + Keys.Add(new KeyMappings()); + } + + InteropEmu.KeyMappingSet mappingSet = new InteropEmu.KeyMappingSet(); + mappingSet.Mapping1 = Keys[0].ToInteropMapping(); + mappingSet.Mapping2 = Keys[1].ToInteropMapping(); + mappingSet.Mapping3 = Keys[2].ToInteropMapping(); + mappingSet.Mapping4 = Keys[3].ToInteropMapping(); + mappingSet.TurboSpeed = TurboSpeed; + return mappingSet; + } + } + + public class InputInfo + { + public ConsoleType ConsoleType = ConsoleType.Nes; + public InteropEmu.ExpansionPortDevice ExpansionPortDevice = InteropEmu.ExpansionPortDevice.None; + public bool UseFourScore = false; + + public List Controllers = new List(); + + public void InitializeDefaults() + { + while(Controllers.Count < 4) { + var controllerInfo = new ControllerInfo(); + controllerInfo.ControllerType = Controllers.Count == 0 ? InteropEmu.ControllerType.StandardController : InteropEmu.ControllerType.None; + + if(Controllers.Count == 0) { + controllerInfo.Keys.Add(new KeyMappings(0, 0)); + controllerInfo.Keys.Add(new KeyMappings(0, 1)); + } + Controllers.Add(controllerInfo); + } + } + + public static void ApplyConfig() + { + InputInfo inputInfo = ConfigManager.Config.InputInfo; + + InteropEmu.ExpansionPortDevice expansionDevice; + if(inputInfo.ConsoleType == ConsoleType.Nes) { + expansionDevice = InteropEmu.ExpansionPortDevice.None; + } else { + expansionDevice = inputInfo.ExpansionPortDevice; + } + + InteropEmu.SetConsoleType(inputInfo.ConsoleType); + InteropEmu.SetExpansionDevice(inputInfo.ExpansionPortDevice); + InteropEmu.SetFlag(EmulationFlags.HasFourScore, (inputInfo.ConsoleType == ConsoleType.Nes && inputInfo.UseFourScore) || (inputInfo.ConsoleType == ConsoleType.Famicom && expansionDevice == InteropEmu.ExpansionPortDevice.FourPlayerAdapter)); + for(int i = 0; i < 4; i++) { + InteropEmu.SetControllerType(i, inputInfo.Controllers[i].ControllerType); + InteropEmu.SetControllerKeys(i, inputInfo.Controllers[i].GetKeyMappingSet()); + } + } + } +} diff --git a/GUI.NET/Controls/DXViewer.cs b/GUI.NET/Controls/DXViewer.cs deleted file mode 100644 index b6d082b1..00000000 --- a/GUI.NET/Controls/DXViewer.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace Mesen.GUI.Controls -{ - public partial class DXViewer : UserControl - { - public DXViewer() - { - InitializeComponent(); - } - } -} diff --git a/GUI.NET/Controls/DXViewer.Designer.cs b/GUI.NET/Controls/ctrlRenderer.Designer.cs similarity index 62% rename from GUI.NET/Controls/DXViewer.Designer.cs rename to GUI.NET/Controls/ctrlRenderer.Designer.cs index e26f9b2a..e5ec44ca 100644 --- a/GUI.NET/Controls/DXViewer.Designer.cs +++ b/GUI.NET/Controls/ctrlRenderer.Designer.cs @@ -1,6 +1,6 @@ namespace Mesen.GUI.Controls { - partial class DXViewer + partial class ctrlRenderer { /// /// Required designer variable. @@ -27,8 +27,18 @@ /// private void InitializeComponent() { - components = new System.ComponentModel.Container(); + this.SuspendLayout(); + // + // ctrlRenderer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Name = "ctrlRenderer"; + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ctrlRenderer_MouseDown); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ctrlRenderer_MouseMove); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ctrlRenderer_MouseUp); + this.ResumeLayout(false); + } #endregion diff --git a/GUI.NET/Controls/ctrlRenderer.cs b/GUI.NET/Controls/ctrlRenderer.cs new file mode 100644 index 00000000..2473c7ad --- /dev/null +++ b/GUI.NET/Controls/ctrlRenderer.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Config; + +namespace Mesen.GUI.Controls +{ + public partial class ctrlRenderer : UserControl + { + private bool _rightButtonDown = false; + + public ctrlRenderer() + { + InitializeComponent(); + } + + private void ctrlRenderer_MouseDown(object sender, MouseEventArgs e) + { + if(e.Button == MouseButtons.Left) { + InteropEmu.ZapperSetTriggerState(0, true); + InteropEmu.ZapperSetTriggerState(1, true); + } else if(e.Button == MouseButtons.Right) { + _rightButtonDown = true; + } + } + + private void ctrlRenderer_MouseMove(object sender, MouseEventArgs e) + { + if(InteropEmu.HasZapper()) { + this.Cursor = Cursors.Cross; + } else { + this.Cursor = Cursors.Default; + } + + if(_rightButtonDown) { + InteropEmu.ZapperSetPosition(0, -1, -1); + InteropEmu.ZapperSetPosition(1, -1, -1); + } else { + //TODO + InteropEmu.ZapperSetPosition(0, e.X/4, e.Y/4); + InteropEmu.ZapperSetPosition(1, e.X/4, e.Y/4); + } + } + + private void ctrlRenderer_MouseUp(object sender, MouseEventArgs e) + { + if(e.Button == MouseButtons.Left) { + InteropEmu.ZapperSetTriggerState(0, false); + InteropEmu.ZapperSetTriggerState(1, false); + } else if(e.Button == MouseButtons.Right) { + _rightButtonDown = false; + } + } + } +} diff --git a/GUI.NET/Controls/ctrlRenderer.resx b/GUI.NET/Controls/ctrlRenderer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Controls/ctrlRenderer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Forms/BaseConfigForm.cs b/GUI.NET/Forms/BaseConfigForm.cs index 0be0eb25..4c6f2363 100644 --- a/GUI.NET/Forms/BaseConfigForm.cs +++ b/GUI.NET/Forms/BaseConfigForm.cs @@ -26,6 +26,16 @@ namespace Mesen.GUI.Forms _validateTimer.Interval = 50; _validateTimer.Tick += OnValidateInput; _validateTimer.Start(); + + this.ShowInTaskbar = false; + } + + public new bool ShowInTaskbar + { + set + { + base.ShowInTaskbar = false; + } } protected override void OnLoad(EventArgs e) @@ -135,6 +145,7 @@ namespace Mesen.GUI.Forms protected void UpdateUI() { this.Updating = true; + foreach(KeyValuePair kvp in _bindings) { if(!_fieldInfo.ContainsKey(kvp.Key)) { throw new Exception("Invalid binding key"); @@ -162,6 +173,8 @@ namespace Mesen.GUI.Forms } } else if(kvp.Value is ctrlTrackbar) { ((ctrlTrackbar)kvp.Value).Value = (int)(uint)value; + } else if(kvp.Value is TrackBar) { + ((TrackBar)kvp.Value).Value = (int)(uint)value; } else if(kvp.Value is NumericUpDown) { NumericUpDown nud = kvp.Value as NumericUpDown; decimal val = (decimal)(uint)value; @@ -191,7 +204,14 @@ namespace Mesen.GUI.Forms } } } + this.Updating = false; + + this.AfterUpdateUI(); + } + + virtual protected void AfterUpdateUI() + { } protected void UpdateObject() @@ -219,11 +239,14 @@ namespace Mesen.GUI.Forms field.SetValue(Entity, kvp.Value.Controls.OfType().FirstOrDefault(r => r.Checked).Tag); } else if(kvp.Value is ctrlTrackbar) { field.SetValue(Entity, (UInt32)((ctrlTrackbar)kvp.Value).Value); + } else if(kvp.Value is TrackBar) { + field.SetValue(Entity, (UInt32)((TrackBar)kvp.Value).Value); } else if(kvp.Value is NumericUpDown) { field.SetValue(Entity, (UInt32)((NumericUpDown)kvp.Value).Value); } else if(kvp.Value is ComboBox) { if(field.FieldType.IsSubclassOf(typeof(Enum))) { - field.SetValue(Entity, Enum.Parse(field.FieldType, ((ComboBox)kvp.Value).SelectedItem.ToString())); + object selectedItem = ((ComboBox)kvp.Value).SelectedItem; + field.SetValue(Entity, selectedItem == null ? 0 : Enum.Parse(field.FieldType, selectedItem.ToString())); } else if(field.FieldType == typeof(UInt32)) { UInt32 numericValue; string item = Regex.Replace(((ComboBox)kvp.Value).SelectedItem.ToString(), "[^0-9]", ""); diff --git a/GUI.NET/Forms/Config/ctrlInputPortConfig.Designer.cs b/GUI.NET/Forms/Config/ctrlInputPortConfig.Designer.cs index c05099ce..5f1960ff 100644 --- a/GUI.NET/Forms/Config/ctrlInputPortConfig.Designer.cs +++ b/GUI.NET/Forms/Config/ctrlInputPortConfig.Designer.cs @@ -28,9 +28,9 @@ private void InitializeComponent() { this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.lblControllerType = new System.Windows.Forms.Label(); - this.cboControllerType = new System.Windows.Forms.ComboBox(); this.ctrlStandardController = new Mesen.GUI.Forms.Config.ctrlStandardController(); + this.cboControllerType = new System.Windows.Forms.ComboBox(); + this.lblControllerType = new System.Windows.Forms.Label(); this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // @@ -51,6 +51,29 @@ this.tableLayoutPanel1.Size = new System.Drawing.Size(618, 353); this.tableLayoutPanel1.TabIndex = 1; // + // ctrlStandardController + // + this.tableLayoutPanel1.SetColumnSpan(this.ctrlStandardController, 2); + this.ctrlStandardController.Location = new System.Drawing.Point(3, 30); + this.ctrlStandardController.Name = "ctrlStandardController"; + this.ctrlStandardController.Size = new System.Drawing.Size(611, 320); + this.ctrlStandardController.TabIndex = 3; + // + // cboControllerType + // + this.cboControllerType.Dock = System.Windows.Forms.DockStyle.Top; + this.cboControllerType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboControllerType.FormattingEnabled = true; + this.cboControllerType.Items.AddRange(new object[] { + "None", + "Standard NES Controller", + "Zapper"}); + this.cboControllerType.Location = new System.Drawing.Point(90, 3); + this.cboControllerType.Name = "cboControllerType"; + this.cboControllerType.Size = new System.Drawing.Size(525, 21); + this.cboControllerType.TabIndex = 2; + this.cboControllerType.SelectedIndexChanged += new System.EventHandler(this.cboControllerType_SelectedIndexChanged); + // // lblControllerType // this.lblControllerType.Anchor = System.Windows.Forms.AnchorStyles.Left; @@ -61,28 +84,6 @@ this.lblControllerType.TabIndex = 1; this.lblControllerType.Text = "Controller Type:"; // - // cboControllerType - // - this.cboControllerType.Dock = System.Windows.Forms.DockStyle.Top; - this.cboControllerType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.cboControllerType.FormattingEnabled = true; - this.cboControllerType.Items.AddRange(new object[] { - "None", - "Standard NES Controller"}); - this.cboControllerType.Location = new System.Drawing.Point(90, 3); - this.cboControllerType.Name = "cboControllerType"; - this.cboControllerType.Size = new System.Drawing.Size(525, 21); - this.cboControllerType.TabIndex = 2; - this.cboControllerType.SelectedIndexChanged += new System.EventHandler(this.cboControllerType_SelectedIndexChanged); - // - // ctrlStandardController - // - this.tableLayoutPanel1.SetColumnSpan(this.ctrlStandardController, 2); - this.ctrlStandardController.Location = new System.Drawing.Point(3, 30); - this.ctrlStandardController.Name = "ctrlStandardController"; - this.ctrlStandardController.Size = new System.Drawing.Size(611, 320); - this.ctrlStandardController.TabIndex = 3; - // // ctrlInputPortConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -99,8 +100,8 @@ #endregion private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private ctrlStandardController ctrlStandardController; private System.Windows.Forms.Label lblControllerType; private System.Windows.Forms.ComboBox cboControllerType; - private ctrlStandardController ctrlStandardController; } } diff --git a/GUI.NET/Forms/Config/ctrlInputPortConfig.cs b/GUI.NET/Forms/Config/ctrlInputPortConfig.cs index e6e88d44..63a1c480 100644 --- a/GUI.NET/Forms/Config/ctrlInputPortConfig.cs +++ b/GUI.NET/Forms/Config/ctrlInputPortConfig.cs @@ -23,20 +23,20 @@ namespace Mesen.GUI.Forms.Config public void Initialize(ControllerInfo controllerInfo) { _controllerInfo = controllerInfo; - ctrlStandardController.Initialize(controllerInfo.Keys); + //ctrlStandardController.Initialize(controllerInfo.Keys); cboControllerType.SelectedIndex = (int)_controllerInfo.ControllerType; } public void UpdateConfig() { - _controllerInfo.Keys = ctrlStandardController.GetKeyMappings(); - _controllerInfo.ControllerType = (ControllerType)cboControllerType.SelectedIndex; + //_controllerInfo.Keys = ctrlStandardController.GetKeyMappings(); + _controllerInfo.ControllerType = (InteropEmu.ControllerType)cboControllerType.SelectedIndex; } private void cboControllerType_SelectedIndexChanged(object sender, EventArgs e) { - ctrlStandardController.Visible = ((ControllerType)cboControllerType.SelectedIndex == ControllerType.StandardController); + ctrlStandardController.Visible = ((InteropEmu.ControllerType)cboControllerType.SelectedIndex == InteropEmu.ControllerType.StandardController); } } } diff --git a/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs b/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs index 9c44d18a..38ab6c58 100644 --- a/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs +++ b/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs @@ -28,210 +28,24 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ctrlStandardController)); - this.btnTurboB = new System.Windows.Forms.Button(); - this.btnSelect = new System.Windows.Forms.Button(); - this.btnTurboA = new System.Windows.Forms.Button(); - this.btnStart = new System.Windows.Forms.Button(); - this.btnDown = new System.Windows.Forms.Button(); - this.btnA = new System.Windows.Forms.Button(); - this.btnUp = new System.Windows.Forms.Button(); - this.btnB = new System.Windows.Forms.Button(); - this.btnLeft = new System.Windows.Forms.Button(); - this.btnRight = new System.Windows.Forms.Button(); - this.picControllerLayout = new System.Windows.Forms.PictureBox(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.trkTurboSpeed = new System.Windows.Forms.TrackBar(); - this.lblTurboSpeed = new System.Windows.Forms.Label(); - this.panel1 = new System.Windows.Forms.Panel(); - this.lblSlow = new System.Windows.Forms.Label(); - this.lblTurboFast = new System.Windows.Forms.Label(); this.panel2 = new System.Windows.Forms.Panel(); - ((System.ComponentModel.ISupportInitialize)(this.picControllerLayout)).BeginInit(); - this.tableLayoutPanel1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.trkTurboSpeed)).BeginInit(); - this.panel1.SuspendLayout(); + this.picControllerLayout = new System.Windows.Forms.PictureBox(); + this.btnA = new System.Windows.Forms.Button(); + this.btnDown = new System.Windows.Forms.Button(); + this.btnUp = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.btnB = new System.Windows.Forms.Button(); + this.btnTurboA = new System.Windows.Forms.Button(); + this.btnLeft = new System.Windows.Forms.Button(); + this.btnSelect = new System.Windows.Forms.Button(); + this.btnRight = new System.Windows.Forms.Button(); + this.btnTurboB = new System.Windows.Forms.Button(); this.panel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picControllerLayout)).BeginInit(); this.SuspendLayout(); // - // btnTurboB - // - this.btnTurboB.Location = new System.Drawing.Point(417, 43); - this.btnTurboB.Name = "btnTurboB"; - this.btnTurboB.Size = new System.Drawing.Size(61, 59); - this.btnTurboB.TabIndex = 21; - this.btnTurboB.Text = "B"; - this.btnTurboB.UseVisualStyleBackColor = true; - this.btnTurboB.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnSelect - // - this.btnSelect.Location = new System.Drawing.Point(234, 166); - this.btnSelect.Name = "btnSelect"; - this.btnSelect.Size = new System.Drawing.Size(61, 37); - this.btnSelect.TabIndex = 12; - this.btnSelect.Text = "Q"; - this.btnSelect.UseVisualStyleBackColor = true; - this.btnSelect.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnTurboA - // - this.btnTurboA.Location = new System.Drawing.Point(499, 43); - this.btnTurboA.Name = "btnTurboA"; - this.btnTurboA.Size = new System.Drawing.Size(61, 59); - this.btnTurboA.TabIndex = 20; - this.btnTurboA.Text = "A"; - this.btnTurboA.UseVisualStyleBackColor = true; - this.btnTurboA.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnStart - // - this.btnStart.Location = new System.Drawing.Point(315, 166); - this.btnStart.Name = "btnStart"; - this.btnStart.Size = new System.Drawing.Size(61, 37); - this.btnStart.TabIndex = 13; - this.btnStart.Text = "W"; - this.btnStart.UseVisualStyleBackColor = true; - this.btnStart.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnDown - // - this.btnDown.Location = new System.Drawing.Point(88, 177); - this.btnDown.Name = "btnDown"; - this.btnDown.Size = new System.Drawing.Size(50, 35); - this.btnDown.TabIndex = 19; - this.btnDown.Text = "Down"; - this.btnDown.UseVisualStyleBackColor = true; - this.btnDown.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnA - // - this.btnA.Location = new System.Drawing.Point(499, 155); - this.btnA.Name = "btnA"; - this.btnA.Size = new System.Drawing.Size(61, 59); - this.btnA.TabIndex = 14; - this.btnA.Text = "A"; - this.btnA.UseVisualStyleBackColor = true; - this.btnA.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnUp - // - this.btnUp.Location = new System.Drawing.Point(88, 95); - this.btnUp.Name = "btnUp"; - this.btnUp.Size = new System.Drawing.Size(50, 35); - this.btnUp.TabIndex = 18; - this.btnUp.Text = "Up"; - this.btnUp.UseVisualStyleBackColor = true; - this.btnUp.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnB - // - this.btnB.Location = new System.Drawing.Point(417, 155); - this.btnB.Name = "btnB"; - this.btnB.Size = new System.Drawing.Size(61, 59); - this.btnB.TabIndex = 15; - this.btnB.Text = "B"; - this.btnB.UseVisualStyleBackColor = true; - this.btnB.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnLeft - // - this.btnLeft.Location = new System.Drawing.Point(53, 136); - this.btnLeft.Name = "btnLeft"; - this.btnLeft.Size = new System.Drawing.Size(50, 35); - this.btnLeft.TabIndex = 17; - this.btnLeft.Text = "Left"; - this.btnLeft.UseVisualStyleBackColor = true; - this.btnLeft.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnRight - // - this.btnRight.Location = new System.Drawing.Point(123, 136); - this.btnRight.Name = "btnRight"; - this.btnRight.Size = new System.Drawing.Size(50, 35); - this.btnRight.TabIndex = 16; - this.btnRight.Text = "Right"; - this.btnRight.UseVisualStyleBackColor = true; - this.btnRight.Click += new System.EventHandler(this.btnMapping_Click); - // - // picControllerLayout - // - this.picControllerLayout.Image = ((System.Drawing.Image)(resources.GetObject("picControllerLayout.Image"))); - this.picControllerLayout.Location = new System.Drawing.Point(-8, -12); - this.picControllerLayout.Name = "picControllerLayout"; - this.picControllerLayout.Size = new System.Drawing.Size(629, 292); - this.picControllerLayout.TabIndex = 11; - this.picControllerLayout.TabStop = false; - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 3; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.trkTurboSpeed, 2, 1); - this.tableLayoutPanel1.Controls.Add(this.lblTurboSpeed, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.panel1, 2, 2); - this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 0); - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 3; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(613, 316); - this.tableLayoutPanel1.TabIndex = 22; - // - // trkTurboSpeed - // - this.trkTurboSpeed.LargeChange = 2; - this.trkTurboSpeed.Location = new System.Drawing.Point(493, 272); - this.trkTurboSpeed.Maximum = 3; - this.trkTurboSpeed.Name = "trkTurboSpeed"; - this.trkTurboSpeed.Size = new System.Drawing.Size(117, 26); - this.trkTurboSpeed.TabIndex = 0; - // - // lblTurboSpeed - // - this.lblTurboSpeed.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.lblTurboSpeed.AutoSize = true; - this.lblTurboSpeed.Location = new System.Drawing.Point(415, 278); - this.lblTurboSpeed.Name = "lblTurboSpeed"; - this.lblTurboSpeed.Size = new System.Drawing.Size(72, 13); - this.lblTurboSpeed.TabIndex = 1; - this.lblTurboSpeed.Text = "Turbo Speed:"; - // - // panel1 - // - this.panel1.Controls.Add(this.lblTurboFast); - this.panel1.Controls.Add(this.lblSlow); - this.panel1.Location = new System.Drawing.Point(490, 301); - this.panel1.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(120, 15); - this.panel1.TabIndex = 2; - // - // lblSlow - // - this.lblSlow.AutoSize = true; - this.lblSlow.Location = new System.Drawing.Point(3, 0); - this.lblSlow.Name = "lblSlow"; - this.lblSlow.Size = new System.Drawing.Size(30, 13); - this.lblSlow.TabIndex = 0; - this.lblSlow.Text = "Slow"; - // - // lblTurboFast - // - this.lblTurboFast.AutoSize = true; - this.lblTurboFast.Location = new System.Drawing.Point(90, 0); - this.lblTurboFast.Name = "lblTurboFast"; - this.lblTurboFast.Size = new System.Drawing.Size(27, 13); - this.lblTurboFast.TabIndex = 1; - this.lblTurboFast.Text = "Fast"; - // // panel2 // - this.tableLayoutPanel1.SetColumnSpan(this.panel2, 3); this.panel2.Controls.Add(this.btnTurboB); this.panel2.Controls.Add(this.btnRight); this.panel2.Controls.Add(this.btnSelect); @@ -245,48 +59,146 @@ this.panel2.Controls.Add(this.picControllerLayout); this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; this.panel2.Location = new System.Drawing.Point(0, 0); - this.panel2.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0); + this.panel2.Margin = new System.Windows.Forms.Padding(0); this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(613, 269); + this.panel2.Size = new System.Drawing.Size(585, 210); this.panel2.TabIndex = 3; // + // picControllerLayout + // + this.picControllerLayout.Image = ((System.Drawing.Image)(resources.GetObject("picControllerLayout.Image"))); + this.picControllerLayout.Location = new System.Drawing.Point(0, 0); + this.picControllerLayout.Name = "picControllerLayout"; + this.picControllerLayout.Size = new System.Drawing.Size(615, 211); + this.picControllerLayout.TabIndex = 11; + this.picControllerLayout.TabStop = false; + // + // btnA + // + this.btnA.Location = new System.Drawing.Point(499, 105); + this.btnA.Name = "btnA"; + this.btnA.Size = new System.Drawing.Size(61, 59); + this.btnA.TabIndex = 14; + this.btnA.Text = "A"; + this.btnA.UseVisualStyleBackColor = true; + this.btnA.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnDown + // + this.btnDown.Location = new System.Drawing.Point(68, 141); + this.btnDown.Name = "btnDown"; + this.btnDown.Size = new System.Drawing.Size(64, 35); + this.btnDown.TabIndex = 19; + this.btnDown.Text = "Down"; + this.btnDown.UseVisualStyleBackColor = true; + this.btnDown.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnUp + // + this.btnUp.Location = new System.Drawing.Point(68, 34); + this.btnUp.Name = "btnUp"; + this.btnUp.Size = new System.Drawing.Size(64, 35); + this.btnUp.TabIndex = 18; + this.btnUp.Text = "Up"; + this.btnUp.UseVisualStyleBackColor = true; + this.btnUp.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnStart + // + this.btnStart.Location = new System.Drawing.Point(316, 131); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(61, 37); + this.btnStart.TabIndex = 13; + this.btnStart.Text = "W"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnB + // + this.btnB.Location = new System.Drawing.Point(417, 105); + this.btnB.Name = "btnB"; + this.btnB.Size = new System.Drawing.Size(61, 59); + this.btnB.TabIndex = 15; + this.btnB.Text = "B"; + this.btnB.UseVisualStyleBackColor = true; + this.btnB.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnTurboA + // + this.btnTurboA.Location = new System.Drawing.Point(499, 17); + this.btnTurboA.Name = "btnTurboA"; + this.btnTurboA.Size = new System.Drawing.Size(61, 59); + this.btnTurboA.TabIndex = 20; + this.btnTurboA.Text = "A"; + this.btnTurboA.UseVisualStyleBackColor = true; + this.btnTurboA.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnLeft + // + this.btnLeft.Location = new System.Drawing.Point(29, 90); + this.btnLeft.Name = "btnLeft"; + this.btnLeft.Size = new System.Drawing.Size(64, 35); + this.btnLeft.TabIndex = 17; + this.btnLeft.Text = "Left"; + this.btnLeft.UseVisualStyleBackColor = true; + this.btnLeft.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnSelect + // + this.btnSelect.Location = new System.Drawing.Point(234, 131); + this.btnSelect.Name = "btnSelect"; + this.btnSelect.Size = new System.Drawing.Size(61, 37); + this.btnSelect.TabIndex = 12; + this.btnSelect.Text = "Q"; + this.btnSelect.UseVisualStyleBackColor = true; + this.btnSelect.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnRight + // + this.btnRight.Location = new System.Drawing.Point(108, 90); + this.btnRight.Name = "btnRight"; + this.btnRight.Size = new System.Drawing.Size(64, 35); + this.btnRight.TabIndex = 16; + this.btnRight.Text = "Right"; + this.btnRight.UseVisualStyleBackColor = true; + this.btnRight.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnTurboB + // + this.btnTurboB.Location = new System.Drawing.Point(417, 17); + this.btnTurboB.Name = "btnTurboB"; + this.btnTurboB.Size = new System.Drawing.Size(61, 59); + this.btnTurboB.TabIndex = 21; + this.btnTurboB.Text = "B"; + this.btnTurboB.UseVisualStyleBackColor = true; + this.btnTurboB.Click += new System.EventHandler(this.btnMapping_Click); + // // ctrlStandardController // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.tableLayoutPanel1); + this.Controls.Add(this.panel2); this.Name = "ctrlStandardController"; - this.Size = new System.Drawing.Size(612, 317); - ((System.ComponentModel.ISupportInitialize)(this.picControllerLayout)).EndInit(); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.trkTurboSpeed)).EndInit(); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); + this.Size = new System.Drawing.Size(585, 210); this.panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picControllerLayout)).EndInit(); this.ResumeLayout(false); } #endregion + private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Button btnTurboB; + private System.Windows.Forms.Button btnRight; private System.Windows.Forms.Button btnSelect; + private System.Windows.Forms.Button btnLeft; private System.Windows.Forms.Button btnTurboA; + private System.Windows.Forms.Button btnB; private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.Button btnUp; private System.Windows.Forms.Button btnDown; private System.Windows.Forms.Button btnA; - private System.Windows.Forms.Button btnUp; - private System.Windows.Forms.Button btnB; - private System.Windows.Forms.Button btnLeft; - private System.Windows.Forms.Button btnRight; private System.Windows.Forms.PictureBox picControllerLayout; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private System.Windows.Forms.TrackBar trkTurboSpeed; - private System.Windows.Forms.Label lblTurboSpeed; - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Label lblTurboFast; - private System.Windows.Forms.Label lblSlow; - private System.Windows.Forms.Panel panel2; } } diff --git a/GUI.NET/Forms/Config/ctrlStandardController.cs b/GUI.NET/Forms/Config/ctrlStandardController.cs index 006196af..da6b12fa 100644 --- a/GUI.NET/Forms/Config/ctrlStandardController.cs +++ b/GUI.NET/Forms/Config/ctrlStandardController.cs @@ -30,9 +30,20 @@ namespace Mesen.GUI.Forms.Config btnRight.Text = mappings.Right; btnTurboA.Text = mappings.TurboA; btnTurboB.Text = mappings.TurboB; - - trkTurboSpeed.Value = (Int32)mappings.TurboSpeed; - trkTurboSpeed.BackColor = Color.FromArgb(255, trkTurboSpeed.Parent.BackColor); + } + + public void ClearKeys() + { + btnA.Text = ""; + btnB.Text = ""; + btnStart.Text = ""; + btnSelect.Text = ""; + btnUp.Text = ""; + btnDown.Text = ""; + btnLeft.Text = ""; + btnRight.Text = ""; + btnTurboA.Text = ""; + btnTurboB.Text = ""; } private void btnMapping_Click(object sender, EventArgs e) @@ -57,7 +68,6 @@ namespace Mesen.GUI.Forms.Config TurboB = btnTurboB.Text, TurboSelect = string.Empty, TurboStart = string.Empty, - TurboSpeed = (UInt32)trkTurboSpeed.Value }; return mappings; } diff --git a/GUI.NET/Forms/Config/ctrlStandardController.resx b/GUI.NET/Forms/Config/ctrlStandardController.resx index 2eee94b4..4f6c473c 100644 --- a/GUI.NET/Forms/Config/ctrlStandardController.resx +++ b/GUI.NET/Forms/Config/ctrlStandardController.resx @@ -120,126 +120,166 @@ - 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 - KuYPLuZfrE1Fv6zbg29c3E9TB6/Ycn7XMM8nMZlMim9BhabuMeNhm7pW8damo+LDaur6ityf09ylrlH2 - 3NT1y8m9xv0yc1+dfH7v4Nl93mjqKvr9in0V9em9bxV9nz9d3KfX5s/Lv62v6vW/L34IokJTB6/Ycn7X - MM8nMZlMim9BxfPmnuZfAxHj+Xl/uvUBIq3tXlW8temoODYDfzzzo7P5XrNrTV03Jeef+9ll7j/KG+8R - Syp23dS1in55+dulG7BuvF78QEpFr+NlU/e18tzEVbxxVbWi16bXtd9L1++765deP3+cP7ufpg5eseX8 - rmGeT2IymRTfggpN3WPGQzd1rSI2HRXHZqD/PXp+X1fF+zV1/cMS55/7sWWum5GHaeqOKvonibuB/vlF - PjV1vXb9XPQ6HvVL1s9XP3vc+bPbPyu/P94+y/fa90BTB6/Qcn7XMM8nMZlMim9BhabuMePhm7qjihdN - R8VTM3B+n3MV79fUve3l1++Wh3j59VLFz8svL3IvmrqK/pUu3cB1vn9w5aivpPbVz48u97ts6o4/UPGV - Y27Ja+rgFVvO7xrm+SQmk0nxLah43tzT/GsgYjw/70+3PkCktX0tKp6bjooPq6n7YunBq/5BiYr+6dVu - YD+93O6Xursp+87F/Xodz5uzvmrazfXle+M+WXrwteX2G2tT8btyeSVQUwev2HJ+1zDPJzGZTIpvQYWm - 7jHjYZu6iqtNR8VzM3Dh+MuHe826+Tife/rlwBXd1PXLgedz538poef7a/UVqH6/2GdK13t+z95yvz03 - df19dZPVN1pfffthuF9/3+dNXb8/7unXzFyq+FX5xTJOTd03S3+dj5/ljk20pg5eoeX8rmGeT2IymRTf - gornzT3NvwYixvPz/nTrA0Ra2z2quNp0VHSTd5w793SFraKvKF3O/WqZ+8VZ7uj/n9Xun+7sH5joN/cf - 57uZefrFxmf368blqeZeVRz/QsbTy6YA71LF0/+hl/lrYjKZFN+CCk3dY8bDNnVHFXdtOir6vXy7+vNf - AFtR0R9qmOeTmEwmxbegQlP3mPHwTR0A+9Xb0mFryvNJTCaT4ltQoal7zNDUAbBbvS0dtqY8n8RkMim+ - BRWauscMTR0Au9Xb0mFryvNJTCaT4ltQoal7zNDUAbBbvS0dtqY8n8RkMim+BRWauscMTR0Au9Xb0mFr - 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 + w9JudSxN4uTegdtxMDGTJx9jTjD8v3jG6a1XrR1S21eOSVIrkh4ReXj2a1WX/FBwsjZLlqN3x8trr+8t + 4UselnarY2kSJ/cO3I6Difmj4M23WbWMOcxMHqe1feWYJBRJT4/xgpIsFXFj6xP9GPucJW+JxwVLlqNx + 3rlN7T09lZ+Th6Xd6liaxMm9A7fjYGL+MHjzl61axhxmJo/T2r5yTJIfYzOs4QgIE/7FtdfrbMkdgwdn + nX+UsORG8fTo9ef3IeFLHpZ2q2NpEif3DtyOg4n5g+DNt121TM98enxGfGZ8Vnx2fE5cFFeMK8XFceW4 + SnChv6vG1eLqcY24ZlwrrhPXjevFDeKGcaPgyAA3feXee9xahtt2cMFFrnvFZR34yDznU3DOGUuqLFdR + aPD3/vK4XXxFfGXw0fA7xFcHE8PXxNfGneLOcZe4a3xdfH18Q9w97hH3jHvFveMb4z5x3/jmuF/cP74l + HhDfFg+Mb48Hx3fEdwb/7/y74ruDE4y/J74vHhZvDMYpv/NOqe0r0rYSTnRffaqt0vfoeEutr6eEL3lY + 2q2OpUmc3DtwOw4m5iXBmzkcz38MfjoeG/w/zcfHzwaH658YTwo++vpz8fPxC/GUeGo8LfgevxTPiGfG + s+KX49nxK/Gc+LX49XhucGG234znxwvi8vit+O3g0zi/Ey8KPrb84vj94PelsOPIAuepcE4VJ5/z6Seu + pcN1n7hAJldo5n5f3JuOm/hyF/nXB8sMTLhvCv5f4FvjbcFJmO+Id8a74j3x3nhfcBuHD8aHguujfCQ+ + Gpyj8Ffx18Gnhf4m/jbYntoPirqdUttXpDlhGA9DubRbHUuTOLl34HYcTMzvBW9WfxRMFE4UUBRSFFQU + VhRYFFoUXBReFGAUYhRkFGYUaBRqFGwUbhRwFHIUdBR2FHgUehR8FH4UgBSCFIQUhhSIFIoUjBSOFJAU + khSUFJYUmBSaFJwUnhSgFKIUpBSmFKgUqhSsFK4UsBSyFLQUthS4FLoUvBS+FMAUwhTEFMYUyBTKFMwU + zhTQFNIU1BTWFNgU2hTcFN4U4BTiFOQU5hToFOoU7BTuPxk/ET8eHD3bKbV9RZoThvEwlEu71bE0yTi5 + 8x8iHu8LZ+I/6gSdxs9jO1ok7R6WQh4eLGmwtMESB0sdLHmw9MESCEshLImwNMISCUslLJmwdMISCksp + fB+WVlhiYamFJReWXliCYSmGJRmWZliiYamGJRuWbljCYSmHJR2WdljiYamHJR+WflgCYimIJSGOIrDc + wlIRS0YsHbGExFISS0osLbHExFITS04sPbEExVIUS1IsTTHJslTFkhVLVyxhsZTFkhZLWyxxsdTFkhdL + XyyBsRTGkhhLYyyRsVTGkhlLZyyhsZTGkhpLayyxmQNKbV+R5oRhPAzl0m51LE1CAbP6N56AT5ygk/55 + 4GdaJBljzkptX5HmhGE8DOXSbnUsUbJ51Gcf9n2katNJ/7yV2vY9JsaYc1PbV6Q5YRgPQ7m0Wx2S2owx + 56a2r0hzwjAehnJptzoktRljzk1tX5HmhGE8DOXSbnVIajPGnJvaviLNCcN4GMql3eqQ1GaMOTe1fUWa + E4bxMJRLu9Uhqc0Yc25q+4o0JwzjYSiXdqtDUpsx5tzU9hVpThjGw1Au7VaHpDZjzLmp7SvSnDCMh6Fc + 2q0OSW1mman9rSUdD/4zMPynoLRbHZIkScdksxZqdkiSJB2TzVqo2SFJknRMNmuhZockSdIx2ayFmh2S + JEnHZLMWanZIkiQdk81aqNkhSZJ0TDZroWaHJEnSMdmshZodkiRJx2SzFmp2SJIkHZPNWqjZIUmSdEw2 + a6FmhyRJ0jHZrIWaHZIkScdksxZqdkiSJB2TzVqo2SFJknRMNmuhczokSZKOmUWSJElSxTlFkiRJkkaf + /LT/D/XHWcQRIejmAAAAAElFTkSuQmCC \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmControllerConfig.Designer.cs b/GUI.NET/Forms/Config/frmControllerConfig.Designer.cs new file mode 100644 index 00000000..9d40c45c --- /dev/null +++ b/GUI.NET/Forms/Config/frmControllerConfig.Designer.cs @@ -0,0 +1,305 @@ +namespace Mesen.GUI.Forms.Config +{ + partial class frmControllerConfig + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.ctrlStandardController0 = new Mesen.GUI.Forms.Config.ctrlStandardController(); + this.tabMain = new System.Windows.Forms.TabControl(); + this.tpgSet1 = new System.Windows.Forms.TabPage(); + this.tpgSet2 = new System.Windows.Forms.TabPage(); + this.ctrlStandardController1 = new Mesen.GUI.Forms.Config.ctrlStandardController(); + this.tpgSet3 = new System.Windows.Forms.TabPage(); + this.ctrlStandardController2 = new Mesen.GUI.Forms.Config.ctrlStandardController(); + this.tpgSet4 = new System.Windows.Forms.TabPage(); + this.ctrlStandardController3 = new Mesen.GUI.Forms.Config.ctrlStandardController(); + this.btnClear = new System.Windows.Forms.Button(); + this.btnReset = new System.Windows.Forms.Button(); + this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.trkTurboSpeed = new System.Windows.Forms.TrackBar(); + this.lblTurboSpeed = new System.Windows.Forms.Label(); + this.panel1 = new System.Windows.Forms.Panel(); + this.lblTurboFast = new System.Windows.Forms.Label(); + this.lblSlow = new System.Windows.Forms.Label(); + this.baseConfigPanel.SuspendLayout(); + this.tabMain.SuspendLayout(); + this.tpgSet1.SuspendLayout(); + this.tpgSet2.SuspendLayout(); + this.tpgSet3.SuspendLayout(); + this.tpgSet4.SuspendLayout(); + this.flowLayoutPanel2.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trkTurboSpeed)).BeginInit(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // baseConfigPanel + // + this.baseConfigPanel.Controls.Add(this.flowLayoutPanel2); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 288); + this.baseConfigPanel.Size = new System.Drawing.Size(599, 29); + this.baseConfigPanel.Controls.SetChildIndex(this.flowLayoutPanel2, 0); + // + // ctrlStandardController0 + // + this.ctrlStandardController0.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlStandardController0.Location = new System.Drawing.Point(0, 0); + this.ctrlStandardController0.Margin = new System.Windows.Forms.Padding(0); + this.ctrlStandardController0.Name = "ctrlStandardController0"; + this.ctrlStandardController0.Size = new System.Drawing.Size(585, 209); + this.ctrlStandardController0.TabIndex = 0; + // + // tabMain + // + this.tableLayoutPanel1.SetColumnSpan(this.tabMain, 3); + this.tabMain.Controls.Add(this.tpgSet1); + this.tabMain.Controls.Add(this.tpgSet2); + this.tabMain.Controls.Add(this.tpgSet3); + this.tabMain.Controls.Add(this.tpgSet4); + this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabMain.Location = new System.Drawing.Point(3, 3); + this.tabMain.Name = "tabMain"; + this.tabMain.SelectedIndex = 0; + this.tabMain.Size = new System.Drawing.Size(593, 235); + this.tabMain.TabIndex = 3; + // + // tpgSet1 + // + this.tpgSet1.Controls.Add(this.ctrlStandardController0); + this.tpgSet1.Location = new System.Drawing.Point(4, 22); + this.tpgSet1.Name = "tpgSet1"; + this.tpgSet1.Size = new System.Drawing.Size(585, 209); + this.tpgSet1.TabIndex = 0; + this.tpgSet1.Text = "Key Set #1"; + this.tpgSet1.UseVisualStyleBackColor = true; + // + // tpgSet2 + // + this.tpgSet2.Controls.Add(this.ctrlStandardController1); + this.tpgSet2.Location = new System.Drawing.Point(4, 22); + this.tpgSet2.Name = "tpgSet2"; + this.tpgSet2.Size = new System.Drawing.Size(585, 209); + this.tpgSet2.TabIndex = 1; + this.tpgSet2.Text = "Key Set #2"; + this.tpgSet2.UseVisualStyleBackColor = true; + // + // ctrlStandardController1 + // + this.ctrlStandardController1.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlStandardController1.Location = new System.Drawing.Point(0, 0); + this.ctrlStandardController1.Margin = new System.Windows.Forms.Padding(0); + this.ctrlStandardController1.Name = "ctrlStandardController1"; + this.ctrlStandardController1.Size = new System.Drawing.Size(585, 209); + this.ctrlStandardController1.TabIndex = 1; + // + // tpgSet3 + // + this.tpgSet3.Controls.Add(this.ctrlStandardController2); + this.tpgSet3.Location = new System.Drawing.Point(4, 22); + this.tpgSet3.Name = "tpgSet3"; + this.tpgSet3.Size = new System.Drawing.Size(585, 209); + this.tpgSet3.TabIndex = 2; + this.tpgSet3.Text = "Key Set #3"; + this.tpgSet3.UseVisualStyleBackColor = true; + // + // ctrlStandardController2 + // + this.ctrlStandardController2.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlStandardController2.Location = new System.Drawing.Point(0, 0); + this.ctrlStandardController2.Margin = new System.Windows.Forms.Padding(0); + this.ctrlStandardController2.Name = "ctrlStandardController2"; + this.ctrlStandardController2.Size = new System.Drawing.Size(585, 209); + this.ctrlStandardController2.TabIndex = 1; + // + // tpgSet4 + // + this.tpgSet4.Controls.Add(this.ctrlStandardController3); + this.tpgSet4.Location = new System.Drawing.Point(4, 22); + this.tpgSet4.Name = "tpgSet4"; + this.tpgSet4.Size = new System.Drawing.Size(585, 209); + this.tpgSet4.TabIndex = 3; + this.tpgSet4.Text = "Key Set #4"; + this.tpgSet4.UseVisualStyleBackColor = true; + // + // ctrlStandardController3 + // + this.ctrlStandardController3.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlStandardController3.Location = new System.Drawing.Point(0, 0); + this.ctrlStandardController3.Margin = new System.Windows.Forms.Padding(0); + this.ctrlStandardController3.Name = "ctrlStandardController3"; + this.ctrlStandardController3.Size = new System.Drawing.Size(585, 209); + this.ctrlStandardController3.TabIndex = 1; + // + // btnClear + // + this.btnClear.Location = new System.Drawing.Point(118, 3); + this.btnClear.Name = "btnClear"; + this.btnClear.Size = new System.Drawing.Size(109, 23); + this.btnClear.TabIndex = 3; + this.btnClear.Text = "Clear Key Bindings"; + this.btnClear.UseVisualStyleBackColor = true; + this.btnClear.Click += new System.EventHandler(this.btnClear_Click); + // + // btnReset + // + this.btnReset.Location = new System.Drawing.Point(3, 3); + this.btnReset.Name = "btnReset"; + this.btnReset.Size = new System.Drawing.Size(109, 23); + this.btnReset.TabIndex = 4; + this.btnReset.Text = "Reset to Default"; + this.btnReset.UseVisualStyleBackColor = true; + this.btnReset.Visible = false; + this.btnReset.Click += new System.EventHandler(this.btnReset_Click); + // + // flowLayoutPanel2 + // + this.flowLayoutPanel2.Controls.Add(this.btnReset); + this.flowLayoutPanel2.Controls.Add(this.btnClear); + this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Left; + this.flowLayoutPanel2.Location = new System.Drawing.Point(0, 0); + this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel2.Name = "flowLayoutPanel2"; + this.flowLayoutPanel2.Size = new System.Drawing.Size(396, 29); + this.flowLayoutPanel2.TabIndex = 5; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.trkTurboSpeed, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.lblTurboSpeed, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.panel1, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.tabMain, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 3; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(599, 288); + this.tableLayoutPanel1.TabIndex = 23; + // + // trkTurboSpeed + // + this.trkTurboSpeed.LargeChange = 2; + this.trkTurboSpeed.Location = new System.Drawing.Point(479, 244); + this.trkTurboSpeed.Maximum = 3; + this.trkTurboSpeed.Name = "trkTurboSpeed"; + this.trkTurboSpeed.Size = new System.Drawing.Size(117, 26); + this.trkTurboSpeed.TabIndex = 0; + // + // lblTurboSpeed + // + this.lblTurboSpeed.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblTurboSpeed.AutoSize = true; + this.lblTurboSpeed.Location = new System.Drawing.Point(401, 250); + this.lblTurboSpeed.Name = "lblTurboSpeed"; + this.lblTurboSpeed.Size = new System.Drawing.Size(72, 13); + this.lblTurboSpeed.TabIndex = 1; + this.lblTurboSpeed.Text = "Turbo Speed:"; + // + // panel1 + // + this.panel1.Controls.Add(this.lblTurboFast); + this.panel1.Controls.Add(this.lblSlow); + this.panel1.Location = new System.Drawing.Point(476, 273); + this.panel1.Margin = new System.Windows.Forms.Padding(0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(120, 15); + this.panel1.TabIndex = 2; + // + // lblTurboFast + // + this.lblTurboFast.AutoSize = true; + this.lblTurboFast.Location = new System.Drawing.Point(90, 0); + this.lblTurboFast.Name = "lblTurboFast"; + this.lblTurboFast.Size = new System.Drawing.Size(27, 13); + this.lblTurboFast.TabIndex = 1; + this.lblTurboFast.Text = "Fast"; + // + // lblSlow + // + this.lblSlow.AutoSize = true; + this.lblSlow.Location = new System.Drawing.Point(3, 0); + this.lblSlow.Name = "lblSlow"; + this.lblSlow.Size = new System.Drawing.Size(30, 13); + this.lblSlow.TabIndex = 0; + this.lblSlow.Text = "Slow"; + // + // frmControllerConfig + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(599, 317); + this.Controls.Add(this.tableLayoutPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "frmControllerConfig"; + this.Text = "Standard Controller"; + this.Controls.SetChildIndex(this.baseConfigPanel, 0); + this.Controls.SetChildIndex(this.tableLayoutPanel1, 0); + this.baseConfigPanel.ResumeLayout(false); + this.tabMain.ResumeLayout(false); + this.tpgSet1.ResumeLayout(false); + this.tpgSet2.ResumeLayout(false); + this.tpgSet3.ResumeLayout(false); + this.tpgSet4.ResumeLayout(false); + this.flowLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trkTurboSpeed)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private ctrlStandardController ctrlStandardController0; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; + private System.Windows.Forms.Button btnReset; + private System.Windows.Forms.Button btnClear; + private System.Windows.Forms.TabControl tabMain; + private System.Windows.Forms.TabPage tpgSet1; + private System.Windows.Forms.TabPage tpgSet2; + private ctrlStandardController ctrlStandardController1; + private System.Windows.Forms.TabPage tpgSet3; + private ctrlStandardController ctrlStandardController2; + private System.Windows.Forms.TabPage tpgSet4; + private ctrlStandardController ctrlStandardController3; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.TrackBar trkTurboSpeed; + private System.Windows.Forms.Label lblTurboSpeed; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label lblTurboFast; + private System.Windows.Forms.Label lblSlow; + } +} \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmControllerConfig.cs b/GUI.NET/Forms/Config/frmControllerConfig.cs new file mode 100644 index 00000000..8c0f1411 --- /dev/null +++ b/GUI.NET/Forms/Config/frmControllerConfig.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Config; + +namespace Mesen.GUI.Forms.Config +{ + public partial class frmControllerConfig : BaseConfigForm + { + public frmControllerConfig(ControllerInfo controllerInfo) + { + InitializeComponent(); + + Entity = controllerInfo; + + AddBinding("TurboSpeed", trkTurboSpeed); + ctrlStandardController0.Initialize(controllerInfo.Keys[0]); + ctrlStandardController1.Initialize(controllerInfo.Keys[1]); + ctrlStandardController2.Initialize(controllerInfo.Keys[2]); + ctrlStandardController3.Initialize(controllerInfo.Keys[3]); + } + + protected override void UpdateConfig() + { + ControllerInfo controllerInfo = (ControllerInfo)Entity; + controllerInfo.Keys[0] = ctrlStandardController0.GetKeyMappings(); + controllerInfo.Keys[1] = ctrlStandardController1.GetKeyMappings(); + controllerInfo.Keys[2] = ctrlStandardController2.GetKeyMappings(); + controllerInfo.Keys[3] = ctrlStandardController3.GetKeyMappings(); + base.UpdateConfig(); + } + + private void btnClear_Click(object sender, EventArgs e) + { + ControllerInfo controllerInfo = (ControllerInfo)Entity; + if(tabMain.SelectedTab == tpgSet1) { + ctrlStandardController0.ClearKeys(); + } else if(tabMain.SelectedTab == tpgSet2) { + ctrlStandardController1.ClearKeys(); + } else if(tabMain.SelectedTab == tpgSet3) { + ctrlStandardController2.ClearKeys(); + } else if(tabMain.SelectedTab == tpgSet4) { + ctrlStandardController3.ClearKeys(); + } + } + + private void btnReset_Click(object sender, EventArgs e) + { + + } + } +} diff --git a/GUI.NET/Forms/Config/frmControllerConfig.resx b/GUI.NET/Forms/Config/frmControllerConfig.resx new file mode 100644 index 00000000..8766f298 --- /dev/null +++ b/GUI.NET/Forms/Config/frmControllerConfig.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmInputConfig.Designer.cs b/GUI.NET/Forms/Config/frmInputConfig.Designer.cs index 2cfb7a43..57806319 100644 --- a/GUI.NET/Forms/Config/frmInputConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmInputConfig.Designer.cs @@ -28,115 +28,277 @@ private void InitializeComponent() { this.tabMain = new System.Windows.Forms.TabControl(); - this.tpgPort1 = new System.Windows.Forms.TabPage(); - this.ctrlInputPortConfig1 = new Mesen.GUI.Forms.Config.ctrlInputPortConfig(); - this.tpgPort2 = new System.Windows.Forms.TabPage(); - this.ctrlInputPortConfig2 = new Mesen.GUI.Forms.Config.ctrlInputPortConfig(); - this.tpgPort3 = new System.Windows.Forms.TabPage(); - this.ctrlInputPortConfig3 = new Mesen.GUI.Forms.Config.ctrlInputPortConfig(); - this.tpgPort4 = new System.Windows.Forms.TabPage(); - this.ctrlInputPortConfig4 = new Mesen.GUI.Forms.Config.ctrlInputPortConfig(); + this.tpgControllers = new System.Windows.Forms.TabPage(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.btnSetupP4 = new System.Windows.Forms.Button(); + this.btnSetupP3 = new System.Windows.Forms.Button(); + this.lblPlayer1 = new System.Windows.Forms.Label(); + this.lblPlayer2 = new System.Windows.Forms.Label(); + this.cboPlayer4 = new System.Windows.Forms.ComboBox(); + this.cboPlayer3 = new System.Windows.Forms.ComboBox(); + this.cboPlayer1 = new System.Windows.Forms.ComboBox(); + this.lblPlayer4 = new System.Windows.Forms.Label(); + this.cboPlayer2 = new System.Windows.Forms.ComboBox(); + this.lblPlayer3 = new System.Windows.Forms.Label(); + this.btnSetupP1 = new System.Windows.Forms.Button(); + this.btnSetupP2 = new System.Windows.Forms.Button(); + this.lblNesType = new System.Windows.Forms.Label(); + this.cboConsoleType = new System.Windows.Forms.ComboBox(); + this.lblExpansionPort = new System.Windows.Forms.Label(); + this.cboExpansionPort = new System.Windows.Forms.ComboBox(); + this.chkFourScore = new System.Windows.Forms.CheckBox(); this.tpgEmulatorKeys = new System.Windows.Forms.TabPage(); this.tabMain.SuspendLayout(); - this.tpgPort1.SuspendLayout(); - this.tpgPort2.SuspendLayout(); - this.tpgPort3.SuspendLayout(); - this.tpgPort4.SuspendLayout(); + this.tpgControllers.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // + // baseConfigPanel + // + this.baseConfigPanel.Location = new System.Drawing.Point(0, 224); + this.baseConfigPanel.Size = new System.Drawing.Size(348, 29); + // // tabMain // - this.tabMain.Controls.Add(this.tpgPort1); - this.tabMain.Controls.Add(this.tpgPort2); - this.tabMain.Controls.Add(this.tpgPort3); - this.tabMain.Controls.Add(this.tpgPort4); + this.tabMain.Controls.Add(this.tpgControllers); this.tabMain.Controls.Add(this.tpgEmulatorKeys); this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; this.tabMain.Location = new System.Drawing.Point(0, 0); this.tabMain.Name = "tabMain"; this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(633, 376); + this.tabMain.Size = new System.Drawing.Size(348, 253); this.tabMain.TabIndex = 11; // - // tpgPort1 + // tpgControllers // - this.tpgPort1.Controls.Add(this.ctrlInputPortConfig1); - this.tpgPort1.Location = new System.Drawing.Point(4, 22); - this.tpgPort1.Name = "tpgPort1"; - this.tpgPort1.Size = new System.Drawing.Size(625, 350); - this.tpgPort1.TabIndex = 0; - this.tpgPort1.Text = "Port 1"; - this.tpgPort1.UseVisualStyleBackColor = true; + this.tpgControllers.Controls.Add(this.tableLayoutPanel1); + this.tpgControllers.Location = new System.Drawing.Point(4, 22); + this.tpgControllers.Name = "tpgControllers"; + this.tpgControllers.Size = new System.Drawing.Size(340, 227); + this.tpgControllers.TabIndex = 0; + this.tpgControllers.Text = "Controllers"; + this.tpgControllers.UseVisualStyleBackColor = true; // - // ctrlInputPortConfig1 + // tableLayoutPanel1 // - this.ctrlInputPortConfig1.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlInputPortConfig1.Location = new System.Drawing.Point(0, 0); - this.ctrlInputPortConfig1.Margin = new System.Windows.Forms.Padding(0); - this.ctrlInputPortConfig1.Name = "ctrlInputPortConfig1"; - this.ctrlInputPortConfig1.Size = new System.Drawing.Size(625, 350); - this.ctrlInputPortConfig1.TabIndex = 0; + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.btnSetupP4, 2, 7); + this.tableLayoutPanel1.Controls.Add(this.btnSetupP3, 2, 6); + this.tableLayoutPanel1.Controls.Add(this.lblPlayer1, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.lblPlayer2, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.cboPlayer4, 1, 7); + this.tableLayoutPanel1.Controls.Add(this.cboPlayer3, 1, 6); + this.tableLayoutPanel1.Controls.Add(this.cboPlayer1, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.lblPlayer4, 0, 7); + this.tableLayoutPanel1.Controls.Add(this.cboPlayer2, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.lblPlayer3, 0, 6); + this.tableLayoutPanel1.Controls.Add(this.btnSetupP1, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.btnSetupP2, 2, 3); + this.tableLayoutPanel1.Controls.Add(this.lblNesType, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.cboConsoleType, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.lblExpansionPort, 0, 5); + this.tableLayoutPanel1.Controls.Add(this.cboExpansionPort, 1, 5); + this.tableLayoutPanel1.Controls.Add(this.chkFourScore, 0, 4); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 9; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(340, 227); + this.tableLayoutPanel1.TabIndex = 0; // - // tpgPort2 + // btnSetupP4 // - this.tpgPort2.Controls.Add(this.ctrlInputPortConfig2); - this.tpgPort2.Location = new System.Drawing.Point(4, 22); - this.tpgPort2.Name = "tpgPort2"; - this.tpgPort2.Size = new System.Drawing.Size(625, 359); - this.tpgPort2.TabIndex = 1; - this.tpgPort2.Text = "Port 2"; - this.tpgPort2.UseVisualStyleBackColor = true; + this.btnSetupP4.Location = new System.Drawing.Point(279, 171); + this.btnSetupP4.Name = "btnSetupP4"; + this.btnSetupP4.Size = new System.Drawing.Size(56, 21); + this.btnSetupP4.TabIndex = 12; + this.btnSetupP4.Text = "Setup"; + this.btnSetupP4.UseVisualStyleBackColor = true; + this.btnSetupP4.Click += new System.EventHandler(this.btnSetup_Click); // - // ctrlInputPortConfig2 + // btnSetupP3 // - this.ctrlInputPortConfig2.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlInputPortConfig2.Location = new System.Drawing.Point(0, 0); - this.ctrlInputPortConfig2.Name = "ctrlInputPortConfig2"; - this.ctrlInputPortConfig2.Size = new System.Drawing.Size(625, 359); - this.ctrlInputPortConfig2.TabIndex = 1; + this.btnSetupP3.Location = new System.Drawing.Point(279, 144); + this.btnSetupP3.Name = "btnSetupP3"; + this.btnSetupP3.Size = new System.Drawing.Size(56, 21); + this.btnSetupP3.TabIndex = 11; + this.btnSetupP3.Text = "Setup"; + this.btnSetupP3.UseVisualStyleBackColor = true; + this.btnSetupP3.Click += new System.EventHandler(this.btnSetup_Click); // - // tpgPort3 + // lblPlayer1 // - this.tpgPort3.Controls.Add(this.ctrlInputPortConfig3); - this.tpgPort3.Location = new System.Drawing.Point(4, 22); - this.tpgPort3.Name = "tpgPort3"; - this.tpgPort3.Size = new System.Drawing.Size(625, 359); - this.tpgPort3.TabIndex = 2; - this.tpgPort3.Text = "Port 3"; - this.tpgPort3.UseVisualStyleBackColor = true; + this.lblPlayer1.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPlayer1.AutoSize = true; + this.lblPlayer1.Location = new System.Drawing.Point(3, 44); + this.lblPlayer1.Name = "lblPlayer1"; + this.lblPlayer1.Size = new System.Drawing.Size(48, 13); + this.lblPlayer1.TabIndex = 0; + this.lblPlayer1.Text = "Player 1:"; // - // ctrlInputPortConfig3 + // lblPlayer2 // - this.ctrlInputPortConfig3.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlInputPortConfig3.Location = new System.Drawing.Point(0, 0); - this.ctrlInputPortConfig3.Name = "ctrlInputPortConfig3"; - this.ctrlInputPortConfig3.Size = new System.Drawing.Size(625, 359); - this.ctrlInputPortConfig3.TabIndex = 1; + this.lblPlayer2.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPlayer2.AutoSize = true; + this.lblPlayer2.Location = new System.Drawing.Point(3, 71); + this.lblPlayer2.Name = "lblPlayer2"; + this.lblPlayer2.Size = new System.Drawing.Size(48, 13); + this.lblPlayer2.TabIndex = 1; + this.lblPlayer2.Text = "Player 2:"; // - // tpgPort4 + // cboPlayer4 // - this.tpgPort4.Controls.Add(this.ctrlInputPortConfig4); - this.tpgPort4.Location = new System.Drawing.Point(4, 22); - this.tpgPort4.Name = "tpgPort4"; - this.tpgPort4.Size = new System.Drawing.Size(625, 359); - this.tpgPort4.TabIndex = 3; - this.tpgPort4.Text = "Port 4"; - this.tpgPort4.UseVisualStyleBackColor = true; + this.cboPlayer4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboPlayer4.FormattingEnabled = true; + this.cboPlayer4.Location = new System.Drawing.Point(90, 171); + this.cboPlayer4.Name = "cboPlayer4"; + this.cboPlayer4.Size = new System.Drawing.Size(183, 21); + this.cboPlayer4.TabIndex = 8; + this.cboPlayer4.SelectedIndexChanged += new System.EventHandler(this.cboPlayerController_SelectedIndexChanged); // - // ctrlInputPortConfig4 + // cboPlayer3 // - this.ctrlInputPortConfig4.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlInputPortConfig4.Location = new System.Drawing.Point(0, 0); - this.ctrlInputPortConfig4.Margin = new System.Windows.Forms.Padding(0); - this.ctrlInputPortConfig4.Name = "ctrlInputPortConfig4"; - this.ctrlInputPortConfig4.Size = new System.Drawing.Size(625, 359); - this.ctrlInputPortConfig4.TabIndex = 1; + this.cboPlayer3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboPlayer3.FormattingEnabled = true; + this.cboPlayer3.Location = new System.Drawing.Point(90, 144); + this.cboPlayer3.Name = "cboPlayer3"; + this.cboPlayer3.Size = new System.Drawing.Size(183, 21); + this.cboPlayer3.TabIndex = 7; + this.cboPlayer3.SelectedIndexChanged += new System.EventHandler(this.cboPlayerController_SelectedIndexChanged); + // + // cboPlayer1 + // + this.cboPlayer1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboPlayer1.FormattingEnabled = true; + this.cboPlayer1.Location = new System.Drawing.Point(90, 40); + this.cboPlayer1.Name = "cboPlayer1"; + this.cboPlayer1.Size = new System.Drawing.Size(183, 21); + this.cboPlayer1.TabIndex = 4; + this.cboPlayer1.SelectedIndexChanged += new System.EventHandler(this.cboPlayerController_SelectedIndexChanged); + // + // lblPlayer4 + // + this.lblPlayer4.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPlayer4.AutoSize = true; + this.lblPlayer4.Location = new System.Drawing.Point(3, 175); + this.lblPlayer4.Name = "lblPlayer4"; + this.lblPlayer4.Size = new System.Drawing.Size(48, 13); + this.lblPlayer4.TabIndex = 3; + this.lblPlayer4.Text = "Player 4:"; + // + // cboPlayer2 + // + this.cboPlayer2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboPlayer2.FormattingEnabled = true; + this.cboPlayer2.Location = new System.Drawing.Point(90, 67); + this.cboPlayer2.Name = "cboPlayer2"; + this.cboPlayer2.Size = new System.Drawing.Size(183, 21); + this.cboPlayer2.TabIndex = 6; + this.cboPlayer2.SelectedIndexChanged += new System.EventHandler(this.cboPlayerController_SelectedIndexChanged); + // + // lblPlayer3 + // + this.lblPlayer3.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPlayer3.AutoSize = true; + this.lblPlayer3.Location = new System.Drawing.Point(3, 148); + this.lblPlayer3.Name = "lblPlayer3"; + this.lblPlayer3.Size = new System.Drawing.Size(48, 13); + this.lblPlayer3.TabIndex = 2; + this.lblPlayer3.Text = "Player 3:"; + // + // btnSetupP1 + // + this.btnSetupP1.Location = new System.Drawing.Point(279, 40); + this.btnSetupP1.Name = "btnSetupP1"; + this.btnSetupP1.Size = new System.Drawing.Size(56, 21); + this.btnSetupP1.TabIndex = 9; + this.btnSetupP1.Text = "Setup"; + this.btnSetupP1.UseVisualStyleBackColor = true; + this.btnSetupP1.Click += new System.EventHandler(this.btnSetup_Click); + // + // btnSetupP2 + // + this.btnSetupP2.Location = new System.Drawing.Point(279, 67); + this.btnSetupP2.Name = "btnSetupP2"; + this.btnSetupP2.Size = new System.Drawing.Size(56, 21); + this.btnSetupP2.TabIndex = 10; + this.btnSetupP2.Text = "Setup"; + this.btnSetupP2.UseVisualStyleBackColor = true; + this.btnSetupP2.Click += new System.EventHandler(this.btnSetup_Click); + // + // lblNesType + // + this.lblNesType.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblNesType.AutoSize = true; + this.lblNesType.Location = new System.Drawing.Point(3, 7); + this.lblNesType.Name = "lblNesType"; + this.lblNesType.Size = new System.Drawing.Size(75, 13); + this.lblNesType.TabIndex = 13; + this.lblNesType.Text = "Console Type:"; + // + // cboNesType + // + this.cboConsoleType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboConsoleType.FormattingEnabled = true; + this.cboConsoleType.Items.AddRange(new object[] { + "NES", + "Famicom"}); + this.cboConsoleType.Location = new System.Drawing.Point(90, 3); + this.cboConsoleType.Name = "cboNesType"; + this.cboConsoleType.Size = new System.Drawing.Size(109, 21); + this.cboConsoleType.TabIndex = 14; + this.cboConsoleType.SelectedIndexChanged += new System.EventHandler(this.cboNesType_SelectedIndexChanged); + // + // lblExpansionPort + // + this.lblExpansionPort.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblExpansionPort.AutoSize = true; + this.lblExpansionPort.Location = new System.Drawing.Point(3, 121); + this.lblExpansionPort.Name = "lblExpansionPort"; + this.lblExpansionPort.Size = new System.Drawing.Size(81, 13); + this.lblExpansionPort.TabIndex = 16; + this.lblExpansionPort.Text = "Expansion Port:"; + // + // cboExpansionPort + // + this.cboExpansionPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboExpansionPort.FormattingEnabled = true; + this.cboExpansionPort.Location = new System.Drawing.Point(90, 117); + this.cboExpansionPort.Name = "cboExpansionPort"; + this.cboExpansionPort.Size = new System.Drawing.Size(183, 21); + this.cboExpansionPort.TabIndex = 17; + this.cboExpansionPort.SelectedIndexChanged += new System.EventHandler(this.cboExpansionPort_SelectedIndexChanged); + // + // chkFourScore + // + this.chkFourScore.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.chkFourScore.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.chkFourScore, 2); + this.chkFourScore.Location = new System.Drawing.Point(3, 94); + this.chkFourScore.Name = "chkFourScore"; + this.chkFourScore.Size = new System.Drawing.Size(151, 17); + this.chkFourScore.TabIndex = 15; + this.chkFourScore.Text = "Use Four Score accessory"; + this.chkFourScore.UseVisualStyleBackColor = true; + this.chkFourScore.CheckedChanged += new System.EventHandler(this.chkFourScore_CheckedChanged); // // tpgEmulatorKeys // this.tpgEmulatorKeys.Location = new System.Drawing.Point(4, 22); this.tpgEmulatorKeys.Name = "tpgEmulatorKeys"; - this.tpgEmulatorKeys.Size = new System.Drawing.Size(625, 359); + this.tpgEmulatorKeys.Size = new System.Drawing.Size(340, 227); this.tpgEmulatorKeys.TabIndex = 4; this.tpgEmulatorKeys.Text = "Emulator Keys"; this.tpgEmulatorKeys.UseVisualStyleBackColor = true; @@ -145,17 +307,18 @@ // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(633, 406); + this.ClientSize = new System.Drawing.Size(348, 253); this.Controls.Add(this.tabMain); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Name = "frmInputConfig"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Input Settings"; this.Controls.SetChildIndex(this.tabMain, 0); + this.Controls.SetChildIndex(this.baseConfigPanel, 0); this.tabMain.ResumeLayout(false); - this.tpgPort1.ResumeLayout(false); - this.tpgPort2.ResumeLayout(false); - this.tpgPort3.ResumeLayout(false); - this.tpgPort4.ResumeLayout(false); + this.tpgControllers.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); this.ResumeLayout(false); } @@ -163,15 +326,25 @@ #endregion private System.Windows.Forms.TabControl tabMain; - private System.Windows.Forms.TabPage tpgPort2; - private System.Windows.Forms.TabPage tpgPort3; - private System.Windows.Forms.TabPage tpgPort4; private System.Windows.Forms.TabPage tpgEmulatorKeys; - private System.Windows.Forms.TabPage tpgPort1; - private ctrlInputPortConfig ctrlInputPortConfig1; - private ctrlInputPortConfig ctrlInputPortConfig2; - private ctrlInputPortConfig ctrlInputPortConfig3; - private ctrlInputPortConfig ctrlInputPortConfig4; - + private System.Windows.Forms.TabPage tpgControllers; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label lblPlayer1; + private System.Windows.Forms.Label lblPlayer2; + private System.Windows.Forms.Label lblPlayer3; + private System.Windows.Forms.Label lblPlayer4; + private System.Windows.Forms.ComboBox cboPlayer1; + private System.Windows.Forms.ComboBox cboPlayer2; + private System.Windows.Forms.Button btnSetupP1; + private System.Windows.Forms.Button btnSetupP2; + private System.Windows.Forms.Label lblNesType; + private System.Windows.Forms.ComboBox cboConsoleType; + private System.Windows.Forms.Label lblExpansionPort; + private System.Windows.Forms.ComboBox cboExpansionPort; + private System.Windows.Forms.CheckBox chkFourScore; + private System.Windows.Forms.Button btnSetupP3; + private System.Windows.Forms.Button btnSetupP4; + private System.Windows.Forms.ComboBox cboPlayer3; + private System.Windows.Forms.ComboBox cboPlayer4; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmInputConfig.cs b/GUI.NET/Forms/Config/frmInputConfig.cs index 5a14b90e..617ae50f 100644 --- a/GUI.NET/Forms/Config/frmInputConfig.cs +++ b/GUI.NET/Forms/Config/frmInputConfig.cs @@ -17,20 +17,157 @@ namespace Mesen.GUI.Forms.Config { InitializeComponent(); - ctrlInputPortConfig1.Initialize(ConfigManager.Config.Controllers[0]); - ctrlInputPortConfig2.Initialize(ConfigManager.Config.Controllers[1]); - ctrlInputPortConfig3.Initialize(ConfigManager.Config.Controllers[2]); - ctrlInputPortConfig4.Initialize(ConfigManager.Config.Controllers[3]); + Entity = ConfigManager.Config.InputInfo; + + AddBinding("ExpansionPortDevice", cboExpansionPort); + AddBinding("ConsoleType", cboConsoleType); + AddBinding("UseFourScore", chkFourScore); + } + + protected override void AfterUpdateUI() + { + base.AfterUpdateUI(); + + this.UpdateInterface(); + + InputInfo inputInfo = (InputInfo)Entity; + cboPlayer1.SelectedItem = inputInfo.Controllers[0].ControllerType.ToString(); + cboPlayer2.SelectedItem = inputInfo.Controllers[1].ControllerType.ToString(); + cboPlayer3.SelectedItem = inputInfo.Controllers[2].ControllerType.ToString(); + cboPlayer4.SelectedItem = inputInfo.Controllers[3].ControllerType.ToString(); + } + + private void UpdateAvailableControllerTypes() + { + bool isNes = ((InputInfo)Entity).ConsoleType == ConsoleType.Nes; + bool p3and4visible = (isNes && chkFourScore.Checked) || (!isNes && ((InputInfo)Entity).ExpansionPortDevice == InteropEmu.ExpansionPortDevice.FourPlayerAdapter); + + List controllerTypes = new List(new InteropEmu.ControllerType[] { InteropEmu.ControllerType.StandardController }); + SetAvailableControllerTypes(cboPlayer3, controllerTypes.ToArray()); + SetAvailableControllerTypes(cboPlayer4, controllerTypes.ToArray()); + + if(isNes && !chkFourScore.Checked) { + controllerTypes.Add(InteropEmu.ControllerType.Zapper); + } + SetAvailableControllerTypes(cboPlayer1, controllerTypes.ToArray()); + SetAvailableControllerTypes(cboPlayer2, controllerTypes.ToArray()); + } + + private void SetAvailableControllerTypes(ComboBox comboBox, InteropEmu.ControllerType[] controllerTypes) + { + object currentSelection = comboBox.SelectedItem; + comboBox.Items.Clear(); + comboBox.Items.Add(InteropEmu.ControllerType.None.ToString()); + foreach(InteropEmu.ControllerType type in controllerTypes) { + comboBox.Items.Add(type.ToString()); + } + + comboBox.SelectedItem = currentSelection; + if(comboBox.SelectedIndex < 0) { + comboBox.SelectedIndex = 0; + } } protected override void UpdateConfig() { - ctrlInputPortConfig1.UpdateConfig(); - ctrlInputPortConfig2.UpdateConfig(); - ctrlInputPortConfig3.UpdateConfig(); - ctrlInputPortConfig4.UpdateConfig(); + InputInfo inputInfo = (InputInfo)Entity; - ControllerInfo.ApplyConfig(); + inputInfo.Controllers[0].ControllerType = (InteropEmu.ControllerType)Enum.Parse(typeof(InteropEmu.ControllerType), cboPlayer1.SelectedItem.ToString()); + inputInfo.Controllers[1].ControllerType = (InteropEmu.ControllerType)Enum.Parse(typeof(InteropEmu.ControllerType), cboPlayer2.SelectedItem.ToString()); + inputInfo.Controllers[2].ControllerType = (InteropEmu.ControllerType)Enum.Parse(typeof(InteropEmu.ControllerType), cboPlayer3.SelectedItem.ToString()); + inputInfo.Controllers[3].ControllerType = (InteropEmu.ControllerType)Enum.Parse(typeof(InteropEmu.ControllerType), cboPlayer4.SelectedItem.ToString()); + + InputInfo.ApplyConfig(); + } + + private void UpdateInterface() + { + if(!this.Updating) { + UpdateObject(); + bool isNes = ((InputInfo)Entity).ConsoleType == ConsoleType.Nes; + cboExpansionPort.Visible = !isNes; + lblExpansionPort.Visible = !isNes; + chkFourScore.Visible = isNes; + + UpdatePlayer3And4Visibility(); + UpdateAvailableControllerTypes(); + } + } + + private void UpdatePlayer3And4Visibility() + { + bool isNes = ((InputInfo)Entity).ConsoleType == ConsoleType.Nes; + bool visible = (isNes && chkFourScore.Checked) || (!isNes && ((InputInfo)Entity).ExpansionPortDevice == InteropEmu.ExpansionPortDevice.FourPlayerAdapter); + + lblPlayer3.Visible = visible; + lblPlayer4.Visible = visible; + cboPlayer3.Visible = visible; + cboPlayer4.Visible = visible; + btnSetupP3.Visible = visible; + btnSetupP4.Visible = visible; + } + + private void cboNesType_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateInterface(); + } + + private void chkFourScore_CheckedChanged(object sender, EventArgs e) + { + UpdateInterface(); + } + + private void cboExpansionPort_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateInterface(); + } + + private void cboPlayerController_SelectedIndexChanged(object sender, EventArgs e) + { + bool enableButton = (((ComboBox)sender).SelectedItem.Equals(InteropEmu.ControllerType.StandardController.ToString())); + if(sender == cboPlayer1) { + btnSetupP1.Enabled = enableButton; + } else if(sender == cboPlayer2) { + btnSetupP2.Enabled = enableButton; + } else if(sender == cboPlayer3) { + btnSetupP3.Enabled = enableButton; + } else if(sender == cboPlayer4) { + btnSetupP4.Enabled = enableButton; + } + } + + private void btnSetup_Click(object sender, EventArgs e) + { + int index = 0; + if(sender == btnSetupP1) { + index = 0; + } else if(sender == btnSetupP2) { + index = 1; + } else if(sender == btnSetupP3) { + index = 2; + } else if(sender == btnSetupP4) { + index = 3; + } + var frm = new frmControllerConfig(ConfigManager.Config.InputInfo.Controllers[index]); + + Button btn = (Button)sender; + Point point = btn.PointToScreen(new Point(0, btn.Height)); + Rectangle screen = Screen.FromControl(btn).Bounds; + + if(frm.Height + point.Y > screen.Bottom) { + //Show on top instead + point.Y -= btn.Height + frm.Height; + } + + if(frm.Width + point.X > screen.Right) { + //Show on left instead + point.X -= frm.Width - btn.Width; + } + + frm.StartPosition = FormStartPosition.Manual; + frm.Top = point.Y; + frm.Left = point.X; + frm.ShowDialog(this); } } } diff --git a/GUI.NET/Forms/Config/frmInputConfig.resx b/GUI.NET/Forms/Config/frmInputConfig.resx index 1af7de15..8766f298 100644 --- a/GUI.NET/Forms/Config/frmInputConfig.resx +++ b/GUI.NET/Forms/Config/frmInputConfig.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs index 95f73b85..bca41c73 100644 --- a/GUI.NET/Forms/frmMain.Designer.cs +++ b/GUI.NET/Forms/frmMain.Designer.cs @@ -90,12 +90,9 @@ this.mnuTools = new System.Windows.Forms.ToolStripMenuItem(); this.mnuNetPlay = new System.Windows.Forms.ToolStripMenuItem(); this.mnuStartServer = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuStopServer = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuConnect = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); this.mnuFindServer = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuConnect = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuDisconnect = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); this.mnuProfile = new System.Windows.Forms.ToolStripMenuItem(); this.mnuCheats = new System.Windows.Forms.ToolStripMenuItem(); this.mnuMovies = new System.Windows.Forms.ToolStripMenuItem(); @@ -104,6 +101,7 @@ this.mnuRecordFromStart = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRecordFromNow = new System.Windows.Forms.ToolStripMenuItem(); this.mnuStopMovie = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripSeparator(); this.mnuTests = new System.Windows.Forms.ToolStripMenuItem(); this.mnuTestRun = new System.Windows.Forms.ToolStripMenuItem(); this.mnuTestRecordFrom = new System.Windows.Forms.ToolStripMenuItem(); @@ -114,15 +112,14 @@ this.mnuTestStopRecording = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunAllTests = new System.Windows.Forms.ToolStripMenuItem(); this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem(); this.mnuHelp = new System.Windows.Forms.ToolStripMenuItem(); this.mnuCheckForUpdates = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); this.menuTimer = new System.Windows.Forms.Timer(this.components); - this.dxViewer = new Mesen.GUI.Controls.DXViewer(); - this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); - this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripSeparator(); + this.ctrlRenderer = new Mesen.GUI.Controls.ctrlRenderer(); this.menuStrip.SuspendLayout(); this.SuspendLayout(); // @@ -160,49 +157,49 @@ this.mnuOpen.Image = global::Mesen.GUI.Properties.Resources.folder; this.mnuOpen.Name = "mnuOpen"; this.mnuOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); - this.mnuOpen.Size = new System.Drawing.Size(152, 22); + this.mnuOpen.Size = new System.Drawing.Size(146, 22); this.mnuOpen.Text = "Open"; this.mnuOpen.Click += new System.EventHandler(this.mnuOpen_Click); // // toolStripMenuItem4 // this.toolStripMenuItem4.Name = "toolStripMenuItem4"; - this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6); + this.toolStripMenuItem4.Size = new System.Drawing.Size(143, 6); // // mnuSaveState // this.mnuSaveState.Name = "mnuSaveState"; - this.mnuSaveState.Size = new System.Drawing.Size(152, 22); + this.mnuSaveState.Size = new System.Drawing.Size(146, 22); this.mnuSaveState.Text = "Save State"; this.mnuSaveState.DropDownOpening += new System.EventHandler(this.mnuSaveState_DropDownOpening); // // mnuLoadState // this.mnuLoadState.Name = "mnuLoadState"; - this.mnuLoadState.Size = new System.Drawing.Size(152, 22); + this.mnuLoadState.Size = new System.Drawing.Size(146, 22); this.mnuLoadState.Text = "Load State"; this.mnuLoadState.DropDownOpening += new System.EventHandler(this.mnuLoadState_DropDownOpening); // // toolStripMenuItem7 // this.toolStripMenuItem7.Name = "toolStripMenuItem7"; - this.toolStripMenuItem7.Size = new System.Drawing.Size(149, 6); + this.toolStripMenuItem7.Size = new System.Drawing.Size(143, 6); // // mnuRecentFiles // this.mnuRecentFiles.Name = "mnuRecentFiles"; - this.mnuRecentFiles.Size = new System.Drawing.Size(152, 22); + this.mnuRecentFiles.Size = new System.Drawing.Size(146, 22); this.mnuRecentFiles.Text = "Recent Files"; // // toolStripMenuItem6 // this.toolStripMenuItem6.Name = "toolStripMenuItem6"; - this.toolStripMenuItem6.Size = new System.Drawing.Size(149, 6); + this.toolStripMenuItem6.Size = new System.Drawing.Size(143, 6); // // mnuExit // this.mnuExit.Name = "mnuExit"; - this.mnuExit.Size = new System.Drawing.Size(152, 22); + this.mnuExit.Size = new System.Drawing.Size(146, 22); this.mnuExit.Text = "Exit"; this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click); // @@ -558,12 +555,9 @@ // this.mnuNetPlay.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuStartServer, - this.mnuStopServer, + this.mnuConnect, this.toolStripMenuItem2, this.mnuFindServer, - this.mnuConnect, - this.mnuDisconnect, - this.toolStripMenuItem3, this.mnuProfile}); this.mnuNetPlay.Image = global::Mesen.GUI.Properties.Resources.globe_network; this.mnuNetPlay.Name = "mnuNetPlay"; @@ -577,12 +571,12 @@ this.mnuStartServer.Text = "Start Server"; this.mnuStartServer.Click += new System.EventHandler(this.mnuStartServer_Click); // - // mnuStopServer + // mnuConnect // - this.mnuStopServer.Name = "mnuStopServer"; - this.mnuStopServer.Size = new System.Drawing.Size(177, 22); - this.mnuStopServer.Text = "Stop Server"; - this.mnuStopServer.Click += new System.EventHandler(this.mnuStopServer_Click); + this.mnuConnect.Name = "mnuConnect"; + this.mnuConnect.Size = new System.Drawing.Size(177, 22); + this.mnuConnect.Text = "Connect to Server"; + this.mnuConnect.Click += new System.EventHandler(this.mnuConnect_Click); // // toolStripMenuItem2 // @@ -595,25 +589,7 @@ this.mnuFindServer.Name = "mnuFindServer"; this.mnuFindServer.Size = new System.Drawing.Size(177, 22); this.mnuFindServer.Text = "Find Public Server..."; - // - // mnuConnect - // - this.mnuConnect.Name = "mnuConnect"; - this.mnuConnect.Size = new System.Drawing.Size(177, 22); - this.mnuConnect.Text = "Connect..."; - this.mnuConnect.Click += new System.EventHandler(this.mnuConnect_Click); - // - // mnuDisconnect - // - this.mnuDisconnect.Name = "mnuDisconnect"; - this.mnuDisconnect.Size = new System.Drawing.Size(177, 22); - this.mnuDisconnect.Text = "Disconnect"; - this.mnuDisconnect.Click += new System.EventHandler(this.mnuDisconnect_Click); - // - // toolStripMenuItem3 - // - this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(174, 6); + this.mnuFindServer.Visible = false; // // mnuProfile // @@ -677,6 +653,11 @@ this.mnuStopMovie.Text = "Stop"; this.mnuStopMovie.Click += new System.EventHandler(this.mnuStopMovie_Click); // + // toolStripMenuItem12 + // + this.toolStripMenuItem12.Name = "toolStripMenuItem12"; + this.toolStripMenuItem12.Size = new System.Drawing.Size(182, 6); + // // mnuTests // this.mnuTests.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -758,6 +739,11 @@ this.mnuDebugger.Text = "Debugger"; this.mnuDebugger.Click += new System.EventHandler(this.mnuDebugger_Click); // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(182, 6); + // // mnuTakeScreenshot // this.mnuTakeScreenshot.Image = global::Mesen.GUI.Properties.Resources.camera; @@ -801,24 +787,14 @@ // this.menuTimer.Tick += new System.EventHandler(this.menuTimer_Tick); // - // dxViewer + // ctrlRenderer // - this.dxViewer.BackColor = System.Drawing.Color.Black; - this.dxViewer.Location = new System.Drawing.Point(0, 24); - this.dxViewer.Margin = new System.Windows.Forms.Padding(0); - this.dxViewer.Name = "dxViewer"; - this.dxViewer.Size = new System.Drawing.Size(263, 176); - this.dxViewer.TabIndex = 1; - // - // toolStripMenuItem1 - // - this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(182, 6); - // - // toolStripMenuItem12 - // - this.toolStripMenuItem12.Name = "toolStripMenuItem12"; - this.toolStripMenuItem12.Size = new System.Drawing.Size(182, 6); + this.ctrlRenderer.BackColor = System.Drawing.Color.Black; + this.ctrlRenderer.Location = new System.Drawing.Point(0, 24); + this.ctrlRenderer.Margin = new System.Windows.Forms.Padding(0); + this.ctrlRenderer.Name = "ctrlRenderer"; + this.ctrlRenderer.Size = new System.Drawing.Size(263, 176); + this.ctrlRenderer.TabIndex = 1; // // frmMain // @@ -829,7 +805,7 @@ this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.BackColor = System.Drawing.Color.Black; this.ClientSize = new System.Drawing.Size(365, 272); - this.Controls.Add(this.dxViewer); + this.Controls.Add(this.ctrlRenderer); this.Controls.Add(this.menuStrip); this.MainMenuStrip = this.menuStrip; this.Name = "frmMain"; @@ -849,7 +825,7 @@ private System.Windows.Forms.ToolStripMenuItem mnuFile; private System.Windows.Forms.ToolStripMenuItem mnuOpen; private System.Windows.Forms.ToolStripMenuItem mnuGame; - private Mesen.GUI.Controls.DXViewer dxViewer; + private Mesen.GUI.Controls.ctrlRenderer ctrlRenderer; private System.Windows.Forms.ToolStripMenuItem mnuPause; private System.Windows.Forms.ToolStripMenuItem mnuReset; private System.Windows.Forms.ToolStripMenuItem mnuStop; @@ -862,11 +838,8 @@ private System.Windows.Forms.ToolStripMenuItem mnuTools; private System.Windows.Forms.ToolStripMenuItem mnuNetPlay; private System.Windows.Forms.ToolStripMenuItem mnuStartServer; - private System.Windows.Forms.ToolStripMenuItem mnuStopServer; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; private System.Windows.Forms.ToolStripMenuItem mnuConnect; - private System.Windows.Forms.ToolStripMenuItem mnuDisconnect; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; private System.Windows.Forms.ToolStripMenuItem mnuProfile; private System.Windows.Forms.ToolStripMenuItem mnuMovies; private System.Windows.Forms.ToolStripMenuItem mnuPlayMovie; diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs index b623a589..01f74c39 100644 --- a/GUI.NET/Forms/frmMain.cs +++ b/GUI.NET/Forms/frmMain.cs @@ -74,7 +74,7 @@ namespace Mesen.GUI.Forms void InitializeEmu() { - InteropEmu.InitializeEmu(ConfigManager.HomeFolder, this.Handle, this.dxViewer.Handle); + InteropEmu.InitializeEmu(ConfigManager.HomeFolder, this.Handle, this.ctrlRenderer.Handle); foreach(string romPath in ConfigManager.Config.RecentFiles) { InteropEmu.AddKnowGameFolder(Path.GetDirectoryName(romPath).ToLowerInvariant()); } @@ -183,7 +183,7 @@ namespace Mesen.GUI.Forms case VideoAspectRatio.Standard: size.Width = (int)(size.Height * 4 / 3.0); break; case VideoAspectRatio.Widescreen: size.Width = (int)(size.Height * 16 / 9.0); break; } - dxViewer.Size = new Size(size.Width, size.Height); + ctrlRenderer.Size = new Size(size.Width, size.Height); } private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) @@ -198,6 +198,10 @@ namespace Mesen.GUI.Forms this.StartEmuThread(); break; + case InteropEmu.ConsoleNotificationType.DisconnectedFromServer: + ConfigManager.Config.ApplyConfig(); + break; + case InteropEmu.ConsoleNotificationType.GameStopped: CheatInfo.ClearCheats(); break; @@ -320,33 +324,40 @@ namespace Mesen.GUI.Forms this.Text = "Mesen - " + _currentGame; } - mnuSaveState.Enabled = mnuLoadState.Enabled = mnuPause.Enabled = mnuStop.Enabled = mnuReset.Enabled = (_emuThread != null && !InteropEmu.IsConnected()); + bool isNetPlayClient = InteropEmu.IsConnected(); + + mnuSaveState.Enabled = mnuLoadState.Enabled = mnuPause.Enabled = mnuStop.Enabled = mnuReset.Enabled = (_emuThread != null && !isNetPlayClient); mnuPause.Text = InteropEmu.IsPaused() ? "Resume" : "Pause"; mnuPause.Image = InteropEmu.IsPaused() ? Mesen.GUI.Properties.Resources.control_play : Mesen.GUI.Properties.Resources.control_pause; - bool netPlay = InteropEmu.IsServerRunning() || InteropEmu.IsConnected(); + bool netPlay = InteropEmu.IsServerRunning() || isNetPlayClient; - mnuStartServer.Enabled = !netPlay; - mnuStopServer.Enabled = !mnuStartServer.Enabled && !InteropEmu.IsConnected(); + mnuStartServer.Enabled = !isNetPlayClient; + mnuConnect.Enabled = !InteropEmu.IsServerRunning(); - mnuConnect.Enabled = !netPlay; - mnuDisconnect.Enabled = !mnuConnect.Enabled && !InteropEmu.IsServerRunning(); + mnuStartServer.Text = InteropEmu.IsServerRunning() ? "Stop Server" : "Start Server"; + mnuConnect.Text = isNetPlayClient ? "Disconnect" : "Connect to Server"; - mnuCheats.Enabled = !InteropEmu.IsConnected(); - mnuEmulationSpeed.Enabled = !InteropEmu.IsConnected(); + mnuCheats.Enabled = !isNetPlayClient; + mnuEmulationSpeed.Enabled = !isNetPlayClient; + mnuIncreaseSpeed.Enabled = !isNetPlayClient; + mnuDecreaseSpeed.Enabled = !isNetPlayClient; + mnuEmuSpeedMaximumSpeed.Enabled = !isNetPlayClient; + mnuInput.Enabled = !isNetPlayClient; + mnuRegion.Enabled = !isNetPlayClient; bool moviePlaying = InteropEmu.MoviePlaying(); bool movieRecording = InteropEmu.MovieRecording(); mnuPlayMovie.Enabled = !netPlay && !moviePlaying && !movieRecording; mnuStopMovie.Enabled = _emuThread != null && !netPlay && (moviePlaying || movieRecording); mnuRecordFrom.Enabled = _emuThread != null && !moviePlaying && !movieRecording; - mnuRecordFromStart.Enabled = _emuThread != null && !InteropEmu.IsConnected() && !moviePlaying && !movieRecording; + mnuRecordFromStart.Enabled = _emuThread != null && !isNetPlayClient && !moviePlaying && !movieRecording; mnuRecordFromNow.Enabled = _emuThread != null && !moviePlaying && !movieRecording; bool testRecording = InteropEmu.RomTestRecording(); mnuTestRun.Enabled = !netPlay && !moviePlaying && !movieRecording; mnuTestStopRecording.Enabled = _emuThread != null && testRecording; - mnuTestRecordStart.Enabled = _emuThread != null && !InteropEmu.IsConnected() && !moviePlaying && !movieRecording; + mnuTestRecordStart.Enabled = _emuThread != null && !isNetPlayClient && !moviePlaying && !movieRecording; mnuTestRecordNow.Enabled = _emuThread != null && !moviePlaying && !movieRecording; mnuTestRecordMovie.Enabled = !netPlay && !moviePlaying && !movieRecording; mnuTestRecordTest.Enabled = !netPlay && !moviePlaying && !movieRecording; @@ -494,17 +505,25 @@ namespace Mesen.GUI.Forms private void mnuStartServer_Click(object sender, EventArgs e) { - frmServerConfig frm = new frmServerConfig(); - if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) { - InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port); + if(InteropEmu.IsServerRunning()) { + Task.Run(() => InteropEmu.StopServer()); + } else { + frmServerConfig frm = new frmServerConfig(); + if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) { + InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port); + } } } private void mnuConnect_Click(object sender, EventArgs e) { - frmClientConfig frm = new frmClientConfig(); - if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) { - InteropEmu.Connect(ConfigManager.Config.ClientConnectionInfo.Host, ConfigManager.Config.ClientConnectionInfo.Port, ConfigManager.Config.Profile.PlayerName, ConfigManager.Config.Profile.PlayerAvatar, (UInt16)ConfigManager.Config.Profile.PlayerAvatar.Length); + if(InteropEmu.IsConnected()) { + Task.Run(() => InteropEmu.Disconnect()); + } else { + frmClientConfig frm = new frmClientConfig(); + if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) { + InteropEmu.Connect(ConfigManager.Config.ClientConnectionInfo.Host, ConfigManager.Config.ClientConnectionInfo.Port, ConfigManager.Config.Profile.PlayerName, ConfigManager.Config.Profile.PlayerAvatar, (UInt16)ConfigManager.Config.Profile.PlayerAvatar.Length); + } } } @@ -512,16 +531,6 @@ namespace Mesen.GUI.Forms { new frmPlayerProfile().ShowDialog(sender); } - - private void mnuStopServer_Click(object sender, EventArgs e) - { - Task.Run(() => InteropEmu.StopServer()); - } - - private void mnuDisconnect_Click(object sender, EventArgs e) - { - Task.Run(() => InteropEmu.Disconnect()); - } private void mnuExit_Click(object sender, EventArgs e) { @@ -712,7 +721,7 @@ namespace Mesen.GUI.Forms private void mnuCheats_Click(object sender, EventArgs e) { frmCheatList frm = new frmCheatList(); - frm.Show(this); + frm.Show(sender, this); frm.FormClosed += (object a, FormClosedEventArgs b) => { frm = null; CheatInfo.ApplyCheats(); diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index c80f514d..f8a74aed 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -161,7 +161,7 @@ - + @@ -175,11 +175,11 @@ ctrlTrackbar.cs - + UserControl - - DXViewer.cs + + ctrlRenderer.cs Component @@ -322,6 +322,12 @@ ctrlStandardController.cs + + Form + + + frmControllerConfig.cs + Form @@ -397,6 +403,9 @@ ctrlTrackbar.cs + + ctrlRenderer.cs + ctrlBreakpoints.cs @@ -463,6 +472,9 @@ ctrlStandardController.cs + + frmControllerConfig.cs + frmGetKey.cs diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 3534752c..43caf0ae 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -22,11 +22,19 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void ApplyIpsPatch([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string filename); [DllImport(DLLPath)] public static extern void AddKnowGameFolder([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string folder); - [DllImport(DLLPath)] public static extern void AddKeyMappings(int port, KeyMapping mapping); - [DllImport(DLLPath)] public static extern void ClearKeyMappings(int port); + [DllImport(DLLPath)] public static extern void ZapperSetTriggerState(Int32 port, [MarshalAs(UnmanagedType.I1)]bool pulled); + [DllImport(DLLPath)] public static extern void ZapperSetPosition(Int32 port, Int32 x, Int32 y); + [DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HasZapper(); + + [DllImport(DLLPath)] public static extern void SetControllerType(int port, ControllerType type); + [DllImport(DLLPath)] public static extern void SetControllerKeys(int port, KeyMappingSet mapping); + [DllImport(DLLPath)] public static extern void SetExpansionDevice(ExpansionPortDevice device); + [DllImport(DLLPath)] public static extern void SetConsoleType(ConsoleType type); + [DllImport(DLLPath)] public static extern UInt32 GetPressedKey(); [DllImport(DLLPath)] public static extern UInt32 GetKeyCode([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string keyName); [DllImport(DLLPath, EntryPoint="GetKeyName")] private static extern IntPtr GetKeyNameWrapper(UInt32 key); + [DllImport(DLLPath)] public static extern void Run(); [DllImport(DLLPath)] public static extern void Pause(); @@ -286,6 +294,24 @@ namespace Mesen.GUI ResolutionChanged = 11, FdsDiskChanged = 12, FdsBiosNotFound = 13, + ConfigChanged = 14, + DisconnectedFromServer = 15 + } + + public enum ControllerType + { + None = 0, + StandardController = 1, + Zapper = 2, + } + + public struct KeyMappingSet + { + public KeyMapping Mapping1; + public KeyMapping Mapping2; + public KeyMapping Mapping3; + public KeyMapping Mapping4; + public UInt32 TurboSpeed; } public struct KeyMapping @@ -302,7 +328,13 @@ namespace Mesen.GUI public UInt32 TurboB; public UInt32 TurboStart; public UInt32 TurboSelect; - public UInt32 TurboSpeed; + } + + public enum ExpansionPortDevice + { + None = 0, + Zapper = 1, + FourPlayerAdapter = 2, } public struct ScreenSize @@ -467,6 +499,7 @@ namespace Mesen.GUI AllowInvalidInput = 0x08, RemoveSpriteLimit = 0x10, UseHdPacks = 0x20, + HasFourScore = 0x40, PauseOnMovieEnd = 0x0100, PauseWhenInBackground = 0x0200, @@ -519,6 +552,13 @@ namespace Mesen.GUI Dendy = 3, } + public enum ConsoleType + { + Nes = 0, + Famicom = 1, + //VsSystem = 2, + } + public enum AudioChannel { Square1 = 0, diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 17bbf540..906e0448 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -10,7 +10,6 @@ #include "../Core/ClientConnectionData.h" #include "../Core/SaveStateManager.h" #include "../Core/CheatManager.h" -#include "../Core/StandardController.h" #include "../Core/EmulationSettings.h" #include "../Core/VideoDecoder.h" #include "../Core/AutoRomTest.h" @@ -18,7 +17,6 @@ NES::Renderer *_renderer = nullptr; SoundManager *_soundManager = nullptr; -vector> _inputDevices; HWND _windowHandle = nullptr; HWND _viewerHandle = nullptr; string _returnString; @@ -60,10 +58,6 @@ namespace InteropEmu { _soundManager = new SoundManager(_windowHandle); ControlManager::RegisterKeyManager(new WindowsKeyManager(_windowHandle)); - - for(int i = 0; i < 4; i++) { - _inputDevices.push_back(shared_ptr(new StandardController(i))); - } } } @@ -71,8 +65,14 @@ namespace InteropEmu { DllExport void __stdcall ApplyIpsPatch(char* filename) { Console::ApplyIpsPatch(filename); } DllExport void __stdcall AddKnowGameFolder(char* folder) { FolderUtilities::AddKnowGameFolder(folder); } - DllExport void __stdcall AddKeyMappings(uint32_t port, KeyMapping mapping) { _inputDevices[port]->AddKeyMappings(mapping); } - DllExport void __stdcall ClearKeyMappings(uint32_t port) { _inputDevices[port]->ClearKeyMappings(); } + DllExport void __stdcall SetControllerType(uint32_t port, ControllerType type) { EmulationSettings::SetControllerType(port, type); } + DllExport void __stdcall SetControllerKeys(uint32_t port, KeyMappingSet mappings) { EmulationSettings::SetControllerKeys(port, mappings); } + DllExport void __stdcall SetExpansionDevice(ExpansionPortDevice device) { EmulationSettings::SetExpansionDevice(device); } + DllExport void __stdcall SetConsoleType(ConsoleType type) { EmulationSettings::SetConsoleType(type); } + + DllExport bool __stdcall HasZapper() { return ControlManager::HasZapper(); } + DllExport void __stdcall ZapperSetTriggerState(int32_t port, bool pulled) { ControlManager::ZapperSetTriggerState(port, pulled); } + DllExport void __stdcall ZapperSetPosition(int32_t port, int32_t x, int32_t y) { ControlManager::ZapperSetPosition(port, x, y); } DllExport uint32_t __stdcall GetPressedKey() { return ControlManager::GetPressedKey(); } DllExport const char* __stdcall GetKeyName(uint32_t keyCode) @@ -80,7 +80,13 @@ namespace InteropEmu { _returnString = ControlManager::GetKeyName(keyCode); return _returnString.c_str(); } - DllExport uint32_t __stdcall GetKeyCode(char* keyName) { return ControlManager::GetKeyCode(keyName); } + DllExport uint32_t __stdcall GetKeyCode(char* keyName) { + if(keyName) { + return ControlManager::GetKeyCode(keyName); + } else { + return 0; + } + } DllExport void __stdcall Run() { diff --git a/Windows/Renderer.cpp b/Windows/Renderer.cpp index 22cc04a3..93a961f4 100644 --- a/Windows/Renderer.cpp +++ b/Windows/Renderer.cpp @@ -395,7 +395,7 @@ namespace NES void Renderer::Render() { - bool paused = EmulationSettings::CheckFlag(EmulationFlags::Paused) || (EmulationSettings::CheckFlag(EmulationFlags::InBackground) && EmulationSettings::CheckFlag(EmulationFlags::PauseWhenInBackground)); + bool paused = EmulationSettings::IsPaused(); if(_noUpdateCount > 10 || _frameChanged || paused || !_toasts.empty()) { _frameLock.Acquire();