From 87f259c0f5317b8fce2d7bb82e7196a001aab737 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 18 Sep 2019 18:11:37 +0200 Subject: [PATCH 1/6] win32: add license header to shader dialog files --- win32/CShaderParamDlg.cpp | 6 ++++++ win32/CShaderParamDlg.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/win32/CShaderParamDlg.cpp b/win32/CShaderParamDlg.cpp index c62b28ce..33151a97 100644 --- a/win32/CShaderParamDlg.cpp +++ b/win32/CShaderParamDlg.cpp @@ -1,3 +1,9 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + #include "CShaderParamDlg.h" #include "wsnes9x.h" #include "display.h" diff --git a/win32/CShaderParamDlg.h b/win32/CShaderParamDlg.h index e2540bff..a3c84bf8 100644 --- a/win32/CShaderParamDlg.h +++ b/win32/CShaderParamDlg.h @@ -1,3 +1,9 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + #pragma once #include "windows.h" #include "../shaders/glsl.h" From 2e7a345dcad89734097362832d4baae96e032aa7 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 18 Sep 2019 18:04:17 +0200 Subject: [PATCH 2/6] win32: add dialog for saving/loading with preview images --- win32/CSaveLoadWithPreviewDlg.cpp | 281 ++++++++++++++++++++++++++++++ win32/CSaveLoadWithPreviewDlg.h | 37 ++++ win32/rsrc/resource.h | 13 +- win32/rsrc/snes9x.rc | 25 ++- win32/snes9xw.vcxproj | 2 + win32/snes9xw.vcxproj.filters | 8 +- win32/wsnes9x.cpp | 42 +++-- win32/wsnes9x.h | 5 + 8 files changed, 397 insertions(+), 16 deletions(-) create mode 100644 win32/CSaveLoadWithPreviewDlg.cpp create mode 100644 win32/CSaveLoadWithPreviewDlg.h diff --git a/win32/CSaveLoadWithPreviewDlg.cpp b/win32/CSaveLoadWithPreviewDlg.cpp new file mode 100644 index 00000000..e2f1f89c --- /dev/null +++ b/win32/CSaveLoadWithPreviewDlg.cpp @@ -0,0 +1,281 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#include "CSaveLoadWithPreviewDlg.h" + +#include "wsnes9x.h" +#include "../snes9x.h" +#include "../ppu.h" +#include "../display.h" +#include +#include +#include + +CSaveLoadWithPreviewDlg::CSaveLoadWithPreviewDlg(bool is_save_dialog) +{ + for(int i = 0; i < NUM_DIALOG_SLOTS; i++) + { + previewHbmps[i] = NULL; + } + this->is_save_dialog = is_save_dialog; +} + + +CSaveLoadWithPreviewDlg::~CSaveLoadWithPreviewDlg() +{ + delete_preview_bmps(); +} + +bool CreatePreviewHbitmap(HBITMAP *hbmp) +{ + // create a HBITMAP to store the preview images in 32bit RGB + uint8_t* buffer = NULL; + BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER), 1); + bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bm->bmiHeader.biWidth = PREVIEW_IMAGE_WIDTH; + bm->bmiHeader.biHeight = -PREVIEW_IMAGE_HEIGHT; // negative is top-down + bm->bmiHeader.biPlanes = 1; + bm->bmiHeader.biBitCount = 32; + bm->bmiHeader.biCompression = BI_RGB; + bm->bmiHeader.biSizeImage = 0; + *hbmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0); + if(*hbmp == NULL) { + return false; + } + return true; +} + +void CSaveLoadWithPreviewDlg::delete_preview_bmps() +{ + for(int i = 0; i < NUM_DIALOG_SLOTS; i++) + { + if(previewHbmps[i]) + { + DeleteObject(previewHbmps[i]); + } + } +} + +bool CSaveLoadWithPreviewDlg::init_preview_bmps() +{ + for(int i = 0; i < NUM_DIALOG_SLOTS; i++) + { + if(!CreatePreviewHbitmap(&previewHbmps[i])) + return false; + } + return true; +} + +void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) +{ + // load the snapshot to receive the saved screenshot + FreezeUnfreezeSlot(slot, FALSE); + + // create temporary bitmap storage for screenshot, 16bit RGB + uint8_t* buffer = NULL; + BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), 1); + bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bm->bmiHeader.biWidth = IPPU.RenderedScreenWidth; + bm->bmiHeader.biHeight = -IPPU.RenderedScreenHeight; // negative is top-down + bm->bmiHeader.biPlanes = 1; + bm->bmiHeader.biBitCount = 16; + bm->bmiHeader.biCompression = BI_BITFIELDS; + bm->bmiHeader.biSizeImage = IPPU.RenderedScreenWidth * IPPU.RenderedScreenHeight * 2; + *(unsigned long *)&bm->bmiColors[0] = FIRST_COLOR_MASK_RGB565; + *(unsigned long *)&bm->bmiColors[1] = SECOND_COLOR_MASK_RGB565; + *(unsigned long *)&bm->bmiColors[2] = THIRD_COLOR_MASK_RGB565; + HBITMAP imageBmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0); + if(imageBmp == NULL) + { + free(bm); + return; + } + + int row_bytes = IPPU.RenderedScreenWidth * 2 / 4 * 4; // DIBs always have 4-byte aligned rows + if(IPPU.RenderedScreenWidth * 2 % 4) + row_bytes += 4; + + // copy saved screenshot into temporary bitmap + uint16 *screen = GFX.Screen; + for(int h = 0; h < IPPU.RenderedScreenHeight; h++, screen += GFX.RealPPL) + { + uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes)); + for(int w = 0; w < IPPU.RenderedScreenWidth; w++) + { + row_start[w] = screen[w]; + } + } + + // strech temporary bitmap into HBIMAP for button + HDC cdc = CreateCompatibleDC(GetDC(NULL)); + HGDIOBJ old = SelectObject(cdc, previewHbmps[slot]); + int ret = StretchDIBits(cdc, 0, 0, PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, buffer, bm, DIB_RGB_COLORS, SRCCOPY); + SelectObject(cdc, old); + DeleteDC(cdc); + + free(bm); + + // set image to button + SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]); + + // text with filename and last write time + std::wstring static_text(PathFindFileName((wchar_t*)_tFromChar(Memory.ROMFilename))); + + // get file time details + char filename[_MAX_PATH + 1]; + GetSlotFilename(slot, filename); + HANDLE file_handle = CreateFile(_tFromChar(filename), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(file_handle != INVALID_HANDLE_VALUE) + { + FILETIME ft; + SYSTEMTIME stUTC, stLocal; + // transform from file time to local time + if(GetFileTime(file_handle, NULL, NULL, &ft) && + FileTimeToSystemTime(&ft, &stUTC) && + SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal)) + { + // reserve space for date and time (both received individually) + std::vector date_string; + date_string.resize(max( + GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, NULL, 0, NULL), + GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, NULL, 0) + )); + + GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, &date_string[0], 100, NULL); + static_text.append(L"\n").append(&date_string[0]); + GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, &date_string[0], 100); + static_text.append(L" ").append(&date_string[0]); + } + } + + // set the description text + SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), static_text.c_str()); +} + +void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) +{ + if(is_save_dialog) + SetWindowText(hDlg, L"Save with preview"); + + // we need to load snapshots to receive the preview images, so we save the current state, + // load the slots, then reload the backup + std::string backup_filename = S9xGetFilename(".preview_backup", SNAPSHOT_DIR); + + // create backup + FreezeUnfreeze(backup_filename.c_str(), true); + + int x_pos = 0; + int y_pos = 0; + for(int i = 0; i < NUM_DIALOG_SLOTS; i++) + { + // second row + if(i == NUM_DIALOG_SLOTS / 2) + { + x_pos = 0; + y_pos = PREVIEW_HEIGHT + PREVIEW_TEXT_STATIC_HEIGHT; + } + + // create button and static for one slot + CreateWindow(TEXT("BUTTON"), NULL, WS_CHILDWINDOW | WS_VISIBLE | BS_BITMAP, x_pos, y_pos, PREVIEW_WIDHT, PREVIEW_HEIGHT, hDlg, (HMENU)(UINT_PTR)(IDC_BUTTON_SLOT_1 + i), GUI.hInstance, NULL); + HWND hStatic = CreateWindow(TEXT("STATIC"), TEXT(""), WS_CHILDWINDOW | WS_VISIBLE | SS_CENTER, x_pos, y_pos + PREVIEW_HEIGHT, PREVIEW_WIDHT, PREVIEW_TEXT_STATIC_HEIGHT, hDlg, (HMENU)(UINT_PTR)(IDC_STATIC_SLOT_1 + i), GUI.hInstance, NULL); + x_pos += PREVIEW_WIDHT; + + // set dialog font to static + HFONT dlg_font = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0); + SendMessage(hStatic, WM_SETFONT, (WPARAM)dlg_font, MAKELPARAM(FALSE, 0)); + + // load one slot + load_slot_image_text(i, hDlg); + } + + // resize dialog to fit all buttons and text + int dialog_width = NUM_DIALOG_SLOTS / 2 * PREVIEW_WIDHT; + int dialog_height = 2 * (PREVIEW_HEIGHT + PREVIEW_TEXT_STATIC_HEIGHT) + 40; // +40 for cancel button + + // reposition cancel button + RECT rect_cancel, client_rect; + GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rect_cancel); + POINT topleft = { rect_cancel.left, rect_cancel.top }; + ScreenToClient(hDlg, &topleft); + GetClientRect(hDlg, &client_rect); + MoveWindow(GetDlgItem(hDlg, IDCANCEL), dialog_width - (client_rect.right - topleft.x), dialog_height - 30, rect_cancel.right - rect_cancel.left, rect_cancel.bottom - rect_cancel.top, TRUE); + + // get monitor dimensions + HMONITOR hm; + MONITORINFO mi; + hm = MonitorFromWindow(GUI.hWnd, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(hm, &mi); + + // get title bar and borders + RECT rcMargins = { 0,0,0,0 }; + AdjustWindowRectEx(&rcMargins, GetWindowStyle(hDlg), FALSE, GetWindowExStyle(hDlg)); + rcMargins.left = abs(rcMargins.left); + rcMargins.top = abs(rcMargins.top); + + // add margins to window dimensions and position window in center of screen + dialog_height += rcMargins.top + rcMargins.bottom; + dialog_width += rcMargins.left + rcMargins.right; + int left = (mi.rcWork.right - mi.rcWork.left - dialog_width) / 2; + int top = (mi.rcWork.bottom - mi.rcWork.top - dialog_height) / 2; + SetWindowPos(hDlg, NULL, left, top, dialog_width, dialog_height, SWP_NOZORDER); + + // load backup, remove temporary state + FreezeUnfreeze(backup_filename.c_str(), false); + remove(backup_filename.c_str()); +} + +INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CSaveLoadWithPreviewDlg* dlg = (CSaveLoadWithPreviewDlg*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + switch(msg) + { + case WM_INITDIALOG: + { + SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); + dlg = (CSaveLoadWithPreviewDlg*)lParam; + dlg->init_window(hDlg); + } + return true; + case WM_COMMAND: + { + // return which button was pressed, or -1 for cancel + int id = LOWORD(wParam); + if(id >= IDC_BUTTON_SLOT_1 && id < IDC_BUTTON_SLOT_1 + NUM_DIALOG_SLOTS) + { + EndDialog(hDlg, id - IDC_BUTTON_SLOT_1); + return true; + } + else if(id == IDCANCEL) + { + EndDialog(hDlg, -1); + return true; + } + } + default: + return false; + } +} + +int CSaveLoadWithPreviewDlg::show() +{ + // disable text and confirm for the duration of the dialog + uint32 save_timeout = Settings.InitialInfoStringTimeout; + bool save_confirm = GUI.ConfirmSaveLoad; + Settings.InitialInfoStringTimeout = 0; + GUI.ConfirmSaveLoad = false; + + int ret = -1; + delete_preview_bmps(); + if(init_preview_bmps()) + { + ret = DialogBoxParam(GUI.hInstance, MAKEINTRESOURCE(IDD_DIALOG_LOAD_PREVIEW), GUI.hWnd, DlgLoadWithPreview, (LPARAM)this); + } + + GUI.ConfirmSaveLoad = save_confirm; + Settings.InitialInfoStringTimeout = save_timeout; + return ret; +} diff --git a/win32/CSaveLoadWithPreviewDlg.h b/win32/CSaveLoadWithPreviewDlg.h new file mode 100644 index 00000000..d4147c9f --- /dev/null +++ b/win32/CSaveLoadWithPreviewDlg.h @@ -0,0 +1,37 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#pragma once +#include "windows.h" + +#define NUM_DIALOG_SLOTS 10 + +#define PREVIEW_IMAGE_WIDTH SNES_WIDTH +#define PREVIEW_IMAGE_HEIGHT SNES_HEIGHT +#define PREVIEW_WIDHT (PREVIEW_IMAGE_WIDTH + 10) +#define PREVIEW_HEIGHT (PREVIEW_IMAGE_HEIGHT + 10) +#define PREVIEW_TEXT_STATIC_HEIGHT 50 + +class CSaveLoadWithPreviewDlg +{ +private: + static INT_PTR CALLBACK DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + + HBITMAP previewHbmps[NUM_DIALOG_SLOTS]; + bool is_save_dialog; + + void delete_preview_bmps(); + bool init_preview_bmps(); + void load_slot_image_text(int slot, HWND hDlg); + void init_window(HWND hDlg); + +public: + CSaveLoadWithPreviewDlg(bool is_save_dialog = false); + virtual ~CSaveLoadWithPreviewDlg(); + + int show(); +}; + diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index 8bbce310..94c4888b 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -45,6 +45,7 @@ #define IDI_ICON3 161 #define IDI_ICON4 162 #define IDD_DIALOG_HACKS 164 +#define IDD_DIALOG_LOAD_PREVIEW 167 #define IDC_DRIVER 1001 #define IDC_BUFLEN 1002 #define IDC_RATE 1003 @@ -404,6 +405,8 @@ #define IDC_SFX_CLOCK_SPEED_SPIN 3036 #define IDC_NO_SPRITE_LIMIT 3037 #define IDC_SET_DEFAULTS 3038 +#define IDC_BUTTON_SLOT_1 3039 +#define IDC_STATIC_SLOT_1 3059 #define ID_FILE_EXIT 40001 #define ID_WINDOW_HIDEMENUBAR 40004 #define ID_FILE_AVI_RECORDING 40005 @@ -520,6 +523,8 @@ #define ID_INPUT_BACKGROUNDKEYBOARDHOTKEYS 40176 #define ID_INPUT_DETECTGAMEPADCHANGES 40177 #define ID_EMULATION_HACKS 40178 +#define ID_FILE_LOAD_PREVIEW 40179 +#define ID_FILE_SAVE_PREVIEW 40180 #define ID_FILE_SAVE0 44000 #define ID_FILE_SAVE1 44001 #define ID_FILE_SAVE2 44002 @@ -541,7 +546,7 @@ #define ID_FILE_LOAD7 44027 #define ID_FILE_LOAD8 44028 #define ID_FILE_LOAD9 44029 -#define ID_FILE_LOAD_OOPS 44030 +#define ID_FILE_LOAD_OOPS 44030 #define ID_FILE_LOAD_FILE 44031 #define IDM_MACSRIFLE_TOGGLE 44032 #define IDC_STATIC -1 @@ -550,9 +555,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 167 -#define _APS_NEXT_COMMAND_VALUE 40179 -#define _APS_NEXT_CONTROL_VALUE 3039 +#define _APS_NEXT_RESOURCE_VALUE 169 +#define _APS_NEXT_COMMAND_VALUE 40181 +#define _APS_NEXT_CONTROL_VALUE 3040 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 27bd2ecb..b35065ce 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -26,6 +26,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // Dialog // +IDD_DIALOG_LOAD_PREVIEW DIALOGEX 0, 0, 567, 247 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load with Preview" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,510,226,50,14 +END + IDD_SOUND_OPTS DIALOGEX 0, 0, 414, 158 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU CAPTION "Sound Settings" @@ -753,6 +761,13 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 113 END + IDD_DIALOG_LOAD_PREVIEW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 560 + TOPMARGIN, 7 + BOTTOMMARGIN, 240 + END END #endif // APSTUDIO_INVOKED @@ -912,6 +927,8 @@ BEGIN BEGIN MENUITEM "Dummy", ID_RECENT_DUMMY, INACTIVE END + MENUITEM "Load MultiCart...", ID_FILE_LOADMULTICART + MENUITEM SEPARATOR POPUP "&Save Game Position" BEGIN MENUITEM "Slot #&0", ID_FILE_SAVE0 @@ -944,7 +961,8 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&Select File", ID_FILE_LOAD_FILE END - MENUITEM "Load MultiCart...", ID_FILE_LOADMULTICART + MENUITEM "&Save with Preview", ID_FILE_SAVE_PREVIEW + MENUITEM "&Load with Preview", ID_FILE_LOAD_PREVIEW MENUITEM SEPARATOR POPUP "Save Other" BEGIN @@ -1182,6 +1200,11 @@ BEGIN 0 END +IDD_DIALOG_LOAD_PREVIEW AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // diff --git a/win32/snes9xw.vcxproj b/win32/snes9xw.vcxproj index 8ae8d6ea..f4076502 100644 --- a/win32/snes9xw.vcxproj +++ b/win32/snes9xw.vcxproj @@ -438,6 +438,7 @@ + @@ -582,6 +583,7 @@ + diff --git a/win32/snes9xw.vcxproj.filters b/win32/snes9xw.vcxproj.filters index 6d61a587..fa98da5b 100644 --- a/win32/snes9xw.vcxproj.filters +++ b/win32/snes9xw.vcxproj.filters @@ -285,6 +285,9 @@ Filter + + GUI + @@ -626,6 +629,9 @@ Filter + + GUI + @@ -886,4 +892,4 @@ - + \ No newline at end of file diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 1c8834d5..2424264c 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -35,6 +35,7 @@ #include "CCGShader.h" #include "../shaders/glsl.h" #include "CShaderParamDlg.h" +#include "CSaveLoadWithPreviewDlg.h" #include "../snes9x.h" #include "../memmap.h" #include "../cpuexec.h" @@ -462,9 +463,6 @@ void DoAVIOpen(const TCHAR* filename); void DoAVIClose(int reason); void RestoreGUIDisplay (); void RestoreSNESDisplay (); -void FreezeUnfreezeDialog(bool8 freeze); -void FreezeUnfreezeSlot(int slot, bool8 freeze); -void FreezeUnfreeze (const char *filename, bool8 freeze); void CheckDirectoryIsWritable (const char *filename); static void CheckMenuStates (); static void ResetFrameTimer (); @@ -2148,6 +2146,14 @@ LRESULT CALLBACK WinProc( case ID_FILE_LOAD_FILE: FreezeUnfreezeDialog(FALSE); break; + case ID_FILE_LOAD_PREVIEW: + { + CSaveLoadWithPreviewDlg dlg; + int slot = dlg.show(); + if(slot >= 0) + FreezeUnfreezeSlot(slot, FALSE); + break; + } case ID_FILE_SAVE0: FreezeUnfreezeSlot (0, TRUE); break; @@ -2181,6 +2187,14 @@ LRESULT CALLBACK WinProc( case ID_FILE_SAVE_FILE: FreezeUnfreezeDialog(TRUE); break; + case ID_FILE_SAVE_PREVIEW: + { + CSaveLoadWithPreviewDlg dlg(true); + int slot = dlg.show(); + if(slot >= 0) + FreezeUnfreezeSlot(slot, TRUE); + break; + } case ID_CHEAT_ENTER: RestoreGUIDisplay (); while (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEATER), hWnd, DlgCheater) == NC_SEARCHDB) @@ -3608,16 +3622,21 @@ void FreezeUnfreezeDialog(bool8 freeze) } } +void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]) +{ + char ext[_MAX_EXT + 1]; + + if(slot == -1) + strcpy(ext, ".oops"); + else + snprintf(ext, _MAX_EXT, ".%03d", slot); + strcpy(filename, S9xGetFilename(ext, SNAPSHOT_DIR)); +} + void FreezeUnfreezeSlot(int slot, bool8 freeze) { char filename[_MAX_PATH + 1]; - char ext[_MAX_EXT + 1]; - - if (slot == -1) - strcpy(ext, ".oops"); - else - snprintf(ext, _MAX_EXT, ".%03d", slot); - strcpy(filename, S9xGetFilename(ext, SNAPSHOT_DIR)); + GetSlotFilename(slot, filename); FreezeUnfreeze(filename, freeze); } @@ -3743,6 +3762,9 @@ static void CheckMenuStates () for (int i = ID_FILE_LOAD0; i <= ID_FILE_LOAD_FILE; i++) SetMenuItemInfo(GUI.hMenu, i, FALSE, &mii); + SetMenuItemInfo(GUI.hMenu, ID_FILE_SAVE_PREVIEW, FALSE, &mii); + SetMenuItemInfo(GUI.hMenu, ID_FILE_LOAD_PREVIEW, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_RESET, FALSE, &mii); SetMenuItemInfo (GUI.hMenu, ID_CHEAT_ENTER, FALSE, &mii); SetMenuItemInfo (GUI.hMenu, ID_CHEAT_SEARCH_MODAL, FALSE, &mii); diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index cb09e3cf..199ddd2e 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -26,6 +26,7 @@ #include #endif #include "rsrc/resource.h" +#include "port.h" #define COUNT(a) (sizeof (a) / sizeof (a[0])) #define MAX_AUDIO_NAME_LENGTH 1024 @@ -458,5 +459,9 @@ int GetFilterScale(RenderFilter filterID); bool GetFilterHiResSupport(RenderFilter filterID); const TCHAR * S9xGetDirectoryT (enum s9x_getdirtype); RECT GetWindowMargins(HWND hwnd, UINT width); +void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]); +void FreezeUnfreezeSlot(int slot, bool8 freeze); +void FreezeUnfreezeDialog(bool8 freeze); +void FreezeUnfreeze(const char *filename, bool8 freeze); #endif // !defined(SNES9X_H_INCLUDED) From 3c2ef2aa21a203a19f52a8ceb6049e9d72f59cbd Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 19 Dec 2019 18:18:45 +0100 Subject: [PATCH 3/6] Add function to load only screenshot from snapshot file --- snapshot.cpp | 180 ++++++++++++++++++++++++++++++++++++++++++--------- snapshot.h | 2 + 2 files changed, 153 insertions(+), 29 deletions(-) diff --git a/snapshot.cpp b/snapshot.cpp index 7bda7019..84dd9c41 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1069,6 +1069,38 @@ int S9xUnfreezeGameMem (const uint8 *buf, uint32 bufSize) return result; } +void S9xMessageFromResult(int result, const char* base) +{ + switch(result) + { + case WRONG_FORMAT: + S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); + break; + + case WRONG_VERSION: + S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); + break; + + case WRONG_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); + break; + + case NOT_A_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); + break; + + case SNAPSHOT_INCONSISTENT: + S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; + + case FILE_NOT_FOUND: + default: + sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); + S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; + } +} + bool8 S9xUnfreezeGame (const char *filename) { STREAM stream = NULL; @@ -1088,35 +1120,7 @@ bool8 S9xUnfreezeGame (const char *filename) if (result != SUCCESS) { - switch (result) - { - case WRONG_FORMAT: - S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); - break; - - case WRONG_VERSION: - S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); - break; - - case WRONG_MOVIE_SNAPSHOT: - S9xMessage(S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); - break; - - case NOT_A_MOVIE_SNAPSHOT: - S9xMessage(S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); - break; - - case SNAPSHOT_INCONSISTENT: - S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); - break; - - case FILE_NOT_FOUND: - default: - sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); - S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); - break; - } - + S9xMessageFromResult(result, base); return (FALSE); } @@ -1141,6 +1145,34 @@ bool8 S9xUnfreezeGame (const char *filename) return (FALSE); } +bool8 S9xUnfreezeScreenshot(const char *filename, uint16 **image_buffer, int &width, int &height) +{ + STREAM stream = NULL; + + const char *base = S9xBasename(filename); + + if(S9xOpenSnapshotFile(filename, TRUE, &stream)) + { + int result; + + result = S9xUnfreezeScreenshotFromStream(stream, image_buffer, width, height); + S9xCloseSnapshotFile(stream); + + if(result != SUCCESS) + { + S9xMessageFromResult(result, base); + return (FALSE); + } + + return (TRUE); + } + + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (FALSE); +} + void S9xFreezeToStream (STREAM stream) { char buffer[8192]; @@ -1801,6 +1833,96 @@ int S9xUnfreezeFromStream (STREAM stream) return (result); } +// load screenshot from file, allocating memory for it +int S9xUnfreezeScreenshotFromStream(STREAM stream, uint16 **image_buffer, int &width, int &height) +{ + int result = SUCCESS; + int version, len; + char buffer[PATH_MAX + 1]; + + len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1; + if(READ_STREAM(buffer, len, stream) != (unsigned int)len) + return (WRONG_FORMAT); + + if(strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + + version = atoi(&buffer[strlen(SNAPSHOT_MAGIC) + 1]); + if(version > SNAPSHOT_VERSION) + return (WRONG_VERSION); + + result = UnfreezeBlock(stream, "NAM", (uint8 *)buffer, PATH_MAX); + if(result != SUCCESS) + return (result); + + uint8 *local_screenshot = NULL; + + // skip all blocks until screenshot + SkipBlockWithName(stream, "CPU"); + SkipBlockWithName(stream, "REG"); + SkipBlockWithName(stream, "PPU"); + SkipBlockWithName(stream, "DMA"); + SkipBlockWithName(stream, "VRA"); + SkipBlockWithName(stream, "RAM"); + SkipBlockWithName(stream, "SRA"); + SkipBlockWithName(stream, "FIL"); + SkipBlockWithName(stream, "SND"); + SkipBlockWithName(stream, "CTL"); + SkipBlockWithName(stream, "TIM"); + SkipBlockWithName(stream, "SFX"); + SkipBlockWithName(stream, "SA1"); + SkipBlockWithName(stream, "SAR"); + SkipBlockWithName(stream, "DP1"); + SkipBlockWithName(stream, "DP2"); + SkipBlockWithName(stream, "DP4"); + SkipBlockWithName(stream, "CX4"); + SkipBlockWithName(stream, "ST0"); + SkipBlockWithName(stream, "OBC"); + SkipBlockWithName(stream, "OBM"); + SkipBlockWithName(stream, "S71"); + SkipBlockWithName(stream, "SRT"); + SkipBlockWithName(stream, "CLK"); + SkipBlockWithName(stream, "BSX"); + SkipBlockWithName(stream, "MSU"); + result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); + + + if(result == SUCCESS && local_screenshot) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + + UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version); + + width = min(ssi->Width, IMAGE_WIDTH); + height = min(ssi->Height, IMAGE_HEIGHT); + + *image_buffer = (uint16 *)malloc(width * height * sizeof(uint16)); + + uint8 *rowpix = ssi->Data; + uint16 *screen = (*image_buffer); + + for(int y = 0; y < height; y++, screen += width) + { + for(int x = 0; x < width; x++) + { + uint32 r, g, b; + + r = *(rowpix++); + g = *(rowpix++); + b = *(rowpix++); + + screen[x] = BUILD_PIXEL(r, g, b); + } + } + + delete ssi; + } + + if(local_screenshot) delete[] local_screenshot; + + return (result); +} + static int FreezeSize (int size, int type) { switch (type) diff --git a/snapshot.h b/snapshot.h index f1a5ecc4..03e59856 100644 --- a/snapshot.h +++ b/snapshot.h @@ -31,5 +31,7 @@ bool8 S9xUnfreezeGame (const char *); int S9xUnfreezeGameMem (const uint8 *,uint32); void S9xFreezeToStream (STREAM); int S9xUnfreezeFromStream (STREAM); +bool8 S9xUnfreezeScreenshot(const char *filename, uint16 **image_buffer, int &width, int &height); +int S9xUnfreezeScreenshotFromStream(STREAM stream, uint16 **image_buffer, int &width, int &height); #endif From 04a15d9a2e4766caad28eb06c763a5d8f003c681 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 19 Dec 2019 18:19:50 +0100 Subject: [PATCH 4/6] win32: only load screenshots in preview dialogs --- win32/CSaveLoadWithPreviewDlg.cpp | 167 +++++++++++++++--------------- win32/wsnes9x.cpp | 8 ++ win32/wsnes9x.h | 1 + 3 files changed, 91 insertions(+), 85 deletions(-) diff --git a/win32/CSaveLoadWithPreviewDlg.cpp b/win32/CSaveLoadWithPreviewDlg.cpp index e2f1f89c..fc4cb73b 100644 --- a/win32/CSaveLoadWithPreviewDlg.cpp +++ b/win32/CSaveLoadWithPreviewDlg.cpp @@ -71,88 +71,96 @@ bool CSaveLoadWithPreviewDlg::init_preview_bmps() void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) { - // load the snapshot to receive the saved screenshot - FreezeUnfreezeSlot(slot, FALSE); + uint16 *image_buffer; + int width, height; - // create temporary bitmap storage for screenshot, 16bit RGB - uint8_t* buffer = NULL; - BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), 1); - bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bm->bmiHeader.biWidth = IPPU.RenderedScreenWidth; - bm->bmiHeader.biHeight = -IPPU.RenderedScreenHeight; // negative is top-down - bm->bmiHeader.biPlanes = 1; - bm->bmiHeader.biBitCount = 16; - bm->bmiHeader.biCompression = BI_BITFIELDS; - bm->bmiHeader.biSizeImage = IPPU.RenderedScreenWidth * IPPU.RenderedScreenHeight * 2; - *(unsigned long *)&bm->bmiColors[0] = FIRST_COLOR_MASK_RGB565; - *(unsigned long *)&bm->bmiColors[1] = SECOND_COLOR_MASK_RGB565; - *(unsigned long *)&bm->bmiColors[2] = THIRD_COLOR_MASK_RGB565; - HBITMAP imageBmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0); - if(imageBmp == NULL) + // load the saved screenshot from a snapshot + if(UnfreezeScreenshotSlot(slot, &image_buffer, width, height)) { + // create temporary bitmap storage for screenshot, 16bit RGB + uint8_t* buffer = NULL; + BITMAPINFO *bm = (BITMAPINFO *)calloc(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), 1); + bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bm->bmiHeader.biWidth = width; + bm->bmiHeader.biHeight = -height; // negative is top-down + bm->bmiHeader.biPlanes = 1; + bm->bmiHeader.biBitCount = 16; + bm->bmiHeader.biCompression = BI_BITFIELDS; + bm->bmiHeader.biSizeImage = width * height * 2; + *(unsigned long *)&bm->bmiColors[0] = FIRST_COLOR_MASK_RGB565; + *(unsigned long *)&bm->bmiColors[1] = SECOND_COLOR_MASK_RGB565; + *(unsigned long *)&bm->bmiColors[2] = THIRD_COLOR_MASK_RGB565; + HBITMAP imageBmp = CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&buffer, 0, 0); + if(imageBmp == NULL) + { + free(bm); + return; + } + + int row_bytes = width * 2 / 4 * 4; // DIBs always have 4-byte aligned rows + if(width * 2 % 4) + row_bytes += 4; + + // copy saved screenshot into temporary bitmap + uint16 *screen = image_buffer; + for(int h = 0; h < height; h++, screen += width) + { + uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes)); + for(int w = 0; w < width; w++) + { + row_start[w] = screen[w]; + } + } + + // strech temporary bitmap into HBIMAP for button + HDC cdc = CreateCompatibleDC(GetDC(NULL)); + HGDIOBJ old = SelectObject(cdc, previewHbmps[slot]); + int ret = StretchDIBits(cdc, 0, 0, PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 0, 0, width, height, buffer, bm, DIB_RGB_COLORS, SRCCOPY); + SelectObject(cdc, old); + DeleteDC(cdc); + free(bm); - return; - } - int row_bytes = IPPU.RenderedScreenWidth * 2 / 4 * 4; // DIBs always have 4-byte aligned rows - if(IPPU.RenderedScreenWidth * 2 % 4) - row_bytes += 4; + // set image to button + SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]); - // copy saved screenshot into temporary bitmap - uint16 *screen = GFX.Screen; - for(int h = 0; h < IPPU.RenderedScreenHeight; h++, screen += GFX.RealPPL) - { - uint16_t *row_start = (uint16_t*)(buffer + (h * row_bytes)); - for(int w = 0; w < IPPU.RenderedScreenWidth; w++) + char filename[_MAX_PATH + 1]; + GetSlotFilename(slot, filename); + Utf8ToWide filenameW(filename); + + // text with filename and last write time + std::wstring static_text(PathFindFileName(filenameW)); + + // get file time details + HANDLE file_handle = CreateFile(filenameW, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(file_handle != INVALID_HANDLE_VALUE) { - row_start[w] = screen[w]; + FILETIME ft; + SYSTEMTIME stUTC, stLocal; + // transform from file time to local time + if(GetFileTime(file_handle, NULL, NULL, &ft) && + FileTimeToSystemTime(&ft, &stUTC) && + SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal)) + { + // reserve space for date and time (both received individually) + std::vector date_string; + date_string.resize(max( + GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, NULL, 0, NULL), + GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, NULL, 0) + )); + + GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, &date_string[0], 100, NULL); + static_text.append(L"\n").append(&date_string[0]); + GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, &date_string[0], 100); + static_text.append(L" ").append(&date_string[0]); + } } + + // set the description text + SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), static_text.c_str()); + + free(image_buffer); } - - // strech temporary bitmap into HBIMAP for button - HDC cdc = CreateCompatibleDC(GetDC(NULL)); - HGDIOBJ old = SelectObject(cdc, previewHbmps[slot]); - int ret = StretchDIBits(cdc, 0, 0, PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, buffer, bm, DIB_RGB_COLORS, SRCCOPY); - SelectObject(cdc, old); - DeleteDC(cdc); - - free(bm); - - // set image to button - SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)previewHbmps[slot]); - - // text with filename and last write time - std::wstring static_text(PathFindFileName((wchar_t*)_tFromChar(Memory.ROMFilename))); - - // get file time details - char filename[_MAX_PATH + 1]; - GetSlotFilename(slot, filename); - HANDLE file_handle = CreateFile(_tFromChar(filename), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if(file_handle != INVALID_HANDLE_VALUE) - { - FILETIME ft; - SYSTEMTIME stUTC, stLocal; - // transform from file time to local time - if(GetFileTime(file_handle, NULL, NULL, &ft) && - FileTimeToSystemTime(&ft, &stUTC) && - SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal)) - { - // reserve space for date and time (both received individually) - std::vector date_string; - date_string.resize(max( - GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, NULL, 0, NULL), - GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, NULL, 0) - )); - - GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_AUTOLAYOUT | DATE_LONGDATE, &stLocal, NULL, &date_string[0], 100, NULL); - static_text.append(L"\n").append(&date_string[0]); - GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &stLocal, NULL, &date_string[0], 100); - static_text.append(L" ").append(&date_string[0]); - } - } - - // set the description text - SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), static_text.c_str()); } void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) @@ -160,13 +168,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) if(is_save_dialog) SetWindowText(hDlg, L"Save with preview"); - // we need to load snapshots to receive the preview images, so we save the current state, - // load the slots, then reload the backup - std::string backup_filename = S9xGetFilename(".preview_backup", SNAPSHOT_DIR); - - // create backup - FreezeUnfreeze(backup_filename.c_str(), true); - int x_pos = 0; int y_pos = 0; for(int i = 0; i < NUM_DIALOG_SLOTS; i++) @@ -222,10 +223,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) int left = (mi.rcWork.right - mi.rcWork.left - dialog_width) / 2; int top = (mi.rcWork.bottom - mi.rcWork.top - dialog_height) / 2; SetWindowPos(hDlg, NULL, left, top, dialog_width, dialog_height, SWP_NOZORDER); - - // load backup, remove temporary state - FreezeUnfreeze(backup_filename.c_str(), false); - remove(backup_filename.c_str()); } INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 2424264c..6e01694f 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -3703,6 +3703,14 @@ void FreezeUnfreeze (const char *filename, bool8 freeze) S9xClearPause (PAUSE_FREEZE_FILE); } +bool UnfreezeScreenshotSlot(int slot, uint16 **image_buffer, int &width, int &height) +{ + char filename[_MAX_PATH + 1]; + GetSlotFilename(slot, filename); + + return S9xUnfreezeScreenshot(filename, image_buffer, width, height); +} + void CheckDirectoryIsWritable (const char *filename) { FILE *fs = fopen (filename, "w+"); diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 199ddd2e..d40b1ad0 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -463,5 +463,6 @@ void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]); void FreezeUnfreezeSlot(int slot, bool8 freeze); void FreezeUnfreezeDialog(bool8 freeze); void FreezeUnfreeze(const char *filename, bool8 freeze); +bool UnfreezeScreenshotSlot(int slot, uint16 **image_buffer, int &width, int &height); #endif // !defined(SNES9X_H_INCLUDED) From e47e41627f1f2b009587588b16c93d9098cf7d42 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 20 Dec 2019 16:39:07 +0100 Subject: [PATCH 5/6] win32: add hotkeys for preview dialog --- win32/InputCustom.cpp | 5 +- win32/rsrc/resource.h | 3 + win32/rsrc/snes9x.rc | 184 +++++++++++++++++++++--------------------- win32/wconfig.cpp | 2 +- win32/wsnes9x.cpp | 57 +++++++++---- win32/wsnes9x.h | 7 +- 6 files changed, 145 insertions(+), 113 deletions(-) diff --git a/win32/InputCustom.cpp b/win32/InputCustom.cpp index 013fc54c..de74534f 100644 --- a/win32/InputCustom.cpp +++ b/win32/InputCustom.cpp @@ -488,16 +488,15 @@ int GetNumHotKeysAssignedTo (WORD Key, int modifiers) if(MATCHES_KEY(SlotMinus)) count++; if(MATCHES_KEY(SlotSave)) count++; if(MATCHES_KEY(SlotLoad)) count++; + if(MATCHES_KEY(DialogSave)) count++; + if(MATCHES_KEY(DialogLoad)) count++; if(MATCHES_KEY(BGL1)) count++; if(MATCHES_KEY(BGL2)) count++; if(MATCHES_KEY(BGL3)) count++; if(MATCHES_KEY(BGL4)) count++; if(MATCHES_KEY(BGL5)) count++; if(MATCHES_KEY(ClippingWindows)) count++; -// if(MATCHES_KEY(BGLHack)) count++; if(MATCHES_KEY(Transparency)) count++; -// if(MATCHES_KEY(GLCube)) count++; -// if(MATCHES_KEY(InterpMode7)) count++; if(MATCHES_KEY(JoypadSwap)) count++; if(MATCHES_KEY(SwitchControllers)) count++; if(MATCHES_KEY(TurboA)) count++; diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index 94c4888b..b4d650a3 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -281,6 +281,7 @@ #define IDC_LABEL_UP19 1198 #define IDC_ASPECT 1199 #define IDC_LABEL_UP26 1199 +#define IDC_LABEL_UP27 1200 #define IDC_MESSAGES_IN_IMAGE 1200 #define IDC_RECORD_NOW 1201 #define IDC_MESSAGES_SCALE 1201 @@ -309,6 +310,7 @@ #define IDC_MOVIEROMINFO 1216 #define IDC_SAVE10 1217 #define IDC_CURRENTROMINFO 1217 +#define IDC_DIALOGSAVE 1218 #define IDC_SAVE11 1219 #define IDC_DISPLAY_INPUT 1220 #define IDC_SAVE12 1220 @@ -322,6 +324,7 @@ #define IDC_SAVE20 1228 #define IDC_LABEL_UP20 1229 #define IDC_LABEL_UP21 1230 +#define IDC_DIALOGLOAD 1231 #define IDC_LABEL_UP22 1234 #define IDC_SLOTMINUS 1235 #define IDC_LABEL_UP23 1236 diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index b35065ce..3ceaec92 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -426,91 +426,95 @@ BEGIN CONTROL "Clear SRAM",IDC_CLEARSRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,96,70,10 END -IDD_KEYCUSTOM DIALOGEX 0, 0, 408, 206 +IDD_KEYCUSTOM DIALOGEX 0, 0, 409, 272 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION CAPTION "Customize Special Keys" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - PUSHBUTTON "Cancel",IDCANCEL,354,186,48,14 - PUSHBUTTON "OK",IDOK,300,186,48,14 + PUSHBUTTON "Cancel",IDCANCEL,354,252,48,14 + PUSHBUTTON "OK",IDOK,300,252,48,14 RTEXT "Speed +:",IDC_LABEL_HK1,12,30,72,12 - RTEXT "Frame advance:",IDC_LABEL_HK4,12,66,72,12 - RTEXT "Speed -:",IDC_LABEL_HK2,12,42,72,12 - RTEXT "Pause:",IDC_LABEL_HK3,12,54,72,12 - RTEXT "Frameskip +:",IDC_LABEL_HK6,12,90,72,12 - RTEXT "Movie frame count:",IDC_LABEL_HK11,12,150,72,12 - RTEXT "SuperScope turbo:",IDC_LABEL_HK8,12,114,72,12 - RTEXT "Movie read-only:",IDC_LABEL_HK12,12,162,72,12 - RTEXT "SuperScope pause:",IDC_LABEL_HK9,12,126,72,12 - RTEXT "Frameskip -:",IDC_LABEL_HK7,12,102,72,12 - CONTROL "",IDC_HOTKEY1,"InputCustomHot",WS_TABSTOP,90,30,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY2,"InputCustomHot",WS_TABSTOP,90,42,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY3,"InputCustomHot",WS_TABSTOP,90,54,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY4,"InputCustomHot",WS_TABSTOP,90,66,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY5,"InputCustomHot",WS_TABSTOP,90,78,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY6,"InputCustomHot",WS_TABSTOP,90,90,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY7,"InputCustomHot",WS_TABSTOP,90,102,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY8,"InputCustomHot",WS_TABSTOP,90,114,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY9,"InputCustomHot",WS_TABSTOP,90,126,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY10,"InputCustomHot",WS_TABSTOP,90,138,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY11,"InputCustomHot",WS_TABSTOP,90,150,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY12,"InputCustomHot",WS_TABSTOP,90,162,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_HOTKEY13,"InputCustomHot",WS_TABSTOP,90,174,90,11,WS_EX_CLIENTEDGE - CONTROL "",IDC_SAVE1,"InputCustomHot",WS_TABSTOP,234,18,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 1:",IDC_LABEL_UP2,198,30,30,12 - CONTROL "",IDC_SAVE2,"InputCustomHot",WS_TABSTOP,234,30,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 2:",IDC_LABEL_UP3,198,42,30,12 - CONTROL "",IDC_SAVE3,"InputCustomHot",WS_TABSTOP,234,42,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 3:",IDC_LABEL_UP4,198,54,30,12 - CONTROL "",IDC_SAVE4,"InputCustomHot",WS_TABSTOP,234,54,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 4:",IDC_LABEL_UP5,198,66,30,12 - CONTROL "",IDC_SAVE5,"InputCustomHot",WS_TABSTOP,234,66,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 5:",IDC_LABEL_UP6,198,78,30,12 - CONTROL "",IDC_SAVE6,"InputCustomHot",WS_TABSTOP,234,78,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 6:",IDC_LABEL_UP7,198,90,30,12 - CONTROL "",IDC_SAVE7,"InputCustomHot",WS_TABSTOP,234,90,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 7:",IDC_LABEL_UP8,198,102,30,12 - CONTROL "",IDC_SAVE8,"InputCustomHot",WS_TABSTOP,234,102,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 8:",IDC_LABEL_UP9,198,114,30,12 - CONTROL "",IDC_SAVE9,"InputCustomHot",WS_TABSTOP,234,114,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 9:",IDC_LABEL_UP10,198,126,30,12 - CONTROL "",IDC_SAVE10,"InputCustomHot",WS_TABSTOP,234,126,60,11,WS_EX_CLIENTEDGE - RTEXT "Save 0:",IDC_LABEL_UP11,198,18,30,12 - CONTROL "",IDC_SAVE11,"InputCustomHot",WS_TABSTOP,336,18,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 1:",IDC_LABEL_UP12,300,30,30,12 - CONTROL "",IDC_SAVE12,"InputCustomHot",WS_TABSTOP,336,30,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 2:",IDC_LABEL_UP13,300,42,30,12 - CONTROL "",IDC_SAVE13,"InputCustomHot",WS_TABSTOP,336,42,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 3:",IDC_LABEL_UP14,300,54,30,12 - CONTROL "",IDC_SAVE14,"InputCustomHot",WS_TABSTOP,336,54,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 4:",IDC_LABEL_UP15,300,66,30,12 - CONTROL "",IDC_SAVE15,"InputCustomHot",WS_TABSTOP,336,66,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 5:",IDC_LABEL_UP16,300,78,30,12 - CONTROL "",IDC_SAVE16,"InputCustomHot",WS_TABSTOP,336,78,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 6:",IDC_LABEL_UP17,300,90,30,12 - CONTROL "",IDC_SAVE17,"InputCustomHot",WS_TABSTOP,336,90,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 7:",IDC_LABEL_UP18,300,102,30,12 - CONTROL "",IDC_SAVE18,"InputCustomHot",WS_TABSTOP,336,102,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 8:",IDC_LABEL_UP19,300,114,30,12 - CONTROL "",IDC_SAVE19,"InputCustomHot",WS_TABSTOP,336,114,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 9:",IDC_LABEL_UP20,300,126,30,12 - CONTROL "",IDC_SAVE20,"InputCustomHot",WS_TABSTOP,336,126,60,11,WS_EX_CLIENTEDGE - RTEXT "Load 0:",IDC_LABEL_UP21,300,18,30,12 - RTEXT "Fast-forward:",IDC_LABEL_HK5,12,78,72,12 - RTEXT "Show pressed keys:",IDC_LABEL_HK10,12,138,72,12 - RTEXT "Save screenshot:",IDC_LABEL_HK13,12,174,72,12 - RTEXT "Slot -:",IDC_LABEL_UP22,198,150,30,12 - CONTROL "",IDC_SLOTMINUS,"InputCustomHot",WS_TABSTOP,234,150,60,11,WS_EX_CLIENTEDGE - RTEXT "Slot +:",IDC_LABEL_UP23,300,150,30,12 - CONTROL "",IDC_SLOTPLUS,"InputCustomHot",WS_TABSTOP,336,150,60,11,WS_EX_CLIENTEDGE - RTEXT "Save #:",IDC_LABEL_UP24,198,162,30,12 - CONTROL "",IDC_SLOTSAVE,"InputCustomHot",WS_TABSTOP,234,162,60,11,WS_EX_CLIENTEDGE - RTEXT "Load #:",IDC_LABEL_UP25,300,162,30,12 - CONTROL "",IDC_SLOTLOAD,"InputCustomHot",WS_TABSTOP,336,162,60,11,WS_EX_CLIENTEDGE - LTEXT "Blue means the hotkey is already mapped. Pink means it conflicts with a game button. Red means it's reserved by Windows. A hotkey can be disabled using Escape.",IDC_LABEL_BLUE,192,186,78,12,NOT WS_VISIBLE + RTEXT "Frame advance:",IDC_LABEL_HK4,12,75,72,12 + RTEXT "Speed -:",IDC_LABEL_HK2,12,45,72,12 + RTEXT "Pause:",IDC_LABEL_HK3,12,60,72,12 + RTEXT "Frameskip +:",IDC_LABEL_HK6,12,105,72,12 + RTEXT "Movie frame count:",IDC_LABEL_HK11,12,180,72,12 + RTEXT "SuperScope turbo:",IDC_LABEL_HK8,12,135,72,12 + RTEXT "Movie read-only:",IDC_LABEL_HK12,12,195,72,12 + RTEXT "SuperScope pause:",IDC_LABEL_HK9,12,150,72,12 + RTEXT "Frameskip -:",IDC_LABEL_HK7,12,120,72,12 + CONTROL "",IDC_HOTKEY1,"InputCustomHot",WS_TABSTOP,90,30,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY2,"InputCustomHot",WS_TABSTOP,90,45,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY3,"InputCustomHot",WS_TABSTOP,90,60,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY4,"InputCustomHot",WS_TABSTOP,90,75,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY5,"InputCustomHot",WS_TABSTOP,90,90,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY6,"InputCustomHot",WS_TABSTOP,90,105,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY7,"InputCustomHot",WS_TABSTOP,90,120,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY8,"InputCustomHot",WS_TABSTOP,90,135,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY9,"InputCustomHot",WS_TABSTOP,90,150,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY10,"InputCustomHot",WS_TABSTOP,90,165,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY11,"InputCustomHot",WS_TABSTOP,90,180,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY12,"InputCustomHot",WS_TABSTOP,90,195,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY13,"InputCustomHot",WS_TABSTOP,90,210,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_SAVE1,"InputCustomHot",WS_TABSTOP,217,30,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 1:",IDC_LABEL_UP2,181,45,30,12 + CONTROL "",IDC_SAVE2,"InputCustomHot",WS_TABSTOP,217,45,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 2:",IDC_LABEL_UP3,181,60,30,12 + CONTROL "",IDC_SAVE3,"InputCustomHot",WS_TABSTOP,217,60,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 3:",IDC_LABEL_UP4,181,75,30,12 + CONTROL "",IDC_SAVE4,"InputCustomHot",WS_TABSTOP,217,75,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 4:",IDC_LABEL_UP5,181,90,30,12 + CONTROL "",IDC_SAVE5,"InputCustomHot",WS_TABSTOP,217,90,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 5:",IDC_LABEL_UP6,181,105,30,12 + CONTROL "",IDC_SAVE6,"InputCustomHot",WS_TABSTOP,217,105,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 6:",IDC_LABEL_UP7,181,120,30,12 + CONTROL "",IDC_SAVE7,"InputCustomHot",WS_TABSTOP,217,120,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 7:",IDC_LABEL_UP8,181,135,30,12 + CONTROL "",IDC_SAVE8,"InputCustomHot",WS_TABSTOP,217,135,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 8:",IDC_LABEL_UP9,181,150,30,12 + CONTROL "",IDC_SAVE9,"InputCustomHot",WS_TABSTOP,217,150,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 9:",IDC_LABEL_UP10,181,165,30,12 + CONTROL "",IDC_SAVE10,"InputCustomHot",WS_TABSTOP,217,165,60,12,WS_EX_CLIENTEDGE + RTEXT "Save 0:",IDC_LABEL_UP11,181,30,30,12 + CONTROL "",IDC_SAVE11,"InputCustomHot",WS_TABSTOP,336,30,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 1:",IDC_LABEL_UP12,300,45,30,12 + CONTROL "",IDC_SAVE12,"InputCustomHot",WS_TABSTOP,336,45,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 2:",IDC_LABEL_UP13,300,60,30,12 + CONTROL "",IDC_SAVE13,"InputCustomHot",WS_TABSTOP,336,60,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 3:",IDC_LABEL_UP14,300,75,30,12 + CONTROL "",IDC_SAVE14,"InputCustomHot",WS_TABSTOP,336,75,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 4:",IDC_LABEL_UP15,300,90,30,12 + CONTROL "",IDC_SAVE15,"InputCustomHot",WS_TABSTOP,336,90,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 5:",IDC_LABEL_UP16,300,105,30,12 + CONTROL "",IDC_SAVE16,"InputCustomHot",WS_TABSTOP,336,105,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 6:",IDC_LABEL_UP17,300,120,30,12 + CONTROL "",IDC_SAVE17,"InputCustomHot",WS_TABSTOP,336,120,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 7:",IDC_LABEL_UP18,300,135,30,12 + CONTROL "",IDC_SAVE18,"InputCustomHot",WS_TABSTOP,336,135,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 8:",IDC_LABEL_UP19,300,150,30,12 + CONTROL "",IDC_SAVE19,"InputCustomHot",WS_TABSTOP,336,150,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 9:",IDC_LABEL_UP20,300,165,30,12 + CONTROL "",IDC_SAVE20,"InputCustomHot",WS_TABSTOP,336,165,60,12,WS_EX_CLIENTEDGE + RTEXT "Load 0:",IDC_LABEL_UP21,300,30,30,12 + RTEXT "Fast-forward:",IDC_LABEL_HK5,12,90,72,12 + RTEXT "Show pressed keys:",IDC_LABEL_HK10,12,165,72,12 + RTEXT "Save screenshot:",IDC_LABEL_HK13,12,210,72,12 + RTEXT "Slot -:",IDC_LABEL_UP22,181,195,30,12 + CONTROL "",IDC_SLOTMINUS,"InputCustomHot",WS_TABSTOP,217,195,60,12,WS_EX_CLIENTEDGE + RTEXT "Slot +:",IDC_LABEL_UP23,300,195,30,12 + CONTROL "",IDC_SLOTPLUS,"InputCustomHot",WS_TABSTOP,336,195,60,12,WS_EX_CLIENTEDGE + RTEXT "Save #:",IDC_LABEL_UP24,181,210,30,12 + CONTROL "",IDC_SLOTSAVE,"InputCustomHot",WS_TABSTOP,217,210,60,12,WS_EX_CLIENTEDGE + RTEXT "Load #:",IDC_LABEL_UP25,300,210,30,12 + CONTROL "",IDC_SLOTLOAD,"InputCustomHot",WS_TABSTOP,336,210,60,12,WS_EX_CLIENTEDGE + LTEXT "Blue means the hotkey is already mapped. Pink means it conflicts with a game button. Red means it's reserved by Windows. A hotkey can be disabled using Escape.",IDC_LABEL_BLUE,7,232,269,34 COMBOBOX IDC_HKCOMBO,6,6,60,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "",IDC_STATIC,6,18,180,174,0,WS_EX_TRANSPARENT - GROUPBOX "Save States",IDC_STATIC,192,6,210,174,0,WS_EX_TRANSPARENT + GROUPBOX "",IDC_STATIC,6,21,149,207,0,WS_EX_TRANSPARENT + GROUPBOX "Save States",IDC_STATIC,161,21,241,207,0,WS_EX_TRANSPARENT + RTEXT "Save Dialog:",IDC_LABEL_UP26,165,180,46,12 + CONTROL "",IDC_DIALOGSAVE,"InputCustomHot",WS_TABSTOP,217,180,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_DIALOGLOAD,"InputCustomHot",WS_TABSTOP,336,180,60,12,WS_EX_CLIENTEDGE + RTEXT "Load Dialog:",IDC_LABEL_UP27,284,180,46,12 END IDD_MULTICART DIALOGEX 0, 0, 390, 90 @@ -600,6 +604,14 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN + IDD_DIALOG_LOAD_PREVIEW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 560 + TOPMARGIN, 7 + BOTTOMMARGIN, 240 + END + IDD_SOUND_OPTS, DIALOG BEGIN LEFTMARGIN, 7 @@ -719,10 +731,9 @@ BEGIN IDD_KEYCUSTOM, DIALOG BEGIN - RIGHTMARGIN, 406 - VERTGUIDE, 72 - VERTGUIDE, 92 - BOTTOMMARGIN, 200 + RIGHTMARGIN, 407 + VERTGUIDE, 90 + BOTTOMMARGIN, 266 END IDD_MULTICART, DIALOG @@ -761,13 +772,6 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 113 END - IDD_DIALOG_LOAD_PREVIEW, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 560 - TOPMARGIN, 7 - BOTTOMMARGIN, 240 - END END #endif // APSTUDIO_INVOKED diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index 61b68bfc..f85afcba 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -917,7 +917,7 @@ void WinRegisterConfigItems() ADDN(Save[0],SaveSlot0); ADDN(Save[1],SaveSlot1); ADDN(Save[2],SaveSlot2); ADDN(Save[3],SaveSlot3); ADDN(Save[4],SaveSlot4); ADDN(Save[5],SaveSlot5); ADDN(Save[6],SaveSlot6); ADDN(Save[7],SaveSlot7); ADDN(Save[8],SaveSlot8); ADDN(Save[9],SaveSlot9); ADDN(Load[0],LoadSlot0); ADDN(Load[1],LoadSlot1); ADDN(Load[2],LoadSlot2); ADDN(Load[3],LoadSlot3); ADDN(Load[4],LoadSlot4); ADDN(Load[5],LoadSlot5); ADDN(Load[6],LoadSlot6); ADDN(Load[7],LoadSlot7); ADDN(Load[8],LoadSlot8); ADDN(Load[9],LoadSlot9); ADDN(SelectSave[0],SelectSlot0); ADDN(SelectSave[1],SelectSlot1); ADDN(SelectSave[2],SelectSlot2); ADDN(SelectSave[3],SelectSlot3); ADDN(SelectSave[4],SelectSlot4); ADDN(SelectSave[5],SelectSlot5); ADDN(SelectSave[6],SelectSlot6); ADDN(SelectSave[7],SelectSlot7); ADDN(SelectSave[8],SelectSlot8); ADDN(SelectSave[9],SelectSlot9); - ADD(SaveScreenShot); ADD(SlotPlus); ADD(SlotMinus); ADD(SlotSave); ADD(SlotLoad); + ADD(SaveScreenShot); ADD(SlotPlus); ADD(SlotMinus); ADD(SlotSave); ADD(SlotLoad); ADD(DialogSave); ADD(DialogLoad); ADD(BGL1); ADD(BGL2); ADD(BGL3); ADD(BGL4); ADD(BGL5); ADD(ClippingWindows); /*ADD(BGLHack);*/ ADD(Transparency); /*ADD(HDMA)*/; /*ADD(GLCube);*/ /*ADD(InterpMode7);*/ ADD(JoypadSwap); ADD(SwitchControllers); ADD(ResetGame); ADD(ToggleCheats); diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 6e01694f..49e33827 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -368,16 +368,15 @@ struct SCustomKeys CustomKeys = { {0,0}, // slot minus (disabled by default) {0,0}, // slot save (disabled by default) {0,0}, // slot load (disabled by default) + {VK_F11,CUSTKEY_SHIFT_MASK}, // dialog save + {VK_F11,0}, // dialog load {0,0}, // background layer 1 {0,0}, // background layer 2 {0,0}, // background layer 3 {0,0}, // background layer 4 {0,0}, // sprite layer {0,0}, // Clipping Windows -// {'8',0}, // BG Layering hack {0,0}, // Transparency -// {'6',CUSTKEY_SHIFT_MASK}, // GLCube Mode -// {'9',CUSTKEY_SHIFT_MASK}, // Interpolate Mode 7 {'6',0}, // Joypad Swap {'7',0}, // Switch Controllers {VK_NEXT,CUSTKEY_SHIFT_MASK}, // Turbo A @@ -856,6 +855,18 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) FreezeUnfreezeSlot (GUI.CurrentSaveSlot, false); hitHotKey = true; } + if(wParam == CustomKeys.DialogSave.key + && modifiers == CustomKeys.DialogSave.modifiers) + { + FreezeUnfreezeDialogPreview(true); + hitHotKey = true; + } + if(wParam == CustomKeys.DialogLoad.key + && modifiers == CustomKeys.DialogLoad.modifiers) + { + FreezeUnfreezeDialogPreview(false); + hitHotKey = true; + } if(wParam == CustomKeys.SlotPlus.key && modifiers == CustomKeys.SlotPlus.modifiers) { @@ -2147,13 +2158,8 @@ LRESULT CALLBACK WinProc( FreezeUnfreezeDialog(FALSE); break; case ID_FILE_LOAD_PREVIEW: - { - CSaveLoadWithPreviewDlg dlg; - int slot = dlg.show(); - if(slot >= 0) - FreezeUnfreezeSlot(slot, FALSE); + FreezeUnfreezeDialogPreview(FALSE); break; - } case ID_FILE_SAVE0: FreezeUnfreezeSlot (0, TRUE); break; @@ -2188,13 +2194,8 @@ LRESULT CALLBACK WinProc( FreezeUnfreezeDialog(TRUE); break; case ID_FILE_SAVE_PREVIEW: - { - CSaveLoadWithPreviewDlg dlg(true); - int slot = dlg.show(); - if(slot >= 0) - FreezeUnfreezeSlot(slot, TRUE); + FreezeUnfreezeDialogPreview(TRUE); break; - } case ID_CHEAT_ENTER: RestoreGUIDisplay (); while (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEATER), hWnd, DlgCheater) == NC_SEARCHDB) @@ -3622,6 +3623,17 @@ void FreezeUnfreezeDialog(bool8 freeze) } } +void FreezeUnfreezeDialogPreview(bool8 freeze) +{ + if(Settings.StopEmulation) + return; + + CSaveLoadWithPreviewDlg dlg(freeze); + int slot = dlg.show(); + if(slot >= 0) + FreezeUnfreezeSlot(slot, freeze); +} + void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]) { char ext[_MAX_EXT + 1]; @@ -3652,6 +3664,9 @@ void FreezeUnfreeze (const char *filename, bool8 freeze) } #endif + if(Settings.StopEmulation) + return; + if (GUI.ConfirmSaveLoad) { std::string msg, title; @@ -8397,6 +8412,8 @@ static void set_hotkeyinfo(HWND hDlg) SendDlgItemMessage(hDlg,IDC_SLOTMINUS,WM_USER+44,CustomKeys.SlotMinus.key,CustomKeys.SlotMinus.modifiers); SendDlgItemMessage(hDlg,IDC_SLOTSAVE,WM_USER+44,CustomKeys.SlotSave.key,CustomKeys.SlotSave.modifiers); SendDlgItemMessage(hDlg,IDC_SLOTLOAD,WM_USER+44,CustomKeys.SlotLoad.key,CustomKeys.SlotLoad.modifiers); + SendDlgItemMessage(hDlg, IDC_DIALOGSAVE, WM_USER + 44, CustomKeys.DialogSave.key, CustomKeys.DialogSave.modifiers); + SendDlgItemMessage(hDlg, IDC_DIALOGLOAD, WM_USER + 44, CustomKeys.DialogLoad.key, CustomKeys.DialogLoad.modifiers); int i; for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE1+i,WM_USER+44,CustomKeys.Save[i].key,CustomKeys.Save[i].modifiers); for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE11+i,WM_USER+44,CustomKeys.Load[i].key,CustomKeys.Load[i].modifiers); @@ -8641,6 +8658,16 @@ switch(msg) CustomKeys.SlotSave.key = wParam; CustomKeys.SlotSave.modifiers = modifiers; break; + + case IDC_DIALOGSAVE: + CustomKeys.DialogSave.key = wParam; + CustomKeys.DialogSave.modifiers = modifiers; + break; + + case IDC_DIALOGLOAD: + CustomKeys.DialogLoad.key = wParam; + CustomKeys.DialogLoad.modifiers = modifiers; + break; } if(which >= IDC_SAVE1 && which <= IDC_SAVE10) diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index d40b1ad0..99f88a62 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -308,17 +308,15 @@ struct SCustomKeys { SCustomKey SlotMinus; SCustomKey SlotSave; SCustomKey SlotLoad; + SCustomKey DialogSave; + SCustomKey DialogLoad; SCustomKey BGL1; SCustomKey BGL2; SCustomKey BGL3; SCustomKey BGL4; SCustomKey BGL5; SCustomKey ClippingWindows; -// SCustomKey BGLHack; SCustomKey Transparency; -// SCustomKey GLCube; -// SCustomKey HDMA; -// SCustomKey InterpMode7; SCustomKey JoypadSwap; SCustomKey SwitchControllers; SCustomKey TurboA, TurboB, TurboY, TurboX, TurboL, TurboR, TurboStart, TurboSelect, TurboLeft, TurboUp, TurboRight, TurboDown; @@ -462,6 +460,7 @@ RECT GetWindowMargins(HWND hwnd, UINT width); void GetSlotFilename(int slot, char filename[_MAX_PATH + 1]); void FreezeUnfreezeSlot(int slot, bool8 freeze); void FreezeUnfreezeDialog(bool8 freeze); +void FreezeUnfreezeDialogPreview(bool8 freeze); void FreezeUnfreeze(const char *filename, bool8 freeze); bool UnfreezeScreenshotSlot(int slot, uint16 **image_buffer, int &width, int &height); From 0291042e1c0e77c78f58b92b22a57c5d4ca8f198 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 25 Dec 2019 21:01:48 +0100 Subject: [PATCH 6/6] win32: easier definition of hotkey config dialog layout, change order of hotkeys --- win32/wlanguage.h | 38 +++--- win32/wsnes9x.cpp | 289 +++++++++++++++------------------------------- 2 files changed, 116 insertions(+), 211 deletions(-) diff --git a/win32/wlanguage.h b/win32/wlanguage.h index 8657bdad..334d9ede 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -81,15 +81,15 @@ Nintendo is a trademark.") #define HOTKEYS_LABEL_1_1 TEXT("Speed +:") #define HOTKEYS_LABEL_1_2 TEXT("Speed -:") #define HOTKEYS_LABEL_1_3 TEXT("Pause:") -#define HOTKEYS_LABEL_1_4 TEXT("Frame advance:") +#define HOTKEYS_LABEL_1_4 TEXT("Fast-forward toggle:") #define HOTKEYS_LABEL_1_5 TEXT("Fast forward:") -#define HOTKEYS_LABEL_1_6 TEXT("Skip frames +:") -#define HOTKEYS_LABEL_1_7 TEXT("Skip frames -:") -#define HOTKEYS_LABEL_1_8 TEXT("SuperScope turbo:") -#define HOTKEYS_LABEL_1_9 TEXT("SuperScope pause:") -#define HOTKEYS_LABEL_1_10 TEXT("Show pressed keys:") -#define HOTKEYS_LABEL_1_11 TEXT("Movie frame count:") -#define HOTKEYS_LABEL_1_12 TEXT("Movie read-only:") +#define HOTKEYS_LABEL_1_6 TEXT("Rewind:") +#define HOTKEYS_LABEL_1_7 TEXT("Skip frames +:") +#define HOTKEYS_LABEL_1_8 TEXT("Skip frames -:") +#define HOTKEYS_LABEL_1_9 TEXT("Toggle mute:") +#define HOTKEYS_LABEL_1_10 TEXT("Toggle cheats:") +#define HOTKEYS_LABEL_1_11 TEXT("Quit Snes9x:") +#define HOTKEYS_LABEL_1_12 TEXT("Reset game:") #define HOTKEYS_LABEL_1_13 TEXT("Save screenshot") #define HOTKEYS_LABEL_2_1 TEXT("Graphics layer 1:") #define HOTKEYS_LABEL_2_2 TEXT("Graphics layer 2:") @@ -98,12 +98,12 @@ Nintendo is a trademark.") #define HOTKEYS_LABEL_2_5 TEXT("Sprites layer:") #define HOTKEYS_LABEL_2_6 TEXT("Clipping Windows:") #define HOTKEYS_LABEL_2_7 TEXT("Transparency:") -#define HOTKEYS_LABEL_2_8 TEXT("Fast-forward toggle:") -#define HOTKEYS_LABEL_2_9 TEXT("Rewind:") +#define HOTKEYS_LABEL_2_8 TEXT("Frame advance:") +#define HOTKEYS_LABEL_2_9 TEXT("SuperScope pause:") #define HOTKEYS_LABEL_2_10 TEXT("Switch controllers:") #define HOTKEYS_LABEL_2_11 TEXT("Joypad swap:") -#define HOTKEYS_LABEL_2_12 TEXT("Reset game:") -#define HOTKEYS_LABEL_2_13 TEXT("Toggle cheats:") +#define HOTKEYS_LABEL_2_12 TEXT("Show pressed keys:") +#define HOTKEYS_LABEL_2_13 TEXT("Movie frame count:") #define HOTKEYS_LABEL_3_1 TEXT("Turbo A mode:") #define HOTKEYS_LABEL_3_2 TEXT("Turbo B mode:") #define HOTKEYS_LABEL_3_3 TEXT("Turbo Y mode:") @@ -116,10 +116,20 @@ Nintendo is a trademark.") #define HOTKEYS_LABEL_3_10 TEXT("Turbo Up mode:") #define HOTKEYS_LABEL_3_11 TEXT("Turbo Right mode:") #define HOTKEYS_LABEL_3_12 TEXT("Turbo Down mode:") -#define HOTKEYS_LABEL_3_13 TEXT("Toggle mute:") +#define HOTKEYS_LABEL_3_13 TEXT("SuperScope turbo:") +#define HOTKEYS_LABEL_4_1 TEXT("Select Slot 0:") +#define HOTKEYS_LABEL_4_2 TEXT("Select Slot 1:") +#define HOTKEYS_LABEL_4_3 TEXT("Select Slot 2:") +#define HOTKEYS_LABEL_4_4 TEXT("Select Slot 3:") +#define HOTKEYS_LABEL_4_5 TEXT("Select Slot 4:") +#define HOTKEYS_LABEL_4_6 TEXT("Select Slot 5:") +#define HOTKEYS_LABEL_4_7 TEXT("Select Slot 6:") +#define HOTKEYS_LABEL_4_8 TEXT("Select Slot 7:") +#define HOTKEYS_LABEL_4_9 TEXT("Select Slot 8:") +#define HOTKEYS_LABEL_4_10 TEXT("Select Slot 9:") #define HOTKEYS_LABEL_4_11 TEXT("Save to file:") #define HOTKEYS_LABEL_4_12 TEXT("Load from file:") -#define HOTKEYS_LABEL_4_13 TEXT("Quit Snes9x:") +#define HOTKEYS_LABEL_4_13 TEXT("Movie read-only:") // gaming buttons and axes #define GAMEDEVICE_JOYNUMPREFIX "(J%x)" // don't change this diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 49e33827..36bec98e 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -126,6 +126,8 @@ void S9xDetectJoypads(); #define TIMER_SCANJOYPADS (99999) #define NC_SEARCHDB 0x8000 +#define MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS 13 + #ifdef UNICODE #define S9XW_SHARD_PATH SHARD_PATHW #else @@ -8346,67 +8348,90 @@ switch(msg) return FALSE; } +struct hotkey_dialog_item { + SCustomKey *key_entry; + TCHAR *description; +}; + +// this structure defines the four sub pages in the hotkey config dialog +// to keep an entry blank, set the SCustomKey pointer to NULL and the text to an empty string +static hotkey_dialog_item hotkey_dialog_items[4][MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS] = { + { + { &CustomKeys.SpeedUp, HOTKEYS_LABEL_1_1 }, + { &CustomKeys.SpeedDown, HOTKEYS_LABEL_1_2 }, + { &CustomKeys.Pause, HOTKEYS_LABEL_1_3 }, + { &CustomKeys.FastForwardToggle, HOTKEYS_LABEL_1_4 }, + { &CustomKeys.FastForward, HOTKEYS_LABEL_1_5 }, + { &CustomKeys.Rewind, HOTKEYS_LABEL_1_6 }, + { &CustomKeys.SkipUp, HOTKEYS_LABEL_1_7 }, + { &CustomKeys.SkipDown, HOTKEYS_LABEL_1_8 }, + { &CustomKeys.Mute, HOTKEYS_LABEL_1_9 }, + { &CustomKeys.ToggleCheats, HOTKEYS_LABEL_1_10 }, + { &CustomKeys.QuitS9X, HOTKEYS_LABEL_1_11 }, + { &CustomKeys.ResetGame, HOTKEYS_LABEL_1_12 }, + { &CustomKeys.SaveScreenShot, HOTKEYS_LABEL_1_13 }, + }, + { + { &CustomKeys.BGL1, HOTKEYS_LABEL_2_1 }, + { &CustomKeys.BGL2, HOTKEYS_LABEL_2_2 }, + { &CustomKeys.BGL3, HOTKEYS_LABEL_2_3 }, + { &CustomKeys.BGL4, HOTKEYS_LABEL_2_4 }, + { &CustomKeys.BGL5, HOTKEYS_LABEL_2_5 }, + { &CustomKeys.ClippingWindows, HOTKEYS_LABEL_2_6 }, + { &CustomKeys.Transparency, HOTKEYS_LABEL_2_7 }, + { &CustomKeys.FrameAdvance, HOTKEYS_LABEL_2_8 }, + { &CustomKeys.ScopePause, HOTKEYS_LABEL_2_9 }, + { &CustomKeys.SwitchControllers, HOTKEYS_LABEL_2_10 }, + { &CustomKeys.JoypadSwap, HOTKEYS_LABEL_2_11 }, + { &CustomKeys.ShowPressed, HOTKEYS_LABEL_2_12 }, + { &CustomKeys.FrameCount, HOTKEYS_LABEL_2_13 }, + }, + { + { &CustomKeys.TurboA, HOTKEYS_LABEL_3_1 }, + { &CustomKeys.TurboB, HOTKEYS_LABEL_3_2 }, + { &CustomKeys.TurboY, HOTKEYS_LABEL_3_3 }, + { &CustomKeys.TurboX, HOTKEYS_LABEL_3_4 }, + { &CustomKeys.TurboL, HOTKEYS_LABEL_3_5 }, + { &CustomKeys.TurboR, HOTKEYS_LABEL_3_6 }, + { &CustomKeys.TurboStart, HOTKEYS_LABEL_3_7 }, + { &CustomKeys.TurboSelect, HOTKEYS_LABEL_3_8 }, + { &CustomKeys.TurboLeft, HOTKEYS_LABEL_3_9 }, + { &CustomKeys.TurboUp, HOTKEYS_LABEL_3_10 }, + { &CustomKeys.TurboRight, HOTKEYS_LABEL_3_11 }, + { &CustomKeys.TurboDown, HOTKEYS_LABEL_3_12 }, + { &CustomKeys.ScopeTurbo, HOTKEYS_LABEL_3_13 }, + }, + { + { &CustomKeys.SelectSave[0], HOTKEYS_LABEL_4_1 }, + { &CustomKeys.SelectSave[1], HOTKEYS_LABEL_4_2 }, + { &CustomKeys.SelectSave[2], HOTKEYS_LABEL_4_3 }, + { &CustomKeys.SelectSave[3], HOTKEYS_LABEL_4_4 }, + { &CustomKeys.SelectSave[4], HOTKEYS_LABEL_4_5 }, + { &CustomKeys.SelectSave[5], HOTKEYS_LABEL_4_6 }, + { &CustomKeys.SelectSave[6], HOTKEYS_LABEL_4_7 }, + { &CustomKeys.SelectSave[7], HOTKEYS_LABEL_4_8 }, + { &CustomKeys.SelectSave[8], HOTKEYS_LABEL_4_9 }, + { &CustomKeys.SelectSave[9], HOTKEYS_LABEL_4_10 }, + { &CustomKeys.SaveFileSelect, HOTKEYS_LABEL_4_11 }, + { &CustomKeys.LoadFileSelect, HOTKEYS_LABEL_4_12 }, + { &CustomKeys.ReadOnly, HOTKEYS_LABEL_4_13 }, + }, +}; static void set_hotkeyinfo(HWND hDlg) { int index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0); - switch(index) - { - case 0: - // set page 1 fields - SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.SpeedUp.key,CustomKeys.SpeedUp.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.SpeedDown.key,CustomKeys.SpeedDown.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.Pause.key,CustomKeys.Pause.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.FrameAdvance.key,CustomKeys.FrameAdvance.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.FastForward.key,CustomKeys.FastForward.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.SkipUp.key,CustomKeys.SkipUp.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.SkipDown.key,CustomKeys.SkipDown.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.ScopeTurbo.key,CustomKeys.ScopeTurbo.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.ScopePause.key,CustomKeys.ScopePause.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.ShowPressed.key,CustomKeys.ShowPressed.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.FrameCount.key,CustomKeys.FrameCount.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ReadOnly.key,CustomKeys.ReadOnly.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.SaveScreenShot.key,CustomKeys.SaveScreenShot.modifiers); - break; - case 1: - SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.BGL1.key,CustomKeys.BGL1.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.BGL2.key,CustomKeys.BGL2.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.BGL3.key,CustomKeys.BGL3.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.BGL4.key,CustomKeys.BGL4.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.BGL5.key,CustomKeys.BGL5.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.ClippingWindows.key,CustomKeys.ClippingWindows.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.Transparency.key,CustomKeys.Transparency.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.FastForwardToggle.key,CustomKeys.FastForwardToggle.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.Rewind.key,CustomKeys.Rewind.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.SwitchControllers.key,CustomKeys.SwitchControllers.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.JoypadSwap.key,CustomKeys.JoypadSwap.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ResetGame.key,CustomKeys.ResetGame.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.ToggleCheats.key,CustomKeys.ToggleCheats.modifiers); - break; - case 2: - SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.TurboA.key,CustomKeys.TurboA.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.TurboB.key,CustomKeys.TurboB.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.TurboY.key,CustomKeys.TurboY.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.TurboX.key,CustomKeys.TurboX.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.TurboL.key,CustomKeys.TurboL.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.TurboR.key,CustomKeys.TurboR.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.TurboStart.key,CustomKeys.TurboStart.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.TurboSelect.key,CustomKeys.TurboSelect.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.TurboLeft.key,CustomKeys.TurboLeft.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.TurboUp.key,CustomKeys.TurboUp.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.TurboRight.key,CustomKeys.TurboRight.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.TurboDown.key,CustomKeys.TurboDown.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44, CustomKeys.Mute.key, CustomKeys.Mute.modifiers); - break; - case 3: - for(int i = 0 ; i < 10 ; i++) - SendDlgItemMessage(hDlg,IDC_HOTKEY1+i,WM_USER+44,CustomKeys.SelectSave[i].key,CustomKeys.SelectSave[i].modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44, CustomKeys.SaveFileSelect.key, CustomKeys.SaveFileSelect.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44, CustomKeys.LoadFileSelect.key, CustomKeys.LoadFileSelect.modifiers); - SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.QuitS9X.key,CustomKeys.QuitS9X.modifiers); - break; - } + for(int i = 0; i < MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS; i++) + { + int wParam = 0, lParam = 0; + if(hotkey_dialog_items[index][i].key_entry) + { + wParam = hotkey_dialog_items[index][i].key_entry->key; + lParam = hotkey_dialog_items[index][i].key_entry->modifiers; + } + SendDlgItemMessage(hDlg, IDC_HOTKEY1 + i, WM_USER + 44, wParam, lParam); + } SendDlgItemMessage(hDlg,IDC_SLOTPLUS,WM_USER+44,CustomKeys.SlotPlus.key,CustomKeys.SlotPlus.modifiers); SendDlgItemMessage(hDlg,IDC_SLOTMINUS,WM_USER+44,CustomKeys.SlotMinus.key,CustomKeys.SlotMinus.modifiers); @@ -8418,68 +8443,10 @@ static void set_hotkeyinfo(HWND hDlg) for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE1+i,WM_USER+44,CustomKeys.Save[i].key,CustomKeys.Save[i].modifiers); for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE11+i,WM_USER+44,CustomKeys.Load[i].key,CustomKeys.Load[i].modifiers); - switch(index) - { - case 0: - // set page 1 label text - SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_1_1); - SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_1_2); - SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_1_3); - SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_1_4); - SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_1_5); - SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_1_6); - SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_1_7); - SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_1_8); - SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_1_9); - SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_1_10); - SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_1_11); - SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_1_12); - SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_1_13); - break; - case 1: - SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_2_1); - SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_2_2); - SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_2_3); - SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_2_4); - SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_2_5); - SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_2_6); - SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_2_7); - SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_2_8); - SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_2_9); - SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_2_10); - SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_2_11); - SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_2_12); - SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_2_13); - break; - case 2: - SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_3_1); - SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_3_2); - SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_3_3); - SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_3_4); - SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_3_5); - SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_3_6); - SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_3_7); - SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_3_8); - SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_3_9); - SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_3_10); - SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_3_11); - SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_3_12); - SetDlgItemText(hDlg,IDC_LABEL_HK13, HOTKEYS_LABEL_3_13); - - break; - case 3: - for(int i = 0 ; i < 10 ; i++) - { - TCHAR temp [64]; - _stprintf(temp, TEXT("Select Slot %d"), i); - SetDlgItemText(hDlg,IDC_LABEL_HK1+i,temp); - } - SetDlgItemText(hDlg, IDC_LABEL_HK11, HOTKEYS_LABEL_4_11); - SetDlgItemText(hDlg, IDC_LABEL_HK12, HOTKEYS_LABEL_4_12); - SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_4_13); - - break; - } + for(int i = 0; i < MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS; i++) + { + SetDlgItemText(hDlg, IDC_LABEL_HK1 + i, hotkey_dialog_items[index][i].description); + } } // DlgHotkeyConfig @@ -8560,85 +8527,6 @@ switch(msg) switch(which) { - case IDC_HOTKEY1: - if(index == 0) CustomKeys.SpeedUp.key = wParam, CustomKeys.SpeedUp.modifiers = modifiers; - if(index == 1) CustomKeys.BGL1.key = wParam, CustomKeys.BGL1.modifiers = modifiers; - if(index == 2) CustomKeys.TurboA.key = wParam, CustomKeys.TurboA.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[0].key = wParam, CustomKeys.SelectSave[0].modifiers = modifiers; - break; - case IDC_HOTKEY2: - if(index == 0) CustomKeys.SpeedDown.key = wParam, CustomKeys.SpeedDown.modifiers = modifiers; - if(index == 1) CustomKeys.BGL2.key = wParam, CustomKeys.BGL2.modifiers = modifiers; - if(index == 2) CustomKeys.TurboB.key = wParam, CustomKeys.TurboB.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[1].key = wParam, CustomKeys.SelectSave[1].modifiers = modifiers; - break; - case IDC_HOTKEY3: - if(index == 0) CustomKeys.Pause.key = wParam, CustomKeys.Pause.modifiers = modifiers; - if(index == 1) CustomKeys.BGL3.key = wParam, CustomKeys.BGL3.modifiers = modifiers; - if(index == 2) CustomKeys.TurboY.key = wParam, CustomKeys.TurboY.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[2].key = wParam, CustomKeys.SelectSave[2].modifiers = modifiers; - break; - case IDC_HOTKEY4: - if(index == 0) CustomKeys.FrameAdvance.key = wParam, CustomKeys.FrameAdvance.modifiers = modifiers; - if(index == 1) CustomKeys.BGL4.key = wParam, CustomKeys.BGL4.modifiers = modifiers; - if(index == 2) CustomKeys.TurboX.key = wParam, CustomKeys.TurboX.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[3].key = wParam, CustomKeys.SelectSave[3].modifiers = modifiers; - break; - case IDC_HOTKEY5: - if(index == 0) CustomKeys.FastForward.key = wParam, CustomKeys.FastForward.modifiers = modifiers; - if(index == 1) CustomKeys.BGL5.key = wParam, CustomKeys.BGL5.modifiers = modifiers; - if(index == 2) CustomKeys.TurboL.key = wParam, CustomKeys.TurboL.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[4].key = wParam, CustomKeys.SelectSave[4].modifiers = modifiers; - break; - case IDC_HOTKEY6: - if(index == 0) CustomKeys.SkipUp.key = wParam, CustomKeys.SkipUp.modifiers = modifiers; - if(index == 1) CustomKeys.ClippingWindows.key = wParam, CustomKeys.ClippingWindows.modifiers = modifiers; - if(index == 2) CustomKeys.TurboR.key = wParam, CustomKeys.TurboR.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[5].key = wParam, CustomKeys.SelectSave[5].modifiers = modifiers; - break; - case IDC_HOTKEY7: - if(index == 0) CustomKeys.SkipDown.key = wParam, CustomKeys.SkipDown.modifiers = modifiers; - if(index == 1) CustomKeys.Transparency.key = wParam, CustomKeys.Transparency.modifiers = modifiers; - if(index == 2) CustomKeys.TurboStart.key = wParam, CustomKeys.TurboStart.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[6].key = wParam, CustomKeys.SelectSave[6].modifiers = modifiers; - break; - case IDC_HOTKEY8: - if(index == 0) CustomKeys.ScopeTurbo.key = wParam, CustomKeys.ScopeTurbo.modifiers = modifiers; - if(index == 1) CustomKeys.FastForwardToggle.key = wParam, CustomKeys.FastForwardToggle.modifiers = modifiers; - if(index == 2) CustomKeys.TurboSelect.key = wParam, CustomKeys.TurboSelect.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[7].key = wParam, CustomKeys.SelectSave[7].modifiers = modifiers; - break; - case IDC_HOTKEY9: - if(index == 0) CustomKeys.ScopePause.key = wParam, CustomKeys.ScopePause.modifiers = modifiers; - if(index == 1) CustomKeys.Rewind.key = wParam, CustomKeys.Rewind.modifiers = modifiers; - if(index == 2) CustomKeys.TurboLeft.key = wParam, CustomKeys.TurboLeft.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[8].key = wParam, CustomKeys.SelectSave[8].modifiers = modifiers; - break; - case IDC_HOTKEY10: - if(index == 0) CustomKeys.ShowPressed.key = wParam, CustomKeys.ShowPressed.modifiers = modifiers; - if(index == 1) CustomKeys.SwitchControllers.key = wParam, CustomKeys.SwitchControllers.modifiers = modifiers; - if(index == 2) CustomKeys.TurboUp.key = wParam, CustomKeys.TurboUp.modifiers = modifiers; - if(index == 3) CustomKeys.SelectSave[9].key = wParam, CustomKeys.SelectSave[9].modifiers = modifiers; - break; - case IDC_HOTKEY11: - if(index == 0) CustomKeys.FrameCount.key = wParam, CustomKeys.FrameCount.modifiers = modifiers; - if(index == 1) CustomKeys.JoypadSwap.key = wParam, CustomKeys.JoypadSwap.modifiers = modifiers; - if(index == 2) CustomKeys.TurboRight.key = wParam, CustomKeys.TurboRight.modifiers = modifiers; - if(index == 3) CustomKeys.SaveFileSelect.key = wParam, CustomKeys.SaveFileSelect.modifiers = modifiers; - break; - case IDC_HOTKEY12: - if(index == 0) CustomKeys.ReadOnly.key = wParam, CustomKeys.ReadOnly.modifiers = modifiers; - if(index == 1) CustomKeys.ResetGame.key = wParam, CustomKeys.ResetGame.modifiers = modifiers; - if(index == 2) CustomKeys.TurboDown.key = wParam, CustomKeys.TurboDown.modifiers = modifiers; - if(index == 3) CustomKeys.LoadFileSelect.key = wParam, CustomKeys.LoadFileSelect.modifiers = modifiers; - break; - case IDC_HOTKEY13: - if(index == 0) CustomKeys.SaveScreenShot.key = wParam, CustomKeys.SaveScreenShot.modifiers = modifiers; - if(index == 1) CustomKeys.ToggleCheats.key = wParam, CustomKeys.ToggleCheats.modifiers = modifiers; - if(index == 2) CustomKeys.Mute.key = wParam, CustomKeys.Mute.modifiers = modifiers; - if(index == 3) CustomKeys.QuitS9X.key = wParam, CustomKeys.QuitS9X.modifiers = modifiers; - break; - case IDC_SLOTPLUS: CustomKeys.SlotPlus.key = wParam; CustomKeys.SlotPlus.modifiers = modifiers; @@ -8670,6 +8558,13 @@ switch(msg) break; } + if(which >= IDC_HOTKEY1 && which <= IDC_HOTKEY13) + { + int offset = which - IDC_HOTKEY1; + hotkey_dialog_items[index][offset].key_entry->key = wParam; + hotkey_dialog_items[index][offset].key_entry->modifiers = modifiers; + } + if(which >= IDC_SAVE1 && which <= IDC_SAVE10) { CustomKeys.Save[which-IDC_SAVE1].key = wParam;