From 3c879cc2b37238be461383732e814c418e46d554 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 8 Apr 2019 16:54:24 -0500 Subject: [PATCH] Win32: Add hacks dialog. --- snes9x.cpp | 3 +- snes9x.h | 2 + win32/rsrc/resource.h | 15 ++++- win32/rsrc/snes9x.rc | 64 ++++++++++++++++++++ win32/snes9xw.vcxproj | 12 ++-- win32/snes9xw.vcxproj.filters | 2 + win32/wconfig.cpp | 31 ++++++++++ win32/wsnes9x.cpp | 109 +++++++++++++++++++++++++++++++++- 8 files changed, 228 insertions(+), 10 deletions(-) diff --git a/snes9x.cpp b/snes9x.cpp index d551657d..dcebe76e 100644 --- a/snes9x.cpp +++ b/snes9x.cpp @@ -308,7 +308,8 @@ void S9xLoadConfigFiles (char **argv, int argc) // Hack Settings.SuperFXClockMultiplier = conf.GetUInt("Hack::SuperFXClockMultiplier", 100); - + Settings.OverclockMode = conf.GetUInt("Hack::OverclockMode", 0); + Settings.SeparateEchoBuffer = conf.GetBool("Hack::SeparateEchoBuffer", false); Settings.DisableGameSpecificHacks = !conf.GetBool("Hack::EnableGameSpecificHacks", true); Settings.BlockInvalidVRAMAccessMaster = !conf.GetBool("Hack::AllowInvalidVRAMAccess", false); Settings.HDMATimingHack = conf.GetInt ("Hack::HDMATiming", 100); diff --git a/snes9x.h b/snes9x.h index 75766f38..1fca4ebf 100644 --- a/snes9x.h +++ b/snes9x.h @@ -303,7 +303,9 @@ struct SSettings bool8 OpenGLEnable; + bool8 SeparateEchoBuffer; uint32 SuperFXClockMultiplier; + int OverclockMode; int OneClockCycle; int OneSlowClockCycle; int TwoClockCycles; diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index a7993e92..5cc89d4f 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -44,6 +44,7 @@ #define IDI_ICON2 160 #define IDI_ICON3 161 #define IDI_ICON4 162 +#define IDD_DIALOG_HACKS 164 #define IDC_DRIVER 1001 #define IDC_BUFLEN 1002 #define IDC_RATE 1003 @@ -203,6 +204,7 @@ #define IDC_COMBO1 1155 #define IDC_C_LOADWATCH 1155 #define IDC_OUTPUTMETHOD 1155 +#define IDC_CPU_OVERCLOCK 1155 #define IDC_NC_ADDRESS 1156 #define IDC_C_SAVEWATCH 1156 #define IDC_ASPECTDROP 1156 @@ -394,6 +396,12 @@ #define IDC_ROM_SPLITTER 3027 #define IDC_SYSLINK_DX 3028 #define IDC_STATIC_ICON 3029 +#define IDC_INVALID_VRAM 3030 +#define IDC_SEPARATE_ECHO_BUFFER 3031 +#define IDC_SOUND_INTERPOLATION 3033 +#define IDC_SFX_CLOCK_SPEED 3035 +#define IDC_SFX_CLOCK_SPEED_SPIN 3036 +#define IDC_NO_SPRITE_LIMIT 3037 #define ID_FILE_EXIT 40001 #define ID_WINDOW_HIDEMENUBAR 40004 #define ID_FILE_AVI_RECORDING 40005 @@ -509,6 +517,7 @@ #define ID_SAVEMEMPACK 40175 #define ID_INPUT_BACKGROUNDKEYBOARDHOTKEYS 40176 #define ID_INPUT_DETECTGAMEPADCHANGES 40177 +#define ID_EMULATION_HACKS 40178 #define ID_FILE_SAVE0 44000 #define ID_FILE_SAVE1 44001 #define ID_FILE_SAVE2 44002 @@ -538,9 +547,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 164 -#define _APS_NEXT_COMMAND_VALUE 40178 -#define _APS_NEXT_CONTROL_VALUE 3032 +#define _APS_NEXT_RESOURCE_VALUE 167 +#define _APS_NEXT_COMMAND_VALUE 40179 +#define _APS_NEXT_CONTROL_VALUE 3038 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 58864e7a..19284dfd 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -560,6 +560,26 @@ BEGIN ICON "",IDC_STATIC_ICON,7,7,20,20,SS_CENTERIMAGE | SS_REALSIZEIMAGE | WS_GROUP END +IDD_DIALOG_HACKS DIALOGEX 0, 0, 234, 120 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Emulator Hacks" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,126,100,48,14 + PUSHBUTTON "Cancel",IDCANCEL,180,100,48,14 + RTEXT "SuperFX Clock Speed %:",IDC_STATIC,12,6,90,8 + RTEXT "CPU Overclock:",IDC_STATIC,12,24,90,8 + RTEXT "Sound Interpolation Type:",IDC_STATIC,6,42,96,8 + EDITTEXT IDC_SFX_CLOCK_SPEED,108,6,42,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SFX_CLOCK_SPEED_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,136,6,12,14 + COMBOBOX IDC_CPU_OVERCLOCK,108,24,54,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SOUND_INTERPOLATION,108,42,120,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Allow Invalid VRAM Access",IDC_INVALID_VRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,60,104,10 + CONTROL "Separate Echo Buffer from RAM",IDC_SEPARATE_ECHO_BUFFER, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,72,123,10 + CONTROL "Disable Sprite Limit",IDC_NO_SPRITE_LIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,84,80,10 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -722,6 +742,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 85 END + + IDD_DIALOG_HACKS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 227 + TOPMARGIN, 7 + BOTTOMMARGIN, 113 + END END #endif // APSTUDIO_INVOKED @@ -935,6 +963,7 @@ BEGIN MENUITEM "Pause &When Inactive", ID_EMULATION_PAUSEWHENINACTIVE MENUITEM "&Frame Advance", ID_FRAME_ADVANCE MENUITEM SEPARATOR + MENUITEM "&Hacks...", ID_EMULATION_HACKS MENUITEM "&Settings...\tAlt+F8", ID_OPTIONS_SETTINGS END POPUP "&Input" @@ -1141,6 +1170,41 @@ BEGIN 0 END +IDD_DIALOG_HACKS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog Info +// + +IDD_DIALOG_HACKS DLGINIT +BEGIN + IDC_CPU_OVERCLOCK, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_CPU_OVERCLOCK, 0x403, 4, 0 +0x6f4c, 0x0077, + IDC_CPU_OVERCLOCK, 0x403, 7, 0 +0x654d, 0x6964, 0x6d75, "\000" + IDC_CPU_OVERCLOCK, 0x403, 4, 0 +0x614d, 0x0078, + IDC_SOUND_INTERPOLATION, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_SOUND_INTERPOLATION, 0x403, 7, 0 +0x694c, 0x656e, 0x7261, "\000" + IDC_SOUND_INTERPOLATION, 0x403, 20, 0 +0x6147, 0x7375, 0x6973, 0x6e61, 0x2820, 0x6361, 0x7563, 0x6172, 0x6574, +0x0029, + IDC_SOUND_INTERPOLATION, 0x403, 6, 0 +0x7543, 0x6962, 0x0063, + IDC_SOUND_INTERPOLATION, 0x403, 5, 0 +0x6953, 0x636e, "\000" + 0 +END + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/win32/snes9xw.vcxproj b/win32/snes9xw.vcxproj index d55881e0..a9c54df2 100644 --- a/win32/snes9xw.vcxproj +++ b/win32/snes9xw.vcxproj @@ -118,7 +118,7 @@ Disabled $(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\..\;$(ProjectDir)zlib\src;$(ProjectDir)..\unzip;$(ProjectDir)libpng\src;$(ProjectDir)..\apu\bapu;$(ProjectDir)glslang\src - _DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;D3D_DEBUG_INFO;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) + _DEBUG;ALLOW_CPU_OVERCLOCK;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;D3D_DEBUG_INFO;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) MultiThreadedDebug Default @@ -167,7 +167,7 @@ Disabled $(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\..\;$(ProjectDir)zlib\src;$(ProjectDir)..\unzip;$(ProjectDir)libpng\src;$(ProjectDir)..\apu\bapu;$(ProjectDir)glslang\src - _DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;D3D_DEBUG_INFO;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) + _DEBUG;ALLOW_CPU_OVERCLOCK;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;D3D_DEBUG_INFO;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) MultiThreadedDebug Default @@ -221,7 +221,7 @@ true true $(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\..\;$(ProjectDir)zlib\src;$(ProjectDir)..\unzip;$(ProjectDir)libpng\src;$(ProjectDir)..\apu\bapu;$(ProjectDir)glslang\src;%(AdditionalIncludeDirectories) - NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) + NDEBUG;ALLOW_CPU_OVERCLOCK;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) true MultiThreaded Default @@ -274,7 +274,7 @@ true true $(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\..\;$(ProjectDir)zlib\src;$(ProjectDir)..\unzip;$(ProjectDir)libpng\src;$(ProjectDir)..\apu\bapu;$(ProjectDir)glslang\src;%(AdditionalIncludeDirectories) - NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) + NDEBUG;ALLOW_CPU_OVERCLOCK;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;NETPLAY_SUPPORT;DIRECTDRAW_SUPPORT;USE_SLANG;%(PreprocessorDefinitions) true MultiThreaded Default @@ -716,6 +716,8 @@ + + @@ -741,4 +743,4 @@ - + \ No newline at end of file diff --git a/win32/snes9xw.vcxproj.filters b/win32/snes9xw.vcxproj.filters index e8f062e0..858ebe5a 100644 --- a/win32/snes9xw.vcxproj.filters +++ b/win32/snes9xw.vcxproj.filters @@ -676,6 +676,8 @@ Resource\Other + + diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index f94f1848..6a9119ef 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -671,6 +671,34 @@ void WinPostLoad(ConfigFile& conf) } } + if (Settings.MaxSpriteTilesPerLine != 34 && Settings.MaxSpriteTilesPerLine != 128) + Settings.MaxSpriteTilesPerLine = 34; + + switch (Settings.OverclockMode) + { + default: + case 0: + Settings.OneClockCycle = 6; + Settings.OneSlowClockCycle = 8; + Settings.TwoClockCycles = 12; + break; + case 1: + Settings.OneClockCycle = 6; + Settings.OneSlowClockCycle = 6; + Settings.TwoClockCycles = 12; + break; + case 2: + Settings.OneClockCycle = 4; + Settings.OneSlowClockCycle = 5; + Settings.TwoClockCycles = 8; + break; + case 3: + Settings.OneClockCycle = 3; + Settings.OneSlowClockCycle = 4; + Settings.TwoClockCycles = 6; + break; + } + ConfigFile::SetNiceAlignment(niceAlignment); ConfigFile::SetShowComments(showComments); ConfigFile::SetAlphaSort(configSort==2); @@ -900,7 +928,10 @@ void WinRegisterConfigItems() #undef ADDN #undef CATEGORY #define CATEGORY "Hack" + AddUIntC("CPUOverclockMode", Settings.OverclockMode, 0, "CPU Overclock: 0=none, 1=min, 2=medium, 3=max"); + AddUIntC("MaxSpriteTilesPerLine", Settings.MaxSpriteTilesPerLine, 34, "Max sprite tiles rendered per line. Default = 34, Unlimited ~= 128"); AddUIntC("SuperFXClockMultiplier", Settings.SuperFXClockMultiplier, 100, "SuperFX speed, in percent (default 100)"); + AddBoolC("SeparateEchoBuffer", Settings.SeparateEchoBuffer, false, "Separate echo buffer from APU ram. For old hacks only."); #undef CATEGORY } diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 98167f32..b55ae59b 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -92,6 +92,7 @@ INT_PTR CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) INT_PTR CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK DlgEmulatorHacksProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); @@ -2228,6 +2229,13 @@ LRESULT CALLBACK WinProc( DialogBox(g_hInst, MAKEINTRESOURCE(IDD_EMU_SETTINGS), hWnd, DlgEmulatorProc); RestoreSNESDisplay (); break; + case ID_EMULATION_HACKS: + RestoreGUIDisplay(); + if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_HACKS), hWnd, DlgEmulatorHacksProc)) + S9xReset(); + else + RestoreSNESDisplay(); + break; case ID_HELP_ABOUT: RestoreGUIDisplay (); DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, DlgAboutProc); @@ -3306,7 +3314,7 @@ int WINAPI WinMain( PCEnd = PCStart; PCEndTicks = timeGetTime()*1000; PCStartTicks = timeGetTime()*1000; - PCFrameTime = PCFrameTimeNTSC = (__int64)((float)PCBase / 60.09881389744051f); + PCFrameTime = PCFrameTimeNTSC = (__int64)((float)PCBase / 59.9968); PCFrameTimePAL = PCBase / 50; @@ -5062,6 +5070,105 @@ INT_PTR CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) default:return false; } } + +INT_PTR CALLBACK DlgEmulatorHacksProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + UDACCEL accel = { 0, 10 }; + bool must_reset = 0; + + switch (msg) + { + case WM_INITDIALOG: + + SendDlgItemMessage(hDlg, IDC_SFX_CLOCK_SPEED_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)400, (short)50)); + SendDlgItemMessage(hDlg, IDC_SFX_CLOCK_SPEED_SPIN, UDM_SETPOS, 0, Settings.SuperFXClockMultiplier); + SendDlgItemMessage(hDlg, IDC_SFX_CLOCK_SPEED_SPIN, UDM_SETACCEL, 1, (LPARAM)&accel); + + SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_ADDSTRING, 0, (LPARAM)TEXT("None")); + SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_ADDSTRING, 0, (LPARAM)TEXT("Low")); + SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_ADDSTRING, 0, (LPARAM)TEXT("Medium")); + SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_ADDSTRING, 0, (LPARAM)TEXT("Max")); + SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_SETCURSEL, Settings.OverclockMode, 0); + + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_ADDSTRING, 0, (LPARAM)TEXT("None")); + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_ADDSTRING, 0, (LPARAM)TEXT("Linear")); + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_ADDSTRING, 0, (LPARAM)TEXT("Gaussian (SNES Hardware)")); + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_ADDSTRING, 0, (LPARAM)TEXT("Cubic")); + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_ADDSTRING, 0, (LPARAM)TEXT("Sinc")); + SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_SETCURSEL, Settings.InterpolationMethod, 0); + + CheckDlgButton(hDlg, IDC_INVALID_VRAM, !Settings.BlockInvalidVRAMAccessMaster); + CheckDlgButton(hDlg, IDC_SEPARATE_ECHO_BUFFER, Settings.SeparateEchoBuffer); + CheckDlgButton(hDlg, IDC_NO_SPRITE_LIMIT, Settings.MaxSpriteTilesPerLine == 128); + + return true; + break; + + case WM_COMMAND: + + switch (LOWORD(wParam)) + { + case IDOK: + if ((!Settings.BlockInvalidVRAMAccessMaster == IsDlgButtonChecked(hDlg, IDC_INVALID_VRAM) || + Settings.SeparateEchoBuffer != IsDlgButtonChecked(hDlg, IDC_SEPARATE_ECHO_BUFFER)) + && !Settings.StopEmulation) + { + + if (MessageBoxA(hDlg, "To make the requested changes, the game will need to be reset.", "Reset Required", MB_OKCANCEL) != IDOK) + return false; + must_reset = true; + } + + Settings.SuperFXClockMultiplier = SendDlgItemMessage(hDlg, IDC_SFX_CLOCK_SPEED_SPIN, UDM_GETPOS, 0, 0); + Settings.OverclockMode = SendDlgItemMessage(hDlg, IDC_CPU_OVERCLOCK, CB_GETCURSEL, 0, 0); + Settings.InterpolationMethod = SendDlgItemMessage(hDlg, IDC_SOUND_INTERPOLATION, CB_GETCURSEL, 0, 0); + Settings.BlockInvalidVRAMAccessMaster = !IsDlgButtonChecked(hDlg, IDC_INVALID_VRAM); + Settings.SeparateEchoBuffer = IsDlgButtonChecked(hDlg, IDC_SEPARATE_ECHO_BUFFER); + Settings.MaxSpriteTilesPerLine = IsDlgButtonChecked(hDlg, IDC_NO_SPRITE_LIMIT) ? 128 : 34; + + switch (Settings.OverclockMode) + { + default: + case 0: + Settings.OneClockCycle = 6; + Settings.OneSlowClockCycle = 8; + Settings.TwoClockCycles = 12; + break; + case 1: + Settings.OneClockCycle = 6; + Settings.OneSlowClockCycle = 6; + Settings.TwoClockCycles = 12; + break; + case 2: + Settings.OneClockCycle = 4; + Settings.OneSlowClockCycle = 6; + Settings.TwoClockCycles = 8; + break; + case 3: + Settings.OneClockCycle = 3; + Settings.OneSlowClockCycle = 4; + Settings.TwoClockCycles = 6; + break; + } + + EndDialog(hDlg, must_reset); + return true; + + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + default: + break; + } + + return true; + break; + + default: + return false; + } +} + INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static TCHAR paths[10][MAX_PATH];