From 5a4c5be0e27edc970006f3c81f12041d2841fa13 Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 30 Dec 2019 17:03:06 +0100 Subject: [PATCH] win32: add save banks, hotkeys, menu changes --- win32/CSaveLoadWithPreviewDlg.cpp | 57 +++++- win32/CSaveLoadWithPreviewDlg.h | 3 +- win32/rsrc/resource.h | 39 ++-- win32/rsrc/snes9x.rc | 327 ++++++++++++++---------------- win32/wconfig.cpp | 1 + win32/wlanguage.h | 15 +- win32/wsnes9x.cpp | 192 +++++++++++------- win32/wsnes9x.h | 14 +- 8 files changed, 365 insertions(+), 283 deletions(-) diff --git a/win32/CSaveLoadWithPreviewDlg.cpp b/win32/CSaveLoadWithPreviewDlg.cpp index 92373b4e..e8d408a1 100644 --- a/win32/CSaveLoadWithPreviewDlg.cpp +++ b/win32/CSaveLoadWithPreviewDlg.cpp @@ -69,13 +69,13 @@ bool CSaveLoadWithPreviewDlg::init_preview_bmps() return true; } -void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) +void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, int bank, HWND hDlg) { uint16 *image_buffer; int width, height; // load the saved screenshot from a snapshot - if(UnfreezeScreenshotSlot(slot, &image_buffer, width, height)) + if(UnfreezeScreenshotSlot(bank * SAVE_SLOTS_PER_BANK + slot, &image_buffer, width, height)) { // create temporary bitmap storage for screenshot, 16bit RGB uint8_t* buffer = NULL; @@ -118,6 +118,7 @@ void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) 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); + DeleteObject(imageBmp); free(bm); @@ -161,6 +162,23 @@ void CSaveLoadWithPreviewDlg::load_slot_image_text(int slot, HWND hDlg) free(image_buffer); } + else + { + // clear image and text + SendMessage(GetDlgItem(hDlg, IDC_BUTTON_SLOT_1 + slot), BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, NULL); + SetWindowText(GetDlgItem(hDlg, IDC_STATIC_SLOT_1 + slot), _T("")); + } +} + +void CSaveLoadWithPreviewDlg::load_current_bank(HWND hDlg) +{ + int bank = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_COMBO_BANK)); + + for (int i = 0; i < NUM_DIALOG_SLOTS; i++) + { + // load one slot + load_slot_image_text(i, bank, hDlg); + } } void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) @@ -187,9 +205,6 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) // 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 @@ -197,13 +212,30 @@ void CSaveLoadWithPreviewDlg::init_window(HWND hDlg) int dialog_height = 2 * (PREVIEW_HEIGHT + PREVIEW_TEXT_STATIC_HEIGHT) + 40; // +40 for cancel button // reposition cancel button - RECT rect_cancel, client_rect; + RECT rect_cancel, rect_bank, 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); + // reposition dropdown + HWND combo_hwnd = GetDlgItem(hDlg, IDC_COMBO_BANK); + GetWindowRect(combo_hwnd, &rect_bank); + topleft.x = rect_bank.left; + topleft.y = rect_bank.top; + ScreenToClient(hDlg, &topleft); + MoveWindow(combo_hwnd, 10, dialog_height - 30, rect_bank.right - rect_bank.left, rect_bank.bottom - rect_bank.top, TRUE); + + // fill bank strings + TCHAR temp[20]; + for (int i = 0; i < NUM_SAVE_BANKS; i++) + { + _stprintf(temp, _T("Bank #%d"), i); + ComboBox_AddString(combo_hwnd, temp); + } + ComboBox_SetCurSel(combo_hwnd, GUI.CurrentSaveBank); + // get monitor dimensions HMONITOR hm; MONITORINFO mi; @@ -223,6 +255,8 @@ 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_current_bank(hDlg); } INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -243,7 +277,9 @@ INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg 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); + int bank = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_COMBO_BANK)); + int slot = id - IDC_BUTTON_SLOT_1; + EndDialog(hDlg, bank * SAVE_SLOTS_PER_BANK + slot); return true; } else if(id == IDCANCEL) @@ -251,6 +287,13 @@ INT_PTR CALLBACK CSaveLoadWithPreviewDlg::DlgLoadWithPreview(HWND hDlg, UINT msg EndDialog(hDlg, -1); return true; } + else if (id == IDC_COMBO_BANK) + { + if (CBN_SELCHANGE == HIWORD(wParam)) + { + dlg->load_current_bank(hDlg); + } + } } default: return false; diff --git a/win32/CSaveLoadWithPreviewDlg.h b/win32/CSaveLoadWithPreviewDlg.h index d4147c9f..60c81c07 100644 --- a/win32/CSaveLoadWithPreviewDlg.h +++ b/win32/CSaveLoadWithPreviewDlg.h @@ -25,7 +25,8 @@ private: void delete_preview_bmps(); bool init_preview_bmps(); - void load_slot_image_text(int slot, HWND hDlg); + void load_current_bank(HWND hDlg); + void load_slot_image_text(int slot, int bank, HWND hDlg); void init_window(HWND hDlg); public: diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index b4d650a3..657aeda9 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -207,6 +207,7 @@ #define IDC_C_LOADWATCH 1155 #define IDC_OUTPUTMETHOD 1155 #define IDC_CPU_OVERCLOCK 1155 +#define IDC_COMBO_BANK 1155 #define IDC_NC_ADDRESS 1156 #define IDC_C_SAVEWATCH 1156 #define IDC_ASPECTDROP 1156 @@ -285,7 +286,9 @@ #define IDC_MESSAGES_IN_IMAGE 1200 #define IDC_RECORD_NOW 1201 #define IDC_MESSAGES_SCALE 1201 +#define IDC_LABEL_UP28 1201 #define IDC_RECORD_RESET 1202 +#define IDC_LABEL_UP29 1202 #define IDC_JOY1 1203 #define IDC_JOY2 1204 #define IDC_JOY3 1205 @@ -325,6 +328,8 @@ #define IDC_LABEL_UP20 1229 #define IDC_LABEL_UP21 1230 #define IDC_DIALOGLOAD 1231 +#define IDC_BANKMINUS 1232 +#define IDC_BANKPLUS 1233 #define IDC_LABEL_UP22 1234 #define IDC_SLOTMINUS 1235 #define IDC_LABEL_UP23 1236 @@ -349,6 +354,7 @@ #define IDC_LABEL_HK12 1255 #define IDC_LABEL_HK13 1256 #define IDC_PLAYWARN 1257 +#define IDC_LABEL_HK14 1257 #define IDC_REDUCEINPUTLAG 1258 #define IDC_INTEGERSCALING 1259 #define IDC_NTSCSCANLINES 1260 @@ -365,6 +371,7 @@ #define IDC_HOTKEY11 2010 #define IDC_HOTKEY12 2011 #define IDC_HOTKEY13 2012 +#define IDC_HOTKEY14 2013 #define IDC_PREV 2147 #define IDC_ENTERED 2148 #define IDC_ENTEREDADDRESS 2157 @@ -528,30 +535,16 @@ #define ID_EMULATION_HACKS 40178 #define ID_FILE_LOAD_PREVIEW 40179 #define ID_FILE_SAVE_PREVIEW 40180 +#define ID_FILE_SAVE_POPUP 40181 +#define ID_FILE_LOAD_POPUP 40182 #define ID_FILE_SAVE0 44000 -#define ID_FILE_SAVE1 44001 -#define ID_FILE_SAVE2 44002 -#define ID_FILE_SAVE3 44003 -#define ID_FILE_SAVE4 44004 -#define ID_FILE_SAVE5 44005 -#define ID_FILE_SAVE6 44006 -#define ID_FILE_SAVE7 44007 -#define ID_FILE_SAVE8 44008 -#define ID_FILE_SAVE9 44009 -#define ID_FILE_SAVE_FILE 44010 -#define ID_FILE_LOAD0 44020 -#define ID_FILE_LOAD1 44021 -#define ID_FILE_LOAD2 44022 -#define ID_FILE_LOAD3 44023 -#define ID_FILE_LOAD4 44024 -#define ID_FILE_LOAD5 44025 -#define ID_FILE_LOAD6 44026 -#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_FILE 44031 -#define IDM_MACSRIFLE_TOGGLE 44032 +#define ID_FILE_SAVE_LAST 44100 +#define ID_FILE_LOAD0 44200 +#define ID_FILE_LOAD_LAST 44300 +#define ID_FILE_SAVE_FILE 44310 +#define ID_FILE_LOAD_OOPS 44330 +#define ID_FILE_LOAD_FILE 44331 +#define IDM_MACSRIFLE_TOGGLE 44332 #define IDC_STATIC -1 // Next default values for new objects diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 3ceaec92..d8cd3f34 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -32,6 +32,7 @@ CAPTION "Load with Preview" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Cancel",IDCANCEL,510,226,50,14 + COMBOBOX IDC_COMBO_BANK,7,226,48,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP END IDD_SOUND_OPTS DIALOGEX 0, 0, 414, 158 @@ -426,13 +427,13 @@ BEGIN CONTROL "Clear SRAM",IDC_CLEARSRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,96,70,10 END -IDD_KEYCUSTOM DIALOGEX 0, 0, 409, 272 +IDD_KEYCUSTOM DIALOGEX 0, 0, 409, 296 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,252,48,14 - PUSHBUTTON "OK",IDOK,300,252,48,14 + PUSHBUTTON "Cancel",IDCANCEL,354,276,48,14 + PUSHBUTTON "OK",IDOK,300,276,48,14 RTEXT "Speed +:",IDC_LABEL_HK1,12,30,72,12 RTEXT "Frame advance:",IDC_LABEL_HK4,12,75,72,12 RTEXT "Speed -:",IDC_LABEL_HK2,12,45,72,12 @@ -499,22 +500,28 @@ BEGIN 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 + RTEXT "Slot -:",IDC_LABEL_UP22,181,210,30,12 + CONTROL "",IDC_SLOTMINUS,"InputCustomHot",WS_TABSTOP,217,210,60,12,WS_EX_CLIENTEDGE + RTEXT "Slot +:",IDC_LABEL_UP23,300,210,30,12 + CONTROL "",IDC_SLOTPLUS,"InputCustomHot",WS_TABSTOP,336,210,60,12,WS_EX_CLIENTEDGE + RTEXT "Save #:",IDC_LABEL_UP24,181,225,30,12 + CONTROL "",IDC_SLOTSAVE,"InputCustomHot",WS_TABSTOP,217,225,60,12,WS_EX_CLIENTEDGE + RTEXT "Load #:",IDC_LABEL_UP25,300,225,30,12 + CONTROL "",IDC_SLOTLOAD,"InputCustomHot",WS_TABSTOP,336,225,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,256,269,34 COMBOBOX IDC_HKCOMBO,6,6,60,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - 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 + GROUPBOX "",IDC_STATIC,6,21,149,226,0,WS_EX_TRANSPARENT + GROUPBOX "Save States",IDC_STATIC,161,21,241,226,0,WS_EX_TRANSPARENT + RTEXT "Save Dialog:",IDC_LABEL_UP26,165,195,46,12 + CONTROL "",IDC_DIALOGSAVE,"InputCustomHot",WS_TABSTOP,217,195,60,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_DIALOGLOAD,"InputCustomHot",WS_TABSTOP,336,195,60,12,WS_EX_CLIENTEDGE + RTEXT "Load Dialog:",IDC_LABEL_UP27,284,195,46,12 + CONTROL "",IDC_BANKMINUS,"InputCustomHot",WS_TABSTOP,217,180,60,12,WS_EX_CLIENTEDGE + RTEXT "Bank -:",IDC_LABEL_UP28,165,180,46,12 + CONTROL "",IDC_BANKPLUS,"InputCustomHot",WS_TABSTOP,336,180,60,12,WS_EX_CLIENTEDGE + RTEXT "Bank +:",IDC_LABEL_UP29,284,180,46,12 + CONTROL "",IDC_HOTKEY14,"InputCustomHot",WS_TABSTOP,89,225,60,12,WS_EX_CLIENTEDGE + RTEXT "Save screenshot:",IDC_LABEL_HK14,11,225,72,12 END IDD_MULTICART DIALOGEX 0, 0, 390, 90 @@ -733,7 +740,7 @@ BEGIN BEGIN RIGHTMARGIN, 407 VERTGUIDE, 90 - BOTTOMMARGIN, 266 + BOTTOMMARGIN, 290 END IDD_MULTICART, DIALOG @@ -922,189 +929,169 @@ END // Menu // -IDR_MENU_US MENU +IDR_MENU_US MENUEX BEGIN - POPUP "&File" + POPUP "&File", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "L&oad Game...\tCtrl+O", ID_FILE_LOAD_GAME - POPUP "Recent &Games" + MENUITEM "L&oad Game...\tCtrl+O", ID_FILE_LOAD_GAME,MFT_STRING,MFS_ENABLED + POPUP "Recent &Games", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "Dummy", ID_RECENT_DUMMY, INACTIVE + MENUITEM "Dummy", ID_RECENT_DUMMY,MFT_STRING,MFS_GRAYED END - MENUITEM "Load MultiCart...", ID_FILE_LOADMULTICART - MENUITEM SEPARATOR - POPUP "&Save Game Position" + MENUITEM "Load MultiCart...", ID_FILE_LOADMULTICART,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + POPUP "&Save Game Position", ID_FILE_SAVE_POPUP,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "Slot #&0", ID_FILE_SAVE0 - MENUITEM "Slot #&1", ID_FILE_SAVE1 - MENUITEM "Slot #&2", ID_FILE_SAVE2 - MENUITEM "Slot #&3", ID_FILE_SAVE3 - MENUITEM "Slot #&4", ID_FILE_SAVE4 - MENUITEM "Slot #&5", ID_FILE_SAVE5 - MENUITEM "Slot #&6", ID_FILE_SAVE6 - MENUITEM "Slot #&7", ID_FILE_SAVE7 - MENUITEM "Slot #&8", ID_FILE_SAVE8 - MENUITEM "Slot #&9", ID_FILE_SAVE9 - MENUITEM SEPARATOR - MENUITEM "&Select File", ID_FILE_SAVE_FILE + MENUITEM MFT_SEPARATOR + MENUITEM "&Select File", ID_FILE_SAVE_FILE,MFT_STRING,MFS_ENABLED END - POPUP "&Load Game Position" + POPUP "&Load Game Position", ID_FILE_LOAD_POPUP,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "Slot #&0", ID_FILE_LOAD0 - MENUITEM "Slot #&1", ID_FILE_LOAD1 - MENUITEM "Slot #&2", ID_FILE_LOAD2 - MENUITEM "Slot #&3", ID_FILE_LOAD3 - MENUITEM "Slot #&4", ID_FILE_LOAD4 - MENUITEM "Slot #&5", ID_FILE_LOAD5 - MENUITEM "Slot #&6", ID_FILE_LOAD6 - MENUITEM "Slot #&7", ID_FILE_LOAD7 - MENUITEM "Slot #&8", ID_FILE_LOAD8 - MENUITEM "Slot #&9", ID_FILE_LOAD9 - MENUITEM SEPARATOR - MENUITEM "Oops File", ID_FILE_LOAD_OOPS - MENUITEM SEPARATOR - MENUITEM "&Select File", ID_FILE_LOAD_FILE + MENUITEM MFT_SEPARATOR + MENUITEM "Oops File", ID_FILE_LOAD_OOPS,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "&Select File", ID_FILE_LOAD_FILE,MFT_STRING,MFS_ENABLED END - MENUITEM "&Save with Preview", ID_FILE_SAVE_PREVIEW - MENUITEM "&Load with Preview", ID_FILE_LOAD_PREVIEW - MENUITEM SEPARATOR - POPUP "Save Other" + MENUITEM "&Save with Preview", ID_FILE_SAVE_PREVIEW,MFT_STRING,MFS_ENABLED + MENUITEM "&Load with Preview", ID_FILE_LOAD_PREVIEW,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + POPUP "Save Other", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "S&ave SPC Data", ID_FILE_SAVE_SPC_DATA - MENUITEM "Save Screenshot", ID_SAVESCREENSHOT - MENUITEM "Sa&ve S-RAM Data", ID_FILE_SAVE_SRAM_DATA - MENUITEM "Save Memory Pack", ID_SAVEMEMPACK + MENUITEM "S&ave SPC Data", ID_FILE_SAVE_SPC_DATA,MFT_STRING,MFS_ENABLED + MENUITEM "Save Screenshot", ID_SAVESCREENSHOT,MFT_STRING,MFS_ENABLED + MENUITEM "Sa&ve S-RAM Data", ID_FILE_SAVE_SRAM_DATA,MFT_STRING,MFS_ENABLED + MENUITEM "Save Memory Pack", ID_SAVEMEMPACK,MFT_STRING,MFS_ENABLED END - MENUITEM "ROM Information...", IDM_ROM_INFO - MENUITEM SEPARATOR - MENUITEM "Movie Play...", ID_FILE_MOVIE_PLAY - MENUITEM "Movie Record...", ID_FILE_MOVIE_RECORD - MENUITEM "Movie Stop", ID_FILE_MOVIE_STOP - MENUITEM SEPARATOR - MENUITEM "AVI Recording", ID_FILE_AVI_RECORDING - MENUITEM SEPARATOR - MENUITEM "&Reset Game", ID_FILE_RESET - MENUITEM "E&xit\tAlt+F4", ID_FILE_EXIT + MENUITEM "ROM Information...", IDM_ROM_INFO,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "Movie Play...", ID_FILE_MOVIE_PLAY,MFT_STRING,MFS_ENABLED + MENUITEM "Movie Record...", ID_FILE_MOVIE_RECORD,MFT_STRING,MFS_ENABLED + MENUITEM "Movie Stop", ID_FILE_MOVIE_STOP,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "AVI Recording", ID_FILE_AVI_RECORDING,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "&Reset Game", ID_FILE_RESET,MFT_STRING,MFS_ENABLED + MENUITEM "E&xit\tAlt+F4", ID_FILE_EXIT,MFT_STRING,MFS_ENABLED END - POPUP "&Emulation" + POPUP "&Emulation", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Pause", ID_FILE_PAUSE - MENUITEM "Pause &When Inactive", ID_EMULATION_PAUSEWHENINACTIVE - MENUITEM "&Frame Advance", ID_FRAME_ADVANCE - MENUITEM SEPARATOR - MENUITEM "&Hacks...", ID_EMULATION_HACKS - MENUITEM "&Settings...\tAlt+F8", ID_OPTIONS_SETTINGS + MENUITEM "&Pause", ID_FILE_PAUSE,MFT_STRING,MFS_ENABLED + MENUITEM "Pause &When Inactive", ID_EMULATION_PAUSEWHENINACTIVE,MFT_STRING,MFS_ENABLED + MENUITEM "&Frame Advance", ID_FRAME_ADVANCE,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "&Hacks...", ID_EMULATION_HACKS,MFT_STRING,MFS_ENABLED + MENUITEM "&Settings...\tAlt+F8", ID_OPTIONS_SETTINGS,MFT_STRING,MFS_ENABLED END - POPUP "&Input" + POPUP "&Input", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Input Configuration...\tAlt+F7", 40022 - MENUITEM "&Customize Hotkeys...\tAlt+F9", ID_OPTIONS_KEYCUSTOM - MENUITEM SEPARATOR - MENUITEM "Enable Background Input", ID_EMULATION_BACKGROUNDINPUT - MENUITEM "Background Keyboard Hotkeys", ID_INPUT_BACKGROUNDKEYBOARDHOTKEYS - MENUITEM SEPARATOR - MENUITEM "Detect gamepad changes", ID_INPUT_DETECTGAMEPADCHANGES - MENUITEM SEPARATOR - MENUITEM "Use SNES Joypad(s)", IDM_SNES_JOYPAD - MENUITEM "Use SNES Mouse", IDM_MOUSE_TOGGLE - MENUITEM "Use Super Scope", IDM_SCOPE_TOGGLE - MENUITEM "Use Super Multitap (5-player)", IDM_ENABLE_MULTITAP - MENUITEM "Use Konami Justifier", IDM_JUSTIFIER - MENUITEM "Use Mouse in alternate port", IDM_MOUSE_SWAPPED - MENUITEM "Use Multitaps (8-player)", IDM_MULTITAP8 - MENUITEM "Use Dual Justifiers", IDM_JUSTIFIERS - MENUITEM "Use M.A.C.S. Rifle", IDM_MACSRIFLE_TOGGLE + MENUITEM "&Input Configuration...\tAlt+F7", 40022,MFT_STRING,MFS_ENABLED + MENUITEM "&Customize Hotkeys...\tAlt+F9", ID_OPTIONS_KEYCUSTOM,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "Enable Background Input", ID_EMULATION_BACKGROUNDINPUT,MFT_STRING,MFS_ENABLED + MENUITEM "Background Keyboard Hotkeys", ID_INPUT_BACKGROUNDKEYBOARDHOTKEYS,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "Detect gamepad changes", ID_INPUT_DETECTGAMEPADCHANGES,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "Use SNES Joypad(s)", IDM_SNES_JOYPAD,MFT_STRING,MFS_ENABLED + MENUITEM "Use SNES Mouse", IDM_MOUSE_TOGGLE,MFT_STRING,MFS_ENABLED + MENUITEM "Use Super Scope", IDM_SCOPE_TOGGLE,MFT_STRING,MFS_ENABLED + MENUITEM "Use Super Multitap (5-player)", IDM_ENABLE_MULTITAP,MFT_STRING,MFS_ENABLED + MENUITEM "Use Konami Justifier", IDM_JUSTIFIER,MFT_STRING,MFS_ENABLED + MENUITEM "Use Mouse in alternate port", IDM_MOUSE_SWAPPED,MFT_STRING,MFS_ENABLED + MENUITEM "Use Multitaps (8-player)", IDM_MULTITAP8,MFT_STRING,MFS_ENABLED + MENUITEM "Use Dual Justifiers", IDM_JUSTIFIERS,MFT_STRING,MFS_ENABLED + MENUITEM "Use M.A.C.S. Rifle", IDM_MACSRIFLE_TOGGLE,MFT_STRING,MFS_ENABLED END - POPUP "&Sound" + POPUP "&Sound", 0,MFT_STRING,MFS_ENABLED BEGIN - POPUP "&Playback Rate" + POPUP "&Playback Rate", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Mute Sound", ID_SOUND_NOSOUND - MENUITEM "8KHz", ID_SOUND_8000HZ - MENUITEM "11KHz", ID_SOUND_11025HZ - MENUITEM "16KHz", ID_SOUND_16000HZ - MENUITEM "22KHz", ID_SOUND_22050HZ - MENUITEM "30KHz", ID_SOUND_30000HZ - MENUITEM "32KHz", ID_SOUND_32000HZ - MENUITEM "35KHz", ID_SOUND_35000HZ - MENUITEM "44KHz", ID_SOUND_44100HZ - MENUITEM "48KHz", ID_SOUND_48000HZ + MENUITEM "&Mute Sound", ID_SOUND_NOSOUND,MFT_STRING,MFS_ENABLED + MENUITEM "8KHz", ID_SOUND_8000HZ,MFT_STRING,MFS_ENABLED + MENUITEM "11KHz", ID_SOUND_11025HZ,MFT_STRING,MFS_ENABLED + MENUITEM "16KHz", ID_SOUND_16000HZ,MFT_STRING,MFS_ENABLED + MENUITEM "22KHz", ID_SOUND_22050HZ,MFT_STRING,MFS_ENABLED + MENUITEM "30KHz", ID_SOUND_30000HZ,MFT_STRING,MFS_ENABLED + MENUITEM "32KHz", ID_SOUND_32000HZ,MFT_STRING,MFS_ENABLED + MENUITEM "35KHz", ID_SOUND_35000HZ,MFT_STRING,MFS_ENABLED + MENUITEM "44KHz", ID_SOUND_44100HZ,MFT_STRING,MFS_ENABLED + MENUITEM "48KHz", ID_SOUND_48000HZ,MFT_STRING,MFS_ENABLED END - POPUP "&Buffer Length" + POPUP "&Buffer Length", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "16ms", ID_SOUND_16MS - MENUITEM "32ms", ID_SOUND_32MS - MENUITEM "48ms", ID_SOUND_48MS - MENUITEM "64ms", ID_SOUND_64MS - MENUITEM "80ms", ID_SOUND_80MS - MENUITEM "96ms", ID_SOUND_96MS - MENUITEM "112ms", ID_SOUND_112MS - MENUITEM "128ms", ID_SOUND_128MS - MENUITEM "144ms", ID_SOUND_144MS - MENUITEM "160ms", ID_SOUND_160MS - MENUITEM "176ms", ID_SOUND_176MS - MENUITEM "192ms", ID_SOUND_192MS - MENUITEM "208ms", ID_SOUND_208MS + MENUITEM "16ms", ID_SOUND_16MS,MFT_STRING,MFS_ENABLED + MENUITEM "32ms", ID_SOUND_32MS,MFT_STRING,MFS_ENABLED + MENUITEM "48ms", ID_SOUND_48MS,MFT_STRING,MFS_ENABLED + MENUITEM "64ms", ID_SOUND_64MS,MFT_STRING,MFS_ENABLED + MENUITEM "80ms", ID_SOUND_80MS,MFT_STRING,MFS_ENABLED + MENUITEM "96ms", ID_SOUND_96MS,MFT_STRING,MFS_ENABLED + MENUITEM "112ms", ID_SOUND_112MS,MFT_STRING,MFS_ENABLED + MENUITEM "128ms", ID_SOUND_128MS,MFT_STRING,MFS_ENABLED + MENUITEM "144ms", ID_SOUND_144MS,MFT_STRING,MFS_ENABLED + MENUITEM "160ms", ID_SOUND_160MS,MFT_STRING,MFS_ENABLED + MENUITEM "176ms", ID_SOUND_176MS,MFT_STRING,MFS_ENABLED + MENUITEM "192ms", ID_SOUND_192MS,MFT_STRING,MFS_ENABLED + MENUITEM "208ms", ID_SOUND_208MS,MFT_STRING,MFS_ENABLED END - POPUP "&Channels" + POPUP "&Channels", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "Channel &1", ID_CHANNELS_CHANNEL1 - MENUITEM "Channel &2", ID_CHANNELS_CHANNEL2 - MENUITEM "Channel &3", ID_CHANNELS_CHANNEL3 - MENUITEM "Channel &4", ID_CHANNELS_CHANNEL4 - MENUITEM "Channel &5", ID_CHANNELS_CHANNEL5 - MENUITEM "Channel &6", ID_CHANNELS_CHANNEL6 - MENUITEM "Channel &7", ID_CHANNELS_CHANNEL7 - MENUITEM "Channel &8", ID_CHANNELS_CHANNEL8 - MENUITEM SEPARATOR - MENUITEM "Enable All", ID_CHANNELS_ENABLEALL + MENUITEM "Channel &1", ID_CHANNELS_CHANNEL1,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &2", ID_CHANNELS_CHANNEL2,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &3", ID_CHANNELS_CHANNEL3,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &4", ID_CHANNELS_CHANNEL4,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &5", ID_CHANNELS_CHANNEL5,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &6", ID_CHANNELS_CHANNEL6,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &7", ID_CHANNELS_CHANNEL7,MFT_STRING,MFS_ENABLED + MENUITEM "Channel &8", ID_CHANNELS_CHANNEL8,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "Enable All", ID_CHANNELS_ENABLEALL,MFT_STRING,MFS_ENABLED END - MENUITEM SEPARATOR - MENUITEM "S&ync Sound\tAlt+]", ID_SOUND_SYNC - MENUITEM "&Settings...\tAlt+T", ID_SOUND_OPTIONS + MENUITEM MFT_SEPARATOR + MENUITEM "S&ync Sound\tAlt+]", ID_SOUND_SYNC,MFT_STRING,MFS_ENABLED + MENUITEM "&Settings...\tAlt+T", ID_SOUND_OPTIONS,MFT_STRING,MFS_ENABLED END - POPUP "&Video" + POPUP "&Video", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Hide Menubar\tEsc", ID_WINDOW_HIDEMENUBAR - MENUITEM "&Full Screen\tAlt+Enter", ID_WINDOW_FULLSCREEN - POPUP "&Window Size" + MENUITEM "&Hide Menubar\tEsc", ID_WINDOW_HIDEMENUBAR,MFT_STRING,MFS_ENABLED + MENUITEM "&Full Screen\tAlt+Enter", ID_WINDOW_FULLSCREEN,MFT_STRING,MFS_ENABLED + POPUP "&Window Size", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&1x", ID_WINDOW_SIZE_1X - MENUITEM "&2x", ID_WINDOW_SIZE_2X - MENUITEM "&3x", ID_WINDOW_SIZE_3X - MENUITEM "&4x", ID_WINDOW_SIZE_4X + MENUITEM "&1x", ID_WINDOW_SIZE_1X,MFT_STRING,MFS_ENABLED + MENUITEM "&2x", ID_WINDOW_SIZE_2X,MFT_STRING,MFS_ENABLED + MENUITEM "&3x", ID_WINDOW_SIZE_3X,MFT_STRING,MFS_ENABLED + MENUITEM "&4x", ID_WINDOW_SIZE_4X,MFT_STRING,MFS_ENABLED END - MENUITEM SEPARATOR - MENUITEM "&Stretch Image\tAlt+Backspace", ID_WINDOW_STRETCH - MENUITEM "&Maintain Aspect Ratio", ID_WINDOW_ASPECTRATIO - MENUITEM "&Bilinear Filtering", ID_WINDOW_BILINEAR - MENUITEM "Show Frame &Rate", ID_VIDEO_SHOWFRAMERATE - MENUITEM SEPARATOR - MENUITEM "&Display Configuration...\tAlt+F5", ID_OPTIONS_DISPLAY + MENUITEM MFT_SEPARATOR + MENUITEM "&Stretch Image\tAlt+Backspace", ID_WINDOW_STRETCH,MFT_STRING,MFS_ENABLED + MENUITEM "&Maintain Aspect Ratio", ID_WINDOW_ASPECTRATIO,MFT_STRING,MFS_ENABLED + MENUITEM "&Bilinear Filtering", ID_WINDOW_BILINEAR,MFT_STRING,MFS_ENABLED + MENUITEM "Show Frame &Rate", ID_VIDEO_SHOWFRAMERATE,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "&Display Configuration...\tAlt+F5", ID_OPTIONS_DISPLAY,MFT_STRING,MFS_ENABLED END - POPUP "&Cheat" + POPUP "&Cheat", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Game Genie, Pro-Action Replay Codes\tAlt+G", ID_CHEAT_ENTER - MENUITEM "&Search for New Cheats", ID_CHEAT_SEARCH_MODAL - MENUITEM "Search for New Cheats (active)\tAlt+A", 40064 - MENUITEM "&Apply Cheats", ID_CHEAT_APPLY, CHECKED + MENUITEM "&Game Genie, Pro-Action Replay Codes\tAlt+G", ID_CHEAT_ENTER,MFT_STRING,MFS_ENABLED + MENUITEM "&Search for New Cheats", ID_CHEAT_SEARCH_MODAL,MFT_STRING,MFS_ENABLED + MENUITEM "Search for New Cheats (active)\tAlt+A", 40064,MFT_STRING,MFS_ENABLED + MENUITEM "&Apply Cheats", ID_CHEAT_APPLY,MFT_STRING,MFS_CHECKED END - POPUP "&Netplay" + POPUP "&Netplay", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&Connect to Server...", ID_NETPLAY_CONNECT - MENUITEM "&Disconnect from Server", ID_NETPLAY_DISCONNECT - MENUITEM SEPARATOR - MENUITEM "&Act as Server", ID_NETPLAY_SERVER - MENUITEM "&Re-sync all Clients Using Freeze File Now", ID_NETPLAY_SYNC - MENUITEM "&Send ROM Image to Clients Now", ID_NETPLAY_ROM - MENUITEM "S&end ROM Image to Clients", ID_NETPLAY_SEND_ROM_ON_CONNECT - MENUITEM "S&ync Using Reset Game", ID_NETPLAY_SYNC_BY_RESET, CHECKED - MENUITEM SEPARATOR - MENUITEM "&Options...", ID_NETPLAY_OPTIONS + MENUITEM "&Connect to Server...", ID_NETPLAY_CONNECT,MFT_STRING,MFS_ENABLED + MENUITEM "&Disconnect from Server", ID_NETPLAY_DISCONNECT,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR + MENUITEM "&Act as Server", ID_NETPLAY_SERVER,MFT_STRING,MFS_ENABLED + MENUITEM "&Re-sync all Clients Using Freeze File Now", ID_NETPLAY_SYNC,MFT_STRING,MFS_ENABLED + MENUITEM "&Send ROM Image to Clients Now", ID_NETPLAY_ROM,MFT_STRING,MFS_ENABLED + MENUITEM "S&end ROM Image to Clients", ID_NETPLAY_SEND_ROM_ON_CONNECT,MFT_STRING,MFS_ENABLED + MENUITEM "S&ync Using Reset Game", ID_NETPLAY_SYNC_BY_RESET,MFT_STRING,MFS_CHECKED + MENUITEM MFT_SEPARATOR + MENUITEM "&Options...", ID_NETPLAY_OPTIONS,MFT_STRING,MFS_ENABLED END - POPUP "&Help" + POPUP "&Help", 0,MFT_STRING,MFS_ENABLED BEGIN - MENUITEM "&About...", ID_HELP_ABOUT + MENUITEM "&About...", ID_HELP_ABOUT,MFT_STRING,MFS_ENABLED END END diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index cb576a01..e04c5ae5 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -118,6 +118,7 @@ void WinSetDefaultValues () GUI.Language=0; GUI.AllowSoundSync = true; + GUI.CurrentSaveBank = 0; } diff --git a/win32/wlanguage.h b/win32/wlanguage.h index 334d9ede..8b751f61 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -91,6 +91,8 @@ Nintendo is a trademark.") #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_1_14 TEXT("Frame advance:") + #define HOTKEYS_LABEL_2_1 TEXT("Graphics layer 1:") #define HOTKEYS_LABEL_2_2 TEXT("Graphics layer 2:") #define HOTKEYS_LABEL_2_3 TEXT("Graphics layer 3:") @@ -98,12 +100,14 @@ 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("Frame advance:") +#define HOTKEYS_LABEL_2_8 TEXT("SuperScope turbo:") #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("Show pressed keys:") #define HOTKEYS_LABEL_2_13 TEXT("Movie frame count:") +#define HOTKEYS_LABEL_2_14 TEXT("Movie read-only:") + #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,7 +120,8 @@ 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("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:") @@ -129,7 +134,8 @@ Nintendo is a trademark.") #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("Movie read-only:") + + // gaming buttons and axes #define GAMEDEVICE_JOYNUMPREFIX "(J%x)" // don't change this @@ -355,7 +361,8 @@ Nintendo is a trademark.") // Save Messages -#define FREEZE_INFO_SET_SLOT_N "set slot 00%d" +#define FREEZE_INFO_SET_SLOT_N "Set save slot %03d" +#define FREEZE_INFO_SET_BANK_N "Set save bank %03d" // AVI Messages diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 378035a3..c84e093b 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -126,7 +126,7 @@ void S9xDetectJoypads(); #define TIMER_SCANJOYPADS (99999) #define NC_SEARCHDB 0x8000 -#define MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS 13 +#define MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS 14 #ifdef UNICODE #define S9XW_SHARD_PATH SHARD_PATHW @@ -370,6 +370,8 @@ struct SCustomKeys CustomKeys = { {0,0}, // slot minus (disabled by default) {0,0}, // slot save (disabled by default) {0,0}, // slot load (disabled by default) + {0,0}, // bank plus (disabled by default) + {0,0}, // bank minus (disabled by default) {VK_F11,CUSTKEY_SHIFT_MASK}, // dialog save {VK_F11,0}, // dialog load {0,0}, // background layer 1 @@ -452,7 +454,8 @@ struct OpenMovieParams wchar_t Metadata[MOVIE_MAX_METADATA]; }; - +TCHAR g_bankMenuItemStrings[NUM_SAVE_BANKS][20]; +TCHAR g_saveMenuItemStrings[NUM_SAVE_BANKS * SAVE_SLOTS_PER_BANK][20]; StateManager stateMan; @@ -535,6 +538,17 @@ BOOL PostMenuCommand (UINT uID) return FALSE; } +HMENU GetSubMenuById(UINT uID) +{ + MENUITEMINFO mii; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + if (!GetMenuItemInfo(GUI.hMenu, uID, FALSE, &mii)) + return NULL; + return mii.hSubMenu; +} + void S9xMouseOn () { if(Settings.StopEmulation) @@ -829,18 +843,18 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) modifiers |= CUSTKEY_SHIFT_MASK; { - for(int i = 0 ; i < 10 ; i++) + for(int i = 0 ; i < SAVE_SLOTS_PER_BANK; i++) { if(wParam == CustomKeys.Save[i].key && modifiers == CustomKeys.Save[i].modifiers) { - FreezeUnfreezeSlot (i, true); + FreezeUnfreezeSlot (GUI.CurrentSaveBank * SAVE_SLOTS_PER_BANK + i, true); hitHotKey = true; } if(wParam == CustomKeys.Load[i].key && modifiers == CustomKeys.Load[i].modifiers) { - FreezeUnfreezeSlot (i, false); + FreezeUnfreezeSlot (GUI.CurrentSaveBank * SAVE_SLOTS_PER_BANK + i, false); hitHotKey = true; } } @@ -873,7 +887,7 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) && modifiers == CustomKeys.SlotPlus.modifiers) { GUI.CurrentSaveSlot++; - if(GUI.CurrentSaveSlot > 9) + if(GUI.CurrentSaveSlot > LAST_SAVE_SLOT_IN_BANK) GUI.CurrentSaveSlot = 0; static char str [64]; @@ -893,6 +907,32 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot); S9xSetInfoString(str); + hitHotKey = true; + } + if (wParam == CustomKeys.BankPlus.key + && modifiers == CustomKeys.BankPlus.modifiers) + { + GUI.CurrentSaveBank++; + if (GUI.CurrentSaveBank > LAST_SAVE_BANK) + GUI.CurrentSaveBank = 0; + + static char str[64]; + sprintf(str, FREEZE_INFO_SET_BANK_N, GUI.CurrentSaveBank); + S9xSetInfoString(str); + + hitHotKey = true; + } + if (wParam == CustomKeys.BankMinus.key + && modifiers == CustomKeys.BankMinus.modifiers) + { + GUI.CurrentSaveBank--; + if (GUI.CurrentSaveBank < 0) + GUI.CurrentSaveBank = 9; + + static char str[64]; + sprintf(str, FREEZE_INFO_SET_BANK_N, GUI.CurrentSaveBank); + S9xSetInfoString(str); + hitHotKey = true; } } @@ -1218,11 +1258,11 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) if(wParam == CustomKeys.TurboDown.key && modifiers == CustomKeys.TurboDown.modifiers) PostMessage(GUI.hWnd, WM_COMMAND, (WPARAM)(ID_TURBO_DOWN),(LPARAM)(NULL)); - for(int i = 0 ; i < 10 ; i++) + for(int i = 0 ; i < SAVE_SLOTS_PER_BANK; i++) { if(wParam == CustomKeys.SelectSave[i].key && modifiers == CustomKeys.SelectSave[i].modifiers) { - GUI.CurrentSaveSlot = i; + GUI.CurrentSaveSlot = GUI.CurrentSaveBank * SAVE_SLOTS_PER_BANK + i; static char str [64]; sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot); @@ -1529,7 +1569,19 @@ LRESULT CALLBACK WinProc( return 0; case WM_COMMAND: - switch (wParam & 0xffff) + { + int cmd_id = wParam & 0xffff; + if (cmd_id >= ID_FILE_SAVE0 && cmd_id < ID_FILE_SAVE0 + NUM_SAVE_BANKS * SAVE_SLOTS_PER_BANK) + { + FreezeUnfreezeSlot(cmd_id - ID_FILE_SAVE0, TRUE); + break; + } + else if (cmd_id >= ID_FILE_LOAD0 && cmd_id < ID_FILE_LOAD0 + NUM_SAVE_BANKS * SAVE_SLOTS_PER_BANK) + { + FreezeUnfreezeSlot(cmd_id - ID_FILE_LOAD0, FALSE); + break; + } + switch (cmd_id) { case ID_FILE_AVI_RECORDING: if (!GUI.AVIOut) @@ -2123,36 +2175,6 @@ LRESULT CALLBACK WinProc( Settings.FrameAdvance = false; GUI.FrameAdvanceJustPressed = 0; break; - case ID_FILE_LOAD0: - FreezeUnfreezeSlot (0, FALSE); - break; - case ID_FILE_LOAD1: - FreezeUnfreezeSlot (1, FALSE); - break; - case ID_FILE_LOAD2: - FreezeUnfreezeSlot (2, FALSE); - break; - case ID_FILE_LOAD3: - FreezeUnfreezeSlot (3, FALSE); - break; - case ID_FILE_LOAD4: - FreezeUnfreezeSlot (4, FALSE); - break; - case ID_FILE_LOAD5: - FreezeUnfreezeSlot (5, FALSE); - break; - case ID_FILE_LOAD6: - FreezeUnfreezeSlot (6, FALSE); - break; - case ID_FILE_LOAD7: - FreezeUnfreezeSlot (7, FALSE); - break; - case ID_FILE_LOAD8: - FreezeUnfreezeSlot (8, FALSE); - break; - case ID_FILE_LOAD9: - FreezeUnfreezeSlot (9, FALSE); - break; case ID_FILE_LOAD_OOPS: FreezeUnfreezeSlot(-1, FALSE); break; @@ -2162,36 +2184,6 @@ LRESULT CALLBACK WinProc( case ID_FILE_LOAD_PREVIEW: FreezeUnfreezeDialogPreview(FALSE); break; - case ID_FILE_SAVE0: - FreezeUnfreezeSlot (0, TRUE); - break; - case ID_FILE_SAVE1: - FreezeUnfreezeSlot (1, TRUE); - break; - case ID_FILE_SAVE2: - FreezeUnfreezeSlot (2, TRUE); - break; - case ID_FILE_SAVE3: - FreezeUnfreezeSlot (3, TRUE); - break; - case ID_FILE_SAVE4: - FreezeUnfreezeSlot (4, TRUE); - break; - case ID_FILE_SAVE5: - FreezeUnfreezeSlot (5, TRUE); - break; - case ID_FILE_SAVE6: - FreezeUnfreezeSlot (6, TRUE); - break; - case ID_FILE_SAVE7: - FreezeUnfreezeSlot (7, TRUE); - break; - case ID_FILE_SAVE8: - FreezeUnfreezeSlot (8, TRUE); - break; - case ID_FILE_SAVE9: - FreezeUnfreezeSlot (9, TRUE); - break; case ID_FILE_SAVE_FILE: FreezeUnfreezeDialog(TRUE); break; @@ -2316,7 +2308,7 @@ LRESULT CALLBACK WinProc( break; } break; - + } case WM_EXITMENULOOP: UpdateWindow(GUI.hWnd); DrawMenuBar(GUI.hWnd); @@ -2635,6 +2627,40 @@ BOOL WinInit( HINSTANCE hInstance) MessageBox (NULL, TEXT("Failed to initialize the menu.\nThis could indicate a failure of your operating system;\ntry closing some other windows or programs, or restart your computer, before opening Snes9x again.\nOr, if you compiled this program yourself, ensure that Snes9x was built with the proper resource files."), TEXT("Snes9x - Menu Initialization Failure"), MB_OK | MB_ICONSTOP); // return FALSE; // disabled: try to function without the menu } + + // insert bank and slot submenus / menu items + HMENU parent_menu_save = GetSubMenuById(ID_FILE_SAVE_POPUP); + HMENU parent_menu_load = GetSubMenuById(ID_FILE_LOAD_POPUP); + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + + for (int i = 0; i < NUM_SAVE_BANKS; i++) + { + // one bank sub each for save and load + HMENU bank_menu_save = CreatePopupMenu(); + HMENU bank_menu_load = CreatePopupMenu(); + // fill the slot entries into the sub menus + for (int j = 0; j < SAVE_SLOTS_PER_BANK; j++) + { + TCHAR *slot_string = g_saveMenuItemStrings[i * SAVE_SLOTS_PER_BANK + j]; + _stprintf(slot_string, _T("Slot #&%d"), j); + mii.fMask = MIIM_STRING | MIIM_ID; + mii.dwTypeData = slot_string; + mii.wID = ID_FILE_SAVE0 + i * SAVE_SLOTS_PER_BANK + j; + InsertMenuItem(bank_menu_save, j, TRUE, &mii); + mii.wID = ID_FILE_LOAD0 + i * SAVE_SLOTS_PER_BANK + j; + InsertMenuItem(bank_menu_load, j, TRUE, &mii); + } + + // add the bank menus to save and load + _stprintf(g_bankMenuItemStrings[i], _T("Bank #&%d"), i); + mii.fMask = MIIM_STRING | MIIM_SUBMENU; + mii.dwTypeData = g_bankMenuItemStrings[i]; + mii.hSubMenu = bank_menu_save; + InsertMenuItem(parent_menu_save, i, TRUE, &mii); + mii.hSubMenu = bank_menu_load; + InsertMenuItem(parent_menu_load, i, TRUE, &mii); + } #ifdef DEBUGGER if(GUI.hMenu) { InsertMenu(GUI.hMenu,ID_OPTIONS_SETTINGS,MF_BYCOMMAND | MF_STRING | MF_ENABLED,ID_DEBUG_FRAME_ADVANCE,TEXT("&Debug Frame Advance")); @@ -8378,6 +8404,7 @@ static hotkey_dialog_item hotkey_dialog_items[4][MAX_SWITCHABLE_HOTKEY_DIALOG_IT { &CustomKeys.QuitS9X, HOTKEYS_LABEL_1_11 }, { &CustomKeys.ResetGame, HOTKEYS_LABEL_1_12 }, { &CustomKeys.SaveScreenShot, HOTKEYS_LABEL_1_13 }, + { &CustomKeys.FrameAdvance, HOTKEYS_LABEL_1_14 }, }, { { &CustomKeys.BGL1, HOTKEYS_LABEL_2_1 }, @@ -8387,12 +8414,13 @@ static hotkey_dialog_item hotkey_dialog_items[4][MAX_SWITCHABLE_HOTKEY_DIALOG_IT { &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.ScopeTurbo, 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.ReadOnly, HOTKEYS_LABEL_2_14 }, }, { { &CustomKeys.TurboA, HOTKEYS_LABEL_3_1 }, @@ -8407,7 +8435,8 @@ static hotkey_dialog_item hotkey_dialog_items[4][MAX_SWITCHABLE_HOTKEY_DIALOG_IT { &CustomKeys.TurboUp, HOTKEYS_LABEL_3_10 }, { &CustomKeys.TurboRight, HOTKEYS_LABEL_3_11 }, { &CustomKeys.TurboDown, HOTKEYS_LABEL_3_12 }, - { &CustomKeys.ScopeTurbo, HOTKEYS_LABEL_3_13 }, + { NULL, _T("") }, + { NULL, _T("") }, }, { { &CustomKeys.SelectSave[0], HOTKEYS_LABEL_4_1 }, @@ -8422,7 +8451,8 @@ static hotkey_dialog_item hotkey_dialog_items[4][MAX_SWITCHABLE_HOTKEY_DIALOG_IT { &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 }, + { NULL, _T("") }, + { NULL, _T("") }, }, }; @@ -8447,9 +8477,11 @@ static void set_hotkeyinfo(HWND hDlg) 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); + SendDlgItemMessage(hDlg, IDC_BANKPLUS, WM_USER + 44, CustomKeys.BankPlus.key, CustomKeys.BankPlus.modifiers); + SendDlgItemMessage(hDlg, IDC_BANKMINUS, WM_USER + 44, CustomKeys.BankMinus.key, CustomKeys.BankMinus.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); + for(i = 0 ; i < SAVE_SLOTS_PER_BANK; i++) SendDlgItemMessage(hDlg,IDC_SAVE1+i,WM_USER+44,CustomKeys.Save[i].key,CustomKeys.Save[i].modifiers); + for(i = 0 ; i < SAVE_SLOTS_PER_BANK; i++) SendDlgItemMessage(hDlg,IDC_SAVE11+i,WM_USER+44,CustomKeys.Load[i].key,CustomKeys.Load[i].modifiers); for(int i = 0; i < MAX_SWITCHABLE_HOTKEY_DIALOG_ITEMS; i++) { @@ -8564,6 +8596,16 @@ switch(msg) CustomKeys.DialogLoad.key = wParam; CustomKeys.DialogLoad.modifiers = modifiers; break; + + case IDC_BANKPLUS: + CustomKeys.BankPlus.key = wParam; + CustomKeys.BankPlus.modifiers = modifiers; + break; + + case IDC_BANKMINUS: + CustomKeys.BankMinus.key = wParam; + CustomKeys.BankMinus.modifiers = modifiers; + break; } if(which >= IDC_HOTKEY1 && which <= IDC_HOTKEY13) diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 99f88a62..8d8c731b 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -34,6 +34,11 @@ #define MAX_RECENT_GAMES_LIST_SIZE 32 #define MAX_RECENT_HOSTS_LIST_SIZE 16 +#define SAVE_SLOTS_PER_BANK 10 +#define LAST_SAVE_SLOT_IN_BANK (SAVE_SLOTS_PER_BANK - 1) +#define NUM_SAVE_BANKS 10 +#define LAST_SAVE_BANK (NUM_SAVE_BANKS - 1) + #include "_tfwopen.h" #ifdef UNICODE #define _tToChar WideToUtf8 @@ -197,6 +202,7 @@ struct sGUI { int BlueShift; int ControlForced; int CurrentSaveSlot; + int CurrentSaveBank; int MaxRecentGames; int ControllerOption; int ValidControllerOptions; @@ -298,8 +304,8 @@ struct SCustomKeys { SCustomKey ScopePause; SCustomKey FrameCount; SCustomKey ReadOnly; - SCustomKey Save [10]; - SCustomKey Load [10]; + SCustomKey Save [SAVE_SLOTS_PER_BANK]; + SCustomKey Load [SAVE_SLOTS_PER_BANK]; SCustomKey FastForward; SCustomKey FastForwardToggle; SCustomKey ShowPressed; @@ -308,6 +314,8 @@ struct SCustomKeys { SCustomKey SlotMinus; SCustomKey SlotSave; SCustomKey SlotLoad; + SCustomKey BankPlus; + SCustomKey BankMinus; SCustomKey DialogSave; SCustomKey DialogLoad; SCustomKey BGL1; @@ -320,7 +328,7 @@ struct SCustomKeys { SCustomKey JoypadSwap; SCustomKey SwitchControllers; SCustomKey TurboA, TurboB, TurboY, TurboX, TurboL, TurboR, TurboStart, TurboSelect, TurboLeft, TurboUp, TurboRight, TurboDown; - SCustomKey SelectSave [10]; + SCustomKey SelectSave [SAVE_SLOTS_PER_BANK]; SCustomKey ResetGame; SCustomKey ToggleCheats; SCustomKey QuitS9X;