From a9b70dd32bc3529d0cfd1d4dd8a3282e59d8ff90 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 26 Apr 2021 16:29:21 +0200 Subject: [PATCH 01/93] Auto-Generate STROOP Config!!!! (only one line for emu) --- main/win/main_win.cpp | 48 +++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 58ce8b7e..2142cfc5 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -221,6 +221,7 @@ char input_name[255]; char sound_name[255]; char rsp_name[255]; +char stroopConfigLine[150] = {0}; enum EThreadFuncState { TFS_INITMEM, @@ -3048,20 +3049,44 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { BOOL temppaused = !emu_paused; pauseEmu(TRUE); - char buf[31]; - char res; + + // todo: simplify + + // maybe pack formatted and buffer and result into one long char array where you only read necessary part + + char buf[12]; // ram start sprintf(buf, "0x%#08p", rdram); - std::string stdstr_buf = buf; -#ifdef _WIN32 // This will only work on windows - res = MessageBoxA(0, stdstr_buf.c_str(), "RAM Start (Click Yes to Copy)", MB_ICONINFORMATION | MB_TASKMODAL | MB_YESNO); - printf("Buffer size: %d\n", stdstr_buf.size()); - printf("Buffer length: %d\n", stdstr_buf.length()); - if (res == IDYES) { + + if (!stroopConfigLine[0]) { + TCHAR procName[MAX_PATH]; + GetModuleFileName(NULL, procName, MAX_PATH); + _splitpath(procName, 0, 0, procName, 0); + + // yea this is very gross but i cant get sprintf work at all in this case + // apparently you cant do something like this: + + //char* a = (char*)malloc(20); + //char* b = (char*)malloc(20); + //strcpy(a, "hi, %s"); + //strcpy(b, "person"); + //sprintf(a, b); + //printf(a); + + // --- "a" will not be "hi, person" + strcpy(stroopConfigLine, ""); + } + std::string stdstr_buf = stroopConfigLine; +#ifdef _WIN32 + if (MessageBoxA(0, buf, "RAM Start (Click Yes to Copy STROOP config line)", MB_ICONINFORMATION | MB_TASKMODAL | MB_YESNO) == IDYES) { OpenClipboard(mainHWND); EmptyClipboard(); - HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, stdstr_buf.size()+1); + HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, stdstr_buf.size() + 1); if (hg) { - memcpy(GlobalLock(hg), stdstr_buf.c_str(), stdstr_buf.size()+1); + memcpy(GlobalLock(hg), stdstr_buf.c_str(), stdstr_buf.size() + 1); GlobalUnlock(hg); SetClipboardData(CF_TEXT, hg); CloseClipboard(); @@ -3069,10 +3094,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) } else { printf("Failed to copy"); CloseClipboard(); } } - + #endif + if (temppaused) { resumeEmu(TRUE); CheckMenuItem(GetMenu(mainHWND), EMU_PAUSE, MF_BYCOMMAND | MFS_UNCHECKED); From 242e49541b16c24e3e26cdcb8af0cdda1650e514 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 28 Apr 2021 21:06:39 +0200 Subject: [PATCH 02/93] Prompt to close TASInput if already in testing mode --- tasinput_plugin/src/DefDI.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 258f0627..c4368ad8 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1329,7 +1329,9 @@ EXPORT void CALL RomClosed (void) { } void StartFake() { if (fakeStatusThread) { - MessageBox(0, "You can only have 1 testing TASInput running at a time", "Too many instances", MB_TOPMOST); + if (MessageBox(0, "You can only have 1 testing TASInput running at a time. Do you want to kill current TASInput instance?", "Too many instances", MB_TOPMOST | MB_YESNO) == IDNO)return; + // kill tasinput + RomClosed(); return; } From dc73bf45b69a1ddbbe2f2762f0bfcc7ed78b20b2 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 28 Apr 2021 21:11:36 +0200 Subject: [PATCH 03/93] Use fast txtbox method in more places, protection against handles becoming obsolete --- tasinput_plugin/src/DefDI.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index c4368ad8..ff429028 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -61,6 +61,7 @@ bool romIsOpen = false; HMENU hMenu; HANDLE fakeStatusThread = NULL; // fake! used for testing plugin +bool validatedhTxtbox = FALSE; bool lock; //don't focus mupen FILE* cFile; /*combo file conains list of combos in format: @@ -831,13 +832,14 @@ void Status::GetKeys(BUTTONS * Keys) gettingKeys = false; } + VOID SetXYTextFast(HWND parent, BOOL x, char* str) { // Optimized setdlgitemtext: explanation: // GetDlgItem is very slow because of the many controls and this may limit the speed of emulator in some cases(?) // Instead of using SetDlgItemText every time and (internally) calling GetDlgItem, we precompute the handles to x and y textboxes the first time and re-use them // NOTE: this may break when extending dialogs because handle changes (will fix in future) - if (!textXHWND) textXHWND = GetDlgItem(parent, IDC_EDITX); - if (!textYHWND) textYHWND = GetDlgItem(parent, IDC_EDITY); + if (!textXHWND || validatedhTxtbox) textXHWND = GetDlgItem(parent, IDC_EDITX); + if (!textYHWND || validatedhTxtbox) textYHWND = GetDlgItem(parent, IDC_EDITY); if (x) SetWindowText(textXHWND, str); // Is there implicit char* -> long pointer string happening? else SetWindowText(textYHWND, str); @@ -1833,7 +1835,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // initial x/y text field values sprintf(str, "%d", initialStickX); - SetDlgItemText(statusDlg, IDC_EDITX, str); + SetDlgItemText(statusDlg, IDC_EDITX, str); // no need for "fast" version here this only happens one time sprintf(str, "%d", -initialStickY); SetDlgItemText(statusDlg, IDC_EDITY, str); @@ -2047,7 +2049,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) sprintf(str, "%d", (int)(angle2 + (angle2>0 ? 0.5f : -0.5f))); skipEditX = true; } - SetDlgItemText(statusDlg, IDC_EDITX, str); + SetXYTextFast(statusDlg, true, str); if(!AngDisp) sprintf(str, "%d", -overrideY); else @@ -2056,8 +2058,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) sprintf(str, "%d", (int)(0.5f + radialDistance)); skipEditY = true; } - SetDlgItemText(statusDlg, IDC_EDITY, str); - + SetXYTextFast(statusDlg, false, str); radialRecalc = true; overrideOn = true; //joystick dragged with mouse RefreshAnalogPicture(); @@ -2210,7 +2211,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(newOverrideX > 127) newOverrideX = 127; if(newOverrideX < -128) newOverrideX = -128; sprintf(str, "%d", newOverrideX); - SetDlgItemText(statusDlg, IDC_EDITX, str); + SetXYTextFast(statusDlg, true, str); } } else @@ -2221,12 +2222,12 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(newAng >= 360) { sprintf(str, "%d", newAng-360); - SetDlgItemText(statusDlg, IDC_EDITX, str); + SetXYTextFast(statusDlg, true, str); } else if(newAng < 0) { sprintf(str, "%d", newAng+360); - SetDlgItemText(statusDlg, IDC_EDITX, str); + SetXYTextFast(statusDlg, true, str); } float newAngF = (newAng - 90) * (PI/180.0f); newOverrideX = (int)(xScale * radialDistance * cosf((float)newAngF)); @@ -2265,7 +2266,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(newOverrideY > 127) newOverrideY = 127; if(newOverrideY < -128) newOverrideY = -128; sprintf(str, "%d", -newOverrideY); - SetDlgItemText(statusDlg, IDC_EDITY, str); + SetXYTextFast(statusDlg, false, str); } } else @@ -2420,6 +2421,10 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // Resizing wouldn't work, because any resizing causes visible damage to the dialog's background // due to some messages not getting through to repair it StartThread(Control); + + // Invalidate cache + validatedhTxtbox = FALSE; + } break; case IDC_PLAY: activeCombo = ListBox_GetCurSel(GetDlgItem(statusDlg, IDC_MACROLIST)); From 6c4013e04533fb7a2c147946a1f9e4fbd9d6d2b6 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 28 Apr 2021 21:14:18 +0200 Subject: [PATCH 04/93] lmao --- tasinput_plugin/src/DefDI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index ff429028..3b6b907f 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -838,8 +838,8 @@ VOID SetXYTextFast(HWND parent, BOOL x, char* str) { // GetDlgItem is very slow because of the many controls and this may limit the speed of emulator in some cases(?) // Instead of using SetDlgItemText every time and (internally) calling GetDlgItem, we precompute the handles to x and y textboxes the first time and re-use them // NOTE: this may break when extending dialogs because handle changes (will fix in future) - if (!textXHWND || validatedhTxtbox) textXHWND = GetDlgItem(parent, IDC_EDITX); - if (!textYHWND || validatedhTxtbox) textYHWND = GetDlgItem(parent, IDC_EDITY); + if (!textXHWND || !validatedhTxtbox) textXHWND = GetDlgItem(parent, IDC_EDITX); + if (!textYHWND || !validatedhTxtbox) textYHWND = GetDlgItem(parent, IDC_EDITY); if (x) SetWindowText(textXHWND, str); // Is there implicit char* -> long pointer string happening? else SetWindowText(textYHWND, str); From 0c353fe31119aef3890bc7da5abcef7599e1b48c Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Thu, 29 Apr 2021 15:11:00 +0200 Subject: [PATCH 05/93] some debugview improvements (needs polish this is buggy) --- main/win/GUI_LogWindow.c | 40 +++++++++++++++------------------------- main/win/main_win.cpp | 11 +++++------ 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/main/win/GUI_LogWindow.c b/main/win/GUI_LogWindow.c index 03a69617..83455283 100755 --- a/main/win/GUI_LogWindow.c +++ b/main/win/GUI_LogWindow.c @@ -20,13 +20,14 @@ #include "DebugView.h" #include "main_win.h" -int extLogger ; - +int extLogger; +//HINSTANCE dv_hInst; +HMODULE DVHandle; ///////////////// External Logger DLL ////////////////////////////////////////// int CreateExtLogger() { - HMODULE DVHandle; + char TempStr[MAX_PATH]; sprintf(TempStr,"%s%s",AppPath,"debugview.dll") ; @@ -36,23 +37,16 @@ int CreateExtLogger() if (DVHandle) { FileLog = (void (__cdecl *)(char *, ...)) GetProcAddress(DVHandle, "FileLog"); - OpenDV = (HWND (__cdecl *)(HINSTANCE, int)) GetProcAddress(DVHandle, "OpenDV"); - DVMsg = (void (__cdecl *)(int, char *, ...)) GetProcAddress(DVHandle, "DVMsg"); - CloseDV = (void (__cdecl *)(void)) GetProcAddress(DVHandle, "CloseDV"); - ShowDV = (void (__cdecl *)(int)) GetProcAddress(DVHandle, "ShowDV"); - SetUserIcon = (void (__cdecl *)(int, HICON)) GetProcAddress(DVHandle, "SetUserIcon"); - SetUserIconName = (void (__cdecl *)(int, char*)) GetProcAddress(DVHandle, "SetUserIconName"); - DVClear = (void (__cdecl*)( void )) GetProcAddress(DVHandle, "DVClear");; - OpenDV( DVHandle, DV_SHOW ); + OpenDV(DVHandle, DV_HIDE); // ShowDV( DV_HIDE ) ; return 1; @@ -63,24 +57,18 @@ int CreateExtLogger() } /* Show / Hide Management */ -void ShowLogWindow() { - if (extLogger) { - if (ShowDV) ShowDV( DV_SHOW ) ; - } +void ShowLogWindow() { + if (extLogger) ShowDV(DV_SHOW); } -void HideLogWindow() { - if (extLogger) { - if (ShowDV) ShowDV( DV_HIDE ) ; - } +void HideLogWindow() { + if (extLogger) ShowDV(DV_HIDE); } void ShowHideLogWindow() { - if (extLogger) { - if (ShowDV) ShowDV( DV_AUTO ) ; - } + if (extLogger) ShowDV(DV_AUTO); } @@ -162,13 +150,15 @@ void ClearLogWindow() int GUI_CreateLogWindow( HWND hwnd ) { - extLogger = CreateExtLogger() ; - return 0; + extLogger = CreateExtLogger(); + return extLogger; } void CloseLogWindow() { + // if this closes once you can never open it again + // probably this is just shitty programming because debugview source code isnt available if (extLogger) { - if (CloseDV) CloseDV() ; + if (CloseDV) CloseDV(); } } diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 2142cfc5..3ac48a40 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3649,14 +3649,13 @@ int WINAPI WinMain( SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_ACCEPTFILES | WS_EX_LAYERED); //this can't be applied before ShowWindow(), otherwise you must use some fancy function UpdateWindow(hwnd); #endif + EnableMenuItem(GetMenu(hwnd), ID_LOG_WINDOW, MF_DISABLED); #ifdef _DEBUG - GUI_CreateLogWindow(hwnd); + if(GUI_CreateLogWindow(mainHWND)) EnableMenuItem(GetMenu(hwnd), ID_LOG_WINDOW, MF_ENABLED); #endif - if (!extLogger) - { - //DeleteMenu( GetMenu(hwnd), ID_LOG_WINDOW, MF_BYCOMMAND); - EnableMenuItem(GetMenu(hwnd), ID_LOG_WINDOW, MF_GRAYED); - } + + + if (!isKailleraExist()) { From 5ed998bb4f4c4f620777bfd42fa54a5d4a8c2caa Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 1 May 2021 14:31:11 +0200 Subject: [PATCH 06/93] Crash handler first commit --- main/win/main_win.cpp | 8 +++- winproject/mupen64/CrashHandler.cpp | 44 +++++++++++++++++++ winproject/mupen64/CrashHandler.h | 6 +++ winproject/mupen64/mupen64_2017.vcxproj | 2 + .../mupen64/mupen64_2017.vcxproj.filters | 6 +++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 winproject/mupen64/CrashHandler.cpp create mode 100644 winproject/mupen64/CrashHandler.h diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 3ac48a40..0809012c 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -52,6 +52,7 @@ extern "C" { #include "RomSettings.h" #include "GUI_logwindow.h" #include "commandline.h" +#include "CrashHandler.h" #include "../vcr.h" #include "../../r4300/recomph.h" @@ -3516,6 +3517,7 @@ void LoadConfigExternals() { savestates_ignore_nonmovie_warnings = Config.IgnoreStWarnings; } + int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { @@ -3544,7 +3546,6 @@ int WINAPI WinMain( CreateDirectory((path + "ScreenShots").c_str(), NULL); CreateDirectory((path + "plugin").c_str(), NULL); } - emu_launched = 0; emu_paused = 1; /************ Loading Config *******/ @@ -3674,6 +3675,11 @@ int WINAPI WinMain( LoadConfigExternals(); + #ifndef _DEBUG + //warning, this is ignored when debugger is attached (like visual studio) + SetUnhandledExceptionFilter(ExceptionReleaseTarget); + #endif + //RaiseException(1, 0, 0, 0); //shows messagebox from wntdll while(GetMessage(&Msg, NULL, 0, 0) > 0) { if (!TranslateAccelerator(mainHWND,Accel,&Msg) diff --git a/winproject/mupen64/CrashHandler.cpp b/winproject/mupen64/CrashHandler.cpp new file mode 100644 index 00000000..1b890596 --- /dev/null +++ b/winproject/mupen64/CrashHandler.cpp @@ -0,0 +1,44 @@ +#include "CrashHandler.h" +#include "main_win.h" +#include +#include + +void FindModuleName(void* addr) +{ + HMODULE hMods[1024]; + HANDLE hProcess = GetCurrentProcess(); + DWORD cbNeeded; + if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) + { + for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) + { + TCHAR szModName[MAX_PATH]; + + // Get the full path to the module's file. + + if (GetModuleFileNameEx(hProcess, hMods[i], szModName, + sizeof(szModName) / sizeof(TCHAR))) + { + // Print the module name and handle value. + + printf(TEXT("\t%s (0x%08X)\n"), szModName, hMods[i]); + } + } + } +} + +LONG WINAPI ExceptionReleaseTarget(_EXCEPTION_POINTERS* ExceptionInfo) +{ + int len = 0; + char error[2048]; + void* addr = ExceptionInfo->ExceptionRecord->ExceptionAddress; + FindModuleName(addr); + len += sprintf(error, "Addr:%x\n", addr); + len += sprintf(error, "Gfx:%x\n", gfx_name); + len += sprintf(error, "Input:%x\n", input_name); + len += sprintf(error, "Audio:%x\n", sound_name); + len += sprintf(error, "rsp:%x\n", rsp_name); + + int code = MessageBox(0, "Emulator crashed, press OK to try to continue\n Crash log saved to " CRASH_LOG, "Exception", MB_OKCANCEL | MB_ICONERROR); + return code == IDOK ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; +} \ No newline at end of file diff --git a/winproject/mupen64/CrashHandler.h b/winproject/mupen64/CrashHandler.h new file mode 100644 index 00000000..a93a2b73 --- /dev/null +++ b/winproject/mupen64/CrashHandler.h @@ -0,0 +1,6 @@ +#pragma once +#include + +#define CRASH_LOG "crash.log" + +LONG WINAPI ExceptionReleaseTarget(_EXCEPTION_POINTERS* ExceptionInfo) \ No newline at end of file diff --git a/winproject/mupen64/mupen64_2017.vcxproj b/winproject/mupen64/mupen64_2017.vcxproj index c54057ac..06830289 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj +++ b/winproject/mupen64/mupen64_2017.vcxproj @@ -234,6 +234,7 @@ + true true @@ -711,6 +712,7 @@ CompileAsCpp + diff --git a/winproject/mupen64/mupen64_2017.vcxproj.filters b/winproject/mupen64/mupen64_2017.vcxproj.filters index c7ca651c..d0c1f7c4 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj.filters +++ b/winproject/mupen64/mupen64_2017.vcxproj.filters @@ -203,6 +203,9 @@ Source Files\lua + + Source Files\main\win + @@ -442,6 +445,9 @@ Source Files\main + + Source Files\main\win + From 8105f719ad4cdf2107b06794d156120424b7cafc Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 1 May 2021 14:42:08 +0200 Subject: [PATCH 07/93] second commit --- {winproject/mupen64 => main/win}/CrashHandler.cpp | 0 {winproject/mupen64 => main/win}/CrashHandler.h | 0 winproject/mupen64/mupen64_2017.vcxproj | 4 ++-- winproject/mupen64/mupen64_2017.vcxproj.filters | 4 ++-- winproject/mupen64/mupen64_2017.vcxproj.user | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) rename {winproject/mupen64 => main/win}/CrashHandler.cpp (100%) rename {winproject/mupen64 => main/win}/CrashHandler.h (100%) diff --git a/winproject/mupen64/CrashHandler.cpp b/main/win/CrashHandler.cpp similarity index 100% rename from winproject/mupen64/CrashHandler.cpp rename to main/win/CrashHandler.cpp diff --git a/winproject/mupen64/CrashHandler.h b/main/win/CrashHandler.h similarity index 100% rename from winproject/mupen64/CrashHandler.h rename to main/win/CrashHandler.h diff --git a/winproject/mupen64/mupen64_2017.vcxproj b/winproject/mupen64/mupen64_2017.vcxproj index 06830289..5db10879 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj +++ b/winproject/mupen64/mupen64_2017.vcxproj @@ -218,6 +218,7 @@ false + @@ -234,7 +235,6 @@ - true true @@ -389,6 +389,7 @@ CompileAsCpp CompileAsCpp + Default Default @@ -712,7 +713,6 @@ CompileAsCpp - diff --git a/winproject/mupen64/mupen64_2017.vcxproj.filters b/winproject/mupen64/mupen64_2017.vcxproj.filters index d0c1f7c4..778871f8 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj.filters +++ b/winproject/mupen64/mupen64_2017.vcxproj.filters @@ -203,7 +203,7 @@ Source Files\lua - + Source Files\main\win @@ -445,7 +445,7 @@ Source Files\main - + Source Files\main\win diff --git a/winproject/mupen64/mupen64_2017.vcxproj.user b/winproject/mupen64/mupen64_2017.vcxproj.user index ace9a86a..3f030911 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj.user +++ b/winproject/mupen64/mupen64_2017.vcxproj.user @@ -1,3 +1,6 @@  + + false + \ No newline at end of file From 4a5a02d053f1bba47c08826c09f497d77ccc5a24 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 1 May 2021 15:53:52 +0200 Subject: [PATCH 08/93] Exception handler --- main/win/CrashHandler.cpp | 46 ++++++++++++++++++++++++++++----------- main/win/CrashHandler.h | 2 +- main/win/main_win.cpp | 1 + 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/main/win/CrashHandler.cpp b/main/win/CrashHandler.cpp index 1b890596..0d57cda1 100644 --- a/main/win/CrashHandler.cpp +++ b/main/win/CrashHandler.cpp @@ -2,8 +2,15 @@ #include "main_win.h" #include #include +#include "../../winproject/resource.h" //MUPEN_VERSION +#include "vcr.h" -void FindModuleName(void* addr) +//Attempt to find the base module, might be faulty with crazy crashes where everything corrupts +//error - points to the error msg buffer +//addr - where did it crash +//len - current error length so it can append properly +//returns length of appended text +int FindModuleName(char *error, void* addr, int len) { HMODULE hMods[1024]; HANDLE hProcess = GetCurrentProcess(); @@ -12,32 +19,45 @@ void FindModuleName(void* addr) { for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { - TCHAR szModName[MAX_PATH]; - + char modname[MAX_PATH]; // Get the full path to the module's file. - if (GetModuleFileNameEx(hProcess, hMods[i], szModName, - sizeof(szModName) / sizeof(TCHAR))) + if (GetModuleBaseName(hProcess, hMods[i], modname, + sizeof(modname) / sizeof(char))) { - // Print the module name and handle value. - printf(TEXT("\t%s (0x%08X)\n"), szModName, hMods[i]); + // write the address with module + if (hMods[i]ExceptionRecord->ExceptionAddress; - FindModuleName(addr); - len += sprintf(error, "Addr:%x\n", addr); - len += sprintf(error, "Gfx:%x\n", gfx_name); - len += sprintf(error, "Input:%x\n", input_name); - len += sprintf(error, "Audio:%x\n", sound_name); - len += sprintf(error, "rsp:%x\n", rsp_name); + len += FindModuleName(error, addr, len); //appends to error as well + + //emu info + len += sprintf(error + len, "Version:" MUPEN_VERSION "\n"); + len += sprintf(error + len, "Gfx:%s\n", gfx_name); + len += sprintf(error + len, "Input:%s\n", input_name); + len += sprintf(error + len, "Audio:%s\n", sound_name); + len += sprintf(error + len, "rsp:%s\n", rsp_name); + extern int m_task; + //some flags + len += sprintf(error + len, "m_task:%d\n", m_task); + len += sprintf(error + len, "emu_launched:%d\n", emu_launched); + len += sprintf(error + len, "is_capturing_avi:%d\n", VCR_isCapturing()); + + FILE* f = fopen(CRASH_LOG, "w+"); //overwrite + fprintf(f, error); + fclose(f); int code = MessageBox(0, "Emulator crashed, press OK to try to continue\n Crash log saved to " CRASH_LOG, "Exception", MB_OKCANCEL | MB_ICONERROR); return code == IDOK ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; diff --git a/main/win/CrashHandler.h b/main/win/CrashHandler.h index a93a2b73..77be5cec 100644 --- a/main/win/CrashHandler.h +++ b/main/win/CrashHandler.h @@ -3,4 +3,4 @@ #define CRASH_LOG "crash.log" -LONG WINAPI ExceptionReleaseTarget(_EXCEPTION_POINTERS* ExceptionInfo) \ No newline at end of file +LONG WINAPI ExceptionReleaseTarget(_EXCEPTION_POINTERS* ExceptionInfo); \ No newline at end of file diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 0809012c..61537d92 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3679,6 +3679,7 @@ int WINAPI WinMain( //warning, this is ignored when debugger is attached (like visual studio) SetUnhandledExceptionFilter(ExceptionReleaseTarget); #endif + //example //RaiseException(1, 0, 0, 0); //shows messagebox from wntdll while(GetMessage(&Msg, NULL, 0, 0) > 0) { From 6b8999e05c5df75765ace2cefe8dee06a827ced0 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 1 May 2021 16:42:54 +0200 Subject: [PATCH 09/93] Add module base to log --- main/win/CrashHandler.cpp | 2 +- winproject/mupen64/mupen64_2017.vcxproj | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/main/win/CrashHandler.cpp b/main/win/CrashHandler.cpp index 0d57cda1..2aaabe66 100644 --- a/main/win/CrashHandler.cpp +++ b/main/win/CrashHandler.cpp @@ -28,7 +28,7 @@ int FindModuleName(char *error, void* addr, int len) // write the address with module if (hMods[i]MachineX86 UseLinkTimeCodeGeneration false + true From 280c98dad2b92dd88516afb2a1dcfdb69f09697c Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 1 May 2021 16:50:14 +0200 Subject: [PATCH 10/93] no space after newline --- main/win/CrashHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/win/CrashHandler.cpp b/main/win/CrashHandler.cpp index 0d57cda1..82cc285e 100644 --- a/main/win/CrashHandler.cpp +++ b/main/win/CrashHandler.cpp @@ -59,6 +59,6 @@ LONG WINAPI ExceptionReleaseTarget(_EXCEPTION_POINTERS* ExceptionInfo) fprintf(f, error); fclose(f); - int code = MessageBox(0, "Emulator crashed, press OK to try to continue\n Crash log saved to " CRASH_LOG, "Exception", MB_OKCANCEL | MB_ICONERROR); + int code = MessageBox(0, "Emulator crashed, press OK to try to continue\nCrash log saved to " CRASH_LOG, "Exception", MB_OKCANCEL | MB_ICONERROR); return code == IDOK ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; } \ No newline at end of file From 2d7489ebe789a006205f5d3ee010b00881234e4e Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 1 May 2021 17:26:49 +0200 Subject: [PATCH 11/93] TASInput "fix" dpi issue --- tasinput_plugin/src/DefDI.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 3b6b907f..e130f626 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -44,6 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PI 3.14159265358979f #define BUFFER_CHUNK 128 +#undef List // look at line 32 for cause #define aCombo ComboList.at(activeCombo) //so it's a bit cleaner HINSTANCE g_hInstance; @@ -220,11 +221,12 @@ int Status::frameCounter = 0; Status status [NUMBER_OF_CONTROLS]; - -#define STICKPIC_SIZE (131) +//#define STICKPIC_SIZE (131) +UINT STICKPIC_SIZE = 131; int WINAPI DllMain ( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) -{ +{ + switch (fdwReason) { case DLL_PROCESS_ATTACH: @@ -844,6 +846,24 @@ VOID SetXYTextFast(HWND parent, BOOL x, char* str) { if (x) SetWindowText(textXHWND, str); // Is there implicit char* -> long pointer string happening? else SetWindowText(textYHWND, str); } + +BOOL AdjustForDPI(HWND parent, UINT dpi) { + // Adjust for system scaling + + // 96 - normal + // 120 - big + RECT pos; + GetWindowRect(GetDlgItem(parent, IDC_STICKPIC), &pos); + + + if (dpi == 120) { + if(STICKPIC_SIZE != STICKPIC_SIZE + 26) // prevent it from getting infinitely bigger when reinitializing dialog by resizing + STICKPIC_SIZE += 26; + } + + return dpi != 96; + +} void Status::SetKeys(BUTTONS ControllerInput) { if (copyButtons) //copy m64 data to current input @@ -1720,6 +1740,11 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) return TRUE; case WM_INITDIALOG: { + //SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + // sure... did i think it is that easy + + AdjustForDPI(statusDlg, GetDpiForSystem()); + // reset some dialog state dragging = false; lastXDrag = 0; From b2c3d0a3541dad0f82a496e8d70799ed64784bbb Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 1 May 2021 17:28:58 +0200 Subject: [PATCH 12/93] global elite with awp only --- tasinput_plugin/src/DefDI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index e130f626..1cac2bb3 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -857,7 +857,7 @@ BOOL AdjustForDPI(HWND parent, UINT dpi) { if (dpi == 120) { - if(STICKPIC_SIZE != STICKPIC_SIZE + 26) // prevent it from getting infinitely bigger when reinitializing dialog by resizing + if(STICKPIC_SIZE == 131) // prevent it from getting infinitely bigger when reinitializing dialog by resizing STICKPIC_SIZE += 26; } From 86fc619a4adf4b4e8c883d224f5df172895a3298 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 1 May 2021 17:55:41 +0200 Subject: [PATCH 13/93] do u agree? (add todo) --- tasinput_plugin/src/DefDI.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 1cac2bb3..fa47e6c6 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -222,6 +222,8 @@ int Status::frameCounter = 0; Status status [NUMBER_OF_CONTROLS]; //#define STICKPIC_SIZE (131) + +// todo split into x y UINT STICKPIC_SIZE = 131; int WINAPI DllMain ( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) @@ -848,16 +850,20 @@ VOID SetXYTextFast(HWND parent, BOOL x, char* str) { } BOOL AdjustForDPI(HWND parent, UINT dpi) { + // Adjust for system scaling // 96 - normal // 120 - big + + if (STICKPIC_SIZE == 131) return FALSE; // early return (stickpic size is already correct) + // prevent it from getting infinitely bigger when reinitializing dialog by resizing + RECT pos; GetWindowRect(GetDlgItem(parent, IDC_STICKPIC), &pos); - + if (dpi == 120) { - if(STICKPIC_SIZE == 131) // prevent it from getting infinitely bigger when reinitializing dialog by resizing STICKPIC_SIZE += 26; } From bc03734e0a868cc2962cb925453391144f0b33ca Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 1 May 2021 20:26:42 +0200 Subject: [PATCH 14/93] Smarter DPI hack --- tasinput_plugin/src/DefDI.cpp | 43 +++++++++++++++++++++++------------ tasinput_plugin/src/DefDI.h | 2 +- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index fa47e6c6..412f53b4 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -63,6 +63,7 @@ HMENU hMenu; HANDLE fakeStatusThread = NULL; // fake! used for testing plugin bool validatedhTxtbox = FALSE; +UINT systemDPI; bool lock; //don't focus mupen FILE* cFile; /*combo file conains list of combos in format: @@ -841,32 +842,42 @@ VOID SetXYTextFast(HWND parent, BOOL x, char* str) { // Optimized setdlgitemtext: explanation: // GetDlgItem is very slow because of the many controls and this may limit the speed of emulator in some cases(?) // Instead of using SetDlgItemText every time and (internally) calling GetDlgItem, we precompute the handles to x and y textboxes the first time and re-use them - // NOTE: this may break when extending dialogs because handle changes (will fix in future) if (!textXHWND || !validatedhTxtbox) textXHWND = GetDlgItem(parent, IDC_EDITX); if (!textYHWND || !validatedhTxtbox) textYHWND = GetDlgItem(parent, IDC_EDITY); - if (x) SetWindowText(textXHWND, str); // Is there implicit char* -> long pointer string happening? - else SetWindowText(textYHWND, str); + if (x) SetWindowText(textXHWND, str); + else SetWindowText(textYHWND, str); } BOOL AdjustForDPI(HWND parent, UINT dpi) { // Adjust for system scaling - // 96 - normal - // 120 - big + // 96 - 100% + // 120 - 125% - if (STICKPIC_SIZE == 131) return FALSE; // early return (stickpic size is already correct) - // prevent it from getting infinitely bigger when reinitializing dialog by resizing + RECT ctl_pos, ctl_gp_pos; + GetWindowRect(GetDlgItem(parent, IDC_STICKPIC), &ctl_pos); + GetWindowRect(GetDlgItem(parent, IDC_STATICX), &ctl_gp_pos); - RECT pos; - GetWindowRect(GetDlgItem(parent, IDC_STICKPIC), &pos); - - - if (dpi == 120) { - STICKPIC_SIZE += 26; + ctl_gp_pos.left -= 3; // adjust for border + + if (STICKPIC_SIZE == 131) { + // prevent infinitely increasing size + + if (dpi == 120) { + STICKPIC_SIZE = STICKPIC_SIZE*125/100; // * 1.25 works too + } + + + // check for overlap with gpbox and try to fix it + if (ctl_pos.right > ctl_gp_pos.left) { + printf("overlap with groupbox (%d/%d)", ctl_pos.right, ctl_gp_pos.left); + STICKPIC_SIZE = ctl_gp_pos.left; + } } - + //STICKPIC_SIZE = (UINT)STICKPIC_SIZE; // ensure no double + printf("stickpic size: %d\ndpi: %d", STICKPIC_SIZE, dpi); return dpi != 96; } @@ -1749,7 +1760,9 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) //SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); // sure... did i think it is that easy - AdjustForDPI(statusDlg, GetDpiForSystem()); + systemDPI = GetDpiForSystem(); + + AdjustForDPI(statusDlg, systemDPI, TRUE); // reset some dialog state dragging = false; diff --git a/tasinput_plugin/src/DefDI.h b/tasinput_plugin/src/DefDI.h index ef0b04c6..f268749c 100755 --- a/tasinput_plugin/src/DefDI.h +++ b/tasinput_plugin/src/DefDI.h @@ -115,7 +115,7 @@ extern HINSTANCE g_hInstance; enum PopupOptions { None, OnTop, - Float, + Float }; typedef struct { From 2a64863e7eba2f2eae67da2b0ec3b7bf7e0e47f2 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 2 May 2021 12:43:26 +0200 Subject: [PATCH 15/93] TASInput "movable" option --- tasinput_plugin/src/DefDI.cpp | 30 ++++++++++++++++++------------ tasinput_plugin/src/DefDI.h | 4 +++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 412f53b4..7570289a 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -852,7 +852,7 @@ VOID SetXYTextFast(HWND parent, BOOL x, char* str) { BOOL AdjustForDPI(HWND parent, UINT dpi) { // Adjust for system scaling - + // todo: more scaling checks // 96 - 100% // 120 - 125% @@ -1688,6 +1688,7 @@ bool ShowContextMenu(HWND hwnd,HWND hitwnd, int x, int y) hMenu = CreatePopupMenu(); AppendMenu(hMenu, menuConfig.onTop ? MF_CHECKED : 0, OnTop, "Stay on Top"); AppendMenu(hMenu, menuConfig.floatFromParent ? MF_CHECKED : 0, Float, "Show in Taskbar"); + AppendMenu(hMenu, menuConfig.movable ? MF_CHECKED : 0, Movable, "Movable"); lock = true; int res = TrackPopupMenuEx(hMenu, TPM_RETURNCMD | TPM_NONOTIFY, x, y, hwnd, 0); lock = false; @@ -1699,6 +1700,9 @@ bool ShowContextMenu(HWND hwnd,HWND hitwnd, int x, int y) case Float: menuConfig.floatFromParent ^= 1; break; + case Movable: + menuConfig.movable ^= 1; + break; } RefreshChanges(hwnd); DestroyMenu(hMenu); @@ -1762,7 +1766,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) systemDPI = GetDpiForSystem(); - AdjustForDPI(statusDlg, systemDPI, TRUE); + AdjustForDPI(statusDlg, systemDPI); // reset some dialog state dragging = false; @@ -2013,16 +2017,18 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) } else { - dragging = true; - POINT pt; - GetCursorPos(&pt); - dragXStart = pt.x; - dragYStart = pt.y; - - RECT rect; - GetWindowRect(statusDlg, &rect); - dragXStart -= rect.left; - dragYStart -= rect.top; + if (menuConfig.movable) { + dragging = true; + POINT pt; + GetCursorPos(&pt); + dragXStart = pt.x; + dragYStart = pt.y; + + RECT rect; + GetWindowRect(statusDlg, &rect); + dragXStart -= rect.left; + dragYStart -= rect.top; + } } } } diff --git a/tasinput_plugin/src/DefDI.h b/tasinput_plugin/src/DefDI.h index f268749c..6d798f61 100755 --- a/tasinput_plugin/src/DefDI.h +++ b/tasinput_plugin/src/DefDI.h @@ -115,12 +115,14 @@ extern HINSTANCE g_hInstance; enum PopupOptions { None, OnTop, - Float + Float, + Movable }; typedef struct { bool onTop = false; bool floatFromParent = true; + bool movable = true; } MENUCONFIG; //---- From ba3f46eb1502b76760053d2f0dcd667ebbb77848 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 2 May 2021 13:35:31 +0200 Subject: [PATCH 16/93] TASInput dragging rewrite + proper Z ordering with mupen + misc. --- tasinput_plugin/src/DefDI.cpp | 79 +++++++++-------------------------- tasinput_plugin/src/DefDI.h | 12 ++++++ 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 7570289a..b624b0bd 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1682,7 +1682,7 @@ void RefreshChanges(HWND hwnd) bool ShowContextMenu(HWND hwnd,HWND hitwnd, int x, int y) { - if (hitwnd != hwnd || IsMouseOverControl(hwnd, IDC_STICKPIC) || (GetKeyState(VK_LBUTTON) & 0x8000) != 0) return TRUE; + if (hitwnd != hwnd || IsMouseOverControl(hwnd, IDC_STICKPIC) || (GetKeyState(VK_LBUTTON) & 0x8000)) return TRUE; RefreshChanges(hwnd); SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //disable topmost for a second hMenu = CreatePopupMenu(); @@ -1923,6 +1923,12 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // too bad we don't get useful events like WM_MOUSEMOVE or WM_LBUTTONDOWN... case WM_SETCURSOR: + + POINT pt; + GetCursorPos(&pt); + + + nextClick = ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) || (GetAsyncKeyState(VK_RBUTTON) & 0x8000)); lastWasRight = 0!=(GetAsyncKeyState(VK_RBUTTON) & 0x8000); if(!dragging && !lastClick && nextClick) @@ -1937,66 +1943,21 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) else draggingStick = true; } - else if((!HasPanel(1) || // Any non-control area of the window is draggable. - (!IsMouseOverControl(statusDlg,IDC_XABS) && // This is done partly out of necessity, - !IsMouseOverControl(statusDlg,IDC_XSEM) && // because normal automatic window movement - !IsMouseOverControl(statusDlg,IDC_XREL) && // would not work (don't get messages for it), - !IsMouseOverControl(statusDlg,IDC_XRAD) && // and partly because the result occupies - !IsMouseOverControl(statusDlg,IDC_YABS) && // less space and is more convenient - !IsMouseOverControl(statusDlg,IDC_YSEM) && - !IsMouseOverControl(statusDlg,IDC_YREL) && - !IsMouseOverControl(statusDlg,IDC_EDITX) && - !IsMouseOverControl(statusDlg,IDC_EDITY) && - !IsMouseOverControl(statusDlg, IDC_CLEARJOY) && - !IsMouseOverControl(statusDlg,IDC_SPINX) && - !IsMouseOverControl(statusDlg,IDC_SPINY) && - !IsMouseOverControl(statusDlg,IDC_SLIDERX) && - !IsMouseOverControl(statusDlg,IDC_SLIDERY) && - !IsMouseOverControl(statusDlg, IDC_CHECK_ANGDISP) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON0) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON1))) && - (!HasPanel(2) || - (!IsMouseOverControl(statusDlg,IDC_CLEARBUTTONS) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON2) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON3) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON4))) && - (!HasPanel(3) || - (!IsMouseOverControl(statusDlg,IDC_MACROBOX) && - !IsMouseOverControl(statusDlg,IDC_MACROLIST) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON5) && - !IsMouseOverControl(statusDlg,IDC_MOREBUTTON6)))) + // no else if... you cant be over stickpic AND not on it (schrdingers mouse wtf) + if(IsMouseOverControl(statusDlg,IDC_BUTTONSLABEL)) { - if(HasPanel(2) && - (IsMouseOverControl(statusDlg,IDC_CHECK_A) || - IsMouseOverControl(statusDlg,IDC_CHECK_B) || - IsMouseOverControl(statusDlg,IDC_CHECK_L) || - IsMouseOverControl(statusDlg,IDC_CHECK_R) || - IsMouseOverControl(statusDlg,IDC_CHECK_Z) || - IsMouseOverControl(statusDlg,IDC_CHECK_START) || - IsMouseOverControl(statusDlg,IDC_CHECK_CUP) || - IsMouseOverControl(statusDlg,IDC_CHECK_CDOWN) || - IsMouseOverControl(statusDlg,IDC_CHECK_CLEFT) || - IsMouseOverControl(statusDlg,IDC_CHECK_CRIGHT) || - IsMouseOverControl(statusDlg,IDC_CHECK_DUP) || - IsMouseOverControl(statusDlg,IDC_CHECK_DDOWN) || - IsMouseOverControl(statusDlg,IDC_CHECK_DLEFT) || - IsMouseOverControl(statusDlg,IDC_CHECK_DRIGHT))) +#ifdef DEBUG + printf("HWND hit: %d\n", ChildWindowFromPoint(statusDlg, pt)); + printf("HWND deeper 1: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt)); + printf("HWND deeper 2: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt)); +#endif + //we need to go deeper because it wont return lowest control like we want it + // atmost 4 gpboxes down (combo menu) so this should work but will break with major ui changes or edge cases + if(ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt), pt) == GetDlgItem(statusDlg,IDC_BUTTONSLABEL)) { overrideOn = true; //clicking on buttons counts as override if(GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it { -#define UPDATEAUTO(idc,field) \ -{ \ - if(IsMouseOverControl(statusDlg,idc)) \ - { \ - CheckDlgButton(statusDlg,idc,buttonAutofire.field|buttonAutofire2.field ? 0 : 1); \ - BUTTONS &autoFire1 = (frameCounter%2 == 0) ? buttonAutofire : buttonAutofire2; \ - BUTTONS &autoFire2 = (frameCounter%2 == 0) ? buttonAutofire2 : buttonAutofire; \ - autoFire1.field = !(autoFire1.field|autoFire2.field); \ - autoFire2.field = 0; \ - buttonOverride.field = 0; \ - } \ -} UPDATEAUTO(IDC_CHECK_A, A_BUTTON); UPDATEAUTO(IDC_CHECK_B, B_BUTTON); UPDATEAUTO(IDC_CHECK_START, START_BUTTON); @@ -2011,7 +1972,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) UPDATEAUTO(IDC_CHECK_DLEFT, L_DPAD); UPDATEAUTO(IDC_CHECK_DRIGHT, R_DPAD); UPDATEAUTO(IDC_CHECK_DDOWN, D_DPAD); -#undef UPDATEAUTO + ActivateEmulatorWindow(); } } @@ -2019,7 +1980,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { if (menuConfig.movable) { dragging = true; - POINT pt; GetCursorPos(&pt); dragXStart = pt.x; dragYStart = pt.y; @@ -2064,7 +2024,8 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { lastXDrag = newDragX-dragXStart; lastYDrag = newDragY-dragYStart; - SetWindowPos(statusDlg,0, lastXDrag, lastYDrag, 0,0, SWP_NOZORDER|SWP_NOSIZE|SWP_SHOWWINDOW); + // do not + SetWindowPos(statusDlg,0, lastXDrag, lastYDrag, 0,0,/*SWP_NOZORDER|*/SWP_NOSIZE|SWP_SHOWWINDOW); } } else if(draggingStick) diff --git a/tasinput_plugin/src/DefDI.h b/tasinput_plugin/src/DefDI.h index 6d798f61..c445e227 100755 --- a/tasinput_plugin/src/DefDI.h +++ b/tasinput_plugin/src/DefDI.h @@ -133,5 +133,17 @@ BOOL WINAPI CheckForDeviceChange(HKEY hKey); LRESULT CALLBACK StatusDlgProc (HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam); VOID CALLBACK StatusDlgProcTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); +#define UPDATEAUTO(idc,field) \ +{ \ + if(IsMouseOverControl(statusDlg,idc)) \ + { \ + CheckDlgButton(statusDlg,idc,buttonAutofire.field|buttonAutofire2.field ? 0 : 1); \ + BUTTONS &autoFire1 = (frameCounter%2 == 0) ? buttonAutofire : buttonAutofire2; \ + BUTTONS &autoFire2 = (frameCounter%2 == 0) ? buttonAutofire2 : buttonAutofire; \ + autoFire1.field = !(autoFire1.field|autoFire2.field); \ + autoFire2.field = 0; \ + buttonOverride.field = 0; \ + } \ +} #endif \ No newline at end of file From 349f45f6c80cf457d98ca7ad1be56525942d13e4 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 2 May 2021 15:14:23 +0200 Subject: [PATCH 17/93] fix crash with ini file --- main/mupenIniApi.c | 1 + main/win/main_win.cpp | 2 -- winproject/mupen64/mupen64_2017.vcxproj | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main/mupenIniApi.c b/main/mupenIniApi.c index f0904a13..5b71f8f2 100755 --- a/main/mupenIniApi.c +++ b/main/mupenIniApi.c @@ -132,6 +132,7 @@ void ini_openFile() { cur->next_entry = (iniElem*)malloc(sizeof(iniElem)); cur = cur->next_entry; + cur->next_entry = NULL; cur->next_crc = NULL; cur->next_MD5 = NULL; } diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 61537d92..2698bdab 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3675,10 +3675,8 @@ int WINAPI WinMain( LoadConfigExternals(); - #ifndef _DEBUG //warning, this is ignored when debugger is attached (like visual studio) SetUnhandledExceptionFilter(ExceptionReleaseTarget); - #endif //example //RaiseException(1, 0, 0, 0); //shows messagebox from wntdll while(GetMessage(&Msg, NULL, 0, 0) > 0) diff --git a/winproject/mupen64/mupen64_2017.vcxproj b/winproject/mupen64/mupen64_2017.vcxproj index 63d284c0..bcdd48e0 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj +++ b/winproject/mupen64/mupen64_2017.vcxproj @@ -94,13 +94,14 @@ $(OutDir)$(TargetName)$(TargetExt) ../zlib;../../lua;%(AdditionalLibraryDirectories) true - $(OutDir)mupen64.pdb + $(OutDir)mupen64_debug.pdb Windows false false MachineX86 + true true From dfa1e46ac1cf93173a6d6683b7103b7c542fc317 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 2 May 2021 16:13:00 +0200 Subject: [PATCH 18/93] dragging n stuff --- tasinput_plugin/src/DefDI.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index b624b0bd..5bfe4937 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1928,23 +1928,30 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) GetCursorPos(&pt); - + //is any mouse button pressed? nextClick = ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) || (GetAsyncKeyState(VK_RBUTTON) & 0x8000)); - lastWasRight = 0!=(GetAsyncKeyState(VK_RBUTTON) & 0x8000); + + //used for sliders (rightclick reset), remembers if rightclick was pressed + //!! turns it into bool + lastWasRight = !!(GetAsyncKeyState(VK_RBUTTON) & 0x8000); + //if not dragging, previous interacion wasn't click with R or L, and current one (nextClick) is R or L if(!dragging && !lastClick && nextClick) { if(IsMouseOverControl(statusDlg,IDC_STICKPIC)) { + //if clicked RMB and permadrag was active, disable it if(draggingPermaStick || GetAsyncKeyState(VK_RBUTTON) & 0x8000) { draggingPermaStick = !draggingPermaStick; draggingStick = draggingPermaStick; } + //otherwise just drag stick else draggingStick = true; } // no else if... you cant be over stickpic AND not on it (schrdingers mouse wtf) - if(IsMouseOverControl(statusDlg,IDC_BUTTONSLABEL)) + //If mouse over any of the labels and not over joystick, start dragging or autofire + else if(IsMouseOverControl(statusDlg,IDC_BUTTONSLABEL) || IsMouseOverControl(statusDlg, IDC_ANALOGSTICKLABEL)) { #ifdef DEBUG printf("HWND hit: %d\n", ChildWindowFromPoint(statusDlg, pt)); @@ -1953,7 +1960,8 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) #endif //we need to go deeper because it wont return lowest control like we want it // atmost 4 gpboxes down (combo menu) so this should work but will break with major ui changes or edge cases - if(ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt), pt) == GetDlgItem(statusDlg,IDC_BUTTONSLABEL)) + //my comment: grab whatever it hits and it should be the buttons label,then start looking for checkboxes + if(ChildWindowFromPoint(statusDlg, pt) == GetDlgItem(statusDlg,IDC_BUTTONSLABEL)) { overrideOn = true; //clicking on buttons counts as override if(GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it From 8512fb901999ab6042ffe763c0e4e6cf31cba903 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 2 May 2021 16:34:15 +0200 Subject: [PATCH 19/93] Fix autofire not working after recent changes --- tasinput_plugin/src/DefDI.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 5bfe4937..90402839 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1958,10 +1958,8 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) printf("HWND deeper 1: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt)); printf("HWND deeper 2: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt)); #endif - //we need to go deeper because it wont return lowest control like we want it - // atmost 4 gpboxes down (combo menu) so this should work but will break with major ui changes or edge cases - //my comment: grab whatever it hits and it should be the buttons label,then start looking for checkboxes - if(ChildWindowFromPoint(statusDlg, pt) == GetDlgItem(statusDlg,IDC_BUTTONSLABEL)) + //if we are over buttons area and right is clicked, look for autofire candidates + if(lastWasRight && IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL)) { overrideOn = true; //clicking on buttons counts as override if(GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it From cc3fc96c51a9aa9f9168e19632fb36cd3524cdaa Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 2 May 2021 17:00:28 +0200 Subject: [PATCH 20/93] fix autofire being cursor-dependent and not frame-dependent --- tasinput_plugin/src/DefDI.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 90402839..e6e985e6 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1346,9 +1346,10 @@ EXPORT void CALL ReadController ( int Control, BYTE * Command ) // (The frame counter is used only for autofire and combo progression.) if(Control == -1) Status::frameCounter++; -// for(Control = 0; Control < NUMBER_OF_CONTROLS; Control++) -// if(Controller[Control].bActive) -// status[Control].frameCounter++; + + for (char i = 0; i < 4; i++) + SendMessage(status[i].statusDlg, WM_SETCURSOR, 0, 0); + } EXPORT void CALL RomClosed (void) { From 470f335669bce69d84fdff016ce3b1ee5854c1db Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 2 May 2021 17:50:09 +0200 Subject: [PATCH 21/93] Revert 6251fb624e7e342544ccb91da5734fa8bc13e214 --- tasinput_plugin/src/DefDI.cpp | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index e6e985e6..13166bff 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -895,7 +895,7 @@ void Status::SetKeys(BUTTONS ControllerInput) //true if physical controller state is changed (because logical is handled in GetKeys) if (buttonDisplayed.Value != ControllerInput.Value && HasPanel(2)) { -#define UPDATECHECK(idc,field) {if(buttonDisplayed.field != ControllerInput.field) CheckDlgButton(statusDlg, idc, ControllerInput.field^(buttonAutofire2.field|buttonAutofire.field));} +#define UPDATECHECK(idc,field) {if(buttonDisplayed.field != ControllerInput.field) CheckDlgButton(statusDlg, idc, ControllerInput.field);} UPDATECHECK(IDC_CHECK_A, A_BUTTON); UPDATECHECK(IDC_CHECK_B, B_BUTTON); UPDATECHECK(IDC_CHECK_START, START_BUTTON); @@ -910,7 +910,6 @@ void Status::SetKeys(BUTTONS ControllerInput) UPDATECHECK(IDC_CHECK_DLEFT, L_DPAD); UPDATECHECK(IDC_CHECK_DRIGHT, R_DPAD); UPDATECHECK(IDC_CHECK_DDOWN, D_DPAD); -#undef UPDATECHECK buttonDisplayed.Value = ControllerInput.Value; } if(relativeXOn == 3 && radialRecalc) @@ -1349,7 +1348,6 @@ EXPORT void CALL ReadController ( int Control, BYTE * Command ) for (char i = 0; i < 4; i++) SendMessage(status[i].statusDlg, WM_SETCURSOR, 0, 0); - } EXPORT void CALL RomClosed (void) { @@ -2382,21 +2380,20 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) } break; //on checkbox click set buttonOverride and buttonDisplayed field and reset autofire - #define DISP_UPDATE(field) buttonDisplayed.field = buttonOverride.field = IsDlgButtonChecked(statusDlg, LOWORD(wParam))?1:0; buttonAutofire.field=buttonAutofire2.field =0; ActivateEmulatorWindow(); break; - case IDC_CHECK_A: DISP_UPDATE(A_BUTTON); - case IDC_CHECK_B: DISP_UPDATE(B_BUTTON); - case IDC_CHECK_START: DISP_UPDATE(START_BUTTON); - case IDC_CHECK_Z: DISP_UPDATE(Z_TRIG); - case IDC_CHECK_L: DISP_UPDATE(L_TRIG); - case IDC_CHECK_R: DISP_UPDATE(R_TRIG); - case IDC_CHECK_CLEFT: DISP_UPDATE(L_CBUTTON); - case IDC_CHECK_CUP: DISP_UPDATE(U_CBUTTON); - case IDC_CHECK_CRIGHT: DISP_UPDATE(R_CBUTTON); - case IDC_CHECK_CDOWN: DISP_UPDATE(D_CBUTTON); - case IDC_CHECK_DLEFT: DISP_UPDATE(L_DPAD); - case IDC_CHECK_DUP: DISP_UPDATE(U_DPAD); - case IDC_CHECK_DRIGHT: DISP_UPDATE(R_DPAD); - case IDC_CHECK_DDOWN: DISP_UPDATE(D_DPAD); + case IDC_CHECK_A: buttonOverride.A_BUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.A_BUTTON = buttonAutofire2.A_BUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_B: buttonOverride.B_BUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.B_BUTTON = buttonAutofire2.B_BUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_START: buttonOverride.START_BUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.START_BUTTON = buttonAutofire2.START_BUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_Z: buttonOverride.Z_TRIG = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.Z_TRIG = buttonAutofire2.Z_TRIG = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_L: buttonOverride.L_TRIG = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.L_TRIG = buttonAutofire2.L_TRIG = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_R: buttonOverride.R_TRIG = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.R_TRIG = buttonAutofire2.R_TRIG = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_CLEFT: buttonOverride.L_CBUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.L_CBUTTON = buttonAutofire2.L_CBUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_CUP: buttonOverride.U_CBUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.U_CBUTTON = buttonAutofire2.U_CBUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_CRIGHT: buttonOverride.R_CBUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.R_CBUTTON = buttonAutofire2.R_CBUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_CDOWN: buttonOverride.D_CBUTTON = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.D_CBUTTON = buttonAutofire2.D_CBUTTON = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_DLEFT: buttonOverride.L_DPAD = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.L_DPAD = buttonAutofire2.L_DPAD = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_DUP: buttonOverride.U_DPAD = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.U_DPAD = buttonAutofire2.U_DPAD = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_DRIGHT: buttonOverride.R_DPAD = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.R_DPAD = buttonAutofire2.R_DPAD = 0; ActivateEmulatorWindow(); break; + case IDC_CHECK_DDOWN: buttonOverride.D_DPAD = IsDlgButtonChecked(statusDlg, LOWORD(wParam)) ? 1 : 0; buttonAutofire.D_DPAD = buttonAutofire2.D_DPAD = 0; ActivateEmulatorWindow(); break; case IDC_CLEARJOY: overrideAllowed = true; overrideOn = true; overrideX = 0; overrideY = 0; SetDlgItemText(statusDlg, IDC_EDITY, "0"); SetDlgItemText(statusDlg, IDC_EDITX, "0"); RefreshAnalogPicture(); ActivateEmulatorWindow(); break; case IDC_CLEARBUTTONS: buttonOverride.Value = buttonAutofire.Value = buttonAutofire2.Value = 0; GetKeys(0); ActivateEmulatorWindow(); break; case IDC_MOREBUTTON0: From f11f1caeb2bf8bf10e38b55d8103754fd974afbd Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 2 May 2021 18:03:07 +0200 Subject: [PATCH 22/93] Fix dragging out of tasinput --- tasinput_plugin/src/DefDI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index e6e985e6..de818467 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -2040,8 +2040,8 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) POINT pt; GetCursorPos(&pt); ScreenToClient(GetDlgItem(statusDlg, IDC_STICKPIC), &pt); - overrideX = (pt.x*256/STICKPIC_SIZE - 128 + 1); - overrideY = -(pt.y*256/STICKPIC_SIZE - 128 + 1); + overrideX = (pt.x*256/(signed)STICKPIC_SIZE - 128 + 1); + overrideY = -(pt.y*256/(signed)STICKPIC_SIZE - 128 + 1); // normalize out-of-bounds clicks if(overrideX > 127 || overrideY > 127 || overrideX < -128 || overrideY < -129) From 4813a4717486d173ae35e7cdb5db0bdf0e8e7e9e Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 3 May 2021 18:55:26 +0200 Subject: [PATCH 23/93] Also adjust st warn for movie loop --- main/vcr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main/vcr.c b/main/vcr.c index c100bd3e..0872781e 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -2025,6 +2025,8 @@ void VCR_toggleLoopMovie() { m_loopMovie = !m_loopMovie; + extern bool lockNoStWarn; + lockNoStWarn = m_loopMovie; #ifdef __WIN32__ extern HWND mainHWND; From fcf5011dc05da9de91dad55b5ba7f4a58aee0a55 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Tue, 4 May 2021 20:01:46 +0200 Subject: [PATCH 24/93] Fix crash logger not logging module crashes --- main/win/CrashHandler.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/main/win/CrashHandler.cpp b/main/win/CrashHandler.cpp index b3301354..d6f32ddc 100644 --- a/main/win/CrashHandler.cpp +++ b/main/win/CrashHandler.cpp @@ -5,7 +5,7 @@ #include "../../winproject/resource.h" //MUPEN_VERSION #include "vcr.h" -//Attempt to find the base module, might be faulty with crazy crashes where everything corrupts +//Attempt to find crashing module, finds closest base address to crash point which should be the module (right?) //error - points to the error msg buffer //addr - where did it crash //len - current error length so it can append properly @@ -15,22 +15,24 @@ int FindModuleName(char *error, void* addr, int len) HMODULE hMods[1024]; HANDLE hProcess = GetCurrentProcess(); DWORD cbNeeded; + //printf("addr: %p\n", addr); if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) { + HMODULE maxbase = 0; for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { - char modname[MAX_PATH]; - // Get the full path to the module's file. - - if (GetModuleBaseName(hProcess, hMods[i], modname, - sizeof(modname) / sizeof(char))) - { - - // write the address with module - if (hMods[i] maxbase && hMods[i] < addr) + maxbase = hMods[i]; + //char modname[MAX_PATH]; + //GetModuleBaseName(hProcess, maxbase, modname, sizeof(modname) / sizeof(char)); + //printf("%s: %p\n", modname, maxbase); } + // Get the full path to the module's file. + char modname[MAX_PATH]; + if (GetModuleBaseName(hProcess, maxbase, modname,sizeof(modname) / sizeof(char))) + // write the address with module + return sprintf(error+len,"Addr:0x%p (%s 0x%p)\n", addr,modname,maxbase); } return 0; //what } From 9ee511e4fc6c3b694aa5b2ed8d4bf39f904715e8 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Thu, 6 May 2021 20:02:11 +0200 Subject: [PATCH 25/93] Fix titlebar attempt #132 (thanks to Crackhex) --- main/vcr.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 0872781e..18e2f039 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -132,7 +132,7 @@ static int AVIBreakMovie = 0; int titleLength; extern void resetEmu(); -void SetActiveMovie(char* buf, int maxlen); +void SetActiveMovie(char* buf); static int startPlayback(const char *filename, const char *authorUTF8, const char *descriptionUTF8, const bool restarting); static int restartPlayback(); @@ -1142,7 +1142,7 @@ VCR_startRecord( const char *filename, unsigned short flags, const char *authorU } else{ m_task = StartRecording; } - SetActiveMovie(buf, MAX_PATH); + SetActiveMovie(buf); setROMInfo(&m_header); // utf8 strings are also null-terminated so this method still works @@ -1247,31 +1247,23 @@ VCR_stopRecord() //on titlebar, modifies passed buffer!! //if buffer == NULL, remove current active -void SetActiveMovie(char* buf,int maxlen) +void SetActiveMovie(char* buf) { - static bool active = false; char title[MAX_PATH]; - if (buf == NULL && titleLength) + if (buf==NULL) { - GetWindowText(mainHWND, title, MAX_PATH); - title[titleLength] = '\0'; //remove movie being played part - SetWindowText(mainHWND, title); + sprintf(title, MUPEN_VERSION " - %s", ROM_HEADER->nom); } - else if(buf != NULL) + else { - if (!buf) return; - //original length - titleLength = GetWindowText(mainHWND, title, MAX_PATH); + int titleLength = GetWindowText(mainHWND, title, MAX_PATH); _splitpath(buf, 0, 0, buf, 0); //trim trailing spaces because it looks weird while (title[--titleLength] == ' '); title[++titleLength] = '\0'; - - strcat(title, " | "); - strcat(title, buf); - strcat(title, ".m64"); - SetWindowText(mainHWND, title); + sprintf(title, "%s | %s.m64", title, buf); } + SetWindowText(mainHWND, title); } int @@ -1314,7 +1306,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip return -1; } } - if (!restarting) SetActiveMovie(buf, MAX_PATH); // can crash when looping + fast forward, no need to change this + if (!restarting) SetActiveMovie(buf); // can crash when looping + fast forward, no need to change this { int code = read_movie_header(m_file, &m_header); @@ -1594,7 +1586,7 @@ stopPlayback(bool bypassLoopSetting) } #ifdef __WIN32__ extern HWND mainHWND; - SetActiveMovie(NULL, 0); //remove from title + SetActiveMovie(NULL); //remove from title #endif if (m_file && m_task != StartRecording && m_task != Recording) { From 00fdcf58e5c2d93e661a0e75244caae75ac6f9f5 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Fri, 7 May 2021 16:12:41 +0200 Subject: [PATCH 26/93] SetActiveMovie chanes (Courtesy of Crackhex) --- main/vcr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 18e2f039..50a736cf 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1249,23 +1249,23 @@ VCR_stopRecord() //if buffer == NULL, remove current active void SetActiveMovie(char* buf) { + static bool active = false; char title[MAX_PATH]; - if (buf==NULL) + + if (!buf) { sprintf(title, MUPEN_VERSION " - %s", ROM_HEADER->nom); } - else + else if (buf) { - int titleLength = GetWindowText(mainHWND, title, MAX_PATH); + _splitpath(buf, 0, 0, buf, 0); - //trim trailing spaces because it looks weird - while (title[--titleLength] == ' '); - title[++titleLength] = '\0'; - sprintf(title, "%s | %s.m64", title, buf); + sprintf(title, MUPEN_VERSION " - %s | %s.m64", ROM_HEADER->nom, buf); } SetWindowText(mainHWND, title); } + int VCR_startPlayback(const char *filename, const char *authorUTF8, const char *descriptionUTF8) { return startPlayback(filename, authorUTF8, descriptionUTF8, false); From 17e07b8318ffda296e42110595eb7d41d764d26a Mon Sep 17 00:00:00 2001 From: Alex <48759429+Aurumaker72@users.noreply.github.com> Date: Sat, 8 May 2021 20:29:44 +0200 Subject: [PATCH 27/93] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f29a3aaf..db143139 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +### ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) **Experimental - Expect instability** # Mupen64 Lua [![Release](https://img.shields.io/github/v/release/mkdasher/mupen64-rr-lua-?label=Release)](https://github.com/mkdasher/mupen64-rr-lua-/releases) []() From f6aed2b5f32d7d458a52980eb98094ce8295fa07 Mon Sep 17 00:00:00 2001 From: Alex <48759429+Aurumaker72@users.noreply.github.com> Date: Sat, 8 May 2021 20:31:57 +0200 Subject: [PATCH 28/93] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db143139..f56625e9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [comment]: <> (Second image has to be inline so another approach is used) -This repository contains source code for continued development of Mupen64 - Nintendo 64 emulator with TAS support, and TASinput plugin. +This repository contains the latest source code for continued development of Mupen64 - Nintendo 64 emulator with TAS support, and TASinput plugin. This version includes new Features such as: AVISplit, Reset recording, WiiVC and Backwards Compatibility options all in one. From e30780c65c69f658d8dd147e2efdf2ab5236bd57 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 9 May 2021 16:46:33 +0200 Subject: [PATCH 29/93] version bump + limit minimum window size --- main/win/Config.c | 4 ++-- main/win/main_win.cpp | 8 ++++++++ winproject/resource.h | 5 ++++- winproject/rsrc.rc | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/main/win/Config.c b/main/win/Config.c index 2d18266c..dbf754ae 100755 --- a/main/win/Config.c +++ b/main/win/Config.c @@ -143,8 +143,8 @@ void LoadConfig() Config.WindowPosX = ReadCfgInt("Window", "X", (GetSystemMetrics(SM_CXSCREEN) - Config.WindowWidth) / 2); Config.WindowPosY = ReadCfgInt("Window", "Y", (GetSystemMetrics(SM_CYSCREEN) - Config.WindowHeight) / 2); //if mupen was closed by minimising - if (Config.WindowPosX < 0 || Config.WindowWidth < 0) { - printf("\nWindow size too small"); + if (Config.WindowPosX < MIN_WINDOW_W-1 || Config.WindowWidth < MIN_WINDOW_H-1) { + printf("window too small. attempting to fix\n"); Config.WindowWidth = 800; Config.WindowHeight = 600; Config.WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - Config.WindowWidth) / 2; diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 2698bdab..8b4842a6 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2827,6 +2827,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) // return 0; case WM_WINDOWPOSCHANGING: //allow gfx plugin to set arbitrary size return 0; + case WM_GETMINMAXINFO: + { + LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; + lpMMI->ptMinTrackSize.x = MIN_WINDOW_W; + lpMMI->ptMinTrackSize.y = MIN_WINDOW_H; + // this might break small res with gfx plugin!!! + } + case WM_ENTERMENULOOP: AutoPause = emu_paused; if (!emu_paused) diff --git a/winproject/resource.h b/winproject/resource.h index 817fdc11..780d1b80 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -2,7 +2,10 @@ // Plik doczany wygenerowany przez rodowisko Microsoft Visual C++. // Uywany przez: rsrc.rc // -#define MUPEN_VERSION "Mupen 64 1.0.8" +#define MUPEN_VERSION "Mupen 64 1.0.9" + +#define MIN_WINDOW_W 500 +#define MIN_WINDOW_H 250 #define IDR_MYMENU 101 #define IDR_ACCEL 103 diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 8509d24a..eadc7f19 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -167,7 +167,7 @@ BEGIN PUSHBUTTON "Website",IDC_WEBSITE,134,197,60,14 GROUPBOX "About this program",IDC_STATIC,5,65,189,127 LTEXT "Author:\r\n Hacktarux (hacktarux@yahoo.fr)\r\n\nWindows port:\r\n ShadowPrince (shadow@emulation64.com)\r\n linker (linker@mail.bg)\r\n\r\nContributors:\r\n Codex, Falcon4ever, Pir4nhaX, Malcolm,\r\n Olivieryuyu\r\n\r\nThanks to the many others who helped",IDC_STATIC,13,82,173,104 - CONTROL "",133,"Static",SS_BITMAP,0,0,200,100 + LTEXT MUPEN_VERSION,IDC_STATIC,0,0,200,100 END IDD_ADVANCED_OPTIONS DIALOGEX 0, 0, 231, 262 From cc94c285d43718467a0dcb18e52ac266b17c2773 Mon Sep 17 00:00:00 2001 From: crackhex <64289457+crackhex@users.noreply.github.com> Date: Sun, 9 May 2021 13:36:49 -0700 Subject: [PATCH 30/93] New About page logo version --- winproject/icons/logo.bmp | Bin 90054 -> 90054 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/winproject/icons/logo.bmp b/winproject/icons/logo.bmp index 966d00418b2d27ce20a4f1eea05c6b8347e6289f..3886fcbc31eeb002bfb43f8861f16d91fd99cc36 100755 GIT binary patch literal 90054 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 literal 90054 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 Date: Mon, 10 May 2021 17:00:20 +0200 Subject: [PATCH 31/93] Small changes to rom browser threading --- main/win/main_win.cpp | 5 +++-- main/win/rombrowser.c | 8 ++------ main/win/rombrowser.h | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 8b4842a6..5e35b09c 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -1259,7 +1259,7 @@ void pauseEmu(BOOL quiet) BOOL StartRom(char *fullRomPath) { - if (romBrowserbusy) { + if (romBrowserRefreshThread) { display_status("Rom browser busy!"); return TRUE; } @@ -2384,7 +2384,8 @@ if(!continue_vcr_on_restart_mode) static DWORD WINAPI SoundThread(LPVOID lpParam) { - while (emu_launched) aiUpdate(1); + while (emu_launched) + aiUpdate(1); ExitThread(0); } diff --git a/main/win/rombrowser.c b/main/win/rombrowser.c index 2ffca837..b8115b50 100755 --- a/main/win/rombrowser.c +++ b/main/win/rombrowser.c @@ -52,8 +52,7 @@ int RomBrowserFieldsWidth[ROM_COLUMN_FIELDS] = {250,150,70,70,200,100,100}; int RealColumn[ROM_COLUMN_FIELDS] = {0,2,3,4,-1,-1,-1}; static DWORD Id; -HANDLE romBrowserRefreshThread; -bool romBrowserbusy; +HANDLE romBrowserRefreshThread = NULL; char *getFieldName(int col) { @@ -997,15 +996,12 @@ DWORD WINAPI RefreshRomBrowserInternal(LPVOID tParam) { ListView_DeleteAllItems(hRomList); freeRomList(); LoadRomList(); - romBrowserbusy = false; - TerminateThread(romBrowserRefreshThread,0); // is it a good idea for thread to kill itself - // vs is warning too about this... better way? + ExitThread(0); return 0; } void RefreshRomBrowser() { - romBrowserbusy = true; romBrowserRefreshThread = CreateThread(NULL, 0, RefreshRomBrowserInternal, NULL, 0, &Id); } diff --git a/main/win/rombrowser.h b/main/win/rombrowser.h index eb6aba63..51e312e0 100755 --- a/main/win/rombrowser.h +++ b/main/win/rombrowser.h @@ -105,7 +105,7 @@ ROM_INFO *getSelectedRom(); extern HWND romInfoHWND ; extern ITEM_LIST ItemList; -extern bool romBrowserbusy; +extern HANDLE romBrowserRefreshThread; #define ROM_COLUMN_FIELDS 7 #define MAX_RECENT_ROMS 10 From b2beefcc844fc0a16138f823ea7f7db476f119c7 Mon Sep 17 00:00:00 2001 From: crackhex <64289457+crackhex@users.noreply.github.com> Date: Mon, 10 May 2021 08:48:32 -0700 Subject: [PATCH 32/93] cleaned up a couple lines just formatting --- memory/pif.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/memory/pif.c b/memory/pif.c index 66626321..ed52e6ef 100755 --- a/memory/pif.c +++ b/memory/pif.c @@ -548,17 +548,13 @@ void update_pif_read(bool stcheck) } } } - if (stcheck) { - if (!input_delay) { - if (savestates_job & SAVESTATE && stAllowed) - { - savestates_save(); - savestates_job &= ~SAVESTATE; - } + if (stcheck && !input_delay) { + if (savestates_job & SAVESTATE && stAllowed) + { + savestates_save(); + savestates_job &= ~SAVESTATE; } - } - if (savestates_job & LOADSTATE && stAllowed) - { + } else if (savestates_job & LOADSTATE && stAllowed) { savestates_load(false); savestates_job &= ~LOADSTATE; } @@ -610,4 +606,4 @@ void update_pif_read(bool stcheck) printf("---------------------------------\n"); #endif //printf("pif exit\n"); -} \ No newline at end of file +} From 9b09dfa02789d00ae8c6d797ebde7c30d0737cd2 Mon Sep 17 00:00:00 2001 From: crackhex <64289457+crackhex@users.noreply.github.com> Date: Mon, 10 May 2021 09:20:49 -0700 Subject: [PATCH 33/93] removed else if breaks loading st on movie start, code is still cleaned up --- memory/pif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/memory/pif.c b/memory/pif.c index ed52e6ef..15065c1f 100755 --- a/memory/pif.c +++ b/memory/pif.c @@ -554,7 +554,8 @@ void update_pif_read(bool stcheck) savestates_save(); savestates_job &= ~SAVESTATE; } - } else if (savestates_job & LOADSTATE && stAllowed) { + } + if (savestates_job & LOADSTATE && stAllowed) { savestates_load(false); savestates_job &= ~LOADSTATE; } From 4ee36cc6e23d65ec73be0214d1720297b139b8c3 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Thu, 13 May 2021 17:59:00 +0200 Subject: [PATCH 34/93] lol i was very wrong --- main/win/main_win.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 5e35b09c..97ca6f65 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3072,22 +3072,10 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) GetModuleFileName(NULL, procName, MAX_PATH); _splitpath(procName, 0, 0, procName, 0); - // yea this is very gross but i cant get sprintf work at all in this case - // apparently you cant do something like this: - - //char* a = (char*)malloc(20); - //char* b = (char*)malloc(20); - //strcpy(a, "hi, %s"); - //strcpy(b, "person"); - //sprintf(a, b); - //printf(a); - - // --- "a" will not be "hi, person" - strcpy(stroopConfigLine, ""); + sprintf(stroopConfigLine, "", procName, buf); + + + } std::string stdstr_buf = stroopConfigLine; #ifdef _WIN32 From 8fdb168a9536c28bdce58536cfe12a70e19ef00f Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 15 May 2021 14:42:24 +0200 Subject: [PATCH 35/93] Add debug target hooks with macro, add comments, fix m64 garbage frame at end --- main/debughook.c | 12 ++++++++++++ main/debughook.h | 7 +++++++ main/vcr.c | 4 ++-- main/win/CrashHandler.cpp | 10 +++++----- memory/tlb.c | 2 +- r4300/exception.c | 19 ++++++++++++++++++- r4300/pure_interp.c | 4 +++- winproject/mupen64/mupen64_2017.vcxproj | 4 ++++ .../mupen64/mupen64_2017.vcxproj.filters | 6 ++++++ 9 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 main/debughook.c create mode 100644 main/debughook.h diff --git a/main/debughook.c b/main/debughook.c new file mode 100644 index 00000000..c37a4c27 --- /dev/null +++ b/main/debughook.c @@ -0,0 +1,12 @@ +//MSVC ONLY +#include "debughook.h" +#undef fwrite +size_t fwrite2(const void* ptr, size_t size, size_t count, FILE* stream){ + printf("Writing %d bytes: " ,size*count); + for (int i = 0; i < size * count; i++) + { + printf("%hhx", ((const char*)ptr)[i]); + } + printf("\n"); + return fwrite(ptr, size, count, stream); +} \ No newline at end of file diff --git a/main/debughook.h b/main/debughook.h new file mode 100644 index 00000000..fcdbb1fa --- /dev/null +++ b/main/debughook.h @@ -0,0 +1,7 @@ +//MSVC ONLY, included with /FI option in debug target settings +#pragma once +#include + +size_t fwrite2(const void* ptr, size_t size, size_t count, FILE* stream); + +#define fwrite(a,b,c,d) fwrite2(a,b,c,d) \ No newline at end of file diff --git a/main/vcr.c b/main/vcr.c index 18e2f039..efd997c7 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -352,7 +352,7 @@ static void truncateMovie() { // truncate movie controller data to header.length_samples length - long truncLen = MUP_HEADER_SIZE + sizeof(BUTTONS)*(m_header.length_samples+1); + long truncLen = MUP_HEADER_SIZE + sizeof(BUTTONS)*(m_header.length_samples); #ifdef __WIN32__ HANDLE fileHandle = CreateFile(m_filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); @@ -478,7 +478,7 @@ void flush_movie() // (over-)write the controller data fseek(m_file, MUP_HEADER_SIZE, SEEK_SET); - fwrite(m_inputBuffer, 1, sizeof(BUTTONS)*(m_header.length_samples+1), m_file); + fwrite(m_inputBuffer, 1, sizeof(BUTTONS)*(m_header.length_samples), m_file); fflush(m_file); } diff --git a/main/win/CrashHandler.cpp b/main/win/CrashHandler.cpp index d6f32ddc..3131b7f6 100644 --- a/main/win/CrashHandler.cpp +++ b/main/win/CrashHandler.cpp @@ -15,18 +15,18 @@ int FindModuleName(char *error, void* addr, int len) HMODULE hMods[1024]; HANDLE hProcess = GetCurrentProcess(); DWORD cbNeeded; - //printf("addr: %p\n", addr); + printf("addr: %p\n", addr); if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) { HMODULE maxbase = 0; for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { //find closest addr - if (hMods[i] > maxbase && hMods[i] < addr) + if (hMods[i] > maxbase && hMods[i] < addr){ maxbase = hMods[i]; - //char modname[MAX_PATH]; - //GetModuleBaseName(hProcess, maxbase, modname, sizeof(modname) / sizeof(char)); - //printf("%s: %p\n", modname, maxbase); + char modname[MAX_PATH]; + GetModuleBaseName(hProcess, maxbase, modname, sizeof(modname) / sizeof(char)); + printf("%s: %p\n", modname, maxbase);} } // Get the full path to the module's file. char modname[MAX_PATH]; diff --git a/memory/tlb.c b/memory/tlb.c index eda59621..0633f45e 100755 --- a/memory/tlb.c +++ b/memory/tlb.c @@ -38,7 +38,7 @@ unsigned long tlb_LUT_w[0x100000]; extern unsigned long interp_addr; unsigned long virtual_to_physical_address(unsigned long addresse, int w) { - if (addresse >= 0x7f000000 && addresse < 0x80000000) // golden eye hack + if (addresse >= 0x7f000000 && addresse < 0x80000000) // golden eye hack (it uses TLB a lot) { if (ROM_HEADER->CRC1 == sl(0xDCBC50D1)) // US return 0xb0034b30 + (addresse & 0xFFFFFF); diff --git a/r4300/exception.c b/r4300/exception.c index 29d8d760..2fbf586d 100755 --- a/r4300/exception.c +++ b/r4300/exception.c @@ -35,12 +35,14 @@ extern unsigned long interp_addr; +//Unused, this seems to be handled in pure_interp.c prefetch() void address_error_exception() { printf("address_error_exception\n"); stop=1; } +//Unused, an TLB entry is marked as invalid void TLB_invalid_exception() { if (delay_slot) @@ -53,12 +55,14 @@ void TLB_invalid_exception() stop=1; } +//Unused, 64-bit miss (is this even used on n64?) void XTLB_refill_exception(unsigned long long int addresse) { printf("XTLB refill exception\n"); stop=1; } +//Means no such virtual->physical translation exists void TLB_refill_exception(unsigned long address, int w) { int usual_handler = 0, i; @@ -144,32 +148,43 @@ void TLB_refill_exception(unsigned long address, int w) } } +//Unused, aka TLB modified Exception, entry is not writable void TLB_mod_exception() { printf("TLB mod exception\n"); stop=1; } +//Unused void integer_overflow_exception() { printf("integer overflow exception\n"); stop=1; } +//Unused, handled somewhere else void coprocessor_unusable_exception() { printf("coprocessor_unusable_exception\n"); stop=1; } +//General handler, passes execution to default n64 handler void exception_general() { update_count(); + //EXL bit, 1 = exception level Status |= 2; + //Exception return address if (!interpcore) EPC = PC->addr; else EPC = interp_addr; + //printf("exception, Cause: %x EPC: %x \n", Cause, EPC); + + //Highest bit of Cause tells if exception has been executed in branch delay slot + //delay_slot seems to always be 0 or 1, why is there reference to 3 ? + //if delay_slot, arrange the registers as it should be on n64 (emu uses a variable) if(delay_slot==1 || delay_slot==3) { Cause |= 0x80000000; @@ -177,8 +192,10 @@ void exception_general() } else { - Cause &= 0x7FFFFFFF; + Cause &= 0x7FFFFFFF; //make sure its cleared? } + + //exception handler is always at 0x80000180, continue there if (interpcore) { interp_addr = 0x80000180; diff --git a/r4300/pure_interp.c b/r4300/pure_interp.c index 9d3db329..c884e7e3 100755 --- a/r4300/pure_interp.c +++ b/r4300/pure_interp.c @@ -3049,6 +3049,7 @@ void (*interp_ops[64])(void) = SC , SWC1 , NI , NI , NI , SDC1, NI , SD }; +//Get opcode from address (interp_address) void prefetch() { //static FILE *f = NULL; @@ -3096,7 +3097,8 @@ void prefetch() } else { - printf("execution El'addresse :%x\n", (int)interp_addr); + //unmapped memory exception + printf("Exception, attempt to prefetch unmapped memory at: %x\n", (int)interp_addr); stop=1; } } diff --git a/winproject/mupen64/mupen64_2017.vcxproj b/winproject/mupen64/mupen64_2017.vcxproj index bcdd48e0..0f36d46a 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj +++ b/winproject/mupen64/mupen64_2017.vcxproj @@ -88,6 +88,8 @@ 4018;4244;%(DisableSpecificWarnings) CompileAsCpp false + StreamingSIMDExtensions2 + /FI "../main/debughook.h" %(AdditionalOptions) Shlwapi.lib;vfw32.lib;winmm.lib;Comctl32.lib;zlib-2008-x32.lib;%(AdditionalDependencies) @@ -190,6 +192,7 @@ true + @@ -318,6 +321,7 @@ Default true + CompileAsCpp diff --git a/winproject/mupen64/mupen64_2017.vcxproj.filters b/winproject/mupen64/mupen64_2017.vcxproj.filters index 778871f8..040d96ad 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj.filters +++ b/winproject/mupen64/mupen64_2017.vcxproj.filters @@ -206,6 +206,9 @@ Source Files\main\win + + Source Files\main + @@ -448,6 +451,9 @@ Source Files\main\win + + Source Files\main + From 284ae27bd124fb5d4c3d63b469af8784863f9136 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Fri, 21 May 2021 13:12:29 +0200 Subject: [PATCH 36/93] add option to record with the .savestate --- main/savestates.c | 6 +++--- main/vcr.c | 19 ++++++++++++++----- main/vcr.h | 4 ++-- main/win/main_win.cpp | 24 ++++++++++++++++++++---- winproject/resource.h | 1 + winproject/rsrc.rc | 1 + 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/main/savestates.c b/main/savestates.c index aab0cbb6..1264eb2a 100755 --- a/main/savestates.c +++ b/main/savestates.c @@ -283,7 +283,7 @@ void savestates_load(bool silenceNotFoundError) gzclose(f); savestates_job_success = FALSE; - if (VCR_isRecording()) VCR_stopRecord(); + if (VCR_isRecording()) VCR_stopRecord(1); else VCR_stopPlayback(); return; } @@ -405,7 +405,7 @@ void savestates_load(bool silenceNotFoundError) } else { printWarning(errStr); - if (stop && VCR_isRecording()) VCR_stopRecord(); + if (stop && VCR_isRecording()) VCR_stopRecord(1); else if (stop) VCR_stopPlayback(); savestates_job_success = FALSE; goto failedLoad; @@ -424,7 +424,7 @@ void savestates_load(bool silenceNotFoundError) if (VCR_isPlaying()) VCR_stopPlayback(); else - VCR_stopRecord(); + VCR_stopRecord(1); } lockNoStWarn = false; //reset } diff --git a/main/vcr.c b/main/vcr.c index 03c7eda4..13f00e3d 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1073,7 +1073,7 @@ VCR_getKeys( int Control, BUTTONS *Keys ) int -VCR_startRecord( const char *filename, unsigned short flags, const char *authorUTF8, const char *descriptionUTF8 ) +VCR_startRecord( const char *filename, unsigned short flags, const char *authorUTF8, const char *descriptionUTF8, int defExt ) { VCR_coreStopped(); @@ -1135,7 +1135,11 @@ VCR_startRecord( const char *filename, unsigned short flags, const char *authorU break; } - strncat( buf, ".st", PATH_MAX ); + if(defExt) + strncat(buf,".st",PATH_MAX); + else + strncat(buf, ".savestate", PATH_MAX); + savestates_select_filename( buf ); savestates_job |= SAVESTATE; m_task = StartRecordingFromSnapshot; @@ -1170,7 +1174,7 @@ VCR_startRecord( const char *filename, unsigned short flags, const char *authorU int -VCR_stopRecord() +VCR_stopRecord(int defExt) { int retVal = -1; @@ -1187,7 +1191,12 @@ VCR_stopRecord() printf( "[VCR]: Removing files (nothing recorded)\n" ); strcpy( buf, m_filename ); - strncat( m_filename, ".st", PATH_MAX ); + + if (defExt) + strncat(m_filename, ".st", PATH_MAX); + else + strncat(m_filename, ".savestate", PATH_MAX); + if (_unlink( buf ) < 0) fprintf( stderr, "[VCR]: Couldn't remove save state: %s\n", strerror( errno ) ); @@ -2072,7 +2081,7 @@ VCR_coreStopped() case StartRecording: case StartRecordingFromSnapshot: case Recording: - VCR_stopRecord(); + VCR_stopRecord(1); break; case StartPlayback: case StartPlaybackFromSnapshot: diff --git a/main/vcr.h b/main/vcr.h index 623a27da..384bba64 100755 --- a/main/vcr.h +++ b/main/vcr.h @@ -91,8 +91,8 @@ extern void VCR_movieFreeze (char** buf, unsigned long* size); extern int VCR_movieUnfreeze (const char* buf, unsigned long size); extern void VCR_clearAllSaveData(); -extern int VCR_startRecord( const char *filename, unsigned short flags, const char *authorUTF8, const char *descriptionUTF8 ); -extern int VCR_stopRecord(); +extern int VCR_startRecord( const char *filename, unsigned short flags, const char *authorUTF8, const char *descriptionUTF8, int defExt); +extern int VCR_stopRecord(int defExt); extern int VCR_startPlayback( const char *filename, const char *authorUTF8, const char *descriptionUTF8 ); extern int VCR_restartPlayback(); extern int VCR_stopPlayback(); diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 97ca6f65..25261ddd 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -1992,7 +1992,9 @@ LRESULT CALLBACK RecordMovieProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM if(Controls[3].Present && Controls[3].Plugin == PLUGIN_RUMBLE_PAK) strcat(tempbuf, " with rumble pak"); SetDlgItemText(hwnd,IDC_MOVIE_CONTROLLER4_TEXT2,tempbuf); - + + EnableWindow(GetDlgItem(hwnd, IDC_EXTSAVESTATE), 0); // workaround because initial selected button is "Start" + SetFocus(GetDlgItem(hwnd,IDC_INI_AUTHOR)); return FALSE; @@ -2028,7 +2030,10 @@ LRESULT CALLBACK RecordMovieProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM GetDlgItemText(hwnd,IDC_INI_MOVIEFILE,tempbuf,MAX_PATH); unsigned short flag = IsDlgButtonChecked(hwnd, IDC_FROMSNAPSHOT_RADIO) ? MOVIE_START_FROM_SNAPSHOT : IsDlgButtonChecked(hwnd, IDC_FROMSTART_RADIO) ? MOVIE_START_FROM_NOTHING : MOVIE_START_FROM_EEPROM; - if (strlen(tempbuf) == 0 || VCR_startRecord( tempbuf, flag, authorUTF8, descriptionUTF8 ) < 0) + + + + if (strlen(tempbuf) == 0 || VCR_startRecord( tempbuf, flag, authorUTF8, descriptionUTF8, !IsDlgButtonChecked(hwnd, IDC_EXTSAVESTATE)) < 0) { sprintf(tempbuf2, "Couldn't start recording\nof \"%s\".", tempbuf); MessageBox(hwnd, tempbuf2, "VCR", MB_OK); @@ -2082,7 +2087,18 @@ LRESULT CALLBACK RecordMovieProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM strcat(path_buffer, ".m64"); SetDlgItemText(hwnd,IDC_INI_MOVIEFILE,path_buffer); } - } break; + } + break; + + case IDC_FROMEEPROM_RADIO: + EnableWindow(GetDlgItem(hwnd, IDC_EXTSAVESTATE), 0); + break; + case IDC_FROMSNAPSHOT_RADIO: + EnableWindow(GetDlgItem(hwnd, IDC_EXTSAVESTATE), 1); + break; + case IDC_FROMSTART_RADIO: + EnableWindow(GetDlgItem(hwnd, IDC_EXTSAVESTATE), 0); + break; } break; } @@ -3230,7 +3246,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) break; case ID_STOP_RECORD: - if (VCR_stopRecord() < 0) + if (VCR_stopRecord(1) < 0) // seems ok (no) ; // fail quietly // MessageBox(NULL, "Couldn't stop recording.", "VCR", MB_OK); else { diff --git a/winproject/resource.h b/winproject/resource.h index 780d1b80..d888d03b 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -415,6 +415,7 @@ #define IDC_INPUTDELAY 40009 #define IDC_CLUADOUBLEBUFFER 40010 #define IDC_GITREPO 40011 +#define IDC_EXTSAVESTATE 40012 #define IDC_STATIC -1 // Next default values for new objects diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index eadc7f19..4856dfd2 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -527,6 +527,7 @@ BEGIN EDITTEXT IDC_MOVIE_CONTROLLER3_TEXT2,217,176,91,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER EDITTEXT IDC_MOVIE_CONTROLLER4_TEXT2,217,187,91,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER GROUPBOX "Start From",IDC_STARTFROM2,177,88,139,50 + CONTROL ".savestate", IDC_EXTSAVESTATE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 254, 112, 45, 10 CONTROL "Savestate",IDC_FROMSNAPSHOT_RADIO,"Button",BS_AUTORADIOBUTTON,190,112,64,10 CONTROL "Start",IDC_FROMSTART_RADIO,"Button",BS_AUTORADIOBUTTON,190,100,50,10 CONTROL "EEPROM",IDC_FROMEEPROM_RADIO,"Button",BS_AUTORADIOBUTTON,190,125,64,10 From ca60e918802c7d43b18a022c8ce979ebe383ea97 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 23 May 2021 21:03:03 +0200 Subject: [PATCH 37/93] avi small warning if file is inaccessible or something and tasinput spam setcursor message and --- main/vcr.c | 8 ++++++++ main/win/main_win.cpp | 4 ++-- tasinput_plugin/src/DefDI.cpp | 29 ++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 13f00e3d..97490766 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1958,6 +1958,14 @@ int VCR_startCapture( const char *recFilename, const char *aviFilename, bool cod } init_readScreen(); #endif + + FILE* tmpf = fopen(aviFilename, "ab+"); + + if (!tmpf && MessageBox(0, "AVI capture might break because the file is inaccessible. Try anyway?", "File inaccessible", MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDNO) + return -1; + + fclose(tmpf); + if (readScreen == 0) { printError("AVI capture failed because the active video plugin does not support ReadScreen()!"); diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 25261ddd..543cdcd2 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2123,7 +2123,7 @@ void OpenMovieRecordDialog() if (emu_launched&&!emu_paused) pauseEmu(FALSE) ; - DialogBox(GetModuleHandle(NULL), + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_MOVIE_RECORD_DIALOG), mainHWND, (DLGPROC)RecordMovieProc); if (emu_launched&&emu_paused&&!wasPaused) @@ -3089,7 +3089,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) _splitpath(procName, 0, 0, procName, 0); sprintf(stroopConfigLine, "", procName, buf); - + } diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 05944a57..25bf9e03 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -62,6 +62,7 @@ bool romIsOpen = false; HMENU hMenu; HANDLE fakeStatusThread = NULL; // fake! used for testing plugin +HANDLE spamThread = NULL; bool validatedhTxtbox = FALSE; UINT systemDPI; @@ -247,6 +248,7 @@ int WINAPI DllMain ( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) EXPORT void CALL CloseDLL (void) { //Stop and Close Direct Input + if(spamThread) TerminateThread(spamThread, 0); FreeDirectInput(); } @@ -1346,8 +1348,8 @@ EXPORT void CALL ReadController ( int Control, BYTE * Command ) if(Control == -1) Status::frameCounter++; - for (char i = 0; i < 4; i++) - SendMessage(status[i].statusDlg, WM_SETCURSOR, 0, 0); + //for (char i = 0; i < 4; i++) + // SendMessage(status[i].statusDlg, WM_SETCURSOR, 0, 0); } EXPORT void CALL RomClosed (void) { @@ -1570,7 +1572,20 @@ void Status::RefreshAnalogPicture () } } +DWORD WINAPI SpamThread(LPVOID lpParameter) { + while (TRUE) { + for (char i=0;i<4;i++) + if(status[i].statusDlg) + SendMessage(status[i].statusDlg,WM_SETCURSOR,0,0); + + // windows isnt rtos so timer granularity is bad and sleeping for less than 20 miliseconds doesnt reallllyy work.... + + // cope! lol + Sleep(13); + } + return 0; +} DWORD WINAPI StatusDlgThreadProc (LPVOID lpParameter) { int Control = LOBYTE(*(int*)lpParameter); @@ -1898,6 +1913,12 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(IsWindowFromEmulatorProcessActive()) ActivateEmulatorWindow(); + // create thread which spams SETCURSOR message... is this thread safe? + if (!spamThread) { + DWORD dwThreadParam = 0, dwThreadId; + spamThread = CreateThread(0, 0, SpamThread, &dwThreadParam, 0, &dwThreadId); + } + } break; case WM_ACTIVATE: @@ -1922,7 +1943,9 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // too bad we don't get useful events like WM_MOUSEMOVE or WM_LBUTTONDOWN... case WM_SETCURSOR: - +#ifdef DEBUG + //printf("tasinput setcursor message!\n"); +#endif POINT pt; GetCursorPos(&pt); From a740cb1328914cbf603ea73c7ab4130f17772507 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 24 May 2021 16:14:22 +0200 Subject: [PATCH 38/93] Fix rom browser flickering --- main/win/main_win.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 543cdcd2..9c71fb30 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3661,7 +3661,8 @@ int WINAPI WinMain( ShowWindow(hwnd, nCmdShow); // This fixes offscreen recording issue SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_ACCEPTFILES | WS_EX_LAYERED); //this can't be applied before ShowWindow(), otherwise you must use some fancy function - UpdateWindow(hwnd); + ListView_SetExtendedListViewStyleEx(hRomList, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER); + UpdateWindow(hwnd); #endif EnableMenuItem(GetMenu(hwnd), ID_LOG_WINDOW, MF_DISABLED); #ifdef _DEBUG From 924f37685f23f83eec357b9d7f567a1d6c1440d7 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 24 May 2021 16:20:55 +0200 Subject: [PATCH 39/93] ok apparently mainly issue was z ordering --- main/win/main_win.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 9c71fb30..e5a36431 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3661,6 +3661,7 @@ int WINAPI WinMain( ShowWindow(hwnd, nCmdShow); // This fixes offscreen recording issue SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_ACCEPTFILES | WS_EX_LAYERED); //this can't be applied before ShowWindow(), otherwise you must use some fancy function + BringWindowToTop(hRomList); ListView_SetExtendedListViewStyleEx(hRomList, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER); UpdateWindow(hwnd); #endif From 5262f0b316a7bbf87f224cc6449b32fccadaaef0 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Mon, 31 May 2021 20:43:07 +0200 Subject: [PATCH 40/93] Use stored emu hwnd for tasinput --- tasinput_plugin/src/DefDI.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 25bf9e03..875718ea 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1628,6 +1628,11 @@ static bool IsMouseOverControl (HWND hDlg, int dialogItemID) void Status::ActivateEmulatorWindow () { if (lock) return; + if (prevHWnd) + { + SetForegroundWindow(prevHWnd); + return; + } SetFocus(NULL); SetActiveWindow(NULL); // activates whatever the previous window was From 44c3468218c2860839c0cf8c81649739d1b22de5 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Wed, 16 Jun 2021 23:03:55 +0200 Subject: [PATCH 41/93] Wait 2 seconds before starting avi from cmdline to prevent audio issues dirty workaround --- main/win/main_win.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index e5a36431..1d8a188c 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2405,6 +2405,13 @@ static DWORD WINAPI SoundThread(LPVOID lpParam) ExitThread(0); } +static DWORD WINAPI StartMoviesThread(LPVOID lpParam) +{ + Sleep(2000); + StartMovies(); + ExitThread(0); +} + static DWORD WINAPI ThreadFunc(LPVOID lpParam) { @@ -2444,7 +2451,8 @@ static DWORD WINAPI ThreadFunc(LPVOID lpParam) SoundThreadHandle = CreateThread(NULL, 0, SoundThread, NULL, 0, &SOUNDTHREADID); ThreadFuncState = TFS_EMULATING; ShowInfo("Emu thread: Emulation started...."); - StartMovies(); // check commandline args + CreateThread(NULL, 0, StartMoviesThread, NULL, 0, NULL); + //StartMovies(); // check commandline args StartLuaScripts(); StartSavestate(); AtResetCallback(); From 01cef6bd660d44547884559231e9dae4ecfd139f Mon Sep 17 00:00:00 2001 From: crackhex Date: Sat, 26 Jun 2021 03:03:46 -0700 Subject: [PATCH 42/93] I fixed the avi things --- main/vcr.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 97490766..454e1c8d 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -128,7 +128,7 @@ static int soundBufPos = 0; long lastSound = 0; volatile BOOL captureFrameValid = FALSE; static int AVIBreakMovie = 0; - +int AVIIncrement = 1; int titleLength; extern void resetEmu(); @@ -1705,6 +1705,8 @@ VCR_updateScreen() return; } + + if(VCRComp_GetSize() > 0x7B9ACA00) { if(AVIBreakMovie) @@ -1717,21 +1719,22 @@ VCR_updateScreen() VCRComp_finishFile(1); AVIBreakMovie=1; } - int fnlen=strlen(AVIFileName); + char* AVIName = AVIFileName; + int fnlen = strlen(AVIFileName); + if(AVIBreakMovie==2) { - AVIFileName[fnlen-5]++; - if(AVIFileName[fnlen-5]==90) - AVIBreakMovie=1; + strncpy(AVIName, AVIFileName, fnlen - 5 - (int)(log10(AVIIncrement))); + AVIName[fnlen - 5 - (int)(log10(AVIIncrement))] = 0; + sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); + AVIIncrement++; } else { - AVIFileName[fnlen+1]=AVIFileName[fnlen]; - AVIFileName[fnlen]=AVIFileName[fnlen-1]; - AVIFileName[fnlen-1]=AVIFileName[fnlen-2]; - AVIFileName[fnlen-2]=AVIFileName[fnlen-3]; - AVIFileName[fnlen-3]=AVIFileName[fnlen-4]; - AVIFileName[fnlen-4]=65; + strncpy(AVIName, AVIFileName, fnlen - 4 - (int)(log10(AVIIncrement))); + AVIName[fnlen - 4 - (int)(log10(AVIIncrement))] = 0; + sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); + AVIIncrement++; } VCRComp_startFile( AVIFileName, width, height, visByCountrycode(), 0); } From f897246922789182b6bbdb41266a5083a4e0ff77 Mon Sep 17 00:00:00 2001 From: crackhex Date: Sat, 26 Jun 2021 11:56:44 -0700 Subject: [PATCH 43/93] Cleaned up and fixed code because it was 3am and I was tired --- main/vcr.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 454e1c8d..139a9d09 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -128,7 +128,7 @@ static int soundBufPos = 0; long lastSound = 0; volatile BOOL captureFrameValid = FALSE; static int AVIBreakMovie = 0; -int AVIIncrement = 1; +int AVIIncrement = 0; int titleLength; extern void resetEmu(); @@ -1726,16 +1726,14 @@ VCR_updateScreen() { strncpy(AVIName, AVIFileName, fnlen - 5 - (int)(log10(AVIIncrement))); AVIName[fnlen - 5 - (int)(log10(AVIIncrement))] = 0; - sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); - AVIIncrement++; } else { - strncpy(AVIName, AVIFileName, fnlen - 4 - (int)(log10(AVIIncrement))); - AVIName[fnlen - 4 - (int)(log10(AVIIncrement))] = 0; - sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); - AVIIncrement++; + strncpy(AVIName, AVIFileName, fnlen - 4); + AVIName[fnlen - 4] = 0; } + sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); + AVIIncrement++; VCRComp_startFile( AVIFileName, width, height, visByCountrycode(), 0); } @@ -2071,7 +2069,7 @@ VCR_stopCapture() #endif // VCR_stopPlayback(); VCRComp_finishFile(0); - AVIBreakMovie = 0; + AVIBreakMovie = 0; AVIIncrement = 0; printf( "[VCR]: Capture finished.\n" ); // ShowInfo("VCR_stopCapture() done"); return 0; From 1190f97d0680982136da74885e297d1a97280227 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 27 Jun 2021 10:34:42 +0200 Subject: [PATCH 44/93] Lua transparency (fillrect) --- lua/LuaConsole.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index 9ce7a5ff..c608d353 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -22,12 +22,13 @@ #include "../main/savestates.h" #include "../main/win/Config.h" #include - +#include #ifdef LUA_CONSOLE //nice msvc pragma smh #pragma comment(lib, "lua54.lib") +#pragma comment (lib,"Gdiplus.lib") extern unsigned long op; @@ -49,6 +50,7 @@ bool traceLogMode; bool enablePCBreak; bool maximumSpeedMode; bool anyLuaRunning = false; +bool gdiPlusInitialized = false; #define DEBUG_GETLASTERROR 0//if(GetLastError()){ShowInfo("Line:%d GetLastError:%d",__LINE__,GetLastError());SetLastError(0);} @@ -2067,6 +2069,42 @@ int DrawRect(lua_State *L) { luaL_checknumber(L, 3), luaL_checknumber(L, 4)); return 0; } +int FillRectAlpha(lua_State* L) +{ + // lol this is so bad.. branching in drawing code but idc + if (!gdiPlusInitialized) { + // we could do this only once at program startup but what if user doesnt use lua or gdi+ + printf("lua initialize gdiplus\n"); + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + gdiPlusInitialized = true; + } + + Lua* lua = GetLuaClass(L); + RECT rect; + int a, r, g, b; + + rect.bottom = luaL_checknumber(L, 1); + rect.left = luaL_checknumber(L, 2); + rect.right = luaL_checknumber(L, 3); + rect.top = luaL_checknumber(L, 4); + + a = luaL_checknumber(L, 5); + r = luaL_checknumber(L, 6); + g = luaL_checknumber(L, 7); + b = luaL_checknumber(L, 8); + + Gdiplus::Graphics gfx(luaDC); + + Gdiplus::SolidBrush brush(Gdiplus::Color(a, r, g, b)); + + + gfx.FillRectangle(&brush, rect.left, rect.top, rect.right, rect.bottom); + gfx.FillRectangle(&brush, rect.left, rect.top, rect.right, rect.bottom); + + return 0; +} int FillRect(lua_State* L) { /* (Info) @@ -2994,7 +3032,8 @@ const luaL_Reg wguiFuncs[] = { {"text", TextOut}, {"drawtext", DrawText}, {"rect", DrawRect}, - {"fillrect", FillRect}, // Experimental + {"fillrect", FillRect}, + {"fillrecta", FillRectAlpha}, // Experimental {"ellipse", DrawEllipse}, {"polygon", DrawPolygon}, {"line", DrawLine}, From b3159769029cdd05fc6de9ea2b31c7885305fcd3 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 27 Jun 2021 13:34:35 +0200 Subject: [PATCH 45/93] Some changes to gdiplus implemetation --- lua/LuaConsole.cpp | 28 ++++++++++++++++------------ lua/LuaConsole.h | 2 +- main/win/main_win.cpp | 5 +++++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index c608d353..d244008f 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -51,6 +51,7 @@ bool enablePCBreak; bool maximumSpeedMode; bool anyLuaRunning = false; bool gdiPlusInitialized = false; +ULONG_PTR gdiPlusToken; #define DEBUG_GETLASTERROR 0//if(GetLastError()){ShowInfo("Line:%d GetLastError:%d",__LINE__,GetLastError());SetLastError(0);} @@ -2076,19 +2077,19 @@ int FillRectAlpha(lua_State* L) // we could do this only once at program startup but what if user doesnt use lua or gdi+ printf("lua initialize gdiplus\n"); Gdiplus::GdiplusStartupInput gdiplusStartupInput; - ULONG_PTR gdiplusToken; - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + Gdiplus::GdiplusStartup(&gdiPlusToken, &gdiplusStartupInput, NULL); gdiPlusInitialized = true; } Lua* lua = GetLuaClass(L); - RECT rect; - int a, r, g, b; + + int left, top, right, bottom; + byte a, r, g, b; - rect.bottom = luaL_checknumber(L, 1); - rect.left = luaL_checknumber(L, 2); - rect.right = luaL_checknumber(L, 3); - rect.top = luaL_checknumber(L, 4); + bottom = luaL_checknumber(L, 1); + left = luaL_checknumber(L, 2); + right = luaL_checknumber(L, 3); + top = luaL_checknumber(L, 4); a = luaL_checknumber(L, 5); r = luaL_checknumber(L, 6); @@ -2096,12 +2097,15 @@ int FillRectAlpha(lua_State* L) b = luaL_checknumber(L, 8); Gdiplus::Graphics gfx(luaDC); - Gdiplus::SolidBrush brush(Gdiplus::Color(a, r, g, b)); + + // vi sitter hr i venten och spelar lite dota + // activate these for more speed and bad transparency + //gfx.SetInterpolationMode(Gdiplus::InterpolationModeDefault); + //gfx.SetSmoothingMode( Gdiplus::SmoothingModeNone); + //gfx.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf); - - gfx.FillRectangle(&brush, rect.left, rect.top, rect.right, rect.bottom); - gfx.FillRectangle(&brush, rect.left, rect.top, rect.right, rect.bottom); + gfx.FillRectangle(&brush, left, top, right, bottom); return 0; } diff --git a/lua/LuaConsole.h b/lua/LuaConsole.h index a1f0148a..4888ddd7 100755 --- a/lua/LuaConsole.h +++ b/lua/LuaConsole.h @@ -61,7 +61,7 @@ extern bool traceLogMode; extern bool enablePCBreak; extern bool maximumSpeedMode; extern bool anyLuaRunning; - +extern unsigned long gdiPlusToken; #endif diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 1d8a188c..e9dd221c 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -62,6 +62,9 @@ extern "C" { #include "../../memory/pif.h" #undef EMULATOR_MAIN_CPP_DEF +#include +#pragma comment (lib,"Gdiplus.lib") + extern void CountryCodeToCountryName(int countrycode,char *countryname); void StartMovies(); @@ -2508,6 +2511,8 @@ void exit_emu(int postquit) freeRomDirList(); freeRomList(); freeLanguages(); + Gdiplus::GdiplusShutdown(gdiPlusToken); + //printf("free gdiplus\n"); PostQuitMessage (0); } } From ec8153bb768e272d37ef93f5d169b30c0d78be87 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 27 Jun 2021 13:46:49 +0200 Subject: [PATCH 46/93] Minor QoL improvement to toolbar --- main/win/main_win.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index e9dd221c..b3bb0ca4 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2563,7 +2563,15 @@ void ProcessToolTips(LPARAM lParam, HWND hWnd) lpttt->lpszText = TempMessage; break; case EMU_PLAY: - TranslateDefault("Start/Resume Emulation", "Start/Resume Emulation", TempMessage); + if (!emu_launched) { + TranslateDefault("Start Emulation", "Start Emulation", TempMessage); + } + else if (emu_paused) { + TranslateDefault("Resume Emulation", "Resume Emulation", TempMessage); + } + else { + TranslateDefault("Emulating", "Emulating", TempMessage); + } lpttt->lpszText = TempMessage; break; case EMU_PAUSE: From 0c41d6cc690edbb0ae35e2eac094f524038ace98 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 27 Jun 2021 18:06:57 +0200 Subject: [PATCH 47/93] TASInput fix small overlap in DPI adjusting --- tasinput_plugin/src/DefDI.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 875718ea..0893174b 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -863,7 +863,7 @@ BOOL AdjustForDPI(HWND parent, UINT dpi) { GetWindowRect(GetDlgItem(parent, IDC_STATICX), &ctl_gp_pos); ctl_gp_pos.left -= 3; // adjust for border - + if (STICKPIC_SIZE == 131) { // prevent infinitely increasing size @@ -873,11 +873,14 @@ BOOL AdjustForDPI(HWND parent, UINT dpi) { // check for overlap with gpbox and try to fix it - if (ctl_pos.right > ctl_gp_pos.left) { + if (ctl_pos.right+1 > ctl_gp_pos.left) { printf("overlap with groupbox (%d/%d)", ctl_pos.right, ctl_gp_pos.left); - STICKPIC_SIZE = ctl_gp_pos.left; + STICKPIC_SIZE = ctl_gp_pos.left-2; } } + + STICKPIC_SIZE -= 1; + //STICKPIC_SIZE = (UINT)STICKPIC_SIZE; // ensure no double printf("stickpic size: %d\ndpi: %d", STICKPIC_SIZE, dpi); return dpi != 96; From 8883d995bc640a1db13753c0613c882c1d50c059 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 28 Jun 2021 16:47:27 +0200 Subject: [PATCH 48/93] LUA Polygon and ellipse GDI+ --- lua/LuaConsole.cpp | 83 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index d244008f..a90b00ee 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -2070,19 +2070,57 @@ int DrawRect(lua_State *L) { luaL_checknumber(L, 3), luaL_checknumber(L, 4)); return 0; } -int FillRectAlpha(lua_State* L) -{ - // lol this is so bad.. branching in drawing code but idc + +VOID checkGDIPlusInitialized() { + // will be inlined by compiler if (!gdiPlusInitialized) { - // we could do this only once at program startup but what if user doesnt use lua or gdi+ printf("lua initialize gdiplus\n"); Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&gdiPlusToken, &gdiplusStartupInput, NULL); gdiPlusInitialized = true; } +} + +int FillPolygonAlpha(lua_State* L) { + checkGDIPlusInitialized(); Lua* lua = GetLuaClass(L); + + Gdiplus::PointF pt1; + Gdiplus::PointF pt2; + Gdiplus::PointF pt3; + byte a, r, g, b; + + pt1.X = luaL_checknumber(L, 1); + pt1.Y = luaL_checknumber(L, 2); + + pt2.X = luaL_checknumber(L, 3); + pt2.Y = luaL_checknumber(L, 4); + + pt3.X = luaL_checknumber(L, 5); + pt3.Y = luaL_checknumber(L, 6); + + a = luaL_checknumber(L, 7); + r = luaL_checknumber(L, 8); + g = luaL_checknumber(L, 9); + b = luaL_checknumber(L, 10); + + Gdiplus::Graphics gfx(luaDC); + Gdiplus::SolidBrush brush(Gdiplus::Color(a, r, g, b)); + + Gdiplus::PointF pts[3] = {pt1,pt2,pt3}; + gfx.FillPolygon(&brush, pts, 1); + delete[] pts; // i think + + return 0; +} + + +int FillEllipseAlpha(lua_State* L) { + checkGDIPlusInitialized(); + Lua* lua = GetLuaClass(L); + int left, top, right, bottom; byte a, r, g, b; @@ -2098,12 +2136,32 @@ int FillRectAlpha(lua_State* L) Gdiplus::Graphics gfx(luaDC); Gdiplus::SolidBrush brush(Gdiplus::Color(a, r, g, b)); + + gfx.FillEllipse(&brush, left, top, right, bottom); + + return 0; +} +int FillRectAlpha(lua_State* L) +{ + checkGDIPlusInitialized(); + + Lua* lua = GetLuaClass(L); - // vi sitter hr i venten och spelar lite dota - // activate these for more speed and bad transparency - //gfx.SetInterpolationMode(Gdiplus::InterpolationModeDefault); - //gfx.SetSmoothingMode( Gdiplus::SmoothingModeNone); - //gfx.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf); + int left, top, right, bottom; + byte a, r, g, b; + + bottom = luaL_checknumber(L, 1); + left = luaL_checknumber(L, 2); + right = luaL_checknumber(L, 3); + top = luaL_checknumber(L, 4); + + a = luaL_checknumber(L, 5); + r = luaL_checknumber(L, 6); + g = luaL_checknumber(L, 7); + b = luaL_checknumber(L, 8); + + Gdiplus::Graphics gfx(luaDC); + Gdiplus::SolidBrush brush(Gdiplus::Color(a, r, g, b)); gfx.FillRectangle(&brush, left, top, right, bottom); @@ -3037,7 +3095,12 @@ const luaL_Reg wguiFuncs[] = { {"drawtext", DrawText}, {"rect", DrawRect}, {"fillrect", FillRect}, - {"fillrecta", FillRectAlpha}, // Experimental + /**/ + // GDIPlus functions marked with "a" suffix + {"fillrecta", FillRectAlpha}, + {"fillellipsea", FillEllipseAlpha}, + {"fillpolygona", FillPolygonAlpha}, + /* Date: Wed, 30 Jun 2021 19:06:20 +0200 Subject: [PATCH 49/93] fix audio delay on commandline avi (why was this not commited) --- main/win/main_win.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 10193d2d..5688c636 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2415,6 +2415,13 @@ static DWORD WINAPI StartMoviesThread(LPVOID lpParam) ExitThread(0); } +static DWORD WINAPI StartMoviesThread(LPVOID lpParam) +{ + Sleep(2000); + StartMovies(); + ExitThread(0); +} + static DWORD WINAPI ThreadFunc(LPVOID lpParam) { From aa392c06bf231ad36ab4211b8fe555ef63890b4b Mon Sep 17 00:00:00 2001 From: Madghostek Date: Wed, 30 Jun 2021 19:31:25 +0200 Subject: [PATCH 50/93] (might be bad) don't steal focus every milisecond --- tasinput_plugin/src/DefDI.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 0893174b..47b662ff 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -2115,9 +2115,10 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { if(!IsAnyStatusDialogActive()) { - if(gettingKeys) + if (gettingKeys) + printf("getting?!\n"); Sleep(0); - ActivateEmulatorWindow(); + //ActivateEmulatorWindow(); if(!gettingKeys && !(comboTask & (C_RUNNING | C_LOOP)) && !copyButtons) { BUTTONS Keys; @@ -2126,7 +2127,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) GetKeys(&Keys); //used in radial mode I think fakeInput = false; relativeControlNow = false; - ActivateEmulatorWindow(); + //ActivateEmulatorWindow(); } } else From d4530ae899eb56c2cf988e78cf1c3979972de4fc Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 30 Jun 2021 19:54:44 +0200 Subject: [PATCH 51/93] fix small thing --- lua/LuaConsole.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index a90b00ee..92183ebc 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -2111,7 +2111,6 @@ int FillPolygonAlpha(lua_State* L) { Gdiplus::PointF pts[3] = {pt1,pt2,pt3}; gfx.FillPolygon(&brush, pts, 1); - delete[] pts; // i think return 0; } From 664dc50cd82e9d988a737e87c54c8537d6fce84a Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 30 Jun 2021 20:17:30 +0200 Subject: [PATCH 52/93] fix title bar resetting when movie loops --- main/vcr.c | 4 +++- main/win/main_win.cpp | 6 ------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 139a9d09..57b2f690 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1315,7 +1315,9 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip return -1; } } - if (!restarting) SetActiveMovie(buf); // can crash when looping + fast forward, no need to change this + SetActiveMovie(buf); + // can crash when looping + fast forward, no need to change this + // this creates a bug, so i changed it -auru { int code = read_movie_header(m_file, &m_header); diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 5688c636..29d9b0f0 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2415,12 +2415,6 @@ static DWORD WINAPI StartMoviesThread(LPVOID lpParam) ExitThread(0); } -static DWORD WINAPI StartMoviesThread(LPVOID lpParam) -{ - Sleep(2000); - StartMovies(); - ExitThread(0); -} static DWORD WINAPI ThreadFunc(LPVOID lpParam) From 33698cdb24d0a14a901e1c5ef3d7d17b2bc7afc9 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 30 Jun 2021 20:21:26 +0200 Subject: [PATCH 53/93] change avi split size --- main/vcr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/vcr.c b/main/vcr.c index 57b2f690..0f383aef 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -55,6 +55,7 @@ #define MUP_HEADER_SIZE_OLD (512) // bytes #define MUP_HEADER_SIZE (sizeof(SMovieHeader)) #define MUP_HEADER_SIZE_CUR (m_header.version <= 2 ? MUP_HEADER_SIZE_OLD : MUP_HEADER_SIZE) +#define MAX_AVI_SIZE 0x80000000 extern CONFIG Config; @@ -1709,7 +1710,7 @@ VCR_updateScreen() - if(VCRComp_GetSize() > 0x7B9ACA00) + if(VCRComp_GetSize() > MAX_AVI_SIZE) { if(AVIBreakMovie) { From 57644a379fffe489d478d773960671e1c20d70ff Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Wed, 30 Jun 2021 20:28:48 +0200 Subject: [PATCH 54/93] change back lma --- main/vcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/vcr.c b/main/vcr.c index 0f383aef..9f15d4f6 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -55,7 +55,7 @@ #define MUP_HEADER_SIZE_OLD (512) // bytes #define MUP_HEADER_SIZE (sizeof(SMovieHeader)) #define MUP_HEADER_SIZE_CUR (m_header.version <= 2 ? MUP_HEADER_SIZE_OLD : MUP_HEADER_SIZE) -#define MAX_AVI_SIZE 0x80000000 +#define MAX_AVI_SIZE 0x7B9ACA00 extern CONFIG Config; From bfd3642c0d0710571f3cfeba8f25df6f1189b21f Mon Sep 17 00:00:00 2001 From: Madghostek Date: Wed, 30 Jun 2021 20:38:58 +0200 Subject: [PATCH 55/93] simplify avi splitting --- main/vcr.c | 33 +++++++-------------------------- main/win/main_win.cpp | 8 -------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 139a9d09..36cdd108 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1709,31 +1709,12 @@ VCR_updateScreen() if(VCRComp_GetSize() > 0x7B9ACA00) { - if(AVIBreakMovie) - { - VCRComp_finishFile(1); - AVIBreakMovie=2; - } - else - { - VCRComp_finishFile(1); - AVIBreakMovie=1; - } - char* AVIName = AVIFileName; - int fnlen = strlen(AVIFileName); - - if(AVIBreakMovie==2) - { - strncpy(AVIName, AVIFileName, fnlen - 5 - (int)(log10(AVIIncrement))); - AVIName[fnlen - 5 - (int)(log10(AVIIncrement))] = 0; - } - else - { - strncpy(AVIName, AVIFileName, fnlen - 4); - AVIName[fnlen - 4] = 0; - } - sprintf(AVIFileName, "%s%d.avi", AVIName, AVIIncrement + 1); - AVIIncrement++; + static char* endptr; + VCRComp_finishFile(1); + if (!AVIIncrement) + endptr = AVIFileName + strlen(AVIFileName) -4; + //AVIIncrement + sprintf(endptr, "%d.avi", ++AVIIncrement); VCRComp_startFile( AVIFileName, width, height, visByCountrycode(), 0); } @@ -2069,7 +2050,7 @@ VCR_stopCapture() #endif // VCR_stopPlayback(); VCRComp_finishFile(0); - AVIBreakMovie = 0; AVIIncrement = 0; + AVIIncrement = 0; printf( "[VCR]: Capture finished.\n" ); // ShowInfo("VCR_stopCapture() done"); return 0; diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 5688c636..760487aa 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2415,14 +2415,6 @@ static DWORD WINAPI StartMoviesThread(LPVOID lpParam) ExitThread(0); } -static DWORD WINAPI StartMoviesThread(LPVOID lpParam) -{ - Sleep(2000); - StartMovies(); - ExitThread(0); -} - - static DWORD WINAPI ThreadFunc(LPVOID lpParam) { ThreadFuncState = TFS_NONE; From 41e03aad333d9bc489ea9146d0be909c2974714a Mon Sep 17 00:00:00 2001 From: Madghostek Date: Wed, 30 Jun 2021 20:55:39 +0200 Subject: [PATCH 56/93] fix pausing when moving mupen window --- main/win/main_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 760487aa..1c57654b 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2871,7 +2871,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) lpMMI->ptMinTrackSize.y = MIN_WINDOW_H; // this might break small res with gfx plugin!!! } - + break; case WM_ENTERMENULOOP: AutoPause = emu_paused; if (!emu_paused) From 400c980ebb086b518ca49f8e95f6f134f633f9e2 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Thu, 1 Jul 2021 18:38:07 +0200 Subject: [PATCH 57/93] fix the most annoying issue ever --- lua/LuaConsole.cpp | 11 +++++++++-- main/vcr.c | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index 92183ebc..74b3d090 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -660,7 +660,9 @@ INT_PTR CALLBACK DialogProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; } std::string OpenLuaFileDialog() { - EmulationLock lock; + + int storePaused = emu_paused; + pauseEmu(1); OPENFILENAME ofn; char filename[MAX_PATH] = ""; @@ -679,8 +681,13 @@ std::string OpenLuaFileDialog() { ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; ofn.lpstrInitialDir = NULL; - if(!GetOpenFileName(&ofn)) + if (!GetOpenFileName(&ofn)) { + if (!storePaused) resumeEmu(1); return ""; + } + + if (!storePaused) resumeEmu(1); + return ofn.lpstrFile; } void SetButtonState(HWND wnd, bool state) { diff --git a/main/vcr.c b/main/vcr.c index 9f15d4f6..871ac9f7 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -869,6 +869,7 @@ VCR_getKeys( int Control, BUTTONS *Keys ) if (m_task == Idle) return; + if (m_task == StartRecording) { if(!continue_vcr_on_restart_mode) From e0346fc8edd2f8de1f462875edcb05f5bce73020 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Fri, 2 Jul 2021 18:28:23 +0200 Subject: [PATCH 58/93] change literally everything in tasinput because its driving me insane --- tasinput_plugin/src/DefDI.cpp | 76 +++++++++++++++-------------------- tasinput_plugin/src/DefDI.h | 7 ++-- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 47b662ff..e2f2a584 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -62,7 +62,6 @@ bool romIsOpen = false; HMENU hMenu; HANDLE fakeStatusThread = NULL; // fake! used for testing plugin -HANDLE spamThread = NULL; bool validatedhTxtbox = FALSE; UINT systemDPI; @@ -215,6 +214,7 @@ struct Status bool IsWindowFromEmulatorProcessActive (); static bool IsAnyStatusDialogActive (); LRESULT StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam); + void UpdateVisuals(BUTTONS ControllerInput); void GetKeys(BUTTONS * Keys); void SetKeys(BUTTONS ControllerInput); }; @@ -248,7 +248,6 @@ int WINAPI DllMain ( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) EXPORT void CALL CloseDLL (void) { //Stop and Close Direct Input - if(spamThread) TerminateThread(spamThread, 0); FreeDirectInput(); } @@ -811,12 +810,12 @@ void Status::GetKeys(BUTTONS * Keys) ControllerInput.Value ^= buttonAutofire.Value; else ControllerInput.Value ^= buttonAutofire2.Value; - + bool prevOverrideAllowed = overrideAllowed; overrideAllowed = true; if (comboTask != C_PAUSE) { - if (!copyButtons) SetKeys(ControllerInput); //don't overwrite after switching to read write + if (!copyButtons && !fakeInput) SetKeys(ControllerInput); //don't overwrite after switching to read write else LastControllerInput = ControllerInput; copyButtons = false; } @@ -886,6 +885,28 @@ BOOL AdjustForDPI(HWND parent, UINT dpi) { return dpi != 96; } + +//updates buttons +void Status::UpdateVisuals(BUTTONS ControllerInput) +{ +#define UPDATECHECK(idc,field) {if(buttonDisplayed.field != ControllerInput.field) CheckDlgButton(statusDlg, idc, ControllerInput.field);} + UPDATECHECK(IDC_CHECK_A, A_BUTTON); + UPDATECHECK(IDC_CHECK_B, B_BUTTON); + UPDATECHECK(IDC_CHECK_START, START_BUTTON); + UPDATECHECK(IDC_CHECK_L, L_TRIG); + UPDATECHECK(IDC_CHECK_R, R_TRIG); + UPDATECHECK(IDC_CHECK_Z, Z_TRIG); + UPDATECHECK(IDC_CHECK_CUP, U_CBUTTON); + UPDATECHECK(IDC_CHECK_CLEFT, L_CBUTTON); + UPDATECHECK(IDC_CHECK_CRIGHT, R_CBUTTON); + UPDATECHECK(IDC_CHECK_CDOWN, D_CBUTTON); + UPDATECHECK(IDC_CHECK_DUP, U_DPAD); + UPDATECHECK(IDC_CHECK_DLEFT, L_DPAD); + UPDATECHECK(IDC_CHECK_DRIGHT, R_DPAD); + UPDATECHECK(IDC_CHECK_DDOWN, D_DPAD); + buttonDisplayed.Value = ControllerInput.Value&0xFFFF; //fuck off +} + void Status::SetKeys(BUTTONS ControllerInput) { if (copyButtons) //copy m64 data to current input @@ -900,21 +921,7 @@ void Status::SetKeys(BUTTONS ControllerInput) //true if physical controller state is changed (because logical is handled in GetKeys) if (buttonDisplayed.Value != ControllerInput.Value && HasPanel(2)) { -#define UPDATECHECK(idc,field) {if(buttonDisplayed.field != ControllerInput.field) CheckDlgButton(statusDlg, idc, ControllerInput.field);} - UPDATECHECK(IDC_CHECK_A, A_BUTTON); - UPDATECHECK(IDC_CHECK_B, B_BUTTON); - UPDATECHECK(IDC_CHECK_START, START_BUTTON); - UPDATECHECK(IDC_CHECK_L, L_TRIG); - UPDATECHECK(IDC_CHECK_R, R_TRIG); - UPDATECHECK(IDC_CHECK_Z, Z_TRIG); - UPDATECHECK(IDC_CHECK_CUP, U_CBUTTON); - UPDATECHECK(IDC_CHECK_CLEFT, L_CBUTTON); - UPDATECHECK(IDC_CHECK_CRIGHT, R_CBUTTON); - UPDATECHECK(IDC_CHECK_CDOWN, D_CBUTTON); - UPDATECHECK(IDC_CHECK_DUP, U_DPAD); - UPDATECHECK(IDC_CHECK_DLEFT, L_DPAD); - UPDATECHECK(IDC_CHECK_DRIGHT, R_DPAD); - UPDATECHECK(IDC_CHECK_DDOWN, D_DPAD); + UpdateVisuals(ControllerInput); buttonDisplayed.Value = ControllerInput.Value; } if(relativeXOn == 3 && radialRecalc) @@ -1575,20 +1582,6 @@ void Status::RefreshAnalogPicture () } } -DWORD WINAPI SpamThread(LPVOID lpParameter) { - while (TRUE) { - - for (char i=0;i<4;i++) - if(status[i].statusDlg) - SendMessage(status[i].statusDlg,WM_SETCURSOR,0,0); - - // windows isnt rtos so timer granularity is bad and sleeping for less than 20 miliseconds doesnt reallllyy work.... - - // cope! lol - Sleep(13); - } - return 0; -} DWORD WINAPI StatusDlgThreadProc (LPVOID lpParameter) { int Control = LOBYTE(*(int*)lpParameter); @@ -1791,7 +1784,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) AdjustForDPI(statusDlg, systemDPI); // reset some dialog state - dragging = false; lastXDrag = 0; lastYDrag = 0; dragging = false, draggingStick = false, draggingPermaStick = false; @@ -1921,12 +1913,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(IsWindowFromEmulatorProcessActive()) ActivateEmulatorWindow(); - // create thread which spams SETCURSOR message... is this thread safe? - if (!spamThread) { - DWORD dwThreadParam = 0, dwThreadId; - spamThread = CreateThread(0, 0, SpamThread, &dwThreadParam, 0, &dwThreadId); - } - } break; case WM_ACTIVATE: @@ -1969,6 +1955,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { if(IsMouseOverControl(statusDlg,IDC_STICKPIC)) { + SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //start timer during dragging to allow out of bounds drag //if clicked RMB and permadrag was active, disable it if(draggingPermaStick || GetAsyncKeyState(VK_RBUTTON) & 0x8000) { @@ -1984,9 +1971,9 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) else if(IsMouseOverControl(statusDlg,IDC_BUTTONSLABEL) || IsMouseOverControl(statusDlg, IDC_ANALOGSTICKLABEL)) { #ifdef DEBUG - printf("HWND hit: %d\n", ChildWindowFromPoint(statusDlg, pt)); - printf("HWND deeper 1: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt)); - printf("HWND deeper 2: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt)); + //printf("HWND hit: %d\n", ChildWindowFromPoint(statusDlg, pt)); + //printf("HWND deeper 1: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt)); + //printf("HWND deeper 2: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt)); #endif //if we are over buttons area and right is clicked, look for autofire candidates if(lastWasRight && IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL)) @@ -2047,6 +2034,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { draggingStick = false; draggingPermaStick = false; + KillTimer(statusDlg, IDT_TIMER3); if(IsWindowFromEmulatorProcessActive()) ActivateEmulatorWindow(); } @@ -2116,7 +2104,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(!IsAnyStatusDialogActive()) { if (gettingKeys) - printf("getting?!\n"); Sleep(0); //ActivateEmulatorWindow(); if(!gettingKeys && !(comboTask & (C_RUNNING | C_LOOP)) && !copyButtons) @@ -2242,6 +2229,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) EndEdit(activeCombo, (char*)lParam); break; case WM_COMMAND: + dragging = false; //any interaction with controls means we don't want to drag switch (LOWORD(wParam)) { case IDC_EDITX: diff --git a/tasinput_plugin/src/DefDI.h b/tasinput_plugin/src/DefDI.h index c445e227..5ec7d34a 100755 --- a/tasinput_plugin/src/DefDI.h +++ b/tasinput_plugin/src/DefDI.h @@ -140,9 +140,10 @@ VOID CALLBACK StatusDlgProcTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD d CheckDlgButton(statusDlg,idc,buttonAutofire.field|buttonAutofire2.field ? 0 : 1); \ BUTTONS &autoFire1 = (frameCounter%2 == 0) ? buttonAutofire : buttonAutofire2; \ BUTTONS &autoFire2 = (frameCounter%2 == 0) ? buttonAutofire2 : buttonAutofire; \ - autoFire1.field = !(autoFire1.field|autoFire2.field); \ - autoFire2.field = 0; \ - buttonOverride.field = 0; \ + autoFire1.field = 0; \ + autoFire2.field = !(autoFire1.field|autoFire2.field); \ + buttonOverride.field ^= 1; \ + buttonDisplayed.field = autoFire2.field; \ } \ } From af04bc07bd166935c0c7d4aef8d97bae53670e5e Mon Sep 17 00:00:00 2001 From: Madghostek Date: Fri, 2 Jul 2021 19:13:45 +0200 Subject: [PATCH 59/93] Controller has higher priority than tasinput allows unclicking buttons like old tasinput --- tasinput_plugin/src/DefDI.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index e2f2a584..95b5ceed 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -188,6 +188,7 @@ struct Status BUTTONS buttonOverride, buttonAutofire, buttonAutofire2; BUTTONS buttonDisplayed; BUTTONS LastControllerInput; + BUTTONS LastPureControllerInput; //without overrides/combo HWND statusDlg; HWND prevHWnd; HWND lBox; @@ -803,7 +804,15 @@ void Status::GetKeys(BUTTONS * Keys) } else if (comboTask == C_PAUSE) comboStart++; - continue_controller: +continue_controller: + //Allow unpressing with real controller low iq: + //1. realChanged has 1 where something changed + //2. mask out presses, leave releases + //3. remove the releases from override + DWORD realChanged = ControllerInput.Value ^ LastPureControllerInput.Value; + buttonOverride.Value &= ~(realChanged&LastPureControllerInput.Value); + + LastPureControllerInput.Value = ControllerInput.Value; ControllerInput.Value |= buttonOverride.Value; //if((frameCounter/2)%2 == 0) if (frameCounter % 2 == 0) //autofire stuff @@ -823,7 +832,7 @@ void Status::GetKeys(BUTTONS * Keys) ControllerInput.Y_AXIS = overrideY; //Pass Button Info to Emulator Keys->Value = ControllerInput.Value; - buttonOverride.Value = oldOverride; + //buttonOverride.Value = oldOverride; //copy fetched data to combo too if (comboTask == C_RECORD && !fakeInput) { From 411dd42657d31b947d4c940c9c7fd4418c653d32 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 4 Jul 2021 20:47:41 +0200 Subject: [PATCH 60/93] Incompatible plugin warning system --- main/plugin.c | 5 +++++ main/plugin.h | 2 ++ main/win/main_win.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/main/plugin.c b/main/plugin.c index d4b46930..1d3b0958 100755 --- a/main/plugin.c +++ b/main/plugin.c @@ -60,11 +60,16 @@ AUDIO_INFO audio_info; static CONTROL_INFO control_info; static RSP_INFO rsp_info; + void (__cdecl*getDllInfo)(PLUGIN_INFO *PluginInfo); void (__cdecl*dllConfig)(HWND hParent); void (__cdecl*dllTest)(HWND hParent); void (__cdecl*dllAbout)(HWND hParent); + + + + /* dummy functions to prevent mupen from crashing if a plugin is missing */ static void __cdecl dummy_void() {} static BOOL __cdecl dummy_initiateGFX(GFX_INFO Gfx_Info) { return TRUE; } diff --git a/main/plugin.h b/main/plugin.h index e74a3a4b..031a1f2f 100755 --- a/main/plugin.h +++ b/main/plugin.h @@ -1,3 +1,4 @@ +#pragma once /** * Mupen64 - plugin.h * Copyright (C) 2002 Hacktarux @@ -51,6 +52,7 @@ void plugin_exec_config(const char *name); void plugin_exec_test(const char *name); void plugin_exec_about(const char *name); + /* Plugin types */ #define PLUGIN_TYPE_RSP 1 #define PLUGIN_TYPE_GFX 2 diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 1c57654b..7e2d8748 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -226,6 +226,9 @@ char sound_name[255]; char rsp_name[255]; char stroopConfigLine[150] = {0}; +#define INCOMPATIBLE_PLUGINS_AMOUNT 1 // this is so bad +char incompatiblePluginNames[INCOMPATIBLE_PLUGINS_AMOUNT][256] = { "Azi" }; + enum EThreadFuncState { TFS_INITMEM, @@ -498,11 +501,32 @@ static plugins *liste_plugins = NULL, *current; void insert_plugin(plugins *p, char *file_name, char *plugin_name, void *handle, int type,int num) { + + for (int i = 0; i < INCOMPATIBLE_PLUGINS_AMOUNT; i++) + { + if (strstr(plugin_name, incompatiblePluginNames[i])) { + char* msg = (char*)malloc(sizeof(incompatiblePluginNames[i])); + + sprintf(msg, "A incompatible plugin with the name \"%s\" was detected.\ + \nIt is highly recommended to skip loading this plugin as not doing so might cause instability.\ + \nAre you sure you want to load this plugin?", plugin_name); + + int res = MessageBox(0, msg, "Incompatible plugin", MB_YESNO | MB_TOPMOST | MB_ICONWARNING); + + free(msg); + + if(res == IDNO) + return; + } + } + + if (p->next) insert_plugin(p->next, file_name, plugin_name, handle, type, (p->type == type) ? num+1 : num); else { + p->next = (plugins*)malloc(sizeof(plugins)); p->next->type = type; p->next->handle = (HMODULE)handle; From 2e4d9a0c1678e5935a61771f66bf73fa5f3bf7bd Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 4 Jul 2021 21:06:43 +0200 Subject: [PATCH 61/93] Fix messagebox being shown twice --- main/win/main_win.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 7e2d8748..4a5a7aff 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -502,23 +502,7 @@ void insert_plugin(plugins *p, char *file_name, char *plugin_name, void *handle, int type,int num) { - for (int i = 0; i < INCOMPATIBLE_PLUGINS_AMOUNT; i++) - { - if (strstr(plugin_name, incompatiblePluginNames[i])) { - char* msg = (char*)malloc(sizeof(incompatiblePluginNames[i])); - - sprintf(msg, "A incompatible plugin with the name \"%s\" was detected.\ - \nIt is highly recommended to skip loading this plugin as not doing so might cause instability.\ - \nAre you sure you want to load this plugin?", plugin_name); - - int res = MessageBox(0, msg, "Incompatible plugin", MB_YESNO | MB_TOPMOST | MB_ICONWARNING); - - free(msg); - - if(res == IDNO) - return; - } - } + if (p->next) @@ -526,7 +510,23 @@ void insert_plugin(plugins *p, char *file_name, (p->type == type) ? num+1 : num); else { - + for (int i = 0; i < INCOMPATIBLE_PLUGINS_AMOUNT; i++) + { + if (strstr(plugin_name, incompatiblePluginNames[i])) { + char* msg = (char*)malloc(sizeof(incompatiblePluginNames[i])); + + sprintf(msg, "A incompatible plugin with the name \"%s\" was detected.\ + \nIt is highly recommended to skip loading this plugin as not doing so might cause instability.\ + \nAre you sure you want to load this plugin?", plugin_name); + + int res = MessageBox(0, msg, "Incompatible plugin", MB_YESNO | MB_TOPMOST | MB_ICONWARNING); + + free(msg); + + if (res == IDNO) + return; + } + } p->next = (plugins*)malloc(sizeof(plugins)); p->next->type = type; p->next->handle = (HMODULE)handle; From a9a73fe9122b258c588e6481e5078cb6db89177c Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Tue, 6 Jul 2021 14:23:25 +0200 Subject: [PATCH 62/93] M64 drag drop consistency, Plugin blacklist changes --- main/win/main_win.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 4a5a7aff..c3b47adf 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -227,7 +227,7 @@ char rsp_name[255]; char stroopConfigLine[150] = {0}; #define INCOMPATIBLE_PLUGINS_AMOUNT 1 // this is so bad -char incompatiblePluginNames[INCOMPATIBLE_PLUGINS_AMOUNT][256] = { "Azi" }; +const char pluginBlacklist[INCOMPATIBLE_PLUGINS_AMOUNT][256] = { "Azimer\'s Audio v0.7" }; enum EThreadFuncState { @@ -512,8 +512,8 @@ void insert_plugin(plugins *p, char *file_name, { for (int i = 0; i < INCOMPATIBLE_PLUGINS_AMOUNT; i++) { - if (strstr(plugin_name, incompatiblePluginNames[i])) { - char* msg = (char*)malloc(sizeof(incompatiblePluginNames[i])); + if (strstr(plugin_name, pluginBlacklist[i])) { + char* msg = (char*)malloc(sizeof(pluginBlacklist[i])); sprintf(msg, "A incompatible plugin with the name \"%s\" was detected.\ \nIt is highly recommended to skip loading this plugin as not doing so might cause instability.\ @@ -525,6 +525,9 @@ void insert_plugin(plugins *p, char *file_name, if (res == IDNO) return; + else + ; // todo: punch user in the face + } } p->next = (plugins*)malloc(sizeof(plugins)); @@ -2743,6 +2746,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) case WM_DROPFILES: //HDROP hFile = (HDROP) wParam; char fname[MAX_PATH]; + char fname2[MAX_PATH]; LPSTR fext; DragQueryFile((HDROP)wParam, 0, fname, sizeof(fname)); fext = CharUpper(PathFindExtension(fname)); @@ -2752,9 +2756,22 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) else if (lstrcmp(fext, ".M64") == 0) { if (rom) { if (!VCR_getReadOnly()) VCR_toggleReadOnly(); - VCR_startPlayback(fname, 0, 0); - EnableMenuItem(hMenu, ID_STOP_RECORD, MF_GRAYED); - EnableMenuItem(hMenu, ID_STOP_PLAYBACK, MF_ENABLED); + + if (VCR_startPlayback(fname, 0, 0) < 0) { + sprintf(fname2, "Couldn't start playback\nof \"%s\".", fname); + MessageBox(hwnd, fname2, "VCR", MB_OK); + break; // this will introduce a bug: + } + else { + HMENU hMenu = GetMenu(mainHWND); + EnableMenuItem(hMenu, ID_STOP_RECORD, MF_GRAYED); + EnableMenuItem(hMenu, ID_STOP_PLAYBACK, MF_ENABLED); + if (!emu_paused || !emu_launched) + SetStatusTranslatedString(hStatus, 0, "Playback started..."); + else + SetStatusTranslatedString(hStatus, 0, "Playback started. (Paused)"); + } + } } else if (strcmp(fext, ".ST") ==0 || strcmp(fext, ".SAVESTATE") == 0) { @@ -2766,7 +2783,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) else if (strcmp(fext, ".LUA")==0) { if (rom) { for (; *fext; ++fext) *fext = tolower(*fext); // Deep in the code, lua will access file with that path (uppercase extension because stupid, useless programming at line 2677 converts it), see it doesnt exist and fail. - LuaOpenAndRun(fname); + // even this hack will fail under special circumstances + LuaOpenAndRun(fname); } } From 728cf6c427b245c960284925bd82ac74c06bd943 Mon Sep 17 00:00:00 2001 From: Alex <48759429+Aurumaker72@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:36:27 +0200 Subject: [PATCH 63/93] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac151f5c..1aa6d15a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [comment]: <> (Second image has to be inline so another approach is used) [**__\>\> Latest Release \<\<__**](https://github.com/mkdasher/mupen64-rr-lua-/releases/latest/)
-This repository contains the latest source code for continued development of Mupen64 - Nintendo 64 emulator with TAS support, and TASinput plugin. +This repository contains the latest source code for continued development of Mupen64 - Nintendo 64 emulator with TAS support, and TASInput plugin. This version includes new Features such as: AVISplit, Reset recording, WiiVC and Backwards Compatibility options all in one. From d4c2e18aac8a372aa6d57ead0d4b75c432e8c52d Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 10 Jul 2021 08:36:42 +0200 Subject: [PATCH 64/93] VCR fix --- main/vcr.c | 13 ++++++++++++- main/win/main_win.cpp | 4 ++-- main/win/main_win.h | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 73beeaf4..96a85593 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1314,7 +1314,8 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if (m_file == 0 && (m_file = fopen( buf, "rb" )) == 0) { fprintf( stderr, "[VCR]: Cannot start playback, could not open .m64 file '%s': %s\n", filename, strerror( errno ) ); - return -1; + RESET_TITLEBAR + return -1; } } SetActiveMovie(buf); @@ -1513,6 +1514,16 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if(m_header.startFlags & MOVIE_START_FROM_SNAPSHOT) { + // we cant wait for this function to return and then get check in emu(?) thread (savestates_load) + FILE* stBuf; + if ((stBuf = fopen(m_filename, "r"))) fclose(stBuf); + else + { + printf("[VCR]: Early Savestate exist check failed...\n"); + RESET_TITLEBAR; + return -1; + } + // load state printf( "[VCR]: Loading state...\n" ); strcpy( buf, m_filename ); diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index c3b47adf..4c5511d2 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2759,8 +2759,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) if (VCR_startPlayback(fname, 0, 0) < 0) { sprintf(fname2, "Couldn't start playback\nof \"%s\".", fname); - MessageBox(hwnd, fname2, "VCR", MB_OK); - break; // this will introduce a bug: + MessageBox(hwnd, fname2, "VCR", MB_OK|MB_ICONERROR); + break; } else { HMENU hMenu = GetMenu(mainHWND); diff --git a/main/win/main_win.h b/main/win/main_win.h index eec12792..049a29af 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -159,4 +159,6 @@ extern BOOL forceIgnoreRSP; extern BOOL continue_vcr_on_restart_mode; #define IGNORE_RSP (((!Config.limitFps || !manualFPSLimit) && (!Config.skipFrequency || (frame++ % Config.skipFrequency)))) //if frame advancing and either skipfreq is 0 or modulo is 0 +#define RESET_TITLEBAR char tmpwndtitle[200]; sprintf(tmpwndtitle, MUPEN_VERSION " - %s", ROM_HEADER->nom); SetWindowText(mainHWND, tmpwndtitle); + #endif From 7bece9f78ac888cafe81af458287020b2fa87a40 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 11 Jul 2021 17:31:57 +0200 Subject: [PATCH 65/93] Give up file handle access if VCR failed --- main/vcr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/vcr.c b/main/vcr.c index 96a85593..0ec21faf 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1315,6 +1315,8 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip { fprintf( stderr, "[VCR]: Cannot start playback, could not open .m64 file '%s': %s\n", filename, strerror( errno ) ); RESET_TITLEBAR + if (m_file != NULL) + fclose(m_file); return -1; } } @@ -1473,6 +1475,8 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if (dontPlay) { SetWindowText(mainHWND, MUPEN_VERSION); + if(m_file != NULL) + fclose(m_file); return -1; } @@ -1521,6 +1525,8 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip { printf("[VCR]: Early Savestate exist check failed...\n"); RESET_TITLEBAR; + if (m_file != NULL) + fclose(m_file); return -1; } From af91595958cb1665b5eec999a633e7f423850682 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 11 Jul 2021 18:29:19 +0200 Subject: [PATCH 66/93] Fix movies not working lmao ok --- main/vcr.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 0ec21faf..247d5217 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1519,16 +1519,16 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if(m_header.startFlags & MOVIE_START_FROM_SNAPSHOT) { // we cant wait for this function to return and then get check in emu(?) thread (savestates_load) - FILE* stBuf; - if ((stBuf = fopen(m_filename, "r"))) fclose(stBuf); - else - { - printf("[VCR]: Early Savestate exist check failed...\n"); - RESET_TITLEBAR; - if (m_file != NULL) - fclose(m_file); - return -1; - } + //FILE* stBuf; + //if ((stBuf = fopen(m_filename, "r"))) fclose(stBuf); + //else + //{ + // printf("[VCR]: Early Savestate exist check failed...\n"); + // RESET_TITLEBAR; + // if (m_file != NULL) + // fclose(m_file); + // return -1; + //} // load state printf( "[VCR]: Loading state...\n" ); From ead2863c6e1f1002614e052b54d369a2b6912f09 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 11 Jul 2021 18:31:33 +0200 Subject: [PATCH 67/93] CRACKHEX STOP IT --- main/vcr.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 247d5217..00a27c12 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1519,16 +1519,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if(m_header.startFlags & MOVIE_START_FROM_SNAPSHOT) { // we cant wait for this function to return and then get check in emu(?) thread (savestates_load) - //FILE* stBuf; - //if ((stBuf = fopen(m_filename, "r"))) fclose(stBuf); - //else - //{ - // printf("[VCR]: Early Savestate exist check failed...\n"); - // RESET_TITLEBAR; - // if (m_file != NULL) - // fclose(m_file); - // return -1; - //} + // load state printf( "[VCR]: Loading state...\n" ); @@ -1545,6 +1536,18 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip } strncat( buf, ".st", 4); + + FILE* stBuf; + if ((stBuf = fopen(buf, "r"))) fclose(stBuf); + else + { + printf("[VCR]: Early Savestate exist check failed...\n"); + RESET_TITLEBAR; + if (m_file != NULL) + fclose(m_file); + return -1; + } + savestates_select_filename( buf ); savestates_job |= LOADSTATE; m_task = StartPlaybackFromSnapshot; From 0b37004305cd99b5ad8367a8ac3c7651116f7eb3 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 11 Jul 2021 18:35:07 +0200 Subject: [PATCH 68/93] Fix titlebar disappearance --- main/vcr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main/vcr.c b/main/vcr.c index 00a27c12..1910295b 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1475,6 +1475,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if (dontPlay) { SetWindowText(mainHWND, MUPEN_VERSION); + RESET_TITLEBAR if(m_file != NULL) fclose(m_file); return -1; From 0320d82920658dc2c8c7c07e00587515e52c29df Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 12 Jul 2021 14:05:32 +0200 Subject: [PATCH 69/93] Fix titlebar disappearing again --- main/savestates.c | 6 ++++-- main/vcr.c | 29 ++++++++++++++++++----------- main/win/main_win.cpp | 6 ++++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/main/savestates.c b/main/savestates.c index 1264eb2a..6bc3f423 100755 --- a/main/savestates.c +++ b/main/savestates.c @@ -253,8 +253,10 @@ void savestates_load(bool silenceNotFoundError) { if (f == NULL) { - if (silenceNotFoundError) return; - + if (silenceNotFoundError) { + printf("Silent st fail: Savestate \"%s\" not found.\n", filename); + return; + } if (slot > 9) { //print .st not .savestate because diff --git a/main/vcr.c b/main/vcr.c index 1910295b..63f029a5 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -62,6 +62,7 @@ extern CONFIG Config; //stop AVI at m64 end, set by command line avi bool gStopAVI = false; bool captureMarkedStop; +BOOL dontPlay = false; #define BUFFER_GROWTH_SIZE (4096) @@ -943,11 +944,12 @@ VCR_getKeys( int Control, BUTTONS *Keys ) //sprintf(str, "Couldn't find or load this movie's snapshot,\n\"%s\".\nMake sure that file is where Mupen64 can find it.", savestates_get_selected_filename()); //printError(str); m_task = Idle; - extern HWND mainHWND; - char title[MAX_PATH]; - GetWindowText(mainHWND, title, MAX_PATH); - title[titleLength] = '\0'; //remove movie being played part - SetWindowText(mainHWND, title); + if (!dontPlay) { + char title[MAX_PATH]; + GetWindowText(mainHWND, title, MAX_PATH); + title[titleLength] = '\0'; //remove movie being played part + SetWindowText(mainHWND, title); + } getKeys( Control, Keys ); return; } @@ -1273,6 +1275,7 @@ void SetActiveMovie(char* buf) _splitpath(buf, 0, 0, buf, 0); sprintf(title, MUPEN_VERSION " - %s | %s.m64", ROM_HEADER->nom, buf); } + printf("title %s\n", title); SetWindowText(mainHWND, title); } @@ -1333,7 +1336,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip char warningStr [8092]; warningStr[0] = '\0'; - BOOL dontPlay = FALSE; + dontPlay = FALSE; if(!Controls[0].Present && (m_header.controllerFlags & CONTROLLER_1_PRESENT)) { @@ -1409,6 +1412,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip { sprintf(str, "The movie was recorded with the ROM \"%s\",\nbut you are using the ROM \"%s\",\nso the movie probably won't play properly.\n", m_header.romNom, ROM_HEADER->nom); strcat(warningStr, str); + dontPlay = TRUE; } else { @@ -1416,22 +1420,24 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip { sprintf(str, "The movie was recorded with a ROM with country code \"%d\",\nbut you are using a ROM with country code \"%d\",\nso the movie may not play properly.\n", m_header.romCountry, ROM_HEADER->Country_code); strcat(warningStr, str); + dontPlay = TRUE; } else if(ROM_HEADER && m_header.romCRC != ROM_HEADER->CRC1) { - sprintf(str, "The movie was recorded with a ROM that has CRC \"0x%x\",\nbut you are using a ROM with CRC \"0x%x\",\nso the movie may not play properly.\n", (unsigned int)m_header.romCRC, (unsigned int)ROM_HEADER->CRC1); + sprintf(str, "The movie was recorded with a ROM that has CRC \"0x%X\",\nbut you are using a ROM with CRC \"0x%X\",\nso the movie may not play properly.\n", (unsigned int)m_header.romCRC, (unsigned int)ROM_HEADER->CRC1); strcat(warningStr, str); + dontPlay = TRUE; } } if(strlen(warningStr) > 0) { - if(dontPlay) printError(warningStr); else printWarning(warningStr); } + extern char gfx_name[255]; extern char input_name[255]; extern char sound_name[255]; @@ -1474,7 +1480,6 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if (dontPlay) { - SetWindowText(mainHWND, MUPEN_VERSION); RESET_TITLEBAR if(m_file != NULL) fclose(m_file); @@ -1502,7 +1507,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip #ifdef _WIN32 char buf[50]; sprintf(buf, "%d rr", m_header.rerecord_count); - + extern HWND hStatus; SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)buf); #endif @@ -1578,6 +1583,7 @@ int VCR_restartPlayback() { int restartPlayback() { + VCR_setReadOnly(true); // force read only int ret = startPlayback(m_filename, "", "", true); @@ -1620,7 +1626,8 @@ stopPlayback(bool bypassLoopSetting) } #ifdef __WIN32__ extern HWND mainHWND; - SetActiveMovie(NULL); //remove from title + //SetActiveMovie(NULL); //remove from title + RESET_TITLEBAR // maybe #endif if (m_file && m_task != StartRecording && m_task != Recording) { diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 4c5511d2..4b8a6fa8 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2758,8 +2758,9 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) if (!VCR_getReadOnly()) VCR_toggleReadOnly(); if (VCR_startPlayback(fname, 0, 0) < 0) { - sprintf(fname2, "Couldn't start playback\nof \"%s\".", fname); - MessageBox(hwnd, fname2, "VCR", MB_OK|MB_ICONERROR); + //sprintf(fname2, "Couldn't start playback\nof \"%s\".", fname); + //MessageBox(hwnd, fname2, "VCR", MB_OK|MB_ICONERROR); + printf("[VCR]: Drag drop Failed to start playback of %s", fname); break; } else { @@ -2770,6 +2771,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) SetStatusTranslatedString(hStatus, 0, "Playback started..."); else SetStatusTranslatedString(hStatus, 0, "Playback started. (Paused)"); + } } From 6fee46c6c3fcae6d11f472afe000a762846b044e Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 12 Jul 2021 14:22:10 +0200 Subject: [PATCH 70/93] Title bar stability fixes --- main/vcr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main/vcr.c b/main/vcr.c index 63f029a5..1a353320 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1516,6 +1516,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip char buf[100]; sprintf(buf, "[VCR]: Error playing movie: %s.\n", m_errCodeName[code]); printError(buf); + dontPlay = code != 0; // should be stable enough break; } From d0b205677516d6dcbad292ad0956f7d37262aea8 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 12 Jul 2021 14:31:41 +0200 Subject: [PATCH 71/93] Only use debug fwrite on debug target (faster) --- main/debughook.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main/debughook.h b/main/debughook.h index fcdbb1fa..9570d716 100644 --- a/main/debughook.h +++ b/main/debughook.h @@ -4,4 +4,7 @@ size_t fwrite2(const void* ptr, size_t size, size_t count, FILE* stream); -#define fwrite(a,b,c,d) fwrite2(a,b,c,d) \ No newline at end of file +// Only use debug (much slower) fwrite on debug target +#ifdef _DEBUG +#define fwrite(a,b,c,d) fwrite2(a,b,c,d) +#endif \ No newline at end of file From 87304a619eb8d07fe860fb340fc37ce3b5cc4957 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Wed, 14 Jul 2021 21:11:21 +0200 Subject: [PATCH 72/93] option to use 0 based indexing on statusbar matches stroop and wafel and generally is superior (not biased) --- main/vcr.c | 10 ++++++++-- main/win/Config.c | 2 ++ main/win/configdialog.c | 2 ++ main/win/main_win.h | 1 + winproject/resource.h | 1 + winproject/rsrc.rc | 5 +++-- 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 73beeaf4..572730d3 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -2156,7 +2156,10 @@ void VCR_updateFrameCounter () char rr[50]; if (VCR_isRecording()) { - sprintf(str, "%d (%d) %s", (int)m_currentVI, (int)m_currentSample, inputDisplay); + if (Config.zeroIndex) + sprintf(str, "%d (%d) %s", (int)m_currentVI-2, (int)m_currentSample-1, inputDisplay); + else + sprintf(str, "%d (%d) %s", (int)m_currentVI, (int)m_currentSample, inputDisplay); if (m_header.rerecord_count == 0) sprintf(rr, "%d rr", m_header.rerecord_count); else @@ -2164,7 +2167,10 @@ void VCR_updateFrameCounter () } else if (VCR_isPlaying()) { - sprintf(str, "%d/%d (%d/%d) %s", (int)m_currentVI, (int)VCR_getLengthVIs(), (int)m_currentSample, (int)VCR_getLengthSamples(), inputDisplay); + if (Config.zeroIndex) + sprintf(str, "%d/%d (%d/%d) %s", (int)m_currentVI-2, (int)VCR_getLengthVIs()-2, (int)m_currentSample-1, (int)VCR_getLengthSamples()-1, inputDisplay); + else + sprintf(str, "%d/%d (%d/%d) %s", (int)m_currentVI, (int)VCR_getLengthVIs(), (int)m_currentSample, (int)VCR_getLengthSamples(), inputDisplay); if (m_header.rerecord_count == 0) sprintf(rr, "%d rr", m_header.rerecord_count); else diff --git a/main/win/Config.c b/main/win/Config.c index 51ad23b2..9db050a6 100755 --- a/main/win/Config.c +++ b/main/win/Config.c @@ -163,6 +163,7 @@ void LoadConfig() Config.FPSmodifier = ReadCfgInt("General", "Fps Modifier", 100); Config.skipFrequency = ReadCfgInt("General", "Skip Frequency", 8); Config.loopMovie = ReadCfgInt("General", "Loop Movie", 0); + Config.zeroIndex = ReadCfgInt("General", "Zero index", 0); Config.guiDynacore = ReadCfgInt("CPU", "Core", 1); @@ -339,6 +340,7 @@ void SaveConfig() WriteCfgInt("General", "Use Fps Modifier", Config.UseFPSmodifier); WriteCfgInt("General", "Skip Frequency", Config.skipFrequency); WriteCfgInt("General", "Loop Movie", Config.loopMovie); + WriteCfgInt("General", "Zero Index", Config.zeroIndex); //Advanced Vars WriteCfgInt("Advanced", "Start Full Screen", Config.StartFullScreen); diff --git a/main/win/configdialog.c b/main/win/configdialog.c index 2d109102..e2f62a36 100755 --- a/main/win/configdialog.c +++ b/main/win/configdialog.c @@ -685,6 +685,7 @@ BOOL CALLBACK GeneralCfg(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) WriteCheckBoxValue( hwnd, IDC_LIMITFPS, Config.limitFps); WriteCheckBoxValue( hwnd, IDC_INI_COMPRESSED, Config.compressedIni); WriteCheckBoxValue( hwnd, IDC_SPEEDMODIFIER, Config.UseFPSmodifier ); + WriteCheckBoxValue(hwnd, IDC_0INDEX, Config.zeroIndex); SetDlgItemInt(hwnd, IDC_SKIPFREQ, Config.skipFrequency,0); CreateToolTip(IDC_SKIPFREQ, hwnd, "0 = Skip all frames, 1 = Show all frames, n = show every nth frame"); @@ -758,6 +759,7 @@ BOOL CALLBACK GeneralCfg(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) Config.FPSmodifier = SendMessage( hwndTrack , TBM_GETPOS, 0, 0); Config.UseFPSmodifier = ReadCheckBoxValue( hwnd , IDC_SPEEDMODIFIER ); Config.skipFrequency = GetDlgItemInt(hwnd, IDC_SKIPFREQ,0,0); + Config.zeroIndex = ReadCheckBoxValue(hwnd, IDC_0INDEX); if (emu_launched) SetStatusMode( 2 ); else SetStatusMode( 0 ); InitTimer(); diff --git a/main/win/main_win.h b/main/win/main_win.h index eec12792..7994ac18 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -94,6 +94,7 @@ typedef struct _CONFIG { int FPSmodifier; int skipFrequency; BOOL loopMovie; + BOOL zeroIndex; // Advanced vars BOOL StartFullScreen; diff --git a/winproject/resource.h b/winproject/resource.h index 1462aa9f..854d0931 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -148,6 +148,7 @@ #define IDC_DECREASE_MODIFIER 2263 #define IDC_RESET_MODIFIER 2264 #define IDC_SKIPFREQ 2265 +#define IDC_0INDEX 2266 #define STATE_SAVE 3000 diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index ebd8755c..861912ae 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -393,7 +393,7 @@ BEGIN CONTROL "Alert for hacked ROM",IDC_ALERTHACKEDROM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,34,150,10 CONTROL "Alert for save errors",IDC_ALERTSAVESERRORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,49,150,10 GROUPBOX "FPS / VIs",IDC_FPSTITLE,7,71,215,94 - CONTROL "Limit VIs (auto)",IDC_LIMITFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,86,150,10 + CONTROL "Limit VIs (auto)",IDC_LIMITFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,86,69,10 CONTROL "Use Speed Modifier",IDC_SPEEDMODIFIER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,100,150,10 CONTROL "Show FPS",IDC_SHOWFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,134,87,10 CONTROL "Show VIs",IDC_SHOWVIS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,149,79,10 @@ -405,6 +405,7 @@ BEGIN GROUPBOX "Ini file",IDC_INIFILE,7,230,215,26 EDITTEXT IDC_SKIPFREQ,162,138,45,12,ES_AUTOHSCROLL LTEXT "Fast forward skip frequency:",IDC_STATIC,108,133,49,19 + CONTROL "0-index statusbar",IDC_0INDEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,86,69,10 END IDD_MOVIE_PLAYBACK_DIALOG DIALOGEX 0, 0, 342, 330 @@ -528,7 +529,7 @@ BEGIN EDITTEXT IDC_MOVIE_CONTROLLER3_TEXT2,217,176,91,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER EDITTEXT IDC_MOVIE_CONTROLLER4_TEXT2,217,187,91,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER GROUPBOX "Start From",IDC_STARTFROM2,177,88,139,50 - CONTROL ".savestate", IDC_EXTSAVESTATE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 254, 112, 45, 10 + CONTROL ".savestate",IDC_EXTSAVESTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,112,45,10 CONTROL "Savestate",IDC_FROMSNAPSHOT_RADIO,"Button",BS_AUTORADIOBUTTON,190,112,64,10 CONTROL "Start",IDC_FROMSTART_RADIO,"Button",BS_AUTORADIOBUTTON,190,100,50,10 CONTROL "EEPROM",IDC_FROMEEPROM_RADIO,"Button",BS_AUTORADIOBUTTON,190,125,64,10 From d6bba04890568a8eb219d258486fc257c065c0c3 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 19 Jul 2021 14:52:09 +0200 Subject: [PATCH 73/93] Probably fix rom browser getting stuck --- main/win/main_win.cpp | 2 +- main/win/rombrowser.c | 3 +++ main/win/rombrowser.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 4b8a6fa8..fbfc67e0 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -1289,7 +1289,7 @@ void pauseEmu(BOOL quiet) BOOL StartRom(char *fullRomPath) { - if (romBrowserRefreshThread) { + if (romBrowserBusy) { display_status("Rom browser busy!"); return TRUE; } diff --git a/main/win/rombrowser.c b/main/win/rombrowser.c index b8115b50..287a37cd 100755 --- a/main/win/rombrowser.c +++ b/main/win/rombrowser.c @@ -53,6 +53,7 @@ int RomBrowserFieldsWidth[ROM_COLUMN_FIELDS] = {250,150,70,70,200,100,100}; int RealColumn[ROM_COLUMN_FIELDS] = {0,2,3,4,-1,-1,-1}; static DWORD Id; HANDLE romBrowserRefreshThread = NULL; +int romBrowserBusy = 0; char *getFieldName(int col) { @@ -989,6 +990,7 @@ void FastRefreshBrowser() ListViewSort(); } DWORD WINAPI RefreshRomBrowserInternal(LPVOID tParam) { + romBrowserBusy = TRUE; remove(get_cachepath()); SaveRomBrowserDirs(); TOTAL_ROMS_NUMBER = 0; @@ -996,6 +998,7 @@ DWORD WINAPI RefreshRomBrowserInternal(LPVOID tParam) { ListView_DeleteAllItems(hRomList); freeRomList(); LoadRomList(); + romBrowserBusy = FALSE; ExitThread(0); return 0; } diff --git a/main/win/rombrowser.h b/main/win/rombrowser.h index 51e312e0..6fc5b916 100755 --- a/main/win/rombrowser.h +++ b/main/win/rombrowser.h @@ -106,6 +106,7 @@ ROM_INFO *getSelectedRom(); extern HWND romInfoHWND ; extern ITEM_LIST ItemList; extern HANDLE romBrowserRefreshThread; +extern int romBrowserBusy; #define ROM_COLUMN_FIELDS 7 #define MAX_RECENT_ROMS 10 From 95bbfa08f8f0f404c322aa3701d36ea59a6cf57c Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 7 Aug 2021 13:51:06 +0200 Subject: [PATCH 74/93] Improve emulation problem dialog --- main/win/main_win.cpp | 1 + main/win/main_win.h | 1 + main/win/timers.c | 19 ++++++++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index fbfc67e0..bedabb91 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -218,6 +218,7 @@ int recording; HWND hTool, mainHWND, hStatus, hRomList, hStatusProgress; HINSTANCE app_hInstance; BOOL manualFPSLimit = TRUE; +BOOL ignoreErrorEmulation = FALSE; char statusmsg[800]; char gfx_name[255]; diff --git a/main/win/main_win.h b/main/win/main_win.h index 5634f1e7..78eb9d81 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -158,6 +158,7 @@ extern "C" CONFIG Config; extern BOOL forceIgnoreRSP; extern BOOL continue_vcr_on_restart_mode; +extern BOOL ignoreErrorEmulation; #define IGNORE_RSP (((!Config.limitFps || !manualFPSLimit) && (!Config.skipFrequency || (frame++ % Config.skipFrequency)))) //if frame advancing and either skipfreq is 0 or modulo is 0 #define RESET_TITLEBAR char tmpwndtitle[200]; sprintf(tmpwndtitle, MUPEN_VERSION " - %s", ROM_HEADER->nom); SetWindowText(mainHWND, tmpwndtitle); diff --git a/main/win/timers.c b/main/win/timers.c index fc16cc6f..40707453 100755 --- a/main/win/timers.c +++ b/main/win/timers.c @@ -107,9 +107,22 @@ void new_vi() { // fps wont update when emu is stuck so we must check vi/s // vi/s shouldn't go over 300 in normal gameplay while holding down fast forward unless you have repeat speed at uzi speed - if (emu_launched && frame_advancing && VIs > 300 && MessageBox(NULL, "Emulation problem detected, close rom?", "Warning", MB_ICONWARNING | MB_YESNO | MB_TOPMOST | MB_TASKMODAL) == IDYES) { - frame_advancing = false; //don't pause at next open - CreateThread(NULL, 0, closeRom, (LPVOID)1, 0, 0); + if (!ignoreErrorEmulation && emu_launched && frame_advancing || emu_paused /*uh is this good?*/ && VIs > 300) { + int res = MessageBox(NULL, "Emulation problem detected\nPress Abort to close the rom\nPress Retry to continue emulation\nPress ignore to not show this again", "Error", MB_ICONERROR | MB_ABORTRETRYIGNORE | MB_TOPMOST | MB_TASKMODAL); + switch (res) + { + case IDABORT: + frame_advancing = false; //don't pause at next open + CreateThread(NULL, 0, closeRom, (LPVOID)1, 0, 0); + break; + case IDIGNORE: + ignoreErrorEmulation = TRUE; + break; + default: + // dame tu cosita uh ay + break; + } + } //#endif From 5d808044f26345611809171fb842f79a7c7b3312 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 7 Aug 2021 19:29:24 +0200 Subject: [PATCH 75/93] Fix mupen not showing .savestate file when loading --- main/win/main_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index bedabb91..01e36768 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -3293,7 +3293,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) strcpy(path_buffer,""); oifn.lpstrFile = path_buffer, oifn.nMaxFile = sizeof(path_buffer); - oifn.lpstrFilter = "Mupen 64 Saves(*.st)\0*.st;*.st?\0All Files\0*.*\0"; + oifn.lpstrFilter = "Mupen 64 Saves(*.st;*.savestate)\0*.st;*.st?;*.savestate\0All Files\0*.*\0"; oifn.lpstrFileTitle = ""; oifn.nMaxFileTitle = 0; oifn.lpstrInitialDir = ""; From de8f3031fc797a03acb30f62937a3939f304c999 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Mon, 9 Aug 2021 19:04:38 +0200 Subject: [PATCH 76/93] Add tasinput error info when it detects unknown problems this will at least not crash everything --- main/vcr.c | 2 +- r4300/r4300.c | 3 +++ tasinput_plugin/src/DI.cpp | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/main/vcr.c b/main/vcr.c index 154e449a..c11f7a6f 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1884,7 +1884,7 @@ void VCR_aiLenChanged() short *p = (short *)((char*)rdram + (ai_register.ai_dram_addr & 0xFFFFFF)); char* buf = (char*)p; int aiLen = ai_register.ai_len; - + //printf("ailenchanged %p %d\n", p, aiLen); aiLenChanged(); if (m_capture == 0) return; diff --git a/r4300/r4300.c b/r4300/r4300.c index 435d5df6..435ae617 100755 --- a/r4300/r4300.c +++ b/r4300/r4300.c @@ -1409,6 +1409,9 @@ static inline unsigned long update_invalid_addr(unsigned long addr) unsigned long jump_to_address; inline void jump_to_func() { +//#ifdef _DEBUG +// printf("dyna jump: %p\n", addr); +//#endif unsigned long paddr; if (skip_jump) return; paddr = update_invalid_addr(addr); diff --git a/tasinput_plugin/src/DI.cpp b/tasinput_plugin/src/DI.cpp index 00e50f8c..7a161039 100755 --- a/tasinput_plugin/src/DI.cpp +++ b/tasinput_plugin/src/DI.cpp @@ -98,6 +98,11 @@ BOOL CALLBACK DIEnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { bOK = FALSE; } } + if (DInputDev[nCurrentDevices].lpDIDevice == NULL) + { + MessageBox(0, "Fatal device error, please report issue on github", "error", MB_ICONERROR); + return DIENUM_CONTINUE; + } if (bOK == TRUE) { DInputDev[nCurrentDevices].lpDIDevice->Acquire(); From 5614cbc6fadbe9601ce89fb2bb1f6bf79b211f5b Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Mon, 9 Aug 2021 19:15:47 +0200 Subject: [PATCH 77/93] Fix emulation problem dialog showing when it shouldnt? --- lua/LuaConsole.cpp | 2 +- main/win/timers.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index 74b3d090..e8bd9320 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -663,7 +663,7 @@ std::string OpenLuaFileDialog() { int storePaused = emu_paused; pauseEmu(1); - + OPENFILENAME ofn; char filename[MAX_PATH] = ""; diff --git a/main/win/timers.c b/main/win/timers.c index 40707453..50ad5948 100755 --- a/main/win/timers.c +++ b/main/win/timers.c @@ -107,7 +107,7 @@ void new_vi() { // fps wont update when emu is stuck so we must check vi/s // vi/s shouldn't go over 300 in normal gameplay while holding down fast forward unless you have repeat speed at uzi speed - if (!ignoreErrorEmulation && emu_launched && frame_advancing || emu_paused /*uh is this good?*/ && VIs > 300) { + if (!ignoreErrorEmulation && emu_launched && frame_advancing && VIs > 300) { int res = MessageBox(NULL, "Emulation problem detected\nPress Abort to close the rom\nPress Retry to continue emulation\nPress ignore to not show this again", "Error", MB_ICONERROR | MB_ABORTRETRYIGNORE | MB_TOPMOST | MB_TASKMODAL); switch (res) { From 7d0515d65af40371ecd9eeea239cd312dc4fee79 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Tue, 10 Aug 2021 00:01:55 +0200 Subject: [PATCH 78/93] Recent lua scripts list some things might be changed depending on feedback --- lua/LuaConsole.cpp | 11 ++- lua/Recent.cpp | 99 +++++++++++++++++++ lua/Recent.h | 11 +++ main/win/Config.c | 31 +++++- main/win/main_win.cpp | 11 ++- main/win/main_win.h | 8 +- main/win/rombrowser.c | 22 +++-- winproject/mupen64/mupen64_2017.vcxproj | 2 + .../mupen64/mupen64_2017.vcxproj.filters | 14 +++ winproject/resource.h | 3 + winproject/rsrc.rc | 9 +- 11 files changed, 200 insertions(+), 21 deletions(-) create mode 100644 lua/Recent.cpp create mode 100644 lua/Recent.h diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index e8bd9320..4736cf32 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -153,7 +153,6 @@ struct EmulationLock{ } }; -void runLUA(HWND wnd, char path[]); // bad solution void ConsoleWrite(HWND, const char*); void SetWindowLua(HWND wnd, Lua *lua); void SetButtonState(HWND wnd, bool state); @@ -208,8 +207,12 @@ class Lua { hMutex = CreateMutex(0, 0, 0); newLuaState(); runFile(path); - if(isrunning()) + if (isrunning()) + { SetButtonState(ownWnd, true); + AddToRecentScripts(path); + strcpy(Config.LuaScriptPath, path); + } ShowInfo("Lua run"); } void stop() { @@ -338,7 +341,6 @@ class Lua { void runFile(char *path) { //int GetErrorMessage(lua_State *L); int result; - SetButtonState(ownWnd, true); //lua_pushcfunction(L, GetErrorMessage); result = luaL_dofile(L, path); if(result) { @@ -642,8 +644,6 @@ INT_PTR CALLBACK DialogProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { DestroyWindow(wnd); return TRUE; case WM_DESTROY:{ - GetWindowText(GetDlgItem(wnd, IDC_TEXTBOX_LUASCRIPTPATH), - Config.LuaScriptPath, MAX_PATH); LuaMessage::Msg *msg = new LuaMessage::Msg(); msg->type = LuaMessage::DestroyLua; msg->destroyLua.wnd = wnd; @@ -720,6 +720,7 @@ BOOL WmCommand(HWND wnd, WORD id, WORD code, HWND control){ //strcpy(Config.LuaScriptPath, msg->runPath.path); anyLuaRunning = true; luaMessage.post(msg); + shouldSave = true; return TRUE; } case IDC_BUTTON_LUASTOP: { diff --git a/lua/Recent.cpp b/lua/Recent.cpp new file mode 100644 index 00000000..2fc8967b --- /dev/null +++ b/lua/Recent.cpp @@ -0,0 +1,99 @@ +//Based on recent roms but better +#include "Recent.h" +#include "LuaConsole.h" + +#ifdef _WIN32 +#include +#include "win/main_win.h" +#include "../winproject/resource.h" //for menu id +#endif + +//takes config and puts the entries to menu +void BuildRecentScriptsMenu(HWND hwnd) { + int i; + bool empty = false; + MENUITEMINFO menuinfo; + HMENU hMenu = GetMenu(hwnd); + HMENU hSubMenu = GetSubMenu(hMenu, 5); + hSubMenu = GetSubMenu(hSubMenu, 1); + DeleteMenu(hSubMenu, ID_LUA_RECENT, MF_BYCOMMAND); //remove the "no recent scripts" entry, add later if in fact no recent + + menuinfo.cbSize = sizeof(MENUITEMINFO); + menuinfo.fMask = MIIM_TYPE | MIIM_ID; + menuinfo.fType = MFT_STRING; + menuinfo.fState = MFS_ENABLED; + for (i = 0; i < LUA_MAX_RECENT; i++) { + if (strcmp(Config.RecentScripts[i], "") == 0) + { + if (i == 0) + { + menuinfo.dwTypeData = "No recent scripts"; + //menuinfo.fState = MFS_DISABLED; //doesnt work :) + empty = true; + } + else break; + } + else + menuinfo.dwTypeData = Config.RecentScripts[i]; + menuinfo.cch = strlen(menuinfo.dwTypeData); + menuinfo.wID = ID_LUA_RECENT + i; + InsertMenuItem(hSubMenu, i, TRUE, &menuinfo); + if (empty) EnableMenuItem(hSubMenu, ID_LUA_RECENT, MF_DISABLED); + } +} + +void ClearRecent(HWND hwnd, BOOL clear_array) { + int i; + HMENU hMenu; + + hMenu = GetMenu(mainHWND); + for (i = 0; i < LUA_MAX_RECENT; i++) { + DeleteMenu(hMenu, ID_LUA_RECENT + i, MF_BYCOMMAND); + } + if (clear_array) { + memset(Config.RecentScripts, 0, LUA_MAX_RECENT * sizeof(Config.RecentScripts[0])); + } + +} + +void RefreshRecent() +{ + //nuke the menu + ClearRecent(mainHWND,FALSE); + //rebuild + BuildRecentScriptsMenu(mainHWND); + + +} + + +//Adds path to recent paths, if already in list then just moves things around +//newer scripts are earlier in array +void AddToRecentScripts(char* path) +{ + int i = 0; + //Either finds index of path in recent list, or stops at last one + //notice how it doesn't matter if last==path or not, we do same swapping later + for (; i0; --j) + { + strcpy(Config.RecentScripts[j], Config.RecentScripts[j-1]); + } + //now write to top + strcpy(Config.RecentScripts[0], path); + //rebuild menu + RefreshRecent(); +} + +void RunRecentScript(WORD menuItem) +{ + char path[MAX_PATH]; + int index = menuItem - ID_LUA_RECENT; + sprintf(path, Config.RecentScripts[index]); + LuaOpenAndRun(path); +} \ No newline at end of file diff --git a/lua/Recent.h b/lua/Recent.h new file mode 100644 index 00000000..3e2e2dcf --- /dev/null +++ b/lua/Recent.h @@ -0,0 +1,11 @@ +#pragma once +#ifdef _WIN32 +#include //linux trolled +#endif +#define LUA_MAX_RECENT 5 + +//functions +void AddToRecentScripts(char* path); +void BuildRecentScriptsMenu(HWND); +void RunRecentScript(WORD); +void ClearRecent(HWND, BOOL); diff --git a/main/win/Config.c b/main/win/Config.c index 9db050a6..f332a97f 100755 --- a/main/win/Config.c +++ b/main/win/Config.c @@ -29,6 +29,8 @@ #include "commandline.h" #include "../../winproject/resource.h" +#include "../lua/Recent.h" + #define CfgFileName "mupen64.cfg" extern int no_audio_delay; @@ -87,7 +89,7 @@ int ReadCfgInt(char* Section, char* Key, int DefaultValue) void LoadRecentRoms() { int i; - char tempStr[50]; + char tempStr[32]; Config.RecentRomsFreeze = ReadCfgInt("Recent Roms", "Freeze", 0); for (i = 0; i < MAX_RECENT_ROMS; i++) @@ -102,6 +104,20 @@ void LoadRecentRoms() } +//Loads recent scripts from .cfg +void LoadRecentScripts() +{ + char tempStr[32]; + + for (unsigned i = 0; i < LUA_MAX_RECENT; i++) + { + + sprintf(tempStr, "RecentLua%d", i); + ReadCfgString("Recent Scripts", tempStr, "", Config.RecentScripts[i]); + } + +} + void ReadHotkeyConfig(int n, char* name, int cmd, int def) { HOTKEY* h; char t[128]; @@ -133,6 +149,7 @@ void WriteHotkeyConfig(int n, char* name) { void LoadConfig() { LoadRecentRoms(); + LoadRecentScripts(); // Language ReadCfgString("Language", "Default", "English", Config.DefaultLanguage); @@ -316,6 +333,17 @@ void SaveRecentRoms() } } +void SaveRecentScripts() +{ + char tempStr[32]; + + for (unsigned i = 0; i < LUA_MAX_RECENT; i++) + { + sprintf(tempStr, "RecentLua%d", i); + WriteCfgString("Recent Scripts", tempStr, Config.RecentScripts[i]); + } +} + void SaveConfig() { saveWindowSettings(); @@ -323,6 +351,7 @@ void SaveConfig() if (!cmdlineNoGui) { saveBrowserSettings(); SaveRecentRoms(); + SaveRecentScripts(); } //Language diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 01e36768..059853e8 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -17,6 +17,7 @@ #include "LuaConsole.h" +#include "Recent.h" #include "win/DebugInfo.hpp" #if defined(__cplusplus) && !defined(_MSC_VER) @@ -2747,7 +2748,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) case WM_DROPFILES: //HDROP hFile = (HDROP) wParam; char fname[MAX_PATH]; - char fname2[MAX_PATH]; LPSTR fext; DragQueryFile((HDROP)wParam, 0, fname, sizeof(fname)); fext = CharUpper(PathFindExtension(fname)); @@ -2873,6 +2873,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) TranslateMenu(GetMenu( hwnd), hwnd); CreateRomListControl( hwnd); SetRecentList( hwnd); + BuildRecentScriptsMenu(hwnd); EnableToolbar(); EnableStatusbar(); //////////////////////////// @@ -2966,6 +2967,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) ::NewLuaScript((void(*)())lParam); #endif } break; + case ID_LUA_CLEAR_RECENT: { + ClearRecent(hwnd, TRUE); + BuildRecentScriptsMenu(hwnd); + break; + } case ID_MENU_LUASCRIPT_CLOSEALL: { #ifdef LUA_CONSOLE @@ -3494,6 +3500,9 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) } else if (LOWORD(wParam) >= ID_RECENTROMS_FIRST && LOWORD(wParam) < (ID_RECENTROMS_FIRST + MAX_RECENT_ROMS)) { RunRecentRom(LOWORD(wParam)); + } + else if (LOWORD(wParam) >= ID_LUA_RECENT && LOWORD(wParam) < (ID_LUA_RECENT + LUA_MAX_RECENT)) { + RunRecentScript(LOWORD(wParam)); } break; } diff --git a/main/win/main_win.h b/main/win/main_win.h index 78eb9d81..bd1519c6 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -14,6 +14,9 @@ * * ***************************************************************************/ + //for max recent +#include "../lua/Recent.h" + #ifndef MAIN_WIN_H #define MAIN_WIN_H @@ -150,8 +153,9 @@ typedef struct _CONFIG { bool captureOtherWindows; HOTKEY hotkey [NUM_HOTKEYS]; - //Lua - char LuaScriptPath[MAX_PATH]; + //Lua + char LuaScriptPath[MAX_PATH]; + char RecentScripts[LUA_MAX_RECENT][MAX_PATH]; } CONFIG; extern "C" CONFIG Config; diff --git a/main/win/rombrowser.c b/main/win/rombrowser.c index 287a37cd..9c6e0f05 100755 --- a/main/win/rombrowser.c +++ b/main/win/rombrowser.c @@ -1156,6 +1156,9 @@ void ClearRecentList (HWND hwnd,BOOL clear_array) { HMENU hMenu; hMenu = GetMenu(hwnd); + //apparently not needed because windows still is able to find the correct items + //hMenu = GetSubMenu(hMenu, 0); + //hMenu = GetSubMenu(hMenu, 5); for (i = 0; i < MAX_RECENT_ROMS; i ++ ) { DeleteMenu(hMenu, ID_RECENTROMS_FIRST + i, MF_BYCOMMAND); } @@ -1167,22 +1170,21 @@ void ClearRecentList (HWND hwnd,BOOL clear_array) { void SetRecentList(HWND hwnd) { int i; - HMENU hMenu, hSubMenu ; MENUITEMINFO menuinfo; FreezeRecentRoms( hwnd, FALSE ) ; + HMENU hMenu = GetMenu(hwnd); + HMENU hSubMenu = GetSubMenu(hMenu, 0); + hSubMenu = GetSubMenu(hSubMenu, 5); + + menuinfo.cbSize = sizeof(MENUITEMINFO); + menuinfo.fMask = MIIM_TYPE | MIIM_ID; + menuinfo.fType = MFT_STRING; + menuinfo.fState = MFS_ENABLED; for ( i = 0 ; i < MAX_RECENT_ROMS ; i++) { if ( strcmp( Config.RecentRoms[i], "")==0 ) continue; - hMenu = GetMenu(hwnd) ; - hSubMenu = GetSubMenu(hMenu,0); - hSubMenu = GetSubMenu(hSubMenu,5); - - menuinfo.cbSize = sizeof(MENUITEMINFO); - menuinfo.fMask = MIIM_TYPE|MIIM_ID; - menuinfo.fType = MFT_STRING; - menuinfo.fState = MFS_ENABLED; menuinfo.dwTypeData = ParseName( Config.RecentRoms[i]); - menuinfo.cch = sizeof( hSubMenu); + menuinfo.cch = strlen(menuinfo.dwTypeData); menuinfo.wID = ID_RECENTROMS_FIRST + i; InsertMenuItem( hSubMenu, 3 + i, TRUE, &menuinfo); diff --git a/winproject/mupen64/mupen64_2017.vcxproj b/winproject/mupen64/mupen64_2017.vcxproj index 291d73b9..fb60f392 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj +++ b/winproject/mupen64/mupen64_2017.vcxproj @@ -189,6 +189,7 @@ + @@ -319,6 +320,7 @@ + CompileAsCpp Default diff --git a/winproject/mupen64/mupen64_2017.vcxproj.filters b/winproject/mupen64/mupen64_2017.vcxproj.filters index 040d96ad..f336f823 100644 --- a/winproject/mupen64/mupen64_2017.vcxproj.filters +++ b/winproject/mupen64/mupen64_2017.vcxproj.filters @@ -209,6 +209,11 @@ Source Files\main + + + + Source Files\lua + @@ -454,6 +459,15 @@ Source Files\main + + Source Files + + + Source Files + + + Source Files\lua + diff --git a/winproject/resource.h b/winproject/resource.h index 854d0931..26ddf7e7 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -246,6 +246,9 @@ #define ID_MENU_LUASCRIPT_NEW 6020 #define ID_MENU_LUASCRIPT_CLOSEALL 6021 #define ID_TRACELOG 6022 +#define ID_LUA_CLEAR_RECENT 6023 +#define ID_LUA_RECENT 6024 +//6024+5 reserved for recent, unless changed to more #define IDC_HOTKEYS_FLOWGROUP 6101 #define IDC_HOT_SCREENSHOT 6103 diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 861912ae..116d6256 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -136,6 +136,11 @@ BEGIN POPUP "Lua Script" BEGIN MENUITEM "New Instance", ID_MENU_LUASCRIPT_NEW + POPUP "Recent scripts" + BEGIN + MENUITEM "No recent scripts" ID_LUA_RECENT, GRAYED + END + MENUITEM "Clear recent" ID_LUA_CLEAR_RECENT MENUITEM "Close All", ID_MENU_LUASCRIPT_CLOSEALL END END @@ -167,7 +172,7 @@ BEGIN PUSHBUTTON "Website",IDC_WEBSITE,134,197,60,14 GROUPBOX "About this program",IDC_STATIC,5,65,189,127 LTEXT "Author:\r\n Hacktarux (hacktarux@yahoo.fr)\r\n\nWindows port:\r\n ShadowPrince (shadow@emulation64.com)\r\n linker (linker@mail.bg)\r\n\r\nContributors:\r\n Codex, Falcon4ever, Pir4nhaX, Malcolm,\r\n Olivieryuyu\r\n\r\nThanks to the many others who helped",IDC_STATIC,13,82,173,104 - LTEXT MUPEN_VERSION,IDC_STATIC,0,0,200,100 + LTEXT "Mupen 64 1.0.9",IDC_STATIC,0,0,200,100 END IDD_ADVANCED_OPTIONS DIALOGEX 0, 0, 231, 273 @@ -758,7 +763,7 @@ END #endif // APSTUDIO_INVOKED -#endif // Neutral (Default) resources +#endif // Neutralny (Domylny) resources ///////////////////////////////////////////////////////////////////////////// From 5e78776f0b9c1b77b573ef84f84c01d03b6498b8 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Tue, 10 Aug 2021 00:15:03 +0200 Subject: [PATCH 79/93] can u dont --- winproject/rsrc.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 116d6256..98fbd514 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -172,7 +172,7 @@ BEGIN PUSHBUTTON "Website",IDC_WEBSITE,134,197,60,14 GROUPBOX "About this program",IDC_STATIC,5,65,189,127 LTEXT "Author:\r\n Hacktarux (hacktarux@yahoo.fr)\r\n\nWindows port:\r\n ShadowPrince (shadow@emulation64.com)\r\n linker (linker@mail.bg)\r\n\r\nContributors:\r\n Codex, Falcon4ever, Pir4nhaX, Malcolm,\r\n Olivieryuyu\r\n\r\nThanks to the many others who helped",IDC_STATIC,13,82,173,104 - LTEXT "Mupen 64 1.0.9",IDC_STATIC,0,0,200,100 + LTEXT MUPEN_VERSION,IDC_STATIC,0,0,200,100 END IDD_ADVANCED_OPTIONS DIALOGEX 0, 0, 231, 273 From 376585941bc209471bd1ca4b031d5e89aad4a835 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Tue, 10 Aug 2021 09:32:00 +0200 Subject: [PATCH 80/93] LUA Recent Freeze, Reset, Bugfixes --- lua/Recent.cpp | 23 ++++++++++++++--------- lua/Recent.h | 3 ++- main/win/Config.c | 4 ++-- main/win/main_win.cpp | 12 ++++++++++-- main/win/main_win.h | 1 + winproject/resource.h | 2 ++ winproject/rsrc.rc | 6 ++++-- 7 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lua/Recent.cpp b/lua/Recent.cpp index 2fc8967b..15311a71 100644 --- a/lua/Recent.cpp +++ b/lua/Recent.cpp @@ -8,16 +8,18 @@ #include "../winproject/resource.h" //for menu id #endif +BOOL freezeRecentScript; + //takes config and puts the entries to menu void BuildRecentScriptsMenu(HWND hwnd) { int i; bool empty = false; - MENUITEMINFO menuinfo; + MENUITEMINFO menuinfo = { 0 }; HMENU hMenu = GetMenu(hwnd); HMENU hSubMenu = GetSubMenu(hMenu, 5); hSubMenu = GetSubMenu(hSubMenu, 1); - DeleteMenu(hSubMenu, ID_LUA_RECENT, MF_BYCOMMAND); //remove the "no recent scripts" entry, add later if in fact no recent - + //DeleteMenu(hSubMenu, ID_LUA_RECENT, MF_BYCOMMAND); //remove the "no recent scripts" entry, add later if in fact no recent + menuinfo.cbSize = sizeof(MENUITEMINFO); menuinfo.fMask = MIIM_TYPE | MIIM_ID; menuinfo.fType = MFT_STRING; @@ -28,21 +30,22 @@ void BuildRecentScriptsMenu(HWND hwnd) { if (i == 0) { menuinfo.dwTypeData = "No recent scripts"; - //menuinfo.fState = MFS_DISABLED; //doesnt work :) empty = true; } else break; } else menuinfo.dwTypeData = Config.RecentScripts[i]; + + menuinfo.cch = strlen(menuinfo.dwTypeData); - menuinfo.wID = ID_LUA_RECENT + i; - InsertMenuItem(hSubMenu, i, TRUE, &menuinfo); - if (empty) EnableMenuItem(hSubMenu, ID_LUA_RECENT, MF_DISABLED); + menuinfo.wID = ID_LUA_RECENT + i+3; + InsertMenuItem(hSubMenu, i+3, TRUE, &menuinfo); + if (empty) EnableMenuItem(hSubMenu, ID_LUA_RECENT, MF_DISABLED); } } -void ClearRecent(HWND hwnd, BOOL clear_array) { +void ClearRecent(BOOL clear_array) { int i; HMENU hMenu; @@ -59,7 +62,7 @@ void ClearRecent(HWND hwnd, BOOL clear_array) { void RefreshRecent() { //nuke the menu - ClearRecent(mainHWND,FALSE); + ClearRecent(FALSE); //rebuild BuildRecentScriptsMenu(mainHWND); @@ -71,6 +74,8 @@ void RefreshRecent() //newer scripts are earlier in array void AddToRecentScripts(char* path) { + if (Config.RecentScriptsFreeze) return; // fuck off? + int i = 0; //Either finds index of path in recent list, or stops at last one //notice how it doesn't matter if last==path or not, we do same swapping later diff --git a/lua/Recent.h b/lua/Recent.h index 3e2e2dcf..127b07fc 100644 --- a/lua/Recent.h +++ b/lua/Recent.h @@ -1,6 +1,7 @@ #pragma once #ifdef _WIN32 #include //linux trolled + // lol #endif #define LUA_MAX_RECENT 5 @@ -8,4 +9,4 @@ void AddToRecentScripts(char* path); void BuildRecentScriptsMenu(HWND); void RunRecentScript(WORD); -void ClearRecent(HWND, BOOL); +void ClearRecent(BOOL); diff --git a/main/win/Config.c b/main/win/Config.c index f332a97f..8981f788 100755 --- a/main/win/Config.c +++ b/main/win/Config.c @@ -108,7 +108,7 @@ void LoadRecentRoms() void LoadRecentScripts() { char tempStr[32]; - + Config.RecentScriptsFreeze = ReadCfgInt("Recent Scripts", "Freeze", 0); for (unsigned i = 0; i < LUA_MAX_RECENT; i++) { @@ -336,7 +336,7 @@ void SaveRecentRoms() void SaveRecentScripts() { char tempStr[32]; - + WriteCfgInt("Recent Scripts", "Freeze", Config.RecentScriptsFreeze); for (unsigned i = 0; i < LUA_MAX_RECENT; i++) { sprintf(tempStr, "RecentLua%d", i); diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index 059853e8..ea6a81e9 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -2967,8 +2967,15 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) ::NewLuaScript((void(*)())lParam); #endif } break; - case ID_LUA_CLEAR_RECENT: { - ClearRecent(hwnd, TRUE); + case ID_LUA_RECENT_FREEZE: { + HMENU hMenu; + hMenu = GetMenu(mainHWND); + CheckMenuItem(hMenu, ID_LUA_RECENT_FREEZE, (Config.RecentScriptsFreeze ^= 1) ? MF_CHECKED : MF_UNCHECKED); + shouldSave = TRUE; + break; + } + case ID_LUA_RECENT_RESET: { + ClearRecent(TRUE); BuildRecentScriptsMenu(hwnd); break; } @@ -3502,6 +3509,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) RunRecentRom(LOWORD(wParam)); } else if (LOWORD(wParam) >= ID_LUA_RECENT && LOWORD(wParam) < (ID_LUA_RECENT + LUA_MAX_RECENT)) { + printf("run recent script\n"); RunRecentScript(LOWORD(wParam)); } break; diff --git a/main/win/main_win.h b/main/win/main_win.h index bd1519c6..ae301166 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -156,6 +156,7 @@ typedef struct _CONFIG { //Lua char LuaScriptPath[MAX_PATH]; char RecentScripts[LUA_MAX_RECENT][MAX_PATH]; + BOOL RecentScriptsFreeze; } CONFIG; extern "C" CONFIG Config; diff --git a/winproject/resource.h b/winproject/resource.h index 26ddf7e7..26eee87d 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -421,6 +421,8 @@ #define IDC_CLUADOUBLEBUFFER 40010 #define IDC_GITREPO 40011 #define IDC_EXTSAVESTATE 40012 +#define ID_LUA_RECENT_RESET 40013 +#define ID_LUA_RECENT_FREEZE 40014 #define IDC_STATIC -1 // Next default values for new objects diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 98fbd514..7ea17f52 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -138,9 +138,11 @@ BEGIN MENUITEM "New Instance", ID_MENU_LUASCRIPT_NEW POPUP "Recent scripts" BEGIN - MENUITEM "No recent scripts" ID_LUA_RECENT, GRAYED + MENUITEM "Reset", ID_LUA_RECENT_RESET + MENUITEM "Freeze", ID_LUA_RECENT_FREEZE + MENUITEM SEPARATOR + MENUITEM "" ID_LUA_RECENT, GRAYED END - MENUITEM "Clear recent" ID_LUA_CLEAR_RECENT MENUITEM "Close All", ID_MENU_LUASCRIPT_CLOSEALL END END From 8d5df40dcb20946fe733ce9d9ae28c21aea6617c Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Tue, 10 Aug 2021 11:02:57 +0200 Subject: [PATCH 81/93] Small UI change --- winproject/rsrc.rc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 7ea17f52..183c45a0 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -136,6 +136,7 @@ BEGIN POPUP "Lua Script" BEGIN MENUITEM "New Instance", ID_MENU_LUASCRIPT_NEW + MENUITEM SEPARATOR POPUP "Recent scripts" BEGIN MENUITEM "Reset", ID_LUA_RECENT_RESET @@ -143,6 +144,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "" ID_LUA_RECENT, GRAYED END + MENUITEM SEPARATOR MENUITEM "Close All", ID_MENU_LUASCRIPT_CLOSEALL END END From 1249eb87f0ee6aa90ab2b2ef646ffc680ab49ca8 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Thu, 12 Aug 2021 17:20:27 +0200 Subject: [PATCH 82/93] Fix mupen rom recognition --- main/rom.c | 39 +++++++++++++++++++++++++++------------ main/rom.h | 2 +- main/win/rombrowser.c | 9 ++++----- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/main/rom.c b/main/rom.c index aded8b49..3858f4ba 100755 --- a/main/rom.c +++ b/main/rom.c @@ -45,7 +45,9 @@ #include "md5.h" #include "mupenIniApi.h" #include "guifuncs.h" +#include "../main/win/Config.h" #include +#include static FILE *rom_file; static gzFile z_rom_file; @@ -90,14 +92,25 @@ static int findsize() // divide through 131072 works too but im sure compiler is smart enough } -bool validRomExt(std::string str) { +const char* getExt(const char* filename) { + const char* dot = strrchr(filename, '.'); + if (!dot || dot == filename) return ""; + return dot + 1; +} + +bool validRomExt(const char* filename) { +//#ifdef _DEBUG +// printf("%s\n", filename); +//#endif + const char* str = getExt(filename); + if (str == "\0" || str == "0") return 0; // z64,n64,v64,rom - const char* cstr = str.c_str(); - return stricmp(cstr, "z64") || - stricmp(cstr, "n64") || - stricmp(cstr, "v64") || - stricmp(cstr, "rom"); + return !stricmp(str, "z64") || + !stricmp(str, "n64") || + !stricmp(str, "v64") || + !stricmp(str, "rom"); } + static int find_file(char *argv) { z=0; @@ -165,10 +178,9 @@ int rom_read(const char *argv) char buf[1024], arg[1024], *s; strncpy(arg, argv, 1000); - std::string strfileName = argv; - if (strfileName.find_last_of(".") != std::string::npos - && !validRomExt(strfileName.substr(strfileName.find_last_of(".") + 1)) - && !ask_extension()) {goto killRom;} + + if (!validRomExt(argv) && !ask_extension()) + goto killRom; if (find_file(arg)) { @@ -187,9 +199,12 @@ int rom_read(const char *argv) } } } + + printf ("file found\n"); /*------------------------------------------------------------------------*/ - if (findsize() > 64 && !ask_hack())goto killRom; + if (findsize() > 64 && !ask_hack()) goto killRom; + if (rom) free(rom); rom = (unsigned char*)malloc(taille_rom); @@ -394,7 +409,7 @@ int fill_header(const char *argv) { char arg[1024]; strncpy(arg, argv, 1000); - if (find_file(arg)) + if (find_file(arg)/* || !validRomExt(argv) && Config.alertBAD */) { printf ("file not found or wrong path\n"); return 0; diff --git a/main/rom.h b/main/rom.h index 1c5d72ea..85b14402 100755 --- a/main/rom.h +++ b/main/rom.h @@ -34,7 +34,7 @@ int rom_read(const char *argv); int fill_header(const char *argv); bool iequals(const std::string& a, const std::string& b); -bool validRomExt(std::string str); +bool validRomExt(const char* filename); void calculateMD5(const char *argv, unsigned char digest[16]); extern unsigned char *rom; extern int taille_rom; diff --git a/main/win/rombrowser.c b/main/win/rombrowser.c index 9c6e0f05..aee4ced4 100755 --- a/main/win/rombrowser.c +++ b/main/win/rombrowser.c @@ -14,6 +14,7 @@ * * ***************************************************************************/ + #include #include #include @@ -876,11 +877,9 @@ void AddDirToList(char RomBrowserDir[MAX_PATH],BOOL sortflag) strcpy(FullPath,RomBrowserDir); if (FullPath[strlen(RomBrowserDir) - 1] != '\\') { strcat(FullPath,"\\"); } strcat(FullPath,fd.cFileName); - std::string strfileName = FullPath; - if (strfileName.find_last_of(".") != std::string::npos - && !validRomExt(strfileName.substr(strfileName.find_last_of(".") + 1)) && Config.alertBAD) { - continue; - } + + if ((Config.alertBAD||Config.alertHACK) && !validRomExt(FullPath)) continue; + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (Config.RomBrowserRecursion) { AddDirToList(FullPath,FALSE); } From 9465c61859346ffeb084f30bd3329c9bbfbdc141 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Fri, 13 Aug 2021 10:14:24 +0200 Subject: [PATCH 83/93] Fix toolbar broken styles and doubleclick bug --- main/win/main_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/win/main_win.cpp b/main/win/main_win.cpp index ea6a81e9..07b2db38 100644 --- a/main/win/main_win.cpp +++ b/main/win/main_win.cpp @@ -1535,8 +1535,8 @@ void CreateToolBarWindow(HWND hwnd) }; hTool = CreateToolbarEx (hwnd, - WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | - /*WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE |*/ CCS_ADJUSTABLE, + WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS /* | */ + /*CS_ADJUSTABLE no this causes a bug...*/, IDC_TOOLBAR, 10, app_hInstance, IDB_TOOLBAR, (LPCTBBUTTON)&tbButtons, 13, 16, 16, 200, 25, sizeof (TBBUTTON)); From 7d71c2fb3c6617012ea8636d36b82b5f36548ba6 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Fri, 13 Aug 2021 17:42:22 +0200 Subject: [PATCH 84/93] Fix input boxes in tasinput being broken + allow fast dragging and fixes teleporting when dragging from control to outside of it --- tasinput_plugin/src/DefDI.cpp | 42 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 95b5ceed..40ce117a 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -110,6 +110,8 @@ struct Status positioned = false; comboTask = C_IDLE; once = true; + setcursortimer = 0; + dragcounter = 0; } void StartThread(int ControllerNumber) @@ -197,6 +199,8 @@ struct Status int comboTask; int activeCombo; bool fakeInput; + int setcursortimer; //increases every setcursor + int dragcounter; //holds setcursor count when dragging started bool once; @@ -1947,6 +1951,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // too bad we don't get useful events like WM_MOUSEMOVE or WM_LBUTTONDOWN... case WM_SETCURSOR: #ifdef DEBUG + setcursortimer++; //printf("tasinput setcursor message!\n"); #endif POINT pt; @@ -2012,6 +2017,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { if (menuConfig.movable) { dragging = true; + dragcounter = setcursortimer; GetCursorPos(&pt); dragXStart = pt.x; dragYStart = pt.y; @@ -2037,7 +2043,8 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(dragging && !nextClick) { dragging = false; - ActivateEmulatorWindow(); + KillTimer(statusDlg, IDT_TIMER3); + //ActivateEmulatorWindow(); //not needed } if(draggingStick && ((!nextClick && !draggingPermaStick ) || !IsWindowFromEmulatorProcessActive())) { @@ -2047,18 +2054,31 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) if(IsWindowFromEmulatorProcessActive()) ActivateEmulatorWindow(); } - if(dragging) + if (dragging) { - POINT pt; - GetCursorPos(&pt); - int newDragX = pt.x; - int newDragY = pt.y; - if(lastXDrag != newDragX-dragXStart || lastYDrag != newDragY-dragYStart) + //because the WM_COMMAND check is fired after 1 setcursor, it would falsely start drag timer, + //this small workaround checks if at least 2 messages have passed, however I dont think + //WM_COMMAND is ensured to be sent in order after setcursor, so I made it start after 3 messages instead, + //I never observed 2 setcursors go before wm_command + int cntdelta = setcursortimer - dragcounter; + //printf("drag delta: %d\n", cntdelta); + if (cntdelta == 2) { - lastXDrag = newDragX-dragXStart; - lastYDrag = newDragY-dragYStart; - // do not - SetWindowPos(statusDlg,0, lastXDrag, lastYDrag, 0,0,/*SWP_NOZORDER|*/SWP_NOSIZE|SWP_SHOWWINDOW); + SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //!!VERY SUS!! + } + if (cntdelta > 1) //shouldn't be visible, helps fight teleports after aggresive text select + { + POINT pt; + GetCursorPos(&pt); + int newDragX = pt.x; + int newDragY = pt.y; + if (lastXDrag != newDragX - dragXStart || lastYDrag != newDragY - dragYStart) + { + lastXDrag = newDragX - dragXStart; + lastYDrag = newDragY - dragYStart; + // do not + SetWindowPos(statusDlg, 0, lastXDrag, lastYDrag, 0, 0,/*SWP_NOZORDER|*/SWP_NOSIZE | SWP_SHOWWINDOW); + } } } else if(draggingStick) From 0c2dca6d7f8abf5e96f1699308eefb8c2c471a4c Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 14 Aug 2021 13:33:39 +0200 Subject: [PATCH 85/93] move the counter out of ifdef debug... best bug award 2021 --- tasinput_plugin/src/DefDI.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 40ce117a..44d9b405 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1950,10 +1950,10 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) // too bad we don't get useful events like WM_MOUSEMOVE or WM_LBUTTONDOWN... case WM_SETCURSOR: -#ifdef DEBUG - setcursortimer++; +#ifdef _DEBUG //printf("tasinput setcursor message!\n"); #endif + setcursortimer++; POINT pt; GetCursorPos(&pt); @@ -2061,7 +2061,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) //WM_COMMAND is ensured to be sent in order after setcursor, so I made it start after 3 messages instead, //I never observed 2 setcursors go before wm_command int cntdelta = setcursortimer - dragcounter; - //printf("drag delta: %d\n", cntdelta); + printf("drag delta: %d\n", cntdelta); if (cntdelta == 2) { SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //!!VERY SUS!! From a84f522d78a38f196f67cec7a0a751bc3467a83d Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 14 Aug 2021 13:40:46 +0200 Subject: [PATCH 86/93] fix the --- winproject/rsrc.rc | 1 - 1 file changed, 1 deletion(-) diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 183c45a0..696c1749 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -142,7 +142,6 @@ BEGIN MENUITEM "Reset", ID_LUA_RECENT_RESET MENUITEM "Freeze", ID_LUA_RECENT_FREEZE MENUITEM SEPARATOR - MENUITEM "" ID_LUA_RECENT, GRAYED END MENUITEM SEPARATOR MENUITEM "Close All", ID_MENU_LUASCRIPT_CLOSEALL From ff64eb185be7309a8de1621f3c10ad2efad9d0e4 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 14 Aug 2021 13:58:37 +0200 Subject: [PATCH 87/93] recent luas again --- lua/Recent.cpp | 4 ++-- tasinput_plugin/src/DefDI.cpp | 2 +- winproject/rsrc.rc | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lua/Recent.cpp b/lua/Recent.cpp index 15311a71..38cd9f15 100644 --- a/lua/Recent.cpp +++ b/lua/Recent.cpp @@ -17,7 +17,7 @@ void BuildRecentScriptsMenu(HWND hwnd) { MENUITEMINFO menuinfo = { 0 }; HMENU hMenu = GetMenu(hwnd); HMENU hSubMenu = GetSubMenu(hMenu, 5); - hSubMenu = GetSubMenu(hSubMenu, 1); + hSubMenu = GetSubMenu(hSubMenu, 2); //DeleteMenu(hSubMenu, ID_LUA_RECENT, MF_BYCOMMAND); //remove the "no recent scripts" entry, add later if in fact no recent menuinfo.cbSize = sizeof(MENUITEMINFO); @@ -39,7 +39,7 @@ void BuildRecentScriptsMenu(HWND hwnd) { menuinfo.cch = strlen(menuinfo.dwTypeData); - menuinfo.wID = ID_LUA_RECENT + i+3; + menuinfo.wID = ID_LUA_RECENT + i; InsertMenuItem(hSubMenu, i+3, TRUE, &menuinfo); if (empty) EnableMenuItem(hSubMenu, ID_LUA_RECENT, MF_DISABLED); } diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 44d9b405..b5bf6bb9 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -2061,7 +2061,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) //WM_COMMAND is ensured to be sent in order after setcursor, so I made it start after 3 messages instead, //I never observed 2 setcursors go before wm_command int cntdelta = setcursortimer - dragcounter; - printf("drag delta: %d\n", cntdelta); + //printf("drag delta: %d\n", cntdelta); if (cntdelta == 2) { SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //!!VERY SUS!! diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 183c45a0..696c1749 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -142,7 +142,6 @@ BEGIN MENUITEM "Reset", ID_LUA_RECENT_RESET MENUITEM "Freeze", ID_LUA_RECENT_FREEZE MENUITEM SEPARATOR - MENUITEM "" ID_LUA_RECENT, GRAYED END MENUITEM SEPARATOR MENUITEM "Close All", ID_MENU_LUASCRIPT_CLOSEALL From ab9b336101928185bfb12401a92deea59e356313 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sat, 14 Aug 2021 18:35:23 +0200 Subject: [PATCH 88/93] Fix movies with .savestate not loading on drag and drop (BAD FIX!!!!!) --- main/vcr.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index c11f7a6f..50d86a49 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1542,19 +1542,34 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip break; } + // TODO: FIXME: One should never fear threats. It's like with a dog. + // A dog senses when somebody wrote bad code, and bites. + char* bufnExt = (char*)malloc(strlen(buf)+11); + strcpy(bufnExt, buf); + strncat( buf, ".st", 4); FILE* stBuf; + if ((stBuf = fopen(buf, "r"))) fclose(stBuf); else { - printf("[VCR]: Early Savestate exist check failed...\n"); - RESET_TITLEBAR; - if (m_file != NULL) - fclose(m_file); - return -1; + // try .savestate + strncat(bufnExt, ".savestate", 11); + + if ((stBuf = fopen(bufnExt, "r"))) fclose(stBuf); + else { + printf("[VCR]: Early Savestate exist check failed...\n"); + RESET_TITLEBAR; + if (m_file != NULL) + fclose(m_file); + free(bufnExt); + return -1; + } } + free(bufnExt); + savestates_select_filename( buf ); savestates_job |= LOADSTATE; m_task = StartPlaybackFromSnapshot; From c8e2c4665718b3e1d07c3f8ddbe86a3736e4ef88 Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sat, 14 Aug 2021 23:41:14 +0200 Subject: [PATCH 89/93] Allow dragging tasinput when m64 is playing this needs to be investigated why it works --- tasinput_plugin/src/DefDI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index b5bf6bb9..ef13e81d 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -2258,7 +2258,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) EndEdit(activeCombo, (char*)lParam); break; case WM_COMMAND: - dragging = false; //any interaction with controls means we don't want to drag + if (HIWORD(wParam) < 0x300) dragging = false; //any interaction with controls means we don't want to drag switch (LOWORD(wParam)) { case IDC_EDITX: From 6ff39a6dc265f424fea0dd42140dae92e3e4b8bc Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 15 Aug 2021 09:46:06 +0200 Subject: [PATCH 90/93] Fix tasinput lagging when dragging outside of dialog --- main/vcr.c | 2 +- tasinput_plugin/src/DefDI.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/main/vcr.c b/main/vcr.c index 50d86a49..1fa7870a 100644 --- a/main/vcr.c +++ b/main/vcr.c @@ -1559,7 +1559,7 @@ startPlayback( const char *filename, const char *authorUTF8, const char *descrip if ((stBuf = fopen(bufnExt, "r"))) fclose(stBuf); else { - printf("[VCR]: Early Savestate exist check failed...\n"); + printf("[VCR]: Early Savestate exist check failed. No .savestate or .st found for movie!\n"); RESET_TITLEBAR; if (m_file != NULL) fclose(m_file); diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index b5bf6bb9..7727f7e2 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1969,7 +1969,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { if(IsMouseOverControl(statusDlg,IDC_STICKPIC)) { - SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //start timer during dragging to allow out of bounds drag + SetTimer(statusDlg, IDT_TIMER3, 50/2/2, (TIMERPROC)NULL); //start timer during dragging to allow out of bounds drag //if clicked RMB and permadrag was active, disable it if(draggingPermaStick || GetAsyncKeyState(VK_RBUTTON) & 0x8000) { @@ -2044,6 +2044,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) { dragging = false; KillTimer(statusDlg, IDT_TIMER3); + //if (setcursortimer - dragcounter > 1) //ActivateEmulatorWindow(); //not needed } if(draggingStick && ((!nextClick && !draggingPermaStick ) || !IsWindowFromEmulatorProcessActive())) From a63861d71e2867c671593161d86667e35793acb6 Mon Sep 17 00:00:00 2001 From: Aurumaker72 Date: Sun, 15 Aug 2021 19:38:46 +0200 Subject: [PATCH 91/93] Add Lua simplified dialog option, and lua warn at close --- lua/LuaConsole.cpp | 11 +++++++++- main/win/configdialog.c | 47 +++++++++++++++++++++++++++++++++++++++-- main/win/main_win.h | 2 ++ winproject/resource.h | 5 +++++ winproject/rsrc.rc | 25 ++++++++++++++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) diff --git a/lua/LuaConsole.cpp b/lua/LuaConsole.cpp index 4736cf32..2d454d82 100644 --- a/lua/LuaConsole.cpp +++ b/lua/LuaConsole.cpp @@ -641,6 +641,11 @@ INT_PTR CALLBACK DialogProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { return TRUE; } case WM_CLOSE: + + if (Config.LuaWarnOnClose + && (MessageBox(0, "Are you sure you want to close this dialog and terminate this lua script instance?", "Confirm closing", MB_TASKMODAL | MB_TOPMOST | MB_YESNO | MB_ICONQUESTION) == IDNO)) + return TRUE; + DestroyWindow(wnd); return TRUE; case WM_DESTROY:{ @@ -766,9 +771,13 @@ void CreateLuaWindow(void(*callback)()) { if(!luaDC) { InitializeLuaDC(mainHWND); } + + int LuaWndId = Config.LuaSimpleDialog ? IDD_LUAWINDOW_SIMPLIFIED : IDD_LUAWINDOW; + HWND wnd = CreateDialogParam(app_hInstance, - MAKEINTRESOURCE(IDD_LUAWINDOW), mainHWND, DialogProc, + MAKEINTRESOURCE(LuaWndId), mainHWND, DialogProc, (LPARAM)callback); + ShowWindow(wnd, SW_SHOW); //^uXgbvȂ̂ƓƎv } void ConsoleWrite(HWND wnd, const char *str) { diff --git a/main/win/configdialog.c b/main/win/configdialog.c index e2f62a36..f2f6cd3c 100755 --- a/main/win/configdialog.c +++ b/main/win/configdialog.c @@ -53,6 +53,37 @@ HWND hwndTrack ; extern int no_audio_delay; extern int no_compiled_jump; +BOOL CALLBACK OtherOptionsProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) { + case WM_INITDIALOG: + WriteCheckBoxValue(hwnd, IDC_LUA_SIMPLEDIALOG, Config.LuaSimpleDialog); + WriteCheckBoxValue(hwnd, IDC_LUA_WARNONCLOSE, Config.LuaWarnOnClose); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + + } + break; + + case WM_NOTIFY: + if (((NMHDR FAR*) lParam)->code == PSN_APPLY) { + Config.LuaSimpleDialog = ReadCheckBoxValue(hwnd, IDC_LUA_SIMPLEDIALOG); + Config.LuaWarnOnClose = ReadCheckBoxValue(hwnd, IDC_LUA_WARNONCLOSE); + EnableToolbar(); + EnableStatusbar(); + FastRefreshBrowser(); + LoadConfigExternals(); + } + break; + + default: + return FALSE; + } + return TRUE; +} + void WriteCheckBoxValue( HWND hwnd, int resourceID , int value) { if (value) { @@ -90,10 +121,10 @@ void ReadComboBoxValue(HWND hwnd,int ResourceID,char *ret) } void ChangeSettings(HWND hwndOwner) { - PROPSHEETPAGE psp[5]; + PROPSHEETPAGE psp[6]; PROPSHEETHEADER psh; char ConfigStr[200],DirectoriesStr[200],titleStr[200],settingsStr[200]; - char AdvSettingsStr[200], HotkeysStr[200]; + char AdvSettingsStr[200], HotkeysStr[200], OtherStr[200]; psp[0].dwSize = sizeof(PROPSHEETPAGE); psp[0].dwFlags = PSP_USETITLE; psp[0].hInstance = app_hInstance; @@ -144,6 +175,16 @@ void ChangeSettings(HWND hwndOwner) { psp[4].lParam = 0; psp[4].pfnCallback = NULL; + psp[5].dwSize = sizeof(PROPSHEETPAGE); + psp[5].dwFlags = PSP_USETITLE; + psp[5].hInstance = app_hInstance; + psp[5].pszTemplate = MAKEINTRESOURCE(IDD_OTHER_OPTIONS_DIALOG); + psp[5].pfnDlgProc = OtherOptionsProc; + TranslateDefault("Other", "Other", OtherStr); + psp[5].pszTitle = OtherStr; + psp[5].lParam = 0; + psp[5].pfnCallback = NULL; + psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP; psh.hwndParent = hwndOwner; @@ -1271,6 +1312,8 @@ BOOL CALLBACK HotkeysProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) return TRUE; } + + HWND WINAPI CreateTrackbar( HWND hwndDlg, // handle of dialog box (parent window) UINT iMin, // minimum value in trackbar range diff --git a/main/win/main_win.h b/main/win/main_win.h index ae301166..258ca068 100755 --- a/main/win/main_win.h +++ b/main/win/main_win.h @@ -157,6 +157,8 @@ typedef struct _CONFIG { char LuaScriptPath[MAX_PATH]; char RecentScripts[LUA_MAX_RECENT][MAX_PATH]; BOOL RecentScriptsFreeze; + BOOL LuaSimpleDialog; + BOOL LuaWarnOnClose; } CONFIG; extern "C" CONFIG Config; diff --git a/winproject/resource.h b/winproject/resource.h index 26eee87d..2d56a7fa 100755 --- a/winproject/resource.h +++ b/winproject/resource.h @@ -423,6 +423,11 @@ #define IDC_EXTSAVESTATE 40012 #define ID_LUA_RECENT_RESET 40013 #define ID_LUA_RECENT_FREEZE 40014 +#define IDD_OTHER_OPTIONS_DIALOG 40015 +#define IDC_OTHEROPTIONS 40016 +#define IDC_LUA_WARNONCLOSE 40017 +#define IDC_LUA_SIMPLEDIALOG 40018 +#define IDD_LUAWINDOW_SIMPLIFIED 40019 #define IDC_STATIC -1 // Next default values for new objects diff --git a/winproject/rsrc.rc b/winproject/rsrc.rc index 696c1749..b73ba829 100755 --- a/winproject/rsrc.rc +++ b/winproject/rsrc.rc @@ -215,6 +215,15 @@ BEGIN "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,16,233,78,16 END +IDD_OTHER_OPTIONS_DIALOG DIALOGEX 0, 0, 231, 273 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN +GROUPBOX "Other Options", IDC_OTHEROPTIONS, 7, 7, 215, 60 +CONTROL "Ask on lua close", IDC_LUA_WARNONCLOSE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 16, 20, 100, 10 +CONTROL "Simplfied lua dialog", IDC_LUA_SIMPLEDIALOG, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 16, 30, 100, 10 +END + IDD_AUDIT_ROMS_DIALOG DIALOGEX 0, 0, 183, 138 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Audit ROMs" @@ -250,6 +259,18 @@ BEGIN EDITTEXT IDC_TEXTBOX_LUACONSOLE,7,43,226,116,ES_MULTILINE | ES_READONLY | WS_VSCROLL END +IDD_LUAWINDOW_SIMPLIFIED DIALOGEX 0, 0, 230, 50 +STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "LUA Instance" +FONT 8, "Ms Shell Dlg", 0, 0, 0x1 +BEGIN +PUSHBUTTON "Run", IDC_BUTTON_LUASTATE, 193, 23, 40, 18 +EDITTEXT IDC_TEXTBOX_LUASCRIPTPATH, 7, 7, 226, 14, ES_AUTOHSCROLL +PUSHBUTTON "Browse", IDC_BUTTON_LUABROWSE, 110, 23, 40, 18 +PUSHBUTTON "Stop", IDC_BUTTON_LUASTOP, 151, 23, 40, 18, WS_DISABLED +END + + IDD_DIRECTORIES DIALOGEX 0, 0, 231, 262 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP FONT 8, "Tahoma", 0, 0, 0x0 @@ -666,6 +687,10 @@ BEGIN BEGIN END + IDD_OTHER_OPTIONS_DIALOG, DIALOG + BEGIN + END + IDD_AUDIT_ROMS_DIALOG, DIALOG BEGIN END From bb3ef11aa046458d91309e1f555ce5893c1dce8c Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 15 Aug 2021 20:19:23 +0200 Subject: [PATCH 92/93] Tasinput dragging reafctor turns out these messages work perfectly fine for dragging so now the code is much more clear, also added setCapture() --- tasinput_plugin/src/DefDI.cpp | 191 +++++++++++++++------------------- 1 file changed, 84 insertions(+), 107 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index ef13e81d..848ce97b 100755 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -110,8 +110,6 @@ struct Status positioned = false; comboTask = C_IDLE; once = true; - setcursortimer = 0; - dragcounter = 0; } void StartThread(int ControllerNumber) @@ -199,8 +197,6 @@ struct Status int comboTask; int activeCombo; bool fakeInput; - int setcursortimer; //increases every setcursor - int dragcounter; //holds setcursor count when dragging started bool once; @@ -1629,9 +1625,9 @@ static bool IsMouseOverControl (HWND hDlg, int dialogItemID) RECT rect; GetCursorPos(&pt); - GetWindowRect(GetDlgItem(hDlg, dialogItemID), &rect); - - return (pt.x <= rect.right && pt.x >= rect.left && pt.y <= rect.bottom && pt.y >= rect.top); + if(GetWindowRect(GetDlgItem(hDlg, dialogItemID), &rect)) //failed to get the dimensions + return (pt.x <= rect.right && pt.x >= rect.left && pt.y <= rect.bottom && pt.y >= rect.top); + return FALSE; } void Status::ActivateEmulatorWindow () @@ -1953,7 +1949,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) #ifdef _DEBUG //printf("tasinput setcursor message!\n"); #endif - setcursortimer++; POINT pt; GetCursorPos(&pt); @@ -1964,74 +1959,34 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) //used for sliders (rightclick reset), remembers if rightclick was pressed //!! turns it into bool lastWasRight = !!(GetAsyncKeyState(VK_RBUTTON) & 0x8000); - //if not dragging, previous interacion wasn't click with R or L, and current one (nextClick) is R or L - if(!dragging && !lastClick && nextClick) + //if we are over buttons area and right is clicked, look for autofire candidates + //sadly wm_rbuttondown doesnt work here + if (IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL)) { - if(IsMouseOverControl(statusDlg,IDC_STICKPIC)) - { - SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //start timer during dragging to allow out of bounds drag - //if clicked RMB and permadrag was active, disable it - if(draggingPermaStick || GetAsyncKeyState(VK_RBUTTON) & 0x8000) - { - draggingPermaStick = !draggingPermaStick; - draggingStick = draggingPermaStick; - } - //otherwise just drag stick - else - draggingStick = true; - } - // no else if... you cant be over stickpic AND not on it (schrdingers mouse wtf) - //If mouse over any of the labels and not over joystick, start dragging or autofire - else if(IsMouseOverControl(statusDlg,IDC_BUTTONSLABEL) || IsMouseOverControl(statusDlg, IDC_ANALOGSTICKLABEL)) + overrideOn = true; //clicking on buttons counts as override + if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it { -#ifdef DEBUG - //printf("HWND hit: %d\n", ChildWindowFromPoint(statusDlg, pt)); - //printf("HWND deeper 1: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt)); - //printf("HWND deeper 2: %d\n", ChildWindowFromPoint(ChildWindowFromPoint(ChildWindowFromPoint(statusDlg, pt), pt), pt)); -#endif - //if we are over buttons area and right is clicked, look for autofire candidates - if(lastWasRight && IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL)) - { - overrideOn = true; //clicking on buttons counts as override - if(GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it - { - UPDATEAUTO(IDC_CHECK_A, A_BUTTON); - UPDATEAUTO(IDC_CHECK_B, B_BUTTON); - UPDATEAUTO(IDC_CHECK_START, START_BUTTON); - UPDATEAUTO(IDC_CHECK_L, L_TRIG); - UPDATEAUTO(IDC_CHECK_R, R_TRIG); - UPDATEAUTO(IDC_CHECK_Z, Z_TRIG); - UPDATEAUTO(IDC_CHECK_CUP, U_CBUTTON); - UPDATEAUTO(IDC_CHECK_CLEFT, L_CBUTTON); - UPDATEAUTO(IDC_CHECK_CRIGHT, R_CBUTTON); - UPDATEAUTO(IDC_CHECK_CDOWN, D_CBUTTON); - UPDATEAUTO(IDC_CHECK_DUP, U_DPAD); - UPDATEAUTO(IDC_CHECK_DLEFT, L_DPAD); - UPDATEAUTO(IDC_CHECK_DRIGHT, R_DPAD); - UPDATEAUTO(IDC_CHECK_DDOWN, D_DPAD); - - ActivateEmulatorWindow(); - } - } - else - { - if (menuConfig.movable) { - dragging = true; - dragcounter = setcursortimer; - GetCursorPos(&pt); - dragXStart = pt.x; - dragYStart = pt.y; - - RECT rect; - GetWindowRect(statusDlg, &rect); - dragXStart -= rect.left; - dragYStart -= rect.top; - } - } + UPDATEAUTO(IDC_CHECK_A, A_BUTTON); + UPDATEAUTO(IDC_CHECK_B, B_BUTTON); + UPDATEAUTO(IDC_CHECK_START, START_BUTTON); + UPDATEAUTO(IDC_CHECK_L, L_TRIG); + UPDATEAUTO(IDC_CHECK_R, R_TRIG); + UPDATEAUTO(IDC_CHECK_Z, Z_TRIG); + UPDATEAUTO(IDC_CHECK_CUP, U_CBUTTON); + UPDATEAUTO(IDC_CHECK_CLEFT, L_CBUTTON); + UPDATEAUTO(IDC_CHECK_CRIGHT, R_CBUTTON); + UPDATEAUTO(IDC_CHECK_CDOWN, D_CBUTTON); + UPDATEAUTO(IDC_CHECK_DUP, U_DPAD); + UPDATEAUTO(IDC_CHECK_DLEFT, L_DPAD); + UPDATEAUTO(IDC_CHECK_DRIGHT, R_DPAD); + UPDATEAUTO(IDC_CHECK_DDOWN, D_DPAD); + + ActivateEmulatorWindow(); } } lastClick = nextClick; /* fall through */ + case WM_MOUSEMOVE: case WM_NCHITTEST: case WM_TIMER: skipEditX = false; @@ -2040,45 +1995,18 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) resetXScale = false, SendDlgItemMessage(statusDlg, IDC_SLIDERX, TBM_SETPOS, TRUE, (LPARAM)(LONG)(1000)); if(resetYScale) resetYScale = false, SendDlgItemMessage(statusDlg, IDC_SLIDERY, TBM_SETPOS, TRUE, (LPARAM)(LONG)(1000)); - if(dragging && !nextClick) - { - dragging = false; - KillTimer(statusDlg, IDT_TIMER3); - //ActivateEmulatorWindow(); //not needed - } - if(draggingStick && ((!nextClick && !draggingPermaStick ) || !IsWindowFromEmulatorProcessActive())) - { - draggingStick = false; - draggingPermaStick = false; - KillTimer(statusDlg, IDT_TIMER3); - if(IsWindowFromEmulatorProcessActive()) - ActivateEmulatorWindow(); - } if (dragging) { - //because the WM_COMMAND check is fired after 1 setcursor, it would falsely start drag timer, - //this small workaround checks if at least 2 messages have passed, however I dont think - //WM_COMMAND is ensured to be sent in order after setcursor, so I made it start after 3 messages instead, - //I never observed 2 setcursors go before wm_command - int cntdelta = setcursortimer - dragcounter; - //printf("drag delta: %d\n", cntdelta); - if (cntdelta == 2) - { - SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); //!!VERY SUS!! - } - if (cntdelta > 1) //shouldn't be visible, helps fight teleports after aggresive text select + POINT pt; + GetCursorPos(&pt); + int newDragX = pt.x; + int newDragY = pt.y; + if (lastXDrag != newDragX - dragXStart || lastYDrag != newDragY - dragYStart) { - POINT pt; - GetCursorPos(&pt); - int newDragX = pt.x; - int newDragY = pt.y; - if (lastXDrag != newDragX - dragXStart || lastYDrag != newDragY - dragYStart) - { - lastXDrag = newDragX - dragXStart; - lastYDrag = newDragY - dragYStart; - // do not - SetWindowPos(statusDlg, 0, lastXDrag, lastYDrag, 0, 0,/*SWP_NOZORDER|*/SWP_NOSIZE | SWP_SHOWWINDOW); - } + lastXDrag = newDragX - dragXStart; + lastYDrag = newDragY - dragYStart; + // do not + SetWindowPos(statusDlg, 0, lastXDrag, lastYDrag, 0, 0,/*SWP_NOZORDER|*/SWP_NOSIZE | SWP_SHOWWINDOW); } } else if(draggingStick) @@ -2127,6 +2055,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) overrideOn = true; //joystick dragged with mouse RefreshAnalogPicture(); ActivateEmulatorWindow(); + SetCapture(statusDlg); } else if(IsWindowFromEmulatorProcessActive() &&!lock) { @@ -2157,6 +2086,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) SetWindowPos(statusDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); } break; + case WM_PAINT: { PAINTSTRUCT ps; @@ -2254,11 +2184,58 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) } } break; + case WM_LBUTTONUP: + if (dragging) + { + printf("drag end\n"); + dragging = false; + ReleaseCapture(); + ActivateEmulatorWindow(); + } + if (draggingStick && (!draggingPermaStick || !IsWindowFromEmulatorProcessActive())) + { + draggingStick = false; + draggingPermaStick = false; + ReleaseCapture(); + if (IsWindowFromEmulatorProcessActive()) + ActivateEmulatorWindow(); + } + break; + + case WM_LBUTTONDOWN: //this message is only sent when clicking on non-controls, which is perfect for dragging right + SetCapture(statusDlg); //let mouse escape window + if (!IsMouseOverControl(statusDlg,IDC_STICKPIC)) { + if (menuConfig.movable) + { + printf("drag start\n"); + dragging = true; + GetCursorPos(&pt); + dragXStart = pt.x; + dragYStart = pt.y; + + RECT rect; + GetWindowRect(statusDlg, &rect); + dragXStart -= rect.left; + dragYStart -= rect.top; + } + } + else draggingStick = true; + break; + case WM_RBUTTONDOWN: + + //flip permadrag state and update dragging stick accordingly + if (IsMouseOverControl(statusDlg, IDC_STICKPIC)) + { + draggingPermaStick = !draggingPermaStick; + if (draggingStick = draggingPermaStick) SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); + else KillTimer(statusDlg, IDT_TIMER3); + } + break; case EDIT_END: EndEdit(activeCombo, (char*)lParam); break; case WM_COMMAND: - if (HIWORD(wParam) < 0x300) dragging = false; //any interaction with controls means we don't want to drag + //printf("wmcommand\n"); switch (LOWORD(wParam)) { case IDC_EDITX: From 9fe05029e80276879a56dbde01901a6301873f8c Mon Sep 17 00:00:00 2001 From: Madghostek Date: Sun, 15 Aug 2021 23:09:31 +0200 Subject: [PATCH 93/93] changes --- tasinput_plugin/src/DefDI.cpp | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/tasinput_plugin/src/DefDI.cpp b/tasinput_plugin/src/DefDI.cpp index 848ce97b..5e2dde00 100644 --- a/tasinput_plugin/src/DefDI.cpp +++ b/tasinput_plugin/src/DefDI.cpp @@ -1949,9 +1949,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) #ifdef _DEBUG //printf("tasinput setcursor message!\n"); #endif - POINT pt; - GetCursorPos(&pt); - //is any mouse button pressed? nextClick = ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) || (GetAsyncKeyState(VK_RBUTTON) & 0x8000)); @@ -1961,7 +1958,7 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) lastWasRight = !!(GetAsyncKeyState(VK_RBUTTON) & 0x8000); //if we are over buttons area and right is clicked, look for autofire candidates //sadly wm_rbuttondown doesnt work here - if (IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL)) + if (IsMouseOverControl(statusDlg, IDC_BUTTONSLABEL) && lastWasRight) { overrideOn = true; //clicking on buttons counts as override if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) // right click on a button to autofire it @@ -2054,8 +2051,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) radialRecalc = true; overrideOn = true; //joystick dragged with mouse RefreshAnalogPicture(); - ActivateEmulatorWindow(); - SetCapture(statusDlg); } else if(IsWindowFromEmulatorProcessActive() &&!lock) { @@ -2192,21 +2187,26 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) ReleaseCapture(); ActivateEmulatorWindow(); } - if (draggingStick && (!draggingPermaStick || !IsWindowFromEmulatorProcessActive())) + if (draggingStick) { draggingStick = false; - draggingPermaStick = false; ReleaseCapture(); if (IsWindowFromEmulatorProcessActive()) ActivateEmulatorWindow(); } + if (draggingPermaStick) + { + draggingPermaStick = false; + KillTimer(statusDlg, IDT_TIMER3); + } break; case WM_LBUTTONDOWN: //this message is only sent when clicking on non-controls, which is perfect for dragging right - SetCapture(statusDlg); //let mouse escape window + printf("ld\n"); if (!IsMouseOverControl(statusDlg,IDC_STICKPIC)) { if (menuConfig.movable) { + POINT pt; printf("drag start\n"); dragging = true; GetCursorPos(&pt); @@ -2219,15 +2219,26 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) dragYStart -= rect.top; } } - else draggingStick = true; + else + { + draggingStick = true; + SendMessage(statusDlg, WM_MOUSEMOVE, 0, 0); //updates stick + ActivateEmulatorWindow(); + } + SetCapture(statusDlg); //let mouse escape window + break; case WM_RBUTTONDOWN: - + printf("rd\n"); //flip permadrag state and update dragging stick accordingly if (IsMouseOverControl(statusDlg, IDC_STICKPIC)) { draggingPermaStick = !draggingPermaStick; - if (draggingStick = draggingPermaStick) SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); + if (draggingStick = draggingPermaStick) + { + ActivateEmulatorWindow(); + SetTimer(statusDlg, IDT_TIMER3, 50, (TIMERPROC)NULL); + } else KillTimer(statusDlg, IDT_TIMER3); } break; @@ -2235,7 +2246,6 @@ LRESULT Status::StatusDlgMethod (UINT msg, WPARAM wParam, LPARAM lParam) EndEdit(activeCombo, (char*)lParam); break; case WM_COMMAND: - //printf("wmcommand\n"); switch (LOWORD(wParam)) { case IDC_EDITX: