mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
UI: Added global input options (deadzone, display inputs on screen, etc.)
This commit is contained in:
parent
9f6841eea5
commit
aa6a9699fb
44 changed files with 601 additions and 285 deletions
|
@ -122,6 +122,7 @@
|
||||||
<ClInclude Include="Shared\Interfaces\stdafx.h" />
|
<ClInclude Include="Shared\Interfaces\stdafx.h" />
|
||||||
<ClInclude Include="Shared\KeyDefinitions.h" />
|
<ClInclude Include="Shared\KeyDefinitions.h" />
|
||||||
<ClInclude Include="Shared\Movies\stdafx.h" />
|
<ClInclude Include="Shared\Movies\stdafx.h" />
|
||||||
|
<ClInclude Include="Shared\RenderedFrame.h" />
|
||||||
<ClInclude Include="Shared\RomInfo.h" />
|
<ClInclude Include="Shared\RomInfo.h" />
|
||||||
<ClInclude Include="Shared\stdafx.h" />
|
<ClInclude Include="Shared\stdafx.h" />
|
||||||
<ClInclude Include="NES\NesDefaultVideoFilter.h" />
|
<ClInclude Include="NES\NesDefaultVideoFilter.h" />
|
||||||
|
|
|
@ -819,6 +819,7 @@
|
||||||
<ClInclude Include="NES\Debugger\DummyNesCpu.h" />
|
<ClInclude Include="NES\Debugger\DummyNesCpu.h" />
|
||||||
<ClInclude Include="Gameboy\Debugger\DummyGbCpu.h" />
|
<ClInclude Include="Gameboy\Debugger\DummyGbCpu.h" />
|
||||||
<ClInclude Include="Debugger\DebuggerFeatures.h" />
|
<ClInclude Include="Debugger\DebuggerFeatures.h" />
|
||||||
|
<ClInclude Include="Shared\RenderedFrame.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="SNES\SnesCpu.cpp">
|
<ClCompile Include="SNES\SnesCpu.cpp">
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
#include "Shared/RewindManager.h"
|
#include "Shared/RewindManager.h"
|
||||||
|
#include "Shared/Interfaces/IControlManager.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "Shared/Video/VideoDecoder.h"
|
#include "Shared/Video/VideoDecoder.h"
|
||||||
#include "Shared/NotificationManager.h"
|
#include "Shared/NotificationManager.h"
|
||||||
#include "Shared/MessageManager.h"
|
#include "Shared/MessageManager.h"
|
||||||
|
@ -650,7 +652,7 @@ void GbPpu::SendFrame()
|
||||||
}
|
}
|
||||||
_isFirstFrame = false;
|
_isFirstFrame = false;
|
||||||
|
|
||||||
RenderedFrame frame(_currentBuffer, GbConstants::ScreenWidth, GbConstants::ScreenHeight, 1.0, _state.FrameCount);
|
RenderedFrame frame(_currentBuffer, GbConstants::ScreenWidth, GbConstants::ScreenHeight, 1.0, _state.FrameCount, _gameboy->GetControlManager()->GetPortStates());
|
||||||
#ifdef LIBRETRO
|
#ifdef LIBRETRO
|
||||||
_emu->GetVideoDecoder()->UpdateFrame(frame, true, false);
|
_emu->GetVideoDecoder()->UpdateFrame(frame, true, false);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/InputHud.h"
|
||||||
#include "Utilities/Serializer.h"
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
class GbController : public BaseControlDevice
|
class GbController : public BaseControlDevice
|
||||||
|
@ -57,4 +58,23 @@ public:
|
||||||
void WriteRam(uint16_t addr, uint8_t value) override
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud)
|
||||||
|
{
|
||||||
|
hud.DrawOutline(35, 14);
|
||||||
|
|
||||||
|
hud.DrawButton(5, 3, 3, 3, IsPressed(Buttons::Up));
|
||||||
|
hud.DrawButton(5, 9, 3, 3, IsPressed(Buttons::Down));
|
||||||
|
hud.DrawButton(2, 6, 3, 3, IsPressed(Buttons::Left));
|
||||||
|
hud.DrawButton(8, 6, 3, 3, IsPressed(Buttons::Right));
|
||||||
|
hud.DrawButton(5, 6, 3, 3, false);
|
||||||
|
|
||||||
|
hud.DrawButton(30, 7, 3, 3, IsPressed(Buttons::A));
|
||||||
|
hud.DrawButton(25, 7, 3, 3, IsPressed(Buttons::B));
|
||||||
|
|
||||||
|
hud.DrawButton(13, 9, 4, 2, IsPressed(Buttons::Select));
|
||||||
|
hud.DrawButton(18, 9, 4, 2, IsPressed(Buttons::Start));
|
||||||
|
|
||||||
|
hud.DrawNumber(_port + 1, 16, 2);
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/InputHud.h"
|
||||||
#include "Utilities/Serializer.h"
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
class NesController : public BaseControlDevice
|
class NesController : public BaseControlDevice
|
||||||
|
@ -132,4 +133,23 @@ public:
|
||||||
{
|
{
|
||||||
StrobeProcessWrite(value);
|
StrobeProcessWrite(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud)
|
||||||
|
{
|
||||||
|
hud.DrawOutline(35, 14);
|
||||||
|
|
||||||
|
hud.DrawButton(5, 3, 3, 3, IsPressed(Buttons::Up));
|
||||||
|
hud.DrawButton(5, 9, 3, 3, IsPressed(Buttons::Down));
|
||||||
|
hud.DrawButton(2, 6, 3, 3, IsPressed(Buttons::Left));
|
||||||
|
hud.DrawButton(8, 6, 3, 3, IsPressed(Buttons::Right));
|
||||||
|
hud.DrawButton(5, 6, 3, 3, false);
|
||||||
|
|
||||||
|
hud.DrawButton(30, 7, 3, 3, IsPressed(Buttons::A));
|
||||||
|
hud.DrawButton(25, 7, 3, 3, IsPressed(Buttons::B));
|
||||||
|
|
||||||
|
hud.DrawButton(13, 9, 4, 2, IsPressed(Buttons::Select));
|
||||||
|
hud.DrawButton(18, 9, 4, 2, IsPressed(Buttons::Start));
|
||||||
|
|
||||||
|
hud.DrawNumber(_port + 1, 16, 2);
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Shared/Video/VideoDecoder.h"
|
#include "Shared/Video/VideoDecoder.h"
|
||||||
#include "Shared/RewindManager.h"
|
#include "Shared/RewindManager.h"
|
||||||
#include "Shared/NotificationManager.h"
|
#include "Shared/NotificationManager.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "MemoryOperationType.h"
|
#include "MemoryOperationType.h"
|
||||||
|
|
||||||
#include "EventType.h"
|
#include "EventType.h"
|
||||||
|
@ -1071,7 +1072,7 @@ template<class T> void NesPpu<T>::SendFrame()
|
||||||
_emu->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone, _currentOutputBuffer);
|
_emu->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone, _currentOutputBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderedFrame frame(_currentOutputBuffer, NesConstants::ScreenWidth, NesConstants::ScreenHeight, 1.0, _frameCount);
|
RenderedFrame frame(_currentOutputBuffer, NesConstants::ScreenWidth, NesConstants::ScreenHeight, 1.0, _frameCount, _console->GetControlManager()->GetPortStates());
|
||||||
frame.Data = frameData; //HD packs
|
frame.Data = frameData; //HD packs
|
||||||
|
|
||||||
#ifdef LIBRETRO
|
#ifdef LIBRETRO
|
||||||
|
@ -1097,7 +1098,7 @@ template<class T> void NesPpu<T>::SendFrameVsDualSystem()
|
||||||
NesConfig& cfg = _settings->GetNesConfig();
|
NesConfig& cfg = _settings->GetNesConfig();
|
||||||
bool forRewind = _emu->GetRewindManager()->IsRewinding();
|
bool forRewind = _emu->GetRewindManager()->IsRewinding();
|
||||||
|
|
||||||
RenderedFrame frame(_currentOutputBuffer, NesConstants::ScreenWidth, NesConstants::ScreenHeight, 1.0, _frameCount);
|
RenderedFrame frame(_currentOutputBuffer, NesConstants::ScreenWidth, NesConstants::ScreenHeight, 1.0, _frameCount, _console->GetControlManager()->GetPortStates());
|
||||||
|
|
||||||
if(cfg.VsDualVideoOutput == VsDualOutputOption::MainSystemOnly && _console->IsVsMainConsole()) {
|
if(cfg.VsDualVideoOutput == VsDualOutputOption::MainSystemOnly && _console->IsVsMainConsole()) {
|
||||||
_emu->GetVideoDecoder()->UpdateFrame(frame, forRewind, forRewind);
|
_emu->GetVideoDecoder()->UpdateFrame(frame, forRewind, forRewind);
|
||||||
|
@ -1119,7 +1120,7 @@ template<class T> void NesPpu<T>::SendFrameVsDualSystem()
|
||||||
in2 += NesConstants::ScreenWidth;
|
in2 += NesConstants::ScreenWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderedFrame mergedFrame(mergedBuffer, NesConstants::ScreenWidth*2, NesConstants::ScreenHeight, 1.0, _frameCount);
|
RenderedFrame mergedFrame(mergedBuffer, NesConstants::ScreenWidth*2, NesConstants::ScreenHeight, 1.0, _frameCount, _console->GetControlManager()->GetPortStates());
|
||||||
_emu->GetVideoDecoder()->UpdateFrame(mergedFrame, true, forRewind);
|
_emu->GetVideoDecoder()->UpdateFrame(mergedFrame, true, forRewind);
|
||||||
delete[] mergedBuffer;
|
delete[] mergedBuffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
#include "SNES/Input/SnesController.h"
|
#include "SNES/Input/SnesController.h"
|
||||||
#include "SNES/SnesConsole.h"
|
#include "SNES/SnesConsole.h"
|
||||||
#include "SNES/InternalRegisters.h"
|
#include "SNES/InternalRegisters.h"
|
||||||
|
#include "Shared/InputHud.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
|
||||||
string Multitap::GetKeyNames()
|
string Multitap::GetKeyNames()
|
||||||
{
|
{
|
||||||
|
@ -149,3 +151,43 @@ void Multitap::WriteRam(uint16_t addr, uint8_t value)
|
||||||
StrobeProcessWrite(value);
|
StrobeProcessWrite(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Multitap::DrawController(InputHud& hud)
|
||||||
|
{
|
||||||
|
InputConfig& cfg = _emu->GetSettings()->GetInputConfig();
|
||||||
|
|
||||||
|
for(int j = 0; j < 4; j++) {
|
||||||
|
int port = j == 0 ? _port : (j + 1);
|
||||||
|
if(cfg.DisplayInputPort[port]) {
|
||||||
|
DrawController(hud, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Multitap::DrawController(InputHud& hud, int port)
|
||||||
|
{
|
||||||
|
int offset = port * Multitap::ButtonCount;
|
||||||
|
|
||||||
|
hud.DrawOutline(35, 14);
|
||||||
|
|
||||||
|
hud.DrawButton(5, 3, 3, 3, IsPressed(Buttons::Up + offset));
|
||||||
|
hud.DrawButton(5, 9, 3, 3, IsPressed(Buttons::Down + offset));
|
||||||
|
hud.DrawButton(2, 6, 3, 3, IsPressed(Buttons::Left + offset));
|
||||||
|
hud.DrawButton(8, 6, 3, 3, IsPressed(Buttons::Right + offset));
|
||||||
|
hud.DrawButton(5, 6, 3, 3, false);
|
||||||
|
|
||||||
|
hud.DrawButton(27, 3, 3, 3, IsPressed(Buttons::X + offset));
|
||||||
|
hud.DrawButton(27, 9, 3, 3, IsPressed(Buttons::B + offset));
|
||||||
|
hud.DrawButton(30, 6, 3, 3, IsPressed(Buttons::A + offset));
|
||||||
|
hud.DrawButton(24, 6, 3, 3, IsPressed(Buttons::Y + offset));
|
||||||
|
|
||||||
|
hud.DrawButton(4, 0, 5, 2, IsPressed(Buttons::L + offset));
|
||||||
|
hud.DrawButton(26, 0, 5, 2, IsPressed(Buttons::R + offset));
|
||||||
|
|
||||||
|
hud.DrawButton(13, 9, 4, 2, IsPressed(Buttons::Select + offset));
|
||||||
|
hud.DrawButton(18, 9, 4, 2, IsPressed(Buttons::Start + offset));
|
||||||
|
|
||||||
|
hud.DrawNumber(port + 1, 16, 2);
|
||||||
|
|
||||||
|
hud.EndDrawController();
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
class InternalRegisters;
|
class InternalRegisters;
|
||||||
class SnesController;
|
class SnesController;
|
||||||
class SnesConsole;
|
class SnesConsole;
|
||||||
|
class InputHud;
|
||||||
|
|
||||||
class Multitap : public BaseControlDevice
|
class Multitap : public BaseControlDevice
|
||||||
{
|
{
|
||||||
|
@ -18,6 +19,8 @@ private:
|
||||||
uint16_t _stateBuffer[4] = {};
|
uint16_t _stateBuffer[4] = {};
|
||||||
InternalRegisters *_internalRegs = nullptr;
|
InternalRegisters *_internalRegs = nullptr;
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud, int port);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
string GetKeyNames() override;
|
string GetKeyNames() override;
|
||||||
void InternalSetStateFromInput() override;
|
void InternalSetStateFromInput() override;
|
||||||
|
@ -33,4 +36,6 @@ public:
|
||||||
|
|
||||||
uint8_t ReadRam(uint16_t addr) override;
|
uint8_t ReadRam(uint16_t addr) override;
|
||||||
void WriteRam(uint16_t addr, uint8_t value) override;
|
void WriteRam(uint16_t addr, uint8_t value) override;
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud) override;
|
||||||
};
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "SNES/Input/SnesController.h"
|
#include "SNES/Input/SnesController.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/InputHud.h"
|
||||||
|
|
||||||
SnesController::SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::SnesController, port, keyMappings)
|
SnesController::SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::SnesController, port, keyMappings)
|
||||||
{
|
{
|
||||||
|
@ -96,3 +97,27 @@ void SnesController::WriteRam(uint16_t addr, uint8_t value)
|
||||||
{
|
{
|
||||||
StrobeProcessWrite(value);
|
StrobeProcessWrite(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SnesController::DrawController(InputHud& hud)
|
||||||
|
{
|
||||||
|
hud.DrawOutline(35, 14);
|
||||||
|
|
||||||
|
hud.DrawButton(5, 3, 3, 3, IsPressed(Buttons::Up));
|
||||||
|
hud.DrawButton(5, 9, 3, 3, IsPressed(Buttons::Down));
|
||||||
|
hud.DrawButton(2, 6, 3, 3, IsPressed(Buttons::Left));
|
||||||
|
hud.DrawButton(8, 6, 3, 3, IsPressed(Buttons::Right));
|
||||||
|
hud.DrawButton(5, 6, 3, 3, false);
|
||||||
|
|
||||||
|
hud.DrawButton(27, 3, 3, 3, IsPressed(Buttons::X));
|
||||||
|
hud.DrawButton(27, 9, 3, 3, IsPressed(Buttons::B));
|
||||||
|
hud.DrawButton(30, 6, 3, 3, IsPressed(Buttons::A));
|
||||||
|
hud.DrawButton(24, 6, 3, 3, IsPressed(Buttons::Y));
|
||||||
|
|
||||||
|
hud.DrawButton(4, 0, 5, 2, IsPressed(Buttons::L));
|
||||||
|
hud.DrawButton(26, 0, 5, 2, IsPressed(Buttons::R));
|
||||||
|
|
||||||
|
hud.DrawButton(13, 9, 4, 2, IsPressed(Buttons::Select));
|
||||||
|
hud.DrawButton(18, 9, 4, 2, IsPressed(Buttons::Start));
|
||||||
|
|
||||||
|
hud.DrawNumber(_port + 1, 16, 2);
|
||||||
|
}
|
||||||
|
|
|
@ -23,4 +23,6 @@ public:
|
||||||
|
|
||||||
uint8_t ReadRam(uint16_t addr) override;
|
uint8_t ReadRam(uint16_t addr) override;
|
||||||
void WriteRam(uint16_t addr, uint8_t value) override;
|
void WriteRam(uint16_t addr, uint8_t value) override;
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud) override;
|
||||||
};
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
#include "Shared/Interfaces/IKeyManager.h"
|
#include "Shared/Interfaces/IKeyManager.h"
|
||||||
#include "Shared/KeyManager.h"
|
#include "Shared/KeyManager.h"
|
||||||
|
#include "Shared/InputHud.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
#include "Utilities/Serializer.h"
|
#include "Utilities/Serializer.h"
|
||||||
|
@ -85,4 +86,14 @@ public:
|
||||||
|
|
||||||
_stateBuffer = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
|
_stateBuffer = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawController(InputHud& hud)
|
||||||
|
{
|
||||||
|
hud.DrawOutline(11, 14);
|
||||||
|
|
||||||
|
hud.DrawButton(1, 1, 4, 5, IsPressed(Buttons::Left));
|
||||||
|
hud.DrawButton(6, 1, 4, 5, IsPressed(Buttons::Right));
|
||||||
|
|
||||||
|
hud.DrawNumber(_port + 1, 4, 7);
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Shared/Video/VideoDecoder.h"
|
#include "Shared/Video/VideoDecoder.h"
|
||||||
#include "Shared/Video/VideoRenderer.h"
|
#include "Shared/Video/VideoRenderer.h"
|
||||||
#include "Shared/NotificationManager.h"
|
#include "Shared/NotificationManager.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "Shared/MessageManager.h"
|
#include "Shared/MessageManager.h"
|
||||||
#include "EventType.h"
|
#include "EventType.h"
|
||||||
#include "Shared/RewindManager.h"
|
#include "Shared/RewindManager.h"
|
||||||
|
@ -1476,7 +1477,7 @@ void SnesPpu::SendFrame()
|
||||||
|
|
||||||
bool isRewinding = _emu->GetRewindManager()->IsRewinding();
|
bool isRewinding = _emu->GetRewindManager()->IsRewinding();
|
||||||
|
|
||||||
RenderedFrame frame(_currentBuffer, width, height, _useHighResOutput ? 0.5 : 1.0, _frameCount);
|
RenderedFrame frame(_currentBuffer, width, height, _useHighResOutput ? 0.5 : 1.0, _frameCount, _console->GetControlManager()->GetPortStates());
|
||||||
#ifdef LIBRETRO
|
#ifdef LIBRETRO
|
||||||
_emu->GetVideoDecoder()->UpdateFrame(frame, true, isRewinding);
|
_emu->GetVideoDecoder()->UpdateFrame(frame, true, isRewinding);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Utilities/ISerializable.h"
|
#include "Utilities/ISerializable.h"
|
||||||
|
|
||||||
class Emulator;
|
class Emulator;
|
||||||
|
class InputHud;
|
||||||
|
|
||||||
class BaseControlDevice : public ISerializable
|
class BaseControlDevice : public ISerializable
|
||||||
{
|
{
|
||||||
|
@ -81,6 +82,8 @@ public:
|
||||||
void SetRawState(ControlDeviceState state);
|
void SetRawState(ControlDeviceState state);
|
||||||
ControlDeviceState GetRawState();
|
ControlDeviceState GetRawState();
|
||||||
|
|
||||||
|
virtual void DrawController(InputHud& hud) {}
|
||||||
|
|
||||||
virtual uint8_t ReadRam(uint16_t addr) = 0;
|
virtual uint8_t ReadRam(uint16_t addr) = 0;
|
||||||
virtual void WriteRam(uint16_t addr, uint8_t value) = 0;
|
virtual void WriteRam(uint16_t addr, uint8_t value) = 0;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ vector<ControllerData> BaseControlManager::GetPortStates()
|
||||||
auto lock = _deviceLock.AcquireSafe();
|
auto lock = _deviceLock.AcquireSafe();
|
||||||
|
|
||||||
vector<ControllerData> states;
|
vector<ControllerData> states;
|
||||||
for(int i = 0; i < 2; i++) {
|
for(int i = 0; i < BaseControlDevice::PortCount; i++) {
|
||||||
shared_ptr<BaseControlDevice> device = GetControlDevice(i);
|
shared_ptr<BaseControlDevice> device = GetControlDevice(i);
|
||||||
if(device) {
|
if(device) {
|
||||||
states.push_back({ device->GetControllerType(), device->GetRawState() });
|
states.push_back({ device->GetControllerType(), device->GetRawState() });
|
||||||
|
|
|
@ -82,7 +82,7 @@ void EmuSettings::SetInputConfig(InputConfig config)
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
InputConfig EmuSettings::GetInputConfig()
|
InputConfig& EmuSettings::GetInputConfig()
|
||||||
{
|
{
|
||||||
return _input;
|
return _input;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
AudioConfig GetAudioConfig();
|
AudioConfig GetAudioConfig();
|
||||||
|
|
||||||
void SetInputConfig(InputConfig config);
|
void SetInputConfig(InputConfig config);
|
||||||
InputConfig GetInputConfig();
|
InputConfig& GetInputConfig();
|
||||||
|
|
||||||
void SetEmulationConfig(EmulationConfig config);
|
void SetEmulationConfig(EmulationConfig config);
|
||||||
EmulationConfig GetEmulationConfig();
|
EmulationConfig GetEmulationConfig();
|
||||||
|
|
|
@ -1,180 +1,181 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "InputHud.h"
|
#include "Shared/InputHud.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/BaseControlManager.h"
|
||||||
|
#include "Shared/Interfaces/IControlManager.h"
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
#include "Shared/Video/DebugHud.h"
|
#include "Shared/Video/DebugHud.h"
|
||||||
|
|
||||||
static constexpr int color[2] = { 0x00111111, 0x00FFFFFF };
|
static constexpr int color[2] = { 0x00111111, 0x00FFFFFF };
|
||||||
|
|
||||||
InputHud::InputHud(Emulator* emu)
|
InputHud::InputHud(Emulator* emu, DebugHud* hud)
|
||||||
{
|
{
|
||||||
_emu = emu;
|
_emu = emu;
|
||||||
|
_hud = hud;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHud::DrawController(int port, ControlDeviceState state, int x, int y, int frameNumber)
|
void InputHud::DrawButton(int x, int y, int width, int height, bool pressed)
|
||||||
{
|
{
|
||||||
//TODO
|
_hud->DrawRectangle(_xOffset + x, _yOffset + y, width, height, color[pressed], true, 1);
|
||||||
/*SnesController controller(_console, 0, KeyMappingSet());
|
}
|
||||||
controller.SetRawState(state);
|
|
||||||
|
|
||||||
shared_ptr<DebugHud> hud = _console->GetDebugHud();
|
|
||||||
hud->DrawRectangle(0 + x, 0 + y, 35, 14, 0x80CCCCCC, true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(0 + x, 0 + y, 35, 14, color[0], false, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(5 + x, 3 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::Up)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(5 + x, 9 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::Down)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(2 + x, 6 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::Left)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(8 + x, 6 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::Right)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(5 + x, 6 + y, 3, 3, color[0], true, 1, frameNumber);
|
|
||||||
|
|
||||||
hud->DrawRectangle(27 + x, 3 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::X)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(27 + x, 9 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::B)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(30 + x, 6 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::A)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(24 + x, 6 + y, 3, 3, color[controller.IsPressed(SnesController::Buttons::Y)], true, 1, frameNumber);
|
|
||||||
|
|
||||||
hud->DrawRectangle(4 + x, 0 + y, 5, 2, color[controller.IsPressed(SnesController::Buttons::L)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(26 + x, 0 + y, 5, 2, color[controller.IsPressed(SnesController::Buttons::R)], true, 1, frameNumber);
|
|
||||||
|
|
||||||
hud->DrawRectangle(13 + x, 9 + y, 4, 2, color[controller.IsPressed(SnesController::Buttons::Select)], true, 1, frameNumber);
|
|
||||||
hud->DrawRectangle(18 + x, 9 + y, 4, 2, color[controller.IsPressed(SnesController::Buttons::Start)], true, 1, frameNumber);
|
|
||||||
|
|
||||||
switch(port) {
|
|
||||||
case 0:
|
|
||||||
//1
|
|
||||||
hud->DrawLine(17 + x, 2 + y, 17 + x, 6 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawLine(16 + x, 6 + y, 18 + x, 6 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawPixel(16 + x, 3 + y, color[0], 1, frameNumber);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
void InputHud::DrawNumber(int number, int x, int y)
|
||||||
|
{
|
||||||
|
switch(number) {
|
||||||
case 1:
|
case 1:
|
||||||
//2
|
_hud->DrawLine(x+1 + _xOffset, y + _yOffset, x+1 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 2 + y, 18 + x, 2 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x + _xOffset, 4 + y + _yOffset, x+2 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawPixel(18 + x, 3 + y, color[0], 1, frameNumber);
|
_hud->DrawPixel(x + _xOffset, 1 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 4 + y, 18 + x, 4 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawPixel(16 + x, 5 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawLine(16 + x, 6 + y, 18 + x, 6 + y, color[0], 1, frameNumber);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
//3
|
_hud->DrawLine(x + _xOffset, y + _yOffset, x+2 + _xOffset, y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 2 + y, 18 + x, 2 + y, color[0], 1, frameNumber);
|
_hud->DrawPixel(x+2 + _xOffset, 1 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawPixel(18 + x, 3 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x + _xOffset, 2 + y + _yOffset, x+2 + _xOffset, 2 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 4 + y, 18 + x, 4 + y, color[0], 1, frameNumber);
|
_hud->DrawPixel(x + _xOffset, 3 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawPixel(18 + x, 5 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x + _xOffset, 4 + y + _yOffset, x+2 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 6 + y, 18 + x, 6 + y, color[0], 1, frameNumber);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
//4
|
_hud->DrawLine(x + _xOffset, y + _yOffset, x+2 + _xOffset, y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 2 + y, 16 + x, 4 + y, color[0], 1, frameNumber);
|
_hud->DrawPixel(x+2 + _xOffset, 1 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(18 + x, 2 + y, 18 + x, 6 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x + _xOffset, 2 + y + _yOffset, x+2 + _xOffset, 2 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 4 + y, 18 + x, 4 + y, color[0], 1, frameNumber);
|
_hud->DrawPixel(x+2 + _xOffset, 3 + y + _yOffset, color[0], 1);
|
||||||
|
_hud->DrawLine(x + _xOffset, 4 + y + _yOffset, x+2 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
//5
|
_hud->DrawLine(x + _xOffset, y + _yOffset, x + _xOffset, 2 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 2 + y, 18 + x, 2 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x+2 + _xOffset, y + _yOffset, x+2 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawPixel(16 + x, 3 + y, color[0], 1, frameNumber);
|
_hud->DrawLine(x + _xOffset, 2 + y + _yOffset, x+2 + _xOffset, 2 + y + _yOffset, color[0], 1);
|
||||||
hud->DrawLine(16 + x, 4 + y, 18 + x, 4 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawPixel(18 + x, 5 + y, color[0], 1, frameNumber);
|
|
||||||
hud->DrawLine(16 + x, 6 + y, 18 + x, 6 + y, color[0], 1, frameNumber);
|
|
||||||
break;
|
break;
|
||||||
}*/
|
|
||||||
|
case 5:
|
||||||
|
_hud->DrawLine(x + _xOffset, y + _yOffset, x+2 + _xOffset, y + _yOffset, color[0], 1);
|
||||||
|
_hud->DrawPixel(x + _xOffset, 1 + y + _yOffset, color[0], 1);
|
||||||
|
_hud->DrawLine(x + _xOffset, 2 + y + _yOffset, x+2 + _xOffset, 2 + y + _yOffset, color[0], 1);
|
||||||
|
_hud->DrawPixel(x+2 + _xOffset, 3 + y + _yOffset, color[0], 1);
|
||||||
|
_hud->DrawLine(x + _xOffset, 4 + y + _yOffset, x+2 + _xOffset, 4 + y + _yOffset, color[0], 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHud::DrawControllers(OverscanDimensions overscan, int frameNumber)
|
void InputHud::DrawOutline(int width, int height)
|
||||||
{
|
{
|
||||||
//TODO
|
InputConfig& cfg = _emu->GetSettings()->GetInputConfig();
|
||||||
/*
|
|
||||||
vector<ControllerData> controllerData = _console->GetControlManager()->GetPortStates();
|
|
||||||
InputConfig cfg = _console->GetSettings()->GetInputConfig();
|
|
||||||
|
|
||||||
int xStart;
|
|
||||||
int yStart;
|
|
||||||
int xOffset = cfg.DisplayInputHorizontally ? 38 : 0;
|
|
||||||
int yOffset = cfg.DisplayInputHorizontally ? 0 : 16;
|
|
||||||
|
|
||||||
switch(cfg.DisplayInputPosition) {
|
switch(cfg.DisplayInputPosition) {
|
||||||
default:
|
default:
|
||||||
case InputDisplayPosition::TopLeft:
|
case InputDisplayPosition::TopLeft:
|
||||||
xStart = overscan.Left + 3;
|
|
||||||
yStart = overscan.Top + 3;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InputDisplayPosition::TopRight:
|
case InputDisplayPosition::TopRight:
|
||||||
xStart = 256 - overscan.Right - 38;
|
_xOffset -= width + 1;
|
||||||
yStart = overscan.Top + 3;
|
|
||||||
xOffset = -xOffset;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InputDisplayPosition::BottomLeft:
|
case InputDisplayPosition::BottomLeft:
|
||||||
xStart = overscan.Left + 3;
|
_yOffset -= height + 1;
|
||||||
yStart = 240 - overscan.Bottom - 18;
|
|
||||||
yOffset = -yOffset;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InputDisplayPosition::BottomRight:
|
case InputDisplayPosition::BottomRight:
|
||||||
xStart = 256 - overscan.Right - 38;
|
_yOffset -= height + 1;
|
||||||
yStart = 240 - overscan.Bottom - 18;
|
_xOffset -= width + 1;
|
||||||
xOffset = -xOffset;
|
|
||||||
yOffset = -yOffset;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < (int)controllerData.size(); i++) {
|
_hud->DrawRectangle(_xOffset, _yOffset, width, height, 0x80CCCCCC, true, 1);
|
||||||
if(controllerData[i].Type == ControllerType::SnesController) {
|
_hud->DrawRectangle(_xOffset, _yOffset, width, height, color[0], false, 1);
|
||||||
if(cfg.DisplayInputPort[i]) {
|
|
||||||
DrawController(i, controllerData[i].State, xStart, yStart, frameNumber);
|
_outlineWidth = width;
|
||||||
xStart += xOffset;
|
_outlineHeight = height;
|
||||||
yStart += yOffset;
|
}
|
||||||
}
|
|
||||||
} else if(controllerData[i].Type == ControllerType::Multitap) {
|
void InputHud::DrawController(ControllerType controllerType, int port, ControlDeviceState state)
|
||||||
uint64_t rawData = 0;
|
{
|
||||||
for(int j = (int)controllerData[i].State.State.size() - 1; j >= 0; j--) {
|
shared_ptr<BaseControlDevice> controller = ((BaseControlManager*)_emu->GetControlManager())->CreateControllerDevice(controllerType, port);
|
||||||
rawData <<= 8;
|
if(!controller) {
|
||||||
rawData |= controllerData[i].State.State[j];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlDeviceState controllers[4] = {};
|
controller->SetRawState(state);
|
||||||
for(int j = 0; j < 4; j++) {
|
controller->DrawController(*this);
|
||||||
controllers[j].State.push_back(rawData & 0xFF);
|
EndDrawController();
|
||||||
controllers[j].State.push_back((rawData >> 8) & 0x0F);
|
}
|
||||||
rawData >>= 12;
|
|
||||||
}
|
void InputHud::EndDrawController()
|
||||||
|
{
|
||||||
if(cfg.DisplayInputPort[i]) {
|
if(_outlineHeight > 0 && _outlineWidth > 0) {
|
||||||
DrawController(i, controllers[0], xStart, yStart, frameNumber);
|
InputConfig& cfg = _emu->GetSettings()->GetInputConfig();
|
||||||
xStart += xOffset;
|
|
||||||
yStart += yOffset;
|
switch(cfg.DisplayInputPosition) {
|
||||||
}
|
default:
|
||||||
|
case InputDisplayPosition::TopLeft:
|
||||||
for(int j = 1; j < 4; j++) {
|
if(cfg.DisplayInputHorizontally) {
|
||||||
if(cfg.DisplayInputPort[j + 1]) {
|
_xOffset += _outlineWidth + 1;
|
||||||
DrawController(j + 1, controllers[j], xStart, yStart, frameNumber);
|
} else {
|
||||||
xStart += xOffset;
|
_yOffset += _outlineHeight + 1;
|
||||||
yStart += yOffset;
|
}
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
} else if(controllerData[i].Type == ControllerType::SuperScope) {
|
case InputDisplayPosition::TopRight:
|
||||||
if(cfg.DisplayInputPort[i]) {
|
if(!cfg.DisplayInputHorizontally) {
|
||||||
SuperScope scope(_console, 0, KeyMappingSet());
|
_xOffset += _outlineWidth + 1;
|
||||||
scope.SetRawState(controllerData[i].State);
|
_yOffset += _outlineHeight + 1;
|
||||||
MousePosition pos = scope.GetCoordinates();
|
}
|
||||||
|
break;
|
||||||
shared_ptr<DebugHud> hud = _console->GetDebugHud();
|
|
||||||
hud->DrawRectangle(pos.X - 1, pos.Y - 1, 3, 3, 0x00111111, true, 1, frameNumber);
|
case InputDisplayPosition::BottomLeft:
|
||||||
hud->DrawRectangle(pos.X - 1, pos.Y - 1, 3, 3, 0x80CCCCCC, false, 1, frameNumber);
|
if(cfg.DisplayInputHorizontally) {
|
||||||
}
|
_xOffset += _outlineWidth + 1;
|
||||||
} else if(controllerData[i].Type == ControllerType::SnesMouse) {
|
_yOffset += _outlineHeight + 1;
|
||||||
if(cfg.DisplayInputPort[i]) {
|
}
|
||||||
SnesMouse mouse(_console, 0);
|
break;
|
||||||
mouse.SetRawState(controllerData[i].State);
|
|
||||||
|
case InputDisplayPosition::BottomRight:
|
||||||
shared_ptr<DebugHud> hud = _console->GetDebugHud();
|
if(cfg.DisplayInputHorizontally) {
|
||||||
hud->DrawRectangle(xStart + 12, yStart, 11, 14, 0x00AAAAAA, true, 1, frameNumber);
|
_yOffset += _outlineHeight + 1;
|
||||||
hud->DrawRectangle(xStart + 12, yStart, 11, 14, color[0], false, 1, frameNumber);
|
} else {
|
||||||
hud->DrawRectangle(xStart + 13, yStart + 1, 4, 5, color[mouse.IsPressed(SnesMouse::Buttons::Left)], true, 1, frameNumber);
|
_xOffset += _outlineWidth + 1;
|
||||||
hud->DrawRectangle(xStart + 18, yStart + 1, 4, 5, color[mouse.IsPressed(SnesMouse::Buttons::Right)], true, 1, frameNumber);
|
}
|
||||||
|
break;
|
||||||
xStart += xOffset;
|
}
|
||||||
yStart += yOffset;
|
|
||||||
}
|
_outlineWidth = 0;
|
||||||
}
|
_outlineHeight = 0;
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHud::DrawControllers(FrameInfo size, vector<ControllerData> controllerData)
|
||||||
|
{
|
||||||
|
InputConfig& cfg = _emu->GetSettings()->GetInputConfig();
|
||||||
|
|
||||||
|
switch(cfg.DisplayInputPosition) {
|
||||||
|
default:
|
||||||
|
case InputDisplayPosition::TopLeft:
|
||||||
|
_xOffset = 2;
|
||||||
|
_yOffset = 2;
|
||||||
|
break;
|
||||||
|
case InputDisplayPosition::TopRight:
|
||||||
|
_xOffset = size.Width - 1;
|
||||||
|
_yOffset = 2;
|
||||||
|
break;
|
||||||
|
case InputDisplayPosition::BottomLeft:
|
||||||
|
_xOffset = 2;
|
||||||
|
_yOffset = size.Height - 1;
|
||||||
|
break;
|
||||||
|
case InputDisplayPosition::BottomRight:
|
||||||
|
_xOffset = size.Width - 1;
|
||||||
|
_yOffset = size.Height - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < (int)controllerData.size(); i++) {
|
||||||
|
if(controllerData[i].Type != ControllerType::None) {
|
||||||
|
DrawController(controllerData[i].Type, i, controllerData[i].State);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,28 @@
|
||||||
#include "ControlDeviceState.h"
|
#include "ControlDeviceState.h"
|
||||||
|
|
||||||
class Emulator;
|
class Emulator;
|
||||||
|
class DebugHud;
|
||||||
|
|
||||||
class InputHud
|
class InputHud
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Emulator* _emu;
|
Emulator* _emu;
|
||||||
|
DebugHud* _hud;
|
||||||
|
|
||||||
void DrawController(int port, ControlDeviceState state, int x, int y, int frameNumber);
|
int _xOffset = 0;
|
||||||
|
int _yOffset = 0;
|
||||||
|
int _outlineWidth = 0;
|
||||||
|
int _outlineHeight = 0;
|
||||||
|
|
||||||
|
void DrawController(ControllerType type, int port, ControlDeviceState state);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InputHud(Emulator *emu);
|
InputHud(Emulator *emu, DebugHud* hud);
|
||||||
|
|
||||||
void DrawControllers(OverscanDimensions overscan, int frameNumber);
|
void DrawOutline(int width, int height);
|
||||||
|
void DrawButton(int x, int y, int width, int height, bool pressed);
|
||||||
|
void DrawNumber(int number, int x, int y);
|
||||||
|
void EndDrawController();
|
||||||
|
|
||||||
|
void DrawControllers(FrameInfo size, vector<ControllerData> controllerData);
|
||||||
};
|
};
|
|
@ -4,6 +4,7 @@
|
||||||
#include "IInputProvider.h"
|
#include "IInputProvider.h"
|
||||||
|
|
||||||
enum class ControllerType;
|
enum class ControllerType;
|
||||||
|
struct ControllerData;
|
||||||
|
|
||||||
class IControlManager
|
class IControlManager
|
||||||
{
|
{
|
||||||
|
@ -20,6 +21,8 @@ public:
|
||||||
virtual shared_ptr<BaseControlDevice> CreateControllerDevice(ControllerType type, uint8_t port) = 0;
|
virtual shared_ptr<BaseControlDevice> CreateControllerDevice(ControllerType type, uint8_t port) = 0;
|
||||||
|
|
||||||
virtual bool HasControlDevice(ControllerType type) = 0;
|
virtual bool HasControlDevice(ControllerType type) = 0;
|
||||||
|
|
||||||
|
virtual vector<ControllerData> GetPortStates() = 0;
|
||||||
|
|
||||||
virtual void SetPollCounter(uint32_t pollCounter) = 0;
|
virtual void SetPollCounter(uint32_t pollCounter) = 0;
|
||||||
virtual uint32_t GetPollCounter() = 0;
|
virtual uint32_t GetPollCounter() = 0;
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Shared/SettingTypes.h"
|
#include "Shared/SettingTypes.h"
|
||||||
|
|
||||||
|
struct RenderedFrame;
|
||||||
|
|
||||||
class IRenderingDevice
|
class IRenderingDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IRenderingDevice() {}
|
virtual ~IRenderingDevice() {}
|
||||||
virtual void UpdateFrame(RenderedFrame frame) = 0;
|
virtual void UpdateFrame(RenderedFrame& frame) = 0;
|
||||||
virtual void Render(uint32_t* hudBuffer, uint32_t width, uint32_t height) = 0;
|
virtual void Render(uint32_t* hudBuffer, uint32_t width, uint32_t height) = 0;
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
virtual void SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) = 0;
|
virtual void SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) = 0;
|
||||||
|
|
38
Core/Shared/RenderedFrame.h
Normal file
38
Core/Shared/RenderedFrame.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/SettingTypes.h"
|
||||||
|
#include "Shared/ControlDeviceState.h"
|
||||||
|
|
||||||
|
struct RenderedFrame
|
||||||
|
{
|
||||||
|
void* FrameBuffer = nullptr;
|
||||||
|
void* Data = nullptr; //Used by HD packs
|
||||||
|
uint32_t Width = 256;
|
||||||
|
uint32_t Height = 240;
|
||||||
|
double Scale = 1.0;
|
||||||
|
uint32_t FrameNumber = 0;
|
||||||
|
vector<ControllerData> InputData;
|
||||||
|
|
||||||
|
RenderedFrame()
|
||||||
|
{}
|
||||||
|
|
||||||
|
RenderedFrame(void* buffer, uint32_t width, uint32_t height, double scale = 1.0, uint32_t frameNumber = 0) :
|
||||||
|
FrameBuffer(buffer),
|
||||||
|
Width(width),
|
||||||
|
Height(height),
|
||||||
|
Scale(scale),
|
||||||
|
FrameNumber(frameNumber),
|
||||||
|
Data(nullptr),
|
||||||
|
InputData({})
|
||||||
|
{}
|
||||||
|
|
||||||
|
RenderedFrame(void* buffer, uint32_t width, uint32_t height, double scale, uint32_t frameNumber, vector<ControllerData> inputData) :
|
||||||
|
FrameBuffer(buffer),
|
||||||
|
Width(width),
|
||||||
|
Height(height),
|
||||||
|
Scale(scale),
|
||||||
|
FrameNumber(frameNumber),
|
||||||
|
Data(nullptr),
|
||||||
|
InputData(inputData)
|
||||||
|
{}
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Shared/Video/VideoRenderer.h"
|
#include "Shared/Video/VideoRenderer.h"
|
||||||
#include "Shared/Audio/SoundMixer.h"
|
#include "Shared/Audio/SoundMixer.h"
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "Shared/Interfaces/IControlManager.h"
|
#include "Shared/Interfaces/IControlManager.h"
|
||||||
|
|
||||||
RewindManager::RewindManager(Emulator* emu)
|
RewindManager::RewindManager(Emulator* emu)
|
||||||
|
@ -220,7 +221,7 @@ void RewindManager::ProcessEndOfFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RewindManager::ProcessFrame(RenderedFrame frame, bool forRewind)
|
void RewindManager::ProcessFrame(RenderedFrame& frame, bool forRewind)
|
||||||
{
|
{
|
||||||
if(_rewindState == RewindState::Starting || _rewindState == RewindState::Started) {
|
if(_rewindState == RewindState::Starting || _rewindState == RewindState::Started) {
|
||||||
if(!forRewind) {
|
if(!forRewind) {
|
||||||
|
@ -354,7 +355,7 @@ bool RewindManager::HasHistory()
|
||||||
return _hasHistory;
|
return _hasHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RewindManager::SendFrame(RenderedFrame frame, bool forRewind)
|
void RewindManager::SendFrame(RenderedFrame& frame, bool forRewind)
|
||||||
{
|
{
|
||||||
ProcessFrame(frame, forRewind);
|
ProcessFrame(frame, forRewind);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
class Emulator;
|
class Emulator;
|
||||||
class EmuSettings;
|
class EmuSettings;
|
||||||
|
struct RenderedFrame;
|
||||||
|
|
||||||
enum class RewindState
|
enum class RewindState
|
||||||
{
|
{
|
||||||
|
@ -55,7 +56,7 @@ private:
|
||||||
void Stop();
|
void Stop();
|
||||||
void ForceStop();
|
void ForceStop();
|
||||||
|
|
||||||
void ProcessFrame(RenderedFrame frame, bool forRewind);
|
void ProcessFrame(RenderedFrame& frame, bool forRewind);
|
||||||
bool ProcessAudio(int16_t* soundBuffer, uint32_t sampleCount);
|
bool ProcessAudio(int16_t* soundBuffer, uint32_t sampleCount);
|
||||||
|
|
||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
|
@ -78,6 +79,6 @@ public:
|
||||||
|
|
||||||
bool HasHistory();
|
bool HasHistory();
|
||||||
|
|
||||||
void SendFrame(RenderedFrame frame, bool forRewind);
|
void SendFrame(RenderedFrame& frame, bool forRewind);
|
||||||
bool SendAudio(int16_t *soundBuffer, uint32_t sampleCount);
|
bool SendAudio(int16_t *soundBuffer, uint32_t sampleCount);
|
||||||
};
|
};
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
#include "Shared/Movies/MovieManager.h"
|
#include "Shared/Movies/MovieManager.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "EventType.h"
|
#include "EventType.h"
|
||||||
#include "Debugger/Debugger.h"
|
#include "Debugger/Debugger.h"
|
||||||
#include "Netplay/GameClient.h"
|
#include "Netplay/GameClient.h"
|
||||||
|
|
|
@ -505,30 +505,6 @@ struct OverscanDimensions
|
||||||
uint32_t Bottom = 0;
|
uint32_t Bottom = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderedFrame
|
|
||||||
{
|
|
||||||
void* FrameBuffer = nullptr;
|
|
||||||
void* Data = nullptr; //Used by HD packs
|
|
||||||
uint32_t Width = 256;
|
|
||||||
uint32_t Height = 240;
|
|
||||||
double Scale = 1.0;
|
|
||||||
uint32_t FrameNumber = 0;
|
|
||||||
|
|
||||||
RenderedFrame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderedFrame(void* buffer, uint32_t width, uint32_t height, double scale = 1.0, uint32_t frameNumber = 0) :
|
|
||||||
FrameBuffer(buffer),
|
|
||||||
Width(width),
|
|
||||||
Height(height),
|
|
||||||
Scale(scale),
|
|
||||||
FrameNumber(frameNumber),
|
|
||||||
Data(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FrameInfo
|
struct FrameInfo
|
||||||
{
|
{
|
||||||
uint32_t Width;
|
uint32_t Width;
|
||||||
|
|
|
@ -17,6 +17,22 @@ protected:
|
||||||
int _yScale = 1;
|
int _yScale = 1;
|
||||||
|
|
||||||
virtual void InternalDraw() = 0;
|
virtual void InternalDraw() = 0;
|
||||||
|
|
||||||
|
void InternalDrawPixel(int32_t offset, int color, uint32_t alpha)
|
||||||
|
{
|
||||||
|
if(alpha != 0xFF000000) {
|
||||||
|
if(_argbBuffer[offset] == 0) {
|
||||||
|
//When drawing on an empty background, premultiply channels & preserve alpha value
|
||||||
|
//This is needed for hardware blending between the HUD and the game screen
|
||||||
|
BlendColors((uint8_t*)&_argbBuffer[offset], (uint8_t*)&color, true);
|
||||||
|
} else {
|
||||||
|
BlendColors((uint8_t*)&_argbBuffer[offset], (uint8_t*)&color);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_argbBuffer[offset] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DrawPixel(uint32_t x, uint32_t y, int color)
|
void DrawPixel(uint32_t x, uint32_t y, int color)
|
||||||
{
|
{
|
||||||
uint32_t alpha = (color & 0xFF000000);
|
uint32_t alpha = (color & 0xFF000000);
|
||||||
|
@ -30,11 +46,7 @@ protected:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alpha != 0xFF000000) {
|
InternalDrawPixel(offset, color, alpha);
|
||||||
BlendColors((uint8_t*)&_argbBuffer[offset], (uint8_t*)&color);
|
|
||||||
} else {
|
|
||||||
_argbBuffer[offset] = color;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int xPixelCount = _useIntegerScaling ? (int)std::floor(_xScale): (int)((x + 1)*_xScale) - (int)(x*_xScale);
|
int xPixelCount = _useIntegerScaling ? (int)std::floor(_xScale): (int)((x + 1)*_xScale) - (int)(x*_xScale);
|
||||||
x = (int)(x * (_useIntegerScaling ? (int)std::floor(_xScale) : _xScale));
|
x = (int)(x * (_useIntegerScaling ? (int)std::floor(_xScale) : _xScale));
|
||||||
|
@ -48,25 +60,25 @@ protected:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alpha != 0xFF000000) {
|
InternalDrawPixel(offset, color, alpha);
|
||||||
BlendColors((uint8_t*)&_argbBuffer[offset], (uint8_t*)&color);
|
|
||||||
} else {
|
|
||||||
_argbBuffer[offset] = color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void BlendColors(uint8_t output[4], uint8_t input[4])
|
__forceinline void BlendColors(uint8_t output[4], uint8_t input[4], bool keepAlpha = false)
|
||||||
{
|
{
|
||||||
uint8_t alpha = input[3] + 1;
|
uint8_t alpha = input[3] + 1;
|
||||||
uint8_t invertedAlpha = 256 - input[3];
|
uint8_t invertedAlpha = 256 - input[3];
|
||||||
output[0] = (uint8_t)((alpha * input[0] + invertedAlpha * output[0]) >> 8);
|
output[0] = (uint8_t)((alpha * input[0] + invertedAlpha * output[0]) >> 8);
|
||||||
output[1] = (uint8_t)((alpha * input[1] + invertedAlpha * output[1]) >> 8);
|
output[1] = (uint8_t)((alpha * input[1] + invertedAlpha * output[1]) >> 8);
|
||||||
output[2] = (uint8_t)((alpha * input[2] + invertedAlpha * output[2]) >> 8);
|
output[2] = (uint8_t)((alpha * input[2] + invertedAlpha * output[2]) >> 8);
|
||||||
output[3] = 0xFF;
|
if(keepAlpha) {
|
||||||
|
output[3] = input[3];
|
||||||
|
} else {
|
||||||
|
output[3] = 0xFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "Shared/Video/ScaleFilter.h"
|
#include "Shared/Video/ScaleFilter.h"
|
||||||
#include "Shared/Video/DebugHud.h"
|
#include "Shared/Video/DebugHud.h"
|
||||||
#include "Shared/InputHud.h"
|
#include "Shared/InputHud.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "Shared/Video/SystemHud.h"
|
#include "Shared/Video/SystemHud.h"
|
||||||
#include "SNES/CartTypes.h"
|
#include "SNES/CartTypes.h"
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ void VideoDecoder::DecodeFrame(bool forRewind)
|
||||||
overscan.Bottom *= _scaleFilter->GetScale();
|
overscan.Bottom *= _scaleFilter->GetScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderedFrame convertedFrame((void*)outputBuffer, frameSize.Width, frameSize.Height, _frame.Scale, _frame.FrameNumber);
|
RenderedFrame convertedFrame((void*)outputBuffer, frameSize.Width, frameSize.Height, _frame.Scale, _frame.FrameNumber, _frame.InputData);
|
||||||
|
|
||||||
_emu->GetDebugHud()->Draw(outputBuffer, frameSize, overscan, _frame.FrameNumber, true);
|
_emu->GetDebugHud()->Draw(outputBuffer, frameSize, overscan, _frame.FrameNumber, true);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Utilities/SimpleLock.h"
|
#include "Utilities/SimpleLock.h"
|
||||||
#include "Utilities/AutoResetEvent.h"
|
#include "Utilities/AutoResetEvent.h"
|
||||||
#include "Shared/SettingTypes.h"
|
#include "Shared/SettingTypes.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
|
|
||||||
class BaseVideoFilter;
|
class BaseVideoFilter;
|
||||||
class ScaleFilter;
|
class ScaleFilter;
|
||||||
|
|
|
@ -19,6 +19,7 @@ VideoRenderer::VideoRenderer(Emulator* emu)
|
||||||
|
|
||||||
_rendererHud.reset(new DebugHud());
|
_rendererHud.reset(new DebugHud());
|
||||||
_systemHud.reset(new SystemHud(_emu, _rendererHud.get()));
|
_systemHud.reset(new SystemHud(_emu, _rendererHud.get()));
|
||||||
|
_inputHud.reset(new InputHud(emu, _rendererHud.get()));
|
||||||
|
|
||||||
_hudSurface = new uint32_t[256*240];
|
_hudSurface = new uint32_t[256*240];
|
||||||
_hudSize.Width = 256;
|
_hudSize.Width = 256;
|
||||||
|
@ -89,7 +90,14 @@ void VideoRenderer::RenderThread()
|
||||||
_hudSize = size;
|
_hudSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderedFrame frame;
|
||||||
|
{
|
||||||
|
_frameLock.AcquireSafe();
|
||||||
|
frame = _lastFrame;
|
||||||
|
}
|
||||||
|
|
||||||
memset(_hudSurface, 0, _hudSize.Width * _hudSize.Height * sizeof(uint32_t));
|
memset(_hudSurface, 0, _hudSize.Width * _hudSize.Height * sizeof(uint32_t));
|
||||||
|
_inputHud->DrawControllers(_hudSize, frame.InputData);
|
||||||
_systemHud->Draw(_hudSize.Width, _hudSize.Height);
|
_systemHud->Draw(_hudSize.Width, _hudSize.Height);
|
||||||
_rendererHud->Draw(_hudSurface, _hudSize, {}, 0, false);
|
_rendererHud->Draw(_hudSurface, _hudSize, {}, 0, false);
|
||||||
_renderer->Render(_hudSurface, _hudSize.Width, _hudSize.Height);
|
_renderer->Render(_hudSurface, _hudSize.Width, _hudSize.Height);
|
||||||
|
@ -97,13 +105,18 @@ void VideoRenderer::RenderThread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoRenderer::UpdateFrame(RenderedFrame frame)
|
void VideoRenderer::UpdateFrame(RenderedFrame& frame)
|
||||||
{
|
{
|
||||||
shared_ptr<IVideoRecorder> recorder = _recorder;
|
shared_ptr<IVideoRecorder> recorder = _recorder;
|
||||||
if(recorder) {
|
if(recorder) {
|
||||||
recorder->AddFrame(frame.FrameBuffer, frame.Width, frame.Height, _emu->GetFps());
|
recorder->AddFrame(frame.FrameBuffer, frame.Width, frame.Height, _emu->GetFps());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_frameLock.AcquireSafe();
|
||||||
|
_lastFrame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
if(_renderer) {
|
if(_renderer) {
|
||||||
_renderer->UpdateFrame(frame);
|
_renderer->UpdateFrame(frame);
|
||||||
_waitForRender.Signal();
|
_waitForRender.Signal();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include "Shared/SettingTypes.h"
|
#include "Shared/SettingTypes.h"
|
||||||
|
#include "Shared/RenderedFrame.h"
|
||||||
#include "Utilities/AutoResetEvent.h"
|
#include "Utilities/AutoResetEvent.h"
|
||||||
#include "Utilities/SimpleLock.h"
|
#include "Utilities/SimpleLock.h"
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ class IRenderingDevice;
|
||||||
class Emulator;
|
class Emulator;
|
||||||
class SystemHud;
|
class SystemHud;
|
||||||
class DebugHud;
|
class DebugHud;
|
||||||
|
class InputHud;
|
||||||
|
|
||||||
class IVideoRecorder;
|
class IVideoRecorder;
|
||||||
enum class VideoCodec;
|
enum class VideoCodec;
|
||||||
|
@ -29,9 +31,13 @@ private:
|
||||||
|
|
||||||
unique_ptr<DebugHud> _rendererHud;
|
unique_ptr<DebugHud> _rendererHud;
|
||||||
unique_ptr<SystemHud> _systemHud;
|
unique_ptr<SystemHud> _systemHud;
|
||||||
|
unique_ptr<InputHud> _inputHud;
|
||||||
uint32_t* _hudSurface = nullptr;
|
uint32_t* _hudSurface = nullptr;
|
||||||
FrameInfo _hudSize = {};
|
FrameInfo _hudSize = {};
|
||||||
|
|
||||||
|
RenderedFrame _lastFrame;
|
||||||
|
SimpleLock _frameLock;
|
||||||
|
|
||||||
shared_ptr<IVideoRecorder> _recorder;
|
shared_ptr<IVideoRecorder> _recorder;
|
||||||
|
|
||||||
void RenderThread();
|
void RenderThread();
|
||||||
|
@ -46,7 +52,7 @@ public:
|
||||||
void StartThread();
|
void StartThread();
|
||||||
void StopThread();
|
void StopThread();
|
||||||
|
|
||||||
void UpdateFrame(RenderedFrame frame);
|
void UpdateFrame(RenderedFrame& frame);
|
||||||
void RegisterRenderingDevice(IRenderingDevice *renderer);
|
void RegisterRenderingDevice(IRenderingDevice *renderer);
|
||||||
void UnregisterRenderingDevice(IRenderingDevice *renderer);
|
void UnregisterRenderingDevice(IRenderingDevice *renderer);
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,8 @@ namespace Mesen.Debugger.Utilities
|
||||||
Audio,
|
Audio,
|
||||||
[IconFile("DipSwitches")]
|
[IconFile("DipSwitches")]
|
||||||
Emulation,
|
Emulation,
|
||||||
|
[IconFile("Controller")]
|
||||||
|
Input,
|
||||||
[IconFile("VideoOptions")]
|
[IconFile("VideoOptions")]
|
||||||
Video,
|
Video,
|
||||||
[IconFile("NesIcon")]
|
[IconFile("NesIcon")]
|
||||||
|
|
|
@ -98,24 +98,29 @@
|
||||||
<Control ID="btnSetupMultitap2">Setup</Control>
|
<Control ID="btnSetupMultitap2">Setup</Control>
|
||||||
<Control ID="btnSetupMultitap3">Setup</Control>
|
<Control ID="btnSetupMultitap3">Setup</Control>
|
||||||
<Control ID="btnSetupMultitap4">Setup</Control>
|
<Control ID="btnSetupMultitap4">Setup</Control>
|
||||||
|
<Control ID="lblKeyBinding">Warning: Your current configuration contains conflicting key bindings - some physical buttons on your keyboard or gamepad are mapped to multiple buttons on the NES controller. If this is not intentional, please review and correct your key bindings.</Control>
|
||||||
|
</Form>
|
||||||
|
<Form ID="InputConfigView">
|
||||||
|
<Control ID="tpgGeneral">General</Control>
|
||||||
|
<Control ID="lblSmall">Small</Control>
|
||||||
|
<Control ID="lblLarge">Large</Control>
|
||||||
|
<Control ID="lblDeadzone">Controller axis deadzone size:</Control>
|
||||||
|
|
||||||
<Control ID="tpgAdvanced">Advanced</Control>
|
<Control ID="lblSensitivity">Mouse speed:</Control>
|
||||||
<Control ID="grpDisplayInput">Display Controller Input</Control>
|
<Control ID="lblLow">Slow</Control>
|
||||||
|
<Control ID="lblHigh">Fast</Control>
|
||||||
|
|
||||||
|
<Control ID="tpgDisplay">Display</Control>
|
||||||
|
<Control ID="lblDisplayInputPorts">Display ports: </Control>
|
||||||
<Control ID="chkDisplayPort1">Port 1</Control>
|
<Control ID="chkDisplayPort1">Port 1</Control>
|
||||||
<Control ID="chkDisplayPort2">Port 2</Control>
|
<Control ID="chkDisplayPort2">Port 2</Control>
|
||||||
<Control ID="chkDisplayPort3">Port 3</Control>
|
<Control ID="chkDisplayPort3">Port 3</Control>
|
||||||
<Control ID="chkDisplayPort4">Port 4</Control>
|
<Control ID="chkDisplayPort4">Port 4</Control>
|
||||||
<Control ID="chkDisplayPort5">Port 5</Control>
|
<Control ID="chkDisplayPort5">Port 5</Control>
|
||||||
<Control ID="lblDisplayPosition">Display Position:</Control>
|
<Control ID="lblDisplayPosition">Display position:</Control>
|
||||||
<Control ID="chkDisplayInputHorizontally">Display horizontally</Control>
|
<Control ID="chkDisplayInputHorizontally">Horizontal display</Control>
|
||||||
|
|
||||||
<Control ID="lblSmall">Small</Control>
|
|
||||||
<Control ID="lblLarge">Large</Control>
|
|
||||||
<Control ID="lblDeadzone">Controller axis deadzone size:</Control>
|
|
||||||
|
|
||||||
<Control ID="chkHideMousePointerForZapper">Hide mouse pointer when using zapper</Control>
|
<Control ID="chkHideMousePointerForZapper">Hide mouse pointer when using zapper</Control>
|
||||||
|
|
||||||
<Control ID="lblKeyBinding">Warning: Your current configuration contains conflicting key bindings - some physical buttons on your keyboard or gamepad are mapped to multiple buttons on the NES controller. If this is not intentional, please review and correct your key bindings.</Control>
|
|
||||||
</Form>
|
</Form>
|
||||||
<Form ID="OverscanConfig">
|
<Form ID="OverscanConfig">
|
||||||
<Control ID="lblLeft">Left</Control>
|
<Control ID="lblLeft">Left</Control>
|
||||||
|
@ -359,6 +364,7 @@
|
||||||
|
|
||||||
<Control ID="tabAudio">Audio</Control>
|
<Control ID="tabAudio">Audio</Control>
|
||||||
<Control ID="tabEmulation">Emulation</Control>
|
<Control ID="tabEmulation">Emulation</Control>
|
||||||
|
<Control ID="tabInput">Input</Control>
|
||||||
<Control ID="tabVideo">Video</Control>
|
<Control ID="tabVideo">Video</Control>
|
||||||
<Control ID="tabNes">NES</Control>
|
<Control ID="tabNes">NES</Control>
|
||||||
<Control ID="tabSnes">SNES</Control>
|
<Control ID="tabSnes">SNES</Control>
|
||||||
|
@ -2160,6 +2166,7 @@ x == [$150] || y == [10]
|
||||||
|
|
||||||
<Value ID="Audio">Audio</Value>
|
<Value ID="Audio">Audio</Value>
|
||||||
<Value ID="Emulation">Emulation</Value>
|
<Value ID="Emulation">Emulation</Value>
|
||||||
|
<Value ID="Input">Input</Value>
|
||||||
<Value ID="Video">Video</Value>
|
<Value ID="Video">Video</Value>
|
||||||
<Value ID="Nes">NES</Value>
|
<Value ID="Nes">NES</Value>
|
||||||
<Value ID="Snes">SNES</Value>
|
<Value ID="Snes">SNES</Value>
|
||||||
|
|
|
@ -323,6 +323,9 @@
|
||||||
<Compile Update="Debugger\Windows\MemoryToolsWindow.axaml.cs">
|
<Compile Update="Debugger\Windows\MemoryToolsWindow.axaml.cs">
|
||||||
<DependentUpon>MemoryToolsWindow.axaml</DependentUpon>
|
<DependentUpon>MemoryToolsWindow.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Views\InputConfigView.axaml.cs">
|
||||||
|
<DependentUpon>InputConfigView.axaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="Views\MainMenuView.axaml.cs">
|
<Compile Update="Views\MainMenuView.axaml.cs">
|
||||||
<DependentUpon>MainMenuView.axaml</DependentUpon>
|
<DependentUpon>MainMenuView.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
|
@ -12,8 +13,15 @@ namespace Mesen.Utilities
|
||||||
{
|
{
|
||||||
foreach(PropertyInfo prop in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
|
foreach(PropertyInfo prop in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
|
||||||
if(prop.GetCustomAttribute<ReactiveAttribute>() != null) {
|
if(prop.GetCustomAttribute<ReactiveAttribute>() != null) {
|
||||||
if(prop.GetValue(target) is ReactiveObject propValue) {
|
object? value = prop.GetValue(target);
|
||||||
|
if(value is ReactiveObject propValue) {
|
||||||
ReactiveHelper.RegisterRecursiveObserver(propValue, handler);
|
ReactiveHelper.RegisterRecursiveObserver(propValue, handler);
|
||||||
|
} else if(value is IList list) {
|
||||||
|
foreach(object listValue in list) {
|
||||||
|
if(listValue is ReactiveObject) {
|
||||||
|
ReactiveHelper.RegisterRecursiveObserver((ReactiveObject)listValue, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +35,15 @@ namespace Mesen.Utilities
|
||||||
{
|
{
|
||||||
foreach(PropertyInfo prop in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
|
foreach(PropertyInfo prop in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
|
||||||
if(prop.GetCustomAttribute<ReactiveAttribute>() != null) {
|
if(prop.GetCustomAttribute<ReactiveAttribute>() != null) {
|
||||||
if(prop.GetValue(target) is ReactiveObject propValue) {
|
object? value = prop.GetValue(target);
|
||||||
|
if(value is ReactiveObject propValue) {
|
||||||
ReactiveHelper.UnregisterRecursiveObserver(propValue, handler);
|
ReactiveHelper.UnregisterRecursiveObserver(propValue, handler);
|
||||||
|
} else if(value is IList list) {
|
||||||
|
foreach(object listValue in list) {
|
||||||
|
if(listValue is ReactiveObject) {
|
||||||
|
ReactiveHelper.UnregisterRecursiveObserver((ReactiveObject)listValue, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace Mesen.ViewModels
|
||||||
public class ConfigViewModel : DisposableViewModel
|
public class ConfigViewModel : DisposableViewModel
|
||||||
{
|
{
|
||||||
[Reactive] public AudioConfigViewModel? Audio { get; set; }
|
[Reactive] public AudioConfigViewModel? Audio { get; set; }
|
||||||
|
[Reactive] public InputConfigViewModel? Input { get; set; }
|
||||||
[Reactive] public VideoConfigViewModel? Video { get; set; }
|
[Reactive] public VideoConfigViewModel? Video { get; set; }
|
||||||
[Reactive] public PreferencesConfigViewModel? Preferences { get; set; }
|
[Reactive] public PreferencesConfigViewModel? Preferences { get; set; }
|
||||||
[Reactive] public EmulationConfigViewModel? Emulation { get; set; }
|
[Reactive] public EmulationConfigViewModel? Emulation { get; set; }
|
||||||
|
@ -38,6 +39,7 @@ namespace Mesen.ViewModels
|
||||||
switch(tab) {
|
switch(tab) {
|
||||||
case ConfigWindowTab.Audio: Audio ??= AddDisposable(new AudioConfigViewModel()); break;
|
case ConfigWindowTab.Audio: Audio ??= AddDisposable(new AudioConfigViewModel()); break;
|
||||||
case ConfigWindowTab.Emulation: Emulation ??= AddDisposable(new EmulationConfigViewModel()); break;
|
case ConfigWindowTab.Emulation: Emulation ??= AddDisposable(new EmulationConfigViewModel()); break;
|
||||||
|
case ConfigWindowTab.Input: Input ??= AddDisposable(new InputConfigViewModel()); break;
|
||||||
case ConfigWindowTab.Video: Video ??= AddDisposable(new VideoConfigViewModel()); break;
|
case ConfigWindowTab.Video: Video ??= AddDisposable(new VideoConfigViewModel()); break;
|
||||||
|
|
||||||
case ConfigWindowTab.Nes:
|
case ConfigWindowTab.Nes:
|
||||||
|
@ -63,6 +65,7 @@ namespace Mesen.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigManager.Config.Audio = Audio?.Config.Clone() ?? ConfigManager.Config.Audio;
|
ConfigManager.Config.Audio = Audio?.Config.Clone() ?? ConfigManager.Config.Audio;
|
||||||
|
ConfigManager.Config.Input = Input?.Config.Clone() ?? ConfigManager.Config.Input;
|
||||||
ConfigManager.Config.Video = Video?.Config.Clone() ?? ConfigManager.Config.Video;
|
ConfigManager.Config.Video = Video?.Config.Clone() ?? ConfigManager.Config.Video;
|
||||||
ConfigManager.Config.Preferences = Preferences?.Config.Clone() ?? ConfigManager.Config.Preferences;
|
ConfigManager.Config.Preferences = Preferences?.Config.Clone() ?? ConfigManager.Config.Preferences;
|
||||||
ConfigManager.Config.Emulation = Emulation?.Config.Clone() ?? ConfigManager.Config.Emulation;
|
ConfigManager.Config.Emulation = Emulation?.Config.Clone() ?? ConfigManager.Config.Emulation;
|
||||||
|
@ -80,12 +83,13 @@ namespace Mesen.ViewModels
|
||||||
{
|
{
|
||||||
Audio = 0,
|
Audio = 0,
|
||||||
Emulation = 1,
|
Emulation = 1,
|
||||||
Video = 2,
|
Input = 2,
|
||||||
|
Video = 3,
|
||||||
Nes = 4,
|
//separator
|
||||||
Snes = 5,
|
Nes = 5,
|
||||||
Gameboy = 6,
|
Snes = 6,
|
||||||
|
Gameboy = 7,
|
||||||
Preferences = 8
|
//separator
|
||||||
|
Preferences = 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Mesen.ViewModels
|
||||||
public class EmulationConfigViewModel : DisposableViewModel
|
public class EmulationConfigViewModel : DisposableViewModel
|
||||||
{
|
{
|
||||||
[Reactive] public EmulationConfig Config { get; set; }
|
[Reactive] public EmulationConfig Config { get; set; }
|
||||||
|
|
||||||
public EmulationConfigViewModel()
|
public EmulationConfigViewModel()
|
||||||
{
|
{
|
||||||
Config = ConfigManager.Config.Emulation.Clone();
|
Config = ConfigManager.Config.Emulation.Clone();
|
||||||
|
@ -19,5 +19,5 @@ namespace Mesen.ViewModels
|
||||||
|
|
||||||
AddDisposable(ReactiveHelper.RegisterRecursiveObserver(Config, (s, e) => { Config.ApplyConfig(); }));
|
AddDisposable(ReactiveHelper.RegisterRecursiveObserver(Config, (s, e) => { Config.ApplyConfig(); }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
23
NewUI/ViewModels/InputConfigViewModel.cs
Normal file
23
NewUI/ViewModels/InputConfigViewModel.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Mesen.Config;
|
||||||
|
using Mesen.Utilities;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
|
namespace Mesen.ViewModels
|
||||||
|
{
|
||||||
|
public class InputConfigViewModel : DisposableViewModel
|
||||||
|
{
|
||||||
|
[Reactive] public InputConfig Config { get; set; }
|
||||||
|
|
||||||
|
public InputConfigViewModel()
|
||||||
|
{
|
||||||
|
Config = ConfigManager.Config.Input.Clone();
|
||||||
|
|
||||||
|
if(Design.IsDesignMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddDisposable(ReactiveHelper.RegisterRecursiveObserver(Config, (s, e) => { Config.ApplyConfig(); }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -374,6 +374,10 @@ namespace Mesen.ViewModels
|
||||||
ActionType = ActionType.Emulation,
|
ActionType = ActionType.Emulation,
|
||||||
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Emulation)
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Emulation)
|
||||||
},
|
},
|
||||||
|
new MainMenuAction() {
|
||||||
|
ActionType = ActionType.Input,
|
||||||
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Input)
|
||||||
|
},
|
||||||
new MainMenuAction() {
|
new MainMenuAction() {
|
||||||
ActionType = ActionType.Video,
|
ActionType = ActionType.Video,
|
||||||
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Video)
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Video)
|
||||||
|
|
|
@ -22,15 +22,15 @@
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Grid ColumnDefinitions="Auto,Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
<Grid ColumnDefinitions="Auto,Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="{l:Translate lblEmulationSpeed}" />
|
<TextBlock Grid.Column="0" Grid.Row="0" Text="{l:Translate lblEmulationSpeed}" />
|
||||||
<NumericUpDown Grid.Column="1" Grid.Row="0" Value="{CompiledBinding Config.EmulationSpeed}" Maximum="5000" Minimum="0" Width="80" />
|
<NumericUpDown Grid.Column="1" Grid.Row="0" Value="{CompiledBinding Config.EmulationSpeed}" Maximum="5000" Minimum="0" />
|
||||||
<TextBlock Grid.Column="2" Grid.Row="0" Text="{l:Translate lblEmuSpeedHint}" />
|
<TextBlock Grid.Column="2" Grid.Row="0" Text="{l:Translate lblEmuSpeedHint}" />
|
||||||
|
|
||||||
<TextBlock Grid.Column="0" Grid.Row="1" Text="{l:Translate lblTurboSpeed}" />
|
<TextBlock Grid.Column="0" Grid.Row="1" Text="{l:Translate lblTurboSpeed}" />
|
||||||
<NumericUpDown Grid.Column="1" Grid.Row="1" Value="{CompiledBinding Config.TurboSpeed}" Maximum="5000" Minimum="0" Width="80" />
|
<NumericUpDown Grid.Column="1" Grid.Row="1" Value="{CompiledBinding Config.TurboSpeed}" Maximum="5000" Minimum="0" />
|
||||||
<TextBlock Grid.Column="2" Grid.Row="1" Text="{l:Translate lblTurboSpeedHint}" />
|
<TextBlock Grid.Column="2" Grid.Row="1" Text="{l:Translate lblTurboSpeedHint}" />
|
||||||
|
|
||||||
<TextBlock Grid.Column="0" Grid.Row="2" Text="{l:Translate lblRewindSpeed}" />
|
<TextBlock Grid.Column="0" Grid.Row="2" Text="{l:Translate lblRewindSpeed}" />
|
||||||
<NumericUpDown Grid.Column="1" Grid.Row="2" Value="{CompiledBinding Config.RewindSpeed}" Maximum="5000" Minimum="0" Width="80" />
|
<NumericUpDown Grid.Column="1" Grid.Row="2" Value="{CompiledBinding Config.RewindSpeed}" Maximum="5000" Minimum="0" />
|
||||||
<TextBlock Grid.Column="2" Grid.Row="2" Text="{l:Translate lblRewindSpeedHint}" />
|
<TextBlock Grid.Column="2" Grid.Row="2" Text="{l:Translate lblRewindSpeedHint}" />
|
||||||
|
|
||||||
<TextBlock Grid.Column="0" Grid.Row="4" Text="{l:Translate lblRunAhead}" />
|
<TextBlock Grid.Column="0" Grid.Row="4" Text="{l:Translate lblRunAhead}" />
|
||||||
|
|
89
NewUI/Views/InputConfigView.axaml
Normal file
89
NewUI/Views/InputConfigView.axaml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<UserControl
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="using:Mesen.ViewModels"
|
||||||
|
xmlns:c="using:Mesen.Controls"
|
||||||
|
xmlns:cfg="using:Mesen.Config"
|
||||||
|
xmlns:l="using:Mesen.Localization"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
x:DataType="vm:InputConfigViewModel"
|
||||||
|
x:Class="Mesen.Views.InputConfigView"
|
||||||
|
>
|
||||||
|
<Design.DataContext>
|
||||||
|
<vm:InputConfigViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
<TabControl TabStripPlacement="Top" SelectedIndex="0">
|
||||||
|
<TabItem Header="{l:Translate tpgGeneral}">
|
||||||
|
<StackPanel>
|
||||||
|
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||||
|
<TextBlock Grid.Row="0" Text="{l:Translate lblDeadzone}" VerticalAlignment="Top" Margin="0 15 5 0" />
|
||||||
|
<c:MesenSlider
|
||||||
|
Margin="12 15 10 0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="4"
|
||||||
|
TickFrequency="1"
|
||||||
|
Width="100"
|
||||||
|
HideValue="True"
|
||||||
|
Value="{CompiledBinding Config.ControllerDeadzoneSize}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid Grid.Row="1" Grid.Column="1" RowDefinitions="Auto" ColumnDefinitions="Auto,*,Auto" Width="115" HorizontalAlignment="Left" Margin="5 -5 5 0">
|
||||||
|
<TextBlock Text="{l:Translate lblSmall}" />
|
||||||
|
<TextBlock Text="{l:Translate lblLarge}" Grid.Column="2" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Text="{l:Translate lblSensitivity}" VerticalAlignment="Top" Margin="0 15 5 0" />
|
||||||
|
<c:MesenSlider
|
||||||
|
Margin="12 15 10 0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="3"
|
||||||
|
TickFrequency="1"
|
||||||
|
Width="100"
|
||||||
|
HideValue="True"
|
||||||
|
Value="{CompiledBinding Config.MouseSensitivity}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid Grid.Row="3" Grid.Column="1" RowDefinitions="Auto" ColumnDefinitions="Auto,*,Auto" Width="107" HorizontalAlignment="Left" Margin="10 -5 5 0">
|
||||||
|
<TextBlock Text="{l:Translate lblLow}" />
|
||||||
|
<TextBlock Text="{l:Translate lblHigh}" Grid.Column="2" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</TabItem>
|
||||||
|
<TabItem Header="{l:Translate tpgDisplay}">
|
||||||
|
<Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto">
|
||||||
|
<TextBlock Text="{l:Translate lblDisplayInputPorts}" VerticalAlignment="Top" Margin="0 5 0 0" />
|
||||||
|
<Grid Grid.Column="1" ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto">
|
||||||
|
<Grid.Styles>
|
||||||
|
<Style Selector="CheckBox">
|
||||||
|
<Setter Property="Margin" Value="0 0 5 0" />
|
||||||
|
</Style>
|
||||||
|
</Grid.Styles>
|
||||||
|
|
||||||
|
<CheckBox Content="{l:Translate chkDisplayPort1}" IsChecked="{CompiledBinding Config.DisplayInputPort1}" />
|
||||||
|
<CheckBox Grid.Column="1" Content="{l:Translate chkDisplayPort2}" IsChecked="{CompiledBinding Config.DisplayInputPort2}" />
|
||||||
|
<CheckBox Grid.Row="1" Content="{l:Translate chkDisplayPort3}" IsChecked="{CompiledBinding Config.DisplayInputPort3}" />
|
||||||
|
<CheckBox Grid.Row="1" Grid.Column="1" Content="{l:Translate chkDisplayPort4}" IsChecked="{CompiledBinding Config.DisplayInputPort4}" />
|
||||||
|
<CheckBox Grid.Row="2" Content="{l:Translate chkDisplayPort5}" IsChecked="{CompiledBinding Config.DisplayInputPort5}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Text="{l:Translate lblDisplayPosition}" />
|
||||||
|
<c:EnumComboBox Grid.Row="1" Grid.Column="1" SelectedItem="{CompiledBinding Config.DisplayInputPosition}" />
|
||||||
|
|
||||||
|
<CheckBox Grid.Row="2" Grid.ColumnSpan="2" IsChecked="{CompiledBinding Config.DisplayInputHorizontally}" Content="{l:Translate chkDisplayInputHorizontally}" />
|
||||||
|
</Grid>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
</TabControl>
|
||||||
|
</UserControl>
|
21
NewUI/Views/InputConfigView.axaml.cs
Normal file
21
NewUI/Views/InputConfigView.axaml.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Mesen.Utilities;
|
||||||
|
using Mesen.Config;
|
||||||
|
|
||||||
|
namespace Mesen.Views
|
||||||
|
{
|
||||||
|
public class InputConfigView : UserControl
|
||||||
|
{
|
||||||
|
public InputConfigView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,9 @@
|
||||||
<DataTemplate DataType="{x:Type vm:EmulationConfigViewModel}">
|
<DataTemplate DataType="{x:Type vm:EmulationConfigViewModel}">
|
||||||
<v:EmulationConfigView />
|
<v:EmulationConfigView />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type vm:InputConfigViewModel}">
|
||||||
|
<v:InputConfigView />
|
||||||
|
</DataTemplate>
|
||||||
<DataTemplate DataType="{x:Type vm:VideoConfigViewModel}">
|
<DataTemplate DataType="{x:Type vm:VideoConfigViewModel}">
|
||||||
<v:VideoConfigView />
|
<v:VideoConfigView />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
@ -71,6 +74,14 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TabItem.Header>
|
</TabItem.Header>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
<TabItem Content="{CompiledBinding Input}">
|
||||||
|
<TabItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="/Assets/Controller.png" Margin="0 0 10 0" />
|
||||||
|
<TextBlock VerticalAlignment="Center" Text="{l:Translate tabInput}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TabItem.Header>
|
||||||
|
</TabItem>
|
||||||
<TabItem Content="{CompiledBinding Video}">
|
<TabItem Content="{CompiledBinding Video}">
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
|
|
|
@ -120,14 +120,6 @@ void Renderer::CleanupDevice()
|
||||||
{
|
{
|
||||||
ResetNesBuffers();
|
ResetNesBuffers();
|
||||||
ReleaseRenderTargetView();
|
ReleaseRenderTargetView();
|
||||||
if(_pAlphaEnableBlendingState) {
|
|
||||||
_pAlphaEnableBlendingState->Release();
|
|
||||||
_pAlphaEnableBlendingState = nullptr;
|
|
||||||
}
|
|
||||||
if(_pDepthDisabledStencilState) {
|
|
||||||
_pDepthDisabledStencilState->Release();
|
|
||||||
_pDepthDisabledStencilState = nullptr;
|
|
||||||
}
|
|
||||||
if(_pSwapChain) {
|
if(_pSwapChain) {
|
||||||
_pSwapChain->SetFullscreenState(false, nullptr);
|
_pSwapChain->SetFullscreenState(false, nullptr);
|
||||||
_pSwapChain->Release();
|
_pSwapChain->Release();
|
||||||
|
@ -318,61 +310,6 @@ HRESULT Renderer::InitDevice()
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc;
|
|
||||||
ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc));
|
|
||||||
depthDisabledStencilDesc.DepthEnable = false;
|
|
||||||
depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
||||||
depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
|
|
||||||
depthDisabledStencilDesc.StencilEnable = true;
|
|
||||||
depthDisabledStencilDesc.StencilReadMask = 0xFF;
|
|
||||||
depthDisabledStencilDesc.StencilWriteMask = 0xFF;
|
|
||||||
depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
|
||||||
depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
|
|
||||||
depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
|
||||||
depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
||||||
depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
|
||||||
depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
|
|
||||||
depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
|
||||||
depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
||||||
|
|
||||||
// Create the state using the device.
|
|
||||||
hr = _pd3dDevice->CreateDepthStencilState(&depthDisabledStencilDesc, &_pDepthDisabledStencilState);
|
|
||||||
if(FAILED(hr)) {
|
|
||||||
MessageManager::Log("D3DDevice::CreateDepthStencilState() failed - Error:" + std::to_string(hr));
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the blend state description.
|
|
||||||
D3D11_BLEND_DESC blendStateDescription;
|
|
||||||
ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC));
|
|
||||||
|
|
||||||
// Create an alpha enabled blend state description.
|
|
||||||
blendStateDescription.RenderTarget[0].BlendEnable = TRUE;
|
|
||||||
blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
|
||||||
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
|
||||||
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
|
||||||
blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
|
||||||
blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
|
||||||
blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
|
||||||
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f;
|
|
||||||
|
|
||||||
// Create the blend state using the description.
|
|
||||||
hr = _pd3dDevice->CreateBlendState(&blendStateDescription, &_pAlphaEnableBlendingState);
|
|
||||||
if(FAILED(hr)) {
|
|
||||||
MessageManager::Log("D3DDevice::CreateBlendState() failed - Error:" + std::to_string(hr));
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
float blendFactor[4];
|
|
||||||
blendFactor[0] = 0.0f;
|
|
||||||
blendFactor[1] = 0.0f;
|
|
||||||
blendFactor[2] = 0.0f;
|
|
||||||
blendFactor[3] = 0.0f;
|
|
||||||
|
|
||||||
_pDeviceContext->OMSetBlendState(_pAlphaEnableBlendingState, blendFactor, 0xffffffff);
|
|
||||||
_pDeviceContext->OMSetDepthStencilState(_pDepthDisabledStencilState, 1);
|
|
||||||
|
|
||||||
hr = CreateEmuTextureBuffers();
|
hr = CreateEmuTextureBuffers();
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -420,7 +357,7 @@ ID3D11ShaderResourceView* Renderer::GetShaderResourceView(ID3D11Texture2D* textu
|
||||||
return shaderResourceView;
|
return shaderResourceView;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::UpdateFrame(RenderedFrame frame)
|
void Renderer::UpdateFrame(RenderedFrame& frame)
|
||||||
{
|
{
|
||||||
SetScreenSize(frame.Width, frame.Height);
|
SetScreenSize(frame.Width, frame.Height);
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@ private:
|
||||||
ID3D11DeviceContext* _pDeviceContext = nullptr;
|
ID3D11DeviceContext* _pDeviceContext = nullptr;
|
||||||
IDXGISwapChain* _pSwapChain = nullptr;
|
IDXGISwapChain* _pSwapChain = nullptr;
|
||||||
ID3D11RenderTargetView* _pRenderTargetView = nullptr;
|
ID3D11RenderTargetView* _pRenderTargetView = nullptr;
|
||||||
ID3D11DepthStencilState* _pDepthDisabledStencilState = nullptr;
|
|
||||||
ID3D11BlendState* _pAlphaEnableBlendingState = nullptr;
|
|
||||||
|
|
||||||
atomic<bool> _needFlip = false;
|
atomic<bool> _needFlip = false;
|
||||||
uint8_t* _textureBuffer[2] = { nullptr, nullptr };
|
uint8_t* _textureBuffer[2] = { nullptr, nullptr };
|
||||||
|
@ -86,5 +84,5 @@ public:
|
||||||
void Reset();
|
void Reset();
|
||||||
void Render(uint32_t* hudBuffer, uint32_t hudWidth, uint32_t hudHeight);
|
void Render(uint32_t* hudBuffer, uint32_t hudWidth, uint32_t hudHeight);
|
||||||
|
|
||||||
void UpdateFrame(RenderedFrame frame);
|
void UpdateFrame(RenderedFrame& frame);
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue