mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-23 17:19:39 +00:00
UI improvements + Gamepad support
This commit is contained in:
parent
1765b9a690
commit
9ada341050
@ -2,6 +2,8 @@
|
||||
#include "Console.h"
|
||||
#include "Timer.h"
|
||||
|
||||
uint32_t Console::Flags = 0;
|
||||
|
||||
Console::Console(wstring filename)
|
||||
{
|
||||
_mapper = MapperFactory::InitializeFromFile(filename);
|
||||
@ -30,7 +32,21 @@ void Console::Reset()
|
||||
void Console::Stop()
|
||||
{
|
||||
_stop = true;
|
||||
while(!_stopped) { }
|
||||
}
|
||||
|
||||
void Console::SetFlags(int flags)
|
||||
{
|
||||
Console::Flags |= flags;
|
||||
}
|
||||
|
||||
void Console::ClearFlags(int flags)
|
||||
{
|
||||
Console::Flags ^= flags;
|
||||
}
|
||||
|
||||
bool Console::CheckFlag(int flag)
|
||||
{
|
||||
return (Console::Flags & flag) == flag;
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
@ -45,7 +61,7 @@ void Console::Run()
|
||||
executedCycles += _cpu->Exec();
|
||||
_ppu->Exec();
|
||||
|
||||
if(limitFrameRate && executedCycles > 30000) {
|
||||
if(CheckFlag(EmulationFlags::LimitFPS) && executedCycles > 30000) {
|
||||
double targetTime = 16.77;
|
||||
elapsedTime = clockTimer.GetElapsedMS();
|
||||
while(targetTime > elapsedTime) {
|
||||
@ -66,7 +82,6 @@ void Console::Run()
|
||||
}
|
||||
|
||||
if(_stop) {
|
||||
_stopped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,16 @@
|
||||
#include "MemoryManager.h"
|
||||
#include "ControlManager.h"
|
||||
|
||||
enum EmulationFlags
|
||||
{
|
||||
LimitFPS = 0x01,
|
||||
};
|
||||
|
||||
class Console
|
||||
{
|
||||
private:
|
||||
static uint32_t Flags;
|
||||
|
||||
unique_ptr<CPU> _cpu;
|
||||
unique_ptr<PPU> _ppu;
|
||||
unique_ptr<BaseMapper> _mapper;
|
||||
@ -17,7 +24,6 @@ class Console
|
||||
unique_ptr<MemoryManager> _memoryManager;
|
||||
|
||||
bool _stop = false;
|
||||
bool _stopped = false;
|
||||
|
||||
public:
|
||||
Console(wstring filename);
|
||||
@ -26,6 +32,11 @@ class Console
|
||||
void Stop();
|
||||
void RunTest(bool callback(Console*));
|
||||
void Reset();
|
||||
|
||||
static bool CheckFlag(int flag);
|
||||
static void SetFlags(int flags);
|
||||
static void ClearFlags(int flags);
|
||||
|
||||
static void RunTests();
|
||||
static void Load(wstring filename);
|
||||
};
|
||||
|
@ -33,8 +33,8 @@ void ControlManager::RefreshStateBuffer(uint8_t port)
|
||||
ButtonState buttonState = controlDevice->GetButtonState();
|
||||
|
||||
//"Button status for each controller is returned as an 8-bit report in the following order: A, B, Select, Start, Up, Down, Left, Right."
|
||||
uint8_t state = buttonState.A | (buttonState.B << 1) | (buttonState.Select << 2) | (buttonState.Start << 3) |
|
||||
(buttonState.Up << 4) | (buttonState.Down << 5) | (buttonState.Left << 6) | (buttonState.Right << 7);
|
||||
uint8_t state = (uint8_t)buttonState.A | ((uint8_t)buttonState.B << 1) | ((uint8_t)buttonState.Select << 2) | ((uint8_t)buttonState.Start << 3) |
|
||||
((uint8_t)buttonState.Up << 4) | ((uint8_t)buttonState.Down << 5) | ((uint8_t)buttonState.Left << 6) | ((uint8_t)buttonState.Right << 7);
|
||||
|
||||
_stateBuffer[port] = state;
|
||||
} else {
|
||||
|
@ -32,7 +32,6 @@ using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::ios;
|
||||
using std::ifstream;
|
||||
//using std::string;
|
||||
using std::wstring;
|
||||
using std::exception;
|
||||
using std::atomic;
|
||||
|
BIN
GUI/GUI.rc
BIN
GUI/GUI.rc
Binary file not shown.
@ -59,7 +59,7 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OptimizeReferences>
|
||||
</OptimizeReferences>
|
||||
<EnableCOMDATFolding>
|
||||
@ -89,7 +89,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<FxCompile>
|
||||
<ShaderType>
|
||||
@ -113,6 +113,7 @@
|
||||
<ClInclude Include="DirectXTK\VertexTypes.h" />
|
||||
<ClInclude Include="DirectXTK\WICTextureLoader.h" />
|
||||
<ClInclude Include="DirectXTK\XboxDDSTextureLoader.h" />
|
||||
<ClInclude Include="GamePad.h" />
|
||||
<ClInclude Include="InputManager.h" />
|
||||
<ClInclude Include="Renderer.h" />
|
||||
<ClInclude Include="Resource.h" />
|
||||
@ -121,6 +122,7 @@
|
||||
<ClInclude Include="MainWindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GamePad.cpp" />
|
||||
<ClCompile Include="InputManager.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="Renderer.cpp" />
|
||||
|
@ -57,9 +57,6 @@
|
||||
<ClInclude Include="DirectXTK\PrimitiveBatch.h">
|
||||
<Filter>Header Files\DirectXTK</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Resource.h">
|
||||
<Filter>Header Files\DirectXTK</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DirectXTK\ScreenGrab.h">
|
||||
<Filter>Header Files\DirectXTK</Filter>
|
||||
</ClInclude>
|
||||
@ -84,6 +81,12 @@
|
||||
<ClInclude Include="InputManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GamePad.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
@ -101,6 +104,9 @@
|
||||
<ClCompile Include="InputManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GamePad.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="GUI.rc">
|
||||
|
27
GUI/GamePad.cpp
Normal file
27
GUI/GamePad.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "stdafx.h"
|
||||
#include "GamePad.h"
|
||||
|
||||
GamePad::GamePad()
|
||||
{
|
||||
}
|
||||
|
||||
bool GamePad::Initialize()
|
||||
{
|
||||
int controllerId = -1;
|
||||
|
||||
for(DWORD i = 0; i < XUSER_MAX_COUNT && controllerId == -1; i++) {
|
||||
ZeroMemory(&_state, sizeof(XINPUT_STATE));
|
||||
|
||||
if(XInputGetState(i, &_state) == ERROR_SUCCESS) {
|
||||
controllerId = i;
|
||||
}
|
||||
}
|
||||
|
||||
return controllerId != -1;
|
||||
}
|
||||
|
||||
bool GamePad::IsPressed(WORD button)
|
||||
{
|
||||
Initialize();
|
||||
return (_state.Gamepad.wButtons & button) != 0;
|
||||
}
|
17
GUI/GamePad.h
Normal file
17
GUI/GamePad.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <Xinput.h>
|
||||
|
||||
class GamePad
|
||||
{
|
||||
private:
|
||||
XINPUT_STATE _state;
|
||||
|
||||
bool Initialize();
|
||||
|
||||
public:
|
||||
GamePad();
|
||||
|
||||
bool IsPressed(WORD button);
|
||||
};
|
@ -9,14 +9,14 @@ bool InputManager::IsKeyPressed(int key)
|
||||
ButtonState InputManager::GetButtonState()
|
||||
{
|
||||
ButtonState state;
|
||||
state.A = IsKeyPressed('A');
|
||||
state.B = IsKeyPressed('S');
|
||||
state.Select = IsKeyPressed('W');
|
||||
state.Start = IsKeyPressed('Q');
|
||||
state.Up = IsKeyPressed(VK_UP);
|
||||
state.Down = IsKeyPressed(VK_DOWN);
|
||||
state.Left = IsKeyPressed(VK_LEFT);
|
||||
state.Right = IsKeyPressed(VK_RIGHT);
|
||||
state.A = IsKeyPressed('A') || _gamePad.IsPressed(XINPUT_GAMEPAD_X);
|
||||
state.B = IsKeyPressed('S') || _gamePad.IsPressed(XINPUT_GAMEPAD_A);
|
||||
state.Select = IsKeyPressed('W') || _gamePad.IsPressed(XINPUT_GAMEPAD_BACK);
|
||||
state.Start = IsKeyPressed('Q') || _gamePad.IsPressed(XINPUT_GAMEPAD_START);
|
||||
state.Up = IsKeyPressed(VK_UP) || _gamePad.IsPressed(XINPUT_GAMEPAD_DPAD_UP);
|
||||
state.Down = IsKeyPressed(VK_DOWN) || _gamePad.IsPressed(XINPUT_GAMEPAD_DPAD_DOWN);
|
||||
state.Left = IsKeyPressed(VK_LEFT) || _gamePad.IsPressed(XINPUT_GAMEPAD_DPAD_LEFT);
|
||||
state.Right = IsKeyPressed(VK_RIGHT) || _gamePad.IsPressed(XINPUT_GAMEPAD_DPAD_RIGHT);
|
||||
|
||||
return state;
|
||||
}
|
@ -2,10 +2,13 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "..\Core\IControlDevice.h"
|
||||
#include "GamePad.h"
|
||||
|
||||
class InputManager : public IControlDevice
|
||||
{
|
||||
private:
|
||||
GamePad _gamePad;
|
||||
|
||||
bool IsKeyPressed(int key);
|
||||
|
||||
public:
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include <io.h>
|
||||
#include <Fcntl.h>
|
||||
#include "resource.h"
|
||||
#include "Resource.h"
|
||||
#include "MainWindow.h"
|
||||
#include "..\Core\Console.h"
|
||||
#include "..\Core\Timer.h"
|
||||
@ -68,25 +66,23 @@ namespace NES
|
||||
Initialize();
|
||||
|
||||
InputManager inputManager;
|
||||
|
||||
ControlManager::RegisterControlDevice(&inputManager, 0);
|
||||
|
||||
HACCEL hAccel = LoadAccelerators(_hInstance, MAKEINTRESOURCE(IDC_Accelerator));
|
||||
if(hAccel == nullptr) {
|
||||
//error
|
||||
std::cout << "error";
|
||||
}
|
||||
|
||||
MSG msg = { 0 };
|
||||
Timer timer;
|
||||
int frameCount = 0;
|
||||
while(WM_QUIT != msg.message) {
|
||||
if(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
if(!TranslateAccelerator(_hWnd, hAccel, &msg)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
} else {
|
||||
_renderer.Render();
|
||||
frameCount++;
|
||||
if(frameCount == 500) {
|
||||
double fps = (double)frameCount / (timer.GetElapsedMS() / 1000);
|
||||
//std::cout << "FPS: " << fps << std::endl;
|
||||
timer.Reset();
|
||||
frameCount = 0;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(1));
|
||||
}
|
||||
@ -177,8 +173,7 @@ namespace NES
|
||||
Stop();
|
||||
|
||||
_console.reset(new Console(filename));
|
||||
std::thread nesThread(&Console::Run, _console.get());
|
||||
nesThread.detach();
|
||||
_emuThread.reset(new thread(&Console::Run, _console.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,12 +181,32 @@ namespace NES
|
||||
{
|
||||
if(_console) {
|
||||
_console->Stop();
|
||||
_emuThread->join();
|
||||
|
||||
_console.release();
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::ToggleMenuCheck(int resourceID)
|
||||
{
|
||||
HMENU hMenu = GetMenu(_hWnd);
|
||||
bool checked = (GetMenuState(hMenu, resourceID, MF_BYCOMMAND) & MF_CHECKED) == MF_CHECKED;
|
||||
CheckMenuItem(hMenu, resourceID, MF_BYCOMMAND | (checked ? MF_UNCHECKED : MF_CHECKED));
|
||||
return !checked;
|
||||
}
|
||||
|
||||
void MainWindow::LimitFPS_Click()
|
||||
{
|
||||
if(ToggleMenuCheck(ID_OPTIONS_LIMITFPS)) {
|
||||
Console::SetFlags(EmulationFlags::LimitFPS);
|
||||
} else {
|
||||
Console::ClearFlags(EmulationFlags::LimitFPS);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK MainWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static MainWindow *mainWindow = MainWindow::GetInstance();
|
||||
PAINTSTRUCT ps;
|
||||
int wmId, wmEvent;
|
||||
HDC hdc;
|
||||
@ -201,13 +216,15 @@ namespace NES
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
switch (wmId) {
|
||||
case IDM_FILE_OPEN:
|
||||
MainWindow::GetInstance()->OpenROM();
|
||||
mainWindow->OpenROM();
|
||||
break;
|
||||
case IDM_FILE_RUNTESTS:
|
||||
|
||||
break;
|
||||
case ID_OPTIONS_LIMITFPS:
|
||||
mainWindow->LimitFPS_Click();
|
||||
break;
|
||||
case IDM_ABOUT:
|
||||
DialogBox(nullptr, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
|
||||
@ -224,8 +241,25 @@ namespace NES
|
||||
EndPaint(hWnd, &ps);
|
||||
break;
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
WINDOWPOS* windowPos;
|
||||
windowPos = (WINDOWPOS*)lParam;
|
||||
|
||||
RECT clientRect;
|
||||
RECT windowRect;
|
||||
LONG xGap;
|
||||
LONG yGap;
|
||||
GetWindowRect(hWnd, &windowRect);
|
||||
GetClientRect(hWnd, &clientRect);
|
||||
|
||||
xGap = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
|
||||
yGap = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
|
||||
|
||||
windowPos->cy = (windowPos->cx - xGap) * 240 / 256 + yGap;
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
MainWindow::GetInstance()->Stop();
|
||||
mainWindow->Stop();
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
|
@ -12,6 +12,7 @@ namespace NES {
|
||||
int _nCmdShow;
|
||||
Renderer _renderer;
|
||||
unique_ptr<Console> _console;
|
||||
unique_ptr<thread> _emuThread;
|
||||
|
||||
bool Initialize();
|
||||
HRESULT InitWindow();
|
||||
@ -23,6 +24,10 @@ namespace NES {
|
||||
return MainWindow::Instance;
|
||||
}
|
||||
|
||||
void LimitFPS_Click();
|
||||
|
||||
bool ToggleMenuCheck(int resourceID);
|
||||
|
||||
public:
|
||||
MainWindow(HINSTANCE hInstance, int nCmdShow) : _hInstance(hInstance), _nCmdShow(nCmdShow)
|
||||
{
|
||||
|
@ -28,8 +28,8 @@ namespace NES
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(_hWnd, &rc);
|
||||
UINT width = rc.right - rc.left;
|
||||
UINT height = rc.bottom - rc.top;
|
||||
UINT width = 256; // rc.right - rc.left;
|
||||
UINT height = 240; // rc.bottom - rc.top;
|
||||
|
||||
UINT createDeviceFlags = 0;
|
||||
#ifdef _DEBUG
|
||||
|
BIN
GUI/resource.h
BIN
GUI/resource.h
Binary file not shown.
@ -28,5 +28,10 @@
|
||||
#include <d3dcompiler.h>
|
||||
#include <directxmath.h>
|
||||
#include <directxcolors.h>
|
||||
#include <io.h>
|
||||
#include <Fcntl.h>
|
||||
#include <thread>
|
||||
|
||||
using std::thread;
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
Loading…
Reference in New Issue
Block a user