diff --git a/src/drivers/win/Win32InputBox.cpp b/src/drivers/win/Win32InputBox.cpp new file mode 100644 index 00000000..f6b53836 --- /dev/null +++ b/src/drivers/win/Win32InputBox.cpp @@ -0,0 +1,354 @@ +#include "Win32InputBox.h" +#include + +#pragma warning (disable: 4312) + +/* +History +---------- +03/02/2006 +- Initial version development + +03/04/2006 +- Lessened the complexity of the class, made it less generic (since its purpose is to be simple) +- Updated the dialog template and made OK button as default button + +*/ + +typedef struct _MSDN_DLGTEMPLATEEX +{ + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x; + short y; + short cx; + short cy; + BYTE _rest[1]; // rest of structure +} MSDN_DLGTEMPLATEEX; + +static bool IsDlgTemplateExtended(DLGTEMPLATE *dlgTemplate) +{ + MSDN_DLGTEMPLATEEX *dgExTemplate = (MSDN_DLGTEMPLATEEX *) dlgTemplate; + + // MSDN excerpt: + //* dlgVer + // Specifies the version number of the extended dialog box template. This member must be 1. + //* signature + // Indicates whether a template is an extended dialog box template. + // If signature is 0xFFFF, this is an extended dialog box template. + // In this case, the dlgVer member specifies the template version number. + // If signature is any value other than 0xFFFF, this is a standard dialog box template that uses the DLGTEMPLATE and DLGITEMTEMPLATE structures. + + return (dgExTemplate->dlgVer == 1) && (dgExTemplate->signature == 0xFFFF); +} + +// Use alignment if supported by the compiler +#ifdef _MSC_VER + #if _MSC_VER > 1200 + __declspec(align(4)) + #endif +#endif + +// per the MSDN, the DLGTEMPLATE must be DWORD aligned +// this was generated by the DlgResToDlgTemplate tool +static unsigned char definputbox_dlg[] = +{ + 0x01,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,0xc8,0x00,0x06, + 0x00,0x16,0x00,0x11,0x00,0xe7,0x00,0x6d,0x00,0x00,0x00,0x00,0x00,0x57,0x00,0x69, + 0x00,0x6e,0x00,0x33,0x00,0x32,0x00,0x49,0x00,0x6e,0x00,0x70,0x00,0x75,0x00,0x74, + 0x00,0x42,0x00,0x6f,0x00,0x78,0x00,0x00,0x00,0x08,0x00,0xbc,0x02,0x00,0x00,0x4d, + 0x00,0x53,0x00,0x20,0x00,0x53,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20, + 0x00,0x44,0x00,0x6c,0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0x00,0x02,0x50,0x06,0x00,0x04,0x00,0x9d,0x00,0x21,0x00,0xe8, + 0x03,0x00,0x00,0xff,0xff,0x82,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x6d,0x00,0x70, + 0x00,0x74,0x00,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x80,0x00,0x81,0x50,0x06,0x00,0x25,0x00,0xd8,0x00,0x0e,0x00,0xe9, + 0x03,0x00,0x00,0xff,0xff,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x84,0x10,0xa1,0x50,0x06,0x00,0x37,0x00,0xd8,0x00,0x31,0x00,0xea, + 0x03,0x00,0x00,0xff,0xff,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x00,0x03,0x50,0xab,0x00,0x04,0x00,0x33,0x00,0x0e,0x00,0x01, + 0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x4f,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x50,0xab,0x00,0x15,0x00,0x33, + 0x00,0x0e,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x43,0x00,0x41,0x00,0x4e, + 0x00,0x43,0x00,0x45,0x00,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x00,0x00,0x27,0x00,0x08,0x00,0x08,0x00,0xff, + 0xff,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0x00,0x00 +}; + +static LPCTSTR definputbox_buttonnames[] = { _T("OK"), _T("CANCEL") }; +static const INT_PTR definputbox_buttonids[] = { IDOK, IDCANCEL }; + +static const INT + definputbox_id_prompt = 1000, + definputbox_id_edit1 = 1001, + definputbox_id_edit2 = 1002; + +WIN32INPUTBOX_PARAM::WIN32INPUTBOX_PARAM() +{ + bMultiline = false; + hwndOwner = 0; + DlgTemplateName = 0; + hInstance = (HINSTANCE) ::GetModuleHandle(0); + DlgTemplateData = definputbox_dlg; + + bCenter = true; + + dwStylesPlus = 0; + dwExStylesPlus = 0; + dwStylesMinus = 0xFFFFFFFF; + dwExStylesMinus = 0xFFFFFFFF; + + xPos = yPos = -1; + + szResult = 0; + nResultSize = 0; +} + +CWin32InputBox::CWin32InputBox(WIN32INPUTBOX_PARAM *param) +{ + _param = param; +} + +CWin32InputBox::~CWin32InputBox() +{ + +} + +void CWin32InputBox::SetParam(WIN32INPUTBOX_PARAM *param) +{ + _param = param; +} + +WIN32INPUTBOX_PARAM *CWin32InputBox::GetParam() +{ + return _param; +} + +INT_PTR CWin32InputBox::InputBoxEx(WIN32INPUTBOX_PARAM *param) +{ + // Check mandatory parameters + if (param->szResult == 0) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + LPDLGTEMPLATE dlgTemplate; + + if (param->DlgTemplateName != 0) + { + HMODULE hModule = (HMODULE)param->hInstance; + HRSRC rcDlg = ::FindResource(hModule, MAKEINTRESOURCE(param->DlgTemplateName), RT_DIALOG); + if (rcDlg == NULL) + return 0; + + HGLOBAL hglobalDlg = ::LoadResource(hModule, rcDlg); + if (hglobalDlg == NULL) + return 0; + + dlgTemplate = (LPDLGTEMPLATE) hglobalDlg; + } + else if (param->DlgTemplateData != 0) + { + dlgTemplate = (LPDLGTEMPLATE) param->DlgTemplateData; + } + + MSDN_DLGTEMPLATEEX *dlgTemplateEx = + IsDlgTemplateExtended((LPDLGTEMPLATE) dlgTemplate) ? (MSDN_DLGTEMPLATEEX *) dlgTemplate : 0; + + if (dlgTemplateEx != 0) + { + dlgTemplateEx->exStyle |= param->dwExStylesPlus; + dlgTemplateEx->style |= param->dwStylesPlus; + dlgTemplateEx->exStyle &= param->dwExStylesMinus; + dlgTemplateEx->style &= param->dwStylesMinus; + + if (param->bCenter) + dlgTemplateEx->style |= DS_CENTER; + + if (param->xPos != -1) + dlgTemplateEx->x = param->xPos; + if (param->yPos != -1) + dlgTemplateEx->y = param->yPos; + } + else + { + dlgTemplate->dwExtendedStyle |= param->dwExStylesPlus; + dlgTemplate->style |= param->dwStylesPlus; + dlgTemplate->dwExtendedStyle &= param->dwExStylesMinus; + dlgTemplate->style &= param->dwStylesMinus; + + if (param->bCenter) + dlgTemplate->style |= DS_CENTER; + + if (param->xPos != -1) + dlgTemplate->x = param->xPos; + + if (param->yPos != -1) + dlgTemplate->y = param->yPos; + } + + CWin32InputBox inputbox(param); + + // Resize dialog and SHOW or HIDE multiline + INT_PTR r = ::DialogBoxIndirectParam(param->hInstance, dlgTemplate, param->hwndOwner, (DLGPROC)DlgProc, (LPARAM)&inputbox); + + return r; +} + +INT_PTR CWin32InputBox::InputBox( + LPCTSTR szTitle, + LPCTSTR szPrompt, + LPTSTR szResult, + DWORD nResultSize, + bool bMultiLine, + HWND hwndParent) +{ + WIN32INPUTBOX_PARAM param; + + param.szTitle = szTitle; + param.szPrompt = szPrompt; + param.szResult = szResult; + param.nResultSize = nResultSize; + param.bMultiline = bMultiLine; + param.hwndOwner = hwndParent; + + return InputBoxEx(¶m); +} + +INT_PTR CWin32InputBox::GetInteger( + LPCTSTR szTitle, + LPCTSTR szPrompt, + int& result, + HWND hwndParent) +{ + WIN32INPUTBOX_PARAM param; + + char szResult[20] = {'0'}; + param.szTitle = szTitle; + param.szPrompt = szPrompt; + param.szResult = szResult; + param.nResultSize = sizeof(szResult); + param.bMultiline = false; + param.hwndOwner = hwndParent; + + INT_PTR ret = InputBoxEx(¶m); + if(ret == IDOK) + result = atoi(szResult); + return ret; +} + +void CWin32InputBox::InitDialog() +{ + // Set the button captions + for (size_t i=0;ihDlg, (int) definputbox_buttonids[i], definputbox_buttonnames[i]); + + // Set other controls + ::SetWindowText(_param->hDlg, _param->szTitle); + ::SetDlgItemText(_param->hDlg, definputbox_id_prompt, _param->szPrompt); + + HWND hwndEdit1 = ::GetDlgItem(_param->hDlg, definputbox_id_edit1); + HWND hwndEdit2 = ::GetDlgItem(_param->hDlg, definputbox_id_edit2); + + if (_param->bMultiline) + _hwndEditCtrl = hwndEdit2; + else + _hwndEditCtrl = hwndEdit1; + + ::SetWindowText(_hwndEditCtrl, _param->szResult); + + RECT rectDlg, rectEdit1, rectEdit2; + + ::GetWindowRect(_param->hDlg, &rectDlg); + ::GetWindowRect(hwndEdit1, &rectEdit1); + ::GetWindowRect(hwndEdit2, &rectEdit2); + + if (_param->bMultiline) + { + ::ShowWindow(hwndEdit1, SW_HIDE); + ::SetWindowPos( + hwndEdit2, + HWND_NOTOPMOST, + rectEdit1.left - rectDlg.left, + (rectEdit1.top - rectDlg.top) - (rectEdit1.bottom - rectEdit1.top), + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + + ::SetWindowPos( + _param->hDlg, + HWND_NOTOPMOST, + 0, + 0, + rectDlg.right - rectDlg.left, + rectDlg.bottom - rectDlg.top - (rectEdit1.bottom - rectEdit1.top), + SWP_NOMOVE); + + } + else + { + ::SetWindowPos( + _param->hDlg, + HWND_NOTOPMOST, + 0, + 0, + rectDlg.right - rectDlg.left, + rectEdit1.bottom - rectDlg.top + 5, + SWP_NOMOVE); + + ::ShowWindow(hwndEdit2, SW_HIDE); + } +} + +// Message handler for about box. +LRESULT CALLBACK CWin32InputBox::DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWin32InputBox *_this = (CWin32InputBox *) ::GetWindowLong(hDlg, GWL_USERDATA); + WIN32INPUTBOX_PARAM *param = _this ? _this->GetParam() : 0; + + switch (message) + { + case WM_INITDIALOG: + { + ::SetWindowLong(hDlg, GWL_USERDATA, (LONG) lParam); + + _this = (CWin32InputBox *) lParam; + _this->_param->hDlg = hDlg; + _this->InitDialog(); + return TRUE; + } + + case WM_COMMAND: + { +#ifdef _MY_DEBUG + CHAR buf[1024]; + static int i=0; + sprintf(buf, "WM_COMMAND: %09d wParam=%08X lParam=%08X\n", i++, wParam, lParam); + OutputDebugString(buf); +#endif + INT_PTR buttonId = LOWORD(wParam); + for (size_t i=0; + i_hwndEditCtrl, + _this->_param->szResult, + _this->_param->nResultSize); + + ::EndDialog(hDlg, buttonId); + return TRUE; + } + } + } + break; + } + return FALSE; +} diff --git a/src/drivers/win/Win32InputBox.h b/src/drivers/win/Win32InputBox.h new file mode 100644 index 00000000..ff1acbe0 --- /dev/null +++ b/src/drivers/win/Win32InputBox.h @@ -0,0 +1,104 @@ +#ifndef __03022006__WIN32INPUTBOX__ +#define __03022006__WIN32INPUTBOX__ + +/* + +This library is (c) Elias Bachaalany aka lallous +You may use this library under the following license agreement: + +The zlib/libpng License. +--------------------------- +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#include +#include + +class CWin32InputBox; + +// Structure used to orient the inputbox behavior +struct WIN32INPUTBOX_PARAM +{ + friend class CWin32InputBox; + + // + IN OPTIONAL bool bMultiline; + + // Pass this as none zero so to use this memory dlg template + IN OPTIONAL LPVOID DlgTemplateData; + + // Pass this as none ZERO so to load DLGTEMPLATE from resources + IN OPTIONAL LPCTSTR DlgTemplateName; + + // passing both "DlgTemplateName" and "DlgTemplateData" ZERO will cause + // the dialog to use his default embedded resource + + // Center on monitor or owner window? + IN OPTIONAL bool bCenter; + + // Want to add more styles to the dialog? + IN OPTIONAL DWORD dwStylesPlus, dwStylesMinus; + IN OPTIONAL DWORD dwExStylesPlus, dwExStylesMinus; + + IN LPCTSTR szTitle, szPrompt; + + // Return buffer + OUT LPTSTR szResult; + IN DWORD nResultSize; + + // Owner window + HWND hwndOwner; + HINSTANCE hInstance; + + short xPos, yPos; + + WIN32INPUTBOX_PARAM(); +private: + HWND hDlg; +}; + +class CWin32InputBox +{ +private: + WIN32INPUTBOX_PARAM *_param; + static LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); + HWND _hwndEditCtrl; + + void InitDialog(); + void SetParam(WIN32INPUTBOX_PARAM *); + WIN32INPUTBOX_PARAM * GetParam(); + +public: + + CWin32InputBox(WIN32INPUTBOX_PARAM *); + ~CWin32InputBox(); + + static INT_PTR InputBoxEx(WIN32INPUTBOX_PARAM *); + static INT_PTR InputBox( + LPCTSTR szTitle, + LPCTSTR szPrompt, + LPTSTR szResult, + DWORD nResultSize, + bool bMultiLine = false, + HWND hwndParent = 0); + + static INT_PTR GetInteger( + LPCTSTR szTitle, + LPCTSTR szPrompt, + int& result, + HWND hwndParent = 0); +}; + +#endif \ No newline at end of file diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 1433ba23..08e2a5b3 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -159,6 +159,80 @@ BEGIN MENUITEM "Save FM2", ID_FILE_SAVEFM2 MENUITEM "&Open FM2", ID_FILE_OPENFM2 END + MENUITEM "Edit", 0 +END + +MEMVIEWMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Save Rom", MENU_MV_FILE_SAVE + MENUITEM "S&ave Rom As...", MENU_MV_FILE_SAVE_AS + MENUITEM "&Load *.TBL File", MENU_MV_FILE_LOAD_TBL + MENUITEM "Unload *.TBL file", MENU_MV_FILE_UNLOAD_TBL + POPUP "&Dump to file" + BEGIN + MENUITEM "&Ram", MENU_MV_FILE_DUMP_RAM + MENUITEM "&PPU Memory", MENU_MV_FILE_DUMP_PPU + END + END + POPUP "&Edit" + BEGIN + MENUITEM "Undo Ctrl+Z", MENU_MV_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Copy", MENU_MV_EDIT_COPY + MENUITEM "Paste", MENU_MV_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Find...", MENU_MV_EDIT_FIND + MENUITEM "Find Next", MENU_MV_EDIT_FIND_NEXT + END + POPUP "&View" + BEGIN + MENUITEM "NES Memory", MENU_MV_VIEW_RAM, CHECKED + MENUITEM "PPU Memory", MENU_MV_VIEW_PPU + MENUITEM "Rom File", MENU_MV_VIEW_ROM + END + POPUP "&Bookmarks" + BEGIN + MENUITEM "&Remove all bookmarks", MENU_MV_BOOKMARKS_RM_ALL + MENUITEM SEPARATOR + END +END + +MEMWATCHMENU MENU +BEGIN + POPUP "File " + BEGIN + MENUITEM "New... Ctrl+N", MEMW_FILE_NEW + MENUITEM "Open... Ctrl+O", MEMW_FILE_OPEN + MENUITEM "Save Ctrl+S", MEMW_FILE_SAVE + MENUITEM "Save As.. Ctrl+Shift+S", MEMW_FILE_SAVEAS + MENUITEM "&Recent", ID_FILE_RECENT + MENUITEM SEPARATOR + MENUITEM "Close Ctrl+W", MEMW_FILE_CLOSE + END + POPUP "Options" + BEGIN + MENUITEM "Load on Startup", MEMW_OPTIONS_LOADSTART + MENUITEM "Load Last File on Startup", MEMW_OPTIONS_LOADLASTFILE + END + POPUP "Help" + BEGIN + MENUITEM "MemWatch Commands", MEMW_HELP_WCOMMANDS + END +END + +TASEDITCONTEXTMENUS MENU +BEGIN + POPUP "Stray" + BEGIN + MENUITEM "&Insert Frames", MENU_STRAY_INSERTFRAMES + END + POPUP "Selected" + BEGIN + MENUITEM "Insert Frame(s)", MENU_INSERTFRAMES + MENUITEM "Delete Frame(s)", MENU_DELETEFRAMES + END END @@ -443,29 +517,6 @@ BEGIN RTEXT "Filter:",65484,6,255,21,12,SS_CENTERIMAGE | NOT WS_GROUP END -MEMVIEW DIALOG 48, 71, 263, 237 -STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Memory Viewer" -FONT 8, "Fixedsys" -BEGIN - DEFPUSHBUTTON "Close",1,200,218,56,14 - EDITTEXT 100,6,4,237,132,ES_CENTER | ES_MULTILINE | ES_READONLY - EDITTEXT 200,14,167,19,12 - EDITTEXT 201,42,167,14,12 - DEFPUSHBUTTON "Poke Me!",202,68,156,42,14 - GROUPBOX "Memory Poke",102,6,146,111,48,WS_TABSTOP - SCROLLBAR 103,244,4,9,132,SBS_VERT - GROUPBOX "Memory File Dump",104,118,146,143,33,WS_TABSTOP - EDITTEXT 210,133,160,19,12 - EDITTEXT 211,189,160,19,12 - LTEXT "through",65483,156,162,29,8 - PUSHBUTTON "Dump Me!",212,213,159,42,14 - GROUPBOX "Memory File Load",65482,6,200,102,33,WS_TABSTOP - EDITTEXT 220,21,213,19,12 - PUSHBUTTON "Load!",222,56,211,42,14 - DEFPUSHBUTTON "HL Store",203,68,176,42,14 -END - MESSAGELOG DIALOG 33, 38, 370, 184 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Message Log" @@ -1211,11 +1262,11 @@ END TASEDIT DIALOGEX 0, 0, 470, 349 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "TAS Editor" +MENU TASEDITMENU FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,273,296 PUSHBUTTON "Hacky truncate after current frame",IDC_HACKY1,313,31,124,38 - PUSHBUTTON "Hacky add 1000 frames",IDC_HACKY2,313,73,124,38 END ASSEMBLER DIALOGEX 0, 0, 202, 135 @@ -1510,72 +1561,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -MEMVIEWMENU MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&Save Rom", MENU_MV_FILE_SAVE - MENUITEM "S&ave Rom As...", MENU_MV_FILE_SAVE_AS - MENUITEM "&Load *.TBL File", MENU_MV_FILE_LOAD_TBL - MENUITEM "Unload *.TBL file", MENU_MV_FILE_UNLOAD_TBL - POPUP "&Dump to file" - BEGIN - MENUITEM "&Ram", MENU_MV_FILE_DUMP_RAM - MENUITEM "&PPU Memory", MENU_MV_FILE_DUMP_PPU - END - END - POPUP "&Edit" - BEGIN - MENUITEM "Undo Ctrl+Z", MENU_MV_EDIT_UNDO - MENUITEM SEPARATOR - MENUITEM "Copy", MENU_MV_EDIT_COPY - MENUITEM "Paste", MENU_MV_EDIT_PASTE - MENUITEM SEPARATOR - MENUITEM "Find...", MENU_MV_EDIT_FIND - MENUITEM "Find Next", MENU_MV_EDIT_FIND_NEXT - END - POPUP "&View" - BEGIN - MENUITEM "NES Memory", MENU_MV_VIEW_RAM, CHECKED - MENUITEM "PPU Memory", MENU_MV_VIEW_PPU - MENUITEM "Rom File", MENU_MV_VIEW_ROM - END - POPUP "&Bookmarks" - BEGIN - MENUITEM "&Remove all bookmarks", MENU_MV_BOOKMARKS_RM_ALL - MENUITEM SEPARATOR - END -END - -MEMWATCHMENU MENU -BEGIN - POPUP "File " - BEGIN - MENUITEM "New... Ctrl+N", MEMW_FILE_NEW - MENUITEM "Open... Ctrl+O", MEMW_FILE_OPEN - MENUITEM "Save Ctrl+S", MEMW_FILE_SAVE - MENUITEM "Save As.. Ctrl+Shift+S", MEMW_FILE_SAVEAS - MENUITEM "&Recent", ID_FILE_RECENT - MENUITEM SEPARATOR - MENUITEM "Close Ctrl+W", MEMW_FILE_CLOSE - END - POPUP "Options" - BEGIN - MENUITEM "Load on Startup", MEMW_OPTIONS_LOADSTART - MENUITEM "Load Last File on Startup", MEMW_OPTIONS_LOADLASTFILE - END - POPUP "Help" - BEGIN - MENUITEM "MemWatch Commands", MEMW_HELP_WCOMMANDS - END -END - - ///////////////////////////////////////////////////////////////////////////// // // Dialog diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 5b782e94..86585c25 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -528,6 +528,13 @@ #define MENU_DISPLAY_OBJ 40148 #define ID_FILE_CONVERTMOVIE 40149 #define MENU_CONVERT_MOVIE 40150 +#define ID_STRAY_INSERTFRAMES 40151 +#define MENU_INSERTFRAMES 40152 +#define ID_SELECTED_INSERTFRAME 40153 +#define ID_SELECTED_DELETEFRAME 40154 +#define MENU_DELETEFRAME 40155 +#define MENU_DELETEFRAMES 40156 +#define MENU_STRAY_INSERTFRAMES 40157 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 #define GUI_BOT_DEBUG 65436 @@ -537,8 +544,8 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 116 -#define _APS_NEXT_COMMAND_VALUE 40151 +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40158 #define _APS_NEXT_CONTROL_VALUE 1133 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index 0dc67501..5d89253f 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -8,6 +8,7 @@ #include "replay.h" #include "movie.h" #include "utils/xstring.h" +#include "Win32InputBox.h" using namespace std; @@ -17,7 +18,7 @@ using namespace std; HWND hwndTasEdit = 0; -static HMENU hmenu; +static HMENU hmenu, hrmenu; static int lastCursor; static HWND hwndList, hwndHeader; static WNDPROC hwndHeader_oldWndproc; @@ -125,6 +126,59 @@ void RedrawList() InvalidateRect(hwndList,0,FALSE); } +enum ECONTEXTMENU +{ + CONTEXTMENU_STRAY = 0, + CONTEXTMENU_SELECTED = 1, +}; + +void ShowMenu(ECONTEXTMENU which, POINT& pt) +{ + HMENU sub = GetSubMenu(hrmenu,(int)which); + TrackPopupMenu(sub,0,pt.x,pt.y,TPM_RIGHTBUTTON,hwndTasEdit,0); +} + +void StrayClickMenu(LPNMITEMACTIVATE info) +{ + POINT pt = info->ptAction; + ClientToScreen(hwndList,&pt); + ShowMenu(CONTEXTMENU_STRAY,pt); +} + +void RightClickMenu(LPNMITEMACTIVATE info) +{ + POINT pt = info->ptAction; + ClientToScreen(hwndList,&pt); + ShowMenu(CONTEXTMENU_SELECTED,pt); +} + +void RightClick(LPNMITEMACTIVATE info) +{ + int index = info->iItem; + int column = info->iSubItem; + + //stray clicks give a context menu: + if(index == -1) + { + StrayClickMenu(info); + return; + } + + //make sure that the click is in our currently selected set. + //if it is not, then we don't know what to do yet + if(selectionFrames.find(index) == selectionFrames.end()) + { + return; + } + + RightClickMenu(info); +} + +void InvalidateGreenZone(int after) +{ + currMovieData.greenZoneCount = std::min(after+1,currMovieData.greenZoneCount); +} + void DoubleClick(LPNMITEMACTIVATE info) { int index = info->iItem; @@ -140,6 +194,7 @@ void DoubleClick(LPNMITEMACTIVATE info) if(index < currMovieData.greenZoneCount) { MovieData::loadSavestateFrom(&currMovieData.records[index].savestate); + currFrameCounter = index; } } else //if an input column was clicked: @@ -151,14 +206,35 @@ void DoubleClick(LPNMITEMACTIVATE info) //update the row ListView_Update(hwndList,index); - //reduce the green zone - currMovieData.greenZoneCount = std::min(index+1,currMovieData.greenZoneCount); + InvalidateGreenZone(index); //redraw everything to show the reduced green zone RedrawList(); } } +//insert frames at the currently selected positions. +static void InsertFrames() +{ + int frames = selectionFrames.size(); + + //this is going to be slow. + + //to keep this from being even slower than it would otherwise be, go ahead and reserve records + currMovieData.records.reserve(currMovieData.records.size()+frames); + + //insert frames before each selection + int ctr=0; + for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++) + { + currMovieData.insertEmpty(*it+ctr,1); + ctr++; + } + + InvalidateGreenZone(*selectionFrames.begin()); + + RedrawList(); +} //the column set operation, for setting a button for a span of selected values static void ColumnSet(int column) @@ -204,8 +280,7 @@ static void ColumnSet(int column) } //reduce the green zone - int firstSelection = *selectionFrames.begin(); - currMovieData.greenZoneCount = std::min(firstSelection,currMovieData.greenZoneCount); + InvalidateGreenZone(*selectionFrames.begin()); //redraw everything to show the reduced green zone RedrawList(); @@ -370,7 +445,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_INITDIALOG: hwndList = GetDlgItem(hwndDlg,IDC_LIST1); InitDialog(); - SetMenu(hwndDlg,hmenu); break; case WM_NOTIFY: @@ -389,6 +463,9 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case NM_DBLCLK: DoubleClick((LPNMITEMACTIVATE)lParam); break; + case NM_RCLICK: + RightClick((LPNMITEMACTIVATE)lParam); + break; case LVN_ITEMCHANGED: ItemChanged((LPNMLISTVIEW) lParam); break; @@ -409,17 +486,24 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_COMMAND: switch(LOWORD(wParam)) { + case MENU_INSERTFRAMES: + InsertFrames(); + break; + case MENU_STRAY_INSERTFRAMES: + { + int frames; + if(CWin32InputBox::GetInteger("Insert Frames", "How many frames?", frames, hwndDlg) == IDOK) + { + currMovieData.insertEmpty(-1,frames); + RedrawList(); + } + } + break; case IDC_HACKY1: //hacky1: delete all items after the current selection currMovieData.records.resize(currFrameCounter+1); UpdateTasEdit(); break; - case IDC_HACKY2: - //hacky1: delete all items after the cur rent selection - currMovieData.records.resize(currMovieData.records.size()+1000); - currMovieData.clearRecordRange(currMovieData.records.size()-1000,1000); - UpdateTasEdit(); - break; case ID_FILE_OPENFM2: Replay_LoadMovie(true); @@ -446,7 +530,11 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar void DoTasEdit() { if(!hmenu) + { hmenu = LoadMenu(fceu_hInstance,"TASEDITMENU"); + hrmenu = LoadMenu(fceu_hInstance,"TASEDITCONTEXTMENUS"); + } + lastCursor = -1; if(!hwndTasEdit) diff --git a/src/movie.cpp b/src/movie.cpp index c3bfa530..7a6d0e3d 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -79,6 +79,21 @@ void MovieData::clearRecordRange(int start, int len) records[i+start].clear(); } +void MovieData::insertEmpty(int at, int frames) +{ + if(at == -1) + { + int currcount = records.size(); + records.resize(records.size()+frames); + clearRecordRange(currcount,frames); + } + else + { + records.insert(records.begin()+at,frames,MovieRecord()); + clearRecordRange(at,frames); + } +} + void MovieData::TryDumpIncremental() { if(movieMode == MOVIEMODE_TASEDIT) @@ -95,6 +110,12 @@ void MovieData::TryDumpIncremental() } } +void MovieRecord::clear() +{ + *(uint32*)&joysticks = 0; + memset(zappers,0,sizeof(zappers)); +} + const char MovieRecord::mnemonics[8] = {'A','B','S','T','U','D','L','R'}; void MovieRecord::dumpJoy(std::ostream* os, uint8 joystate) { @@ -605,6 +626,7 @@ void FCEUMOV_EnterTasEdit() currMovieData.palFlag = FCEUI_GetCurrentVidSystem(0,0)!=0; currMovieData.romChecksum = GameInfo->MD5; currMovieData.romFilename = FileBase; + currMovieData.insertEmpty(0,1); //reset the rom poweron(false); @@ -619,6 +641,9 @@ void FCEUMOV_EnterTasEdit() //and enter tasedit mode movieMode = MOVIEMODE_TASEDIT; + + currMovieData.TryDumpIncremental(); + FCEU_DispMessage("Tasedit engaged"); } diff --git a/src/movie.h b/src/movie.h index 99d39da5..9eb34ad9 100644 --- a/src/movie.h +++ b/src/movie.h @@ -120,9 +120,7 @@ public: return (joysticks[joy] & mask(bit))!=0; } - void clear() { - *(uint32*)&joysticks = 0; - } + void clear(); //a waste of memory in lots of cases.. maybe make it a pointer later? std::vector savestate; @@ -205,6 +203,7 @@ public: void installValue(std::string& key, std::string& val); int dump(std::ostream* os, bool binary); void clearRecordRange(int start, int len); + void insertEmpty(int at, int frames); static bool loadSavestateFrom(std::vector* buf); static void dumpSavestateTo(std::vector* buf, int compressionLevel); diff --git a/vc8/fceux.vcproj b/vc8/fceux.vcproj index 921f7013..63be8bac 100644 --- a/vc8/fceux.vcproj +++ b/vc8/fceux.vcproj @@ -1259,6 +1259,14 @@ RelativePath="..\src\drivers\win\wave.h" > + + + +