From a71771ce977070b9906ecd9a7048a500e771a3f0 Mon Sep 17 00:00:00 2001 From: ansstuff Date: Sun, 20 Nov 2011 21:36:03 +0000 Subject: [PATCH] * multitrack recording * "Superimpose" checkbox (3 states) * Config->Use 1P keys for all single recordings * Config->Combine consecutive Recordings --- src/drivers/win/config.cpp | 6 + src/drivers/win/res.rc | 66 +++---- src/drivers/win/resource.h | 5 +- src/drivers/win/tasedit.cpp | 185 ++++++------------- src/drivers/win/tasedit.h | 13 -- src/drivers/win/taseditlib/bookmark.cpp | 13 +- src/drivers/win/taseditlib/bookmarks.cpp | 9 +- src/drivers/win/taseditlib/greenzone.cpp | 5 +- src/drivers/win/taseditlib/inputhistory.cpp | 85 +++++++-- src/drivers/win/taseditlib/inputhistory.h | 1 + src/drivers/win/taseditlib/inputsnapshot.cpp | 46 ++++- src/drivers/win/taseditlib/inputsnapshot.h | 9 +- src/drivers/win/taseditlib/markers.cpp | 2 - src/drivers/win/taseditlib/playback.cpp | 15 +- src/drivers/win/taseditlib/playback.h | 3 + src/drivers/win/taseditlib/recorder.cpp | 161 ++++++++++++++++ src/drivers/win/taseditlib/recorder.h | 32 ++++ src/drivers/win/taseditlib/tasedit_list.cpp | 13 +- src/drivers/win/taseditlib/tasedit_sel.cpp | 2 - src/drivers/win/taseditlib/taseditproj.cpp | 9 +- src/drivers/win/taseditlib/taseditproj.h | 5 +- src/drivers/win/window.cpp | 2 +- src/movie.cpp | 20 +- vc/vc10_fceux.vcxproj | 2 + vc/vc10_fceux.vcxproj.filters | 2 + 25 files changed, 467 insertions(+), 244 deletions(-) create mode 100644 src/drivers/win/taseditlib/recorder.cpp create mode 100644 src/drivers/win/taseditlib/recorder.h diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index b662ac69..e223a3d2 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -73,11 +73,14 @@ extern bool TASEdit_show_lag_frames; extern bool TASEdit_show_markers; extern bool TASEdit_show_branch_screenshots; extern bool TASEdit_bind_markers; +extern bool TASEdit_use_1p_rec; +extern bool TASEdit_combine_consecutive_rec; extern bool TASEdit_branch_full_movie; extern bool TASEdit_branch_only_when_rec; extern bool TASEdit_view_branches_tree; extern bool TASEdit_branch_scr_hud; extern bool TASEdit_restore_position; +extern int TASEdit_superimpose; extern bool TASEdit_enable_hot_changes; extern int TASEdit_greenzone_capacity; extern int TasEdit_undo_levels; @@ -305,11 +308,14 @@ static CFGSTRUCT fceuconfig[] = { AC(TASEdit_show_markers), AC(TASEdit_show_branch_screenshots), AC(TASEdit_bind_markers), + AC(TASEdit_use_1p_rec), + AC(TASEdit_combine_consecutive_rec), AC(TASEdit_branch_full_movie), AC(TASEdit_branch_only_when_rec), AC(TASEdit_view_branches_tree), AC(TASEdit_branch_scr_hud), AC(TASEdit_restore_position), + AC(TASEdit_superimpose), AC(TASEdit_enable_hot_changes), AC(TASEdit_greenzone_capacity), AC(TasEdit_undo_levels), diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 3123d032..7281096d 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -12,13 +12,11 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// Neutral resources +// Нейтральный resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) -#endif //_WIN32 +#pragma code_page(1251) ///////////////////////////////////////////////////////////////////////////// // @@ -35,7 +33,7 @@ ICON_2 ICON "res/ICON_2.ico" // Menu // -FCEUMENU MENU +FCEUMENU MENU BEGIN POPUP "&File" BEGIN @@ -164,7 +162,7 @@ BEGIN MENUITEM "RAM Search...", ID_RAM_SEARCH MENUITEM "RAM Watch...", ID_RAM_WATCH MENUITEM "&Memory Watch...", MENU_MEMORY_WATCH - MENUITEM "&TAS Edit...", MENU_TASEDIT, INACTIVE + MENUITEM "&TAS Editor...", MENU_TASEDIT, INACTIVE MENUITEM "Convert &FCM...", MENU_CONVERT_MOVIE MENUITEM SEPARATOR POPUP "Autofire &Pattern" @@ -217,7 +215,7 @@ BEGIN END END -TASEDITMENU MENU +TASEDITMENU MENU BEGIN POPUP "&File" BEGIN @@ -276,6 +274,9 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT MENUITEM SEPARATOR + MENUITEM "&Use 1P keys for all single Recordings", ID_CONFIG_USE1PFORRECORDING + MENUITEM "&Combine consecutive Recordings", ID_CONFIG_COMBINECONSECUTIVERECORDINGS + MENUITEM SEPARATOR MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO END POPUP "&Help" @@ -285,7 +286,7 @@ BEGIN END END -MEMVIEWMENU MENU +MEMVIEWMENU MENU BEGIN POPUP "&File" BEGIN @@ -328,7 +329,7 @@ BEGIN END END -MEMWATCHMENU MENU +MEMWATCHMENU MENU BEGIN POPUP "&File " BEGIN @@ -355,7 +356,7 @@ BEGIN END END -TASEDITCONTEXTMENUS MENU +TASEDITCONTEXTMENUS MENU BEGIN POPUP "Stray" BEGIN @@ -377,7 +378,7 @@ BEGIN END END -FCEUCONTEXTMENUS MENU +FCEUCONTEXTMENUS MENU BEGIN POPUP "Game+Movie+readonly" BEGIN @@ -438,7 +439,7 @@ BEGIN END END -RAMWATCH_MENU MENU +RAMWATCH_MENU MENU BEGIN POPUP "File" BEGIN @@ -467,7 +468,7 @@ BEGIN END END -CHEATCONTEXTMENUS MENU +CHEATCONTEXTMENUS MENU BEGIN POPUP "CheatListPopup" BEGIN @@ -478,7 +479,7 @@ BEGIN END END -DEBUGCONTEXTMENUS MENU +DEBUGCONTEXTMENUS MENU BEGIN POPUP "DebugListPopup" BEGIN @@ -486,7 +487,7 @@ BEGIN END END -LUAWINDOW_MENU MENU +LUAWINDOW_MENU MENU BEGIN POPUP "Console" BEGIN @@ -546,7 +547,7 @@ BEGIN LTEXT "Avi Output",IDC_STATIC,10,208,34,8 END -DWBDIALOG DIALOG 33, 99, 250, 56 +DWBDIALOG DIALOG 33, 99, 250, 56 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "DWB!" FONT 8, "MS Sans Serif" @@ -556,7 +557,7 @@ BEGIN PUSHBUTTON "Close",BTN_CLOSE,188,33,50,14 END -FKBDIALOG DIALOG 13, 72, 402, 194 +FKBDIALOG DIALOG 13, 72, 402, 194 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Family Keyboard Configuration" FONT 8, "MS Sans Serif" @@ -736,7 +737,7 @@ BEGIN "Button",BS_AUTOCHECKBOX,174,18,142,12 END -MAHJONGDIALOG DIALOG 65510, 106, 340, 110 +MAHJONGDIALOG DIALOG 65510, 106, 340, 110 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "mahjong" FONT 8, "MS Sans Serif" @@ -837,7 +838,7 @@ BEGIN CTEXT "Tint",65463,123,34,85,8 END -POWERPADDIALOG DIALOG 30, 123, 131, 119 +POWERPADDIALOG DIALOG 30, 123, 131, 119 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Power Pad Configuration" FONT 8, "MS Sans Serif" @@ -858,7 +859,7 @@ BEGIN PUSHBUTTON "12",311,91,59,16,12 END -QUIZKINGDIALOG DIALOG 30, 123, 160, 74 +QUIZKINGDIALOG DIALOG 30, 123, 160, 74 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "quiz king" FONT 8, "MS Sans Serif" @@ -1392,8 +1393,7 @@ BEGIN CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,402,74,23,10 CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,373,87,25,10 CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,402,87,23,10 - CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX,316,100,56,10 - CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX,377,100,51,10 + CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTO3STATE,316,100,56,10 GROUPBOX " History ",IDC_STATIC,310,257,123,114,BS_CENTER,WS_EX_RIGHT EDITTEXT IDC_EDIT1,54,377,251,13,ES_READONLY | NOT WS_TABSTOP PUSHBUTTON "<<",TASEDIT_REWIND_FULL2,315,376,23,14,NOT WS_TABSTOP @@ -1733,7 +1733,7 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,120,80,50,14 END -IDD_PROMPT DIALOG 0, 0, 186, 68 +IDD_PROMPT DIALOG 0, 0, 186, 68 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Input Prompt" FONT 8, "Ms Shell Dlg 2" @@ -1750,7 +1750,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN "DIRCONFIG", DIALOG BEGIN @@ -1864,6 +1864,10 @@ BEGIN BOTTOMMARGIN, 198 END + "TASEDIT", DIALOG + BEGIN + END + "ASSEMBLER", DIALOG BEGIN LEFTMARGIN, 7 @@ -1919,18 +1923,16 @@ BEGIN END #endif // APSTUDIO_INVOKED -#endif // Neutral resources +#endif // Нейтральный resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources +// Английский (США) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) -#endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // @@ -1953,7 +1955,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN "IDD_REPLAY_METADATA", DIALOG BEGIN @@ -1995,7 +1997,7 @@ END // Accelerator // -IDR_ACCELERATOR1 ACCELERATORS +IDR_ACCELERATOR1 ACCELERATORS BEGIN "A", ACCEL_CTRL_A, VIRTKEY, CONTROL, NOINVERT "C", ACCEL_CTRL_C, VIRTKEY, CONTROL, NOINVERT @@ -2017,7 +2019,7 @@ BEGIN "B", ACCEL_CTRL_B, VIRTKEY, CONTROL, NOINVERT END -IDR_RWACCELERATOR ACCELERATORS +IDR_RWACCELERATOR ACCELERATORS BEGIN "N", RAMMENU_FILE_NEW, VIRTKEY, CONTROL "O", RAMMENU_FILE_OPEN, VIRTKEY, CONTROL @@ -2059,7 +2061,7 @@ IDB_BITMAP18 BITMAP "res\\te_18.bmp" IDB_BITMAP19 BITMAP "res\\te_19.bmp" IDB_TE_ARROW BITMAP "res/te_arrow.bmp" IDB_BRANCH_SPRITESHEET BITMAP "res\\branch_spritesheet.bmp" -#endif // English (U.S.) resources +#endif // Английский (США) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index d140e5b7..4f9cae0b 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -901,6 +901,9 @@ #define ID_HELP_ABOUT 40485 #define ID_VIEW_ENABLEHOTCHANGES 40488 #define ID_VIEW_SHOWBRANCHSCREENSHOTS 40489 +#define ID_CONFIG_USE1PFORRECORDING2P 40490 +#define ID_CONFIG_USE1PFORRECORDING 40491 +#define ID_CONFIG_COMBINECONSECUTIVERECORDINGS 40492 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -910,7 +913,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 185 -#define _APS_NEXT_COMMAND_VALUE 40490 +#define _APS_NEXT_COMMAND_VALUE 40493 #define _APS_NEXT_CONTROL_VALUE 1267 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index be66956d..bbfc38e4 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -16,11 +16,23 @@ using namespace std; -int old_multitrack_recording_joypad, multitrack_recording_joypad; -bool old_movie_readonly; +HWND hwndTasEdit = 0; +HMENU hmenu, hrmenu; + bool TASEdit_focus = false; bool Tasedit_rewind_now = false; +// all Taseditor functional modules +TASEDIT_PROJECT project; +INPUT_HISTORY history; +PLAYBACK playback; +RECORDER recorder; +GREENZONE greenzone; +MARKERS markers; +BOOKMARKS bookmarks; +TASEDIT_LIST tasedit_list; +TASEDIT_SELECTION selection; + // saved FCEU config int saved_eoptions; int saved_EnableAutosave; @@ -28,13 +40,16 @@ extern int EnableAutosave; extern EMOVIEMODE movieMode; // maybe we need normal setter for movieMode, to encapsulate it -// vars saved in cfg file +// vars saved in cfg file (need dedicated storage class?) int TasEdit_wndx, TasEdit_wndy; bool TASEdit_follow_playback = true; bool TASEdit_show_lag_frames = true; bool TASEdit_show_markers = true; bool TASEdit_show_branch_screenshots = true; bool TASEdit_bind_markers = true; +bool TASEdit_use_1p_rec = true; +bool TASEdit_combine_consecutive_rec = true; +int TASEdit_superimpose = BST_UNCHECKED; bool TASEdit_branch_full_movie = true; bool TASEdit_branch_only_when_rec = false; bool TASEdit_view_branches_tree = false; @@ -50,27 +65,8 @@ bool TASEdit_jump_to_undo = true; // resources string tasedithelp = "{16CDE0C4-02B0-4A60-A88D-076319909A4D}"; //Name of TASEdit Help page char buttonNames[NUM_JOYPAD_BUTTONS][2] = {"A", "B", "S", "T", "U", "D", "L", "R"}; -char windowCaptions[6][30] = { "TAS Editor", - "TAS Editor (Recording All)", - "TAS Editor (Recording 1P)", - "TAS Editor (Recording 2P)", - "TAS Editor (Recording 3P)", - "TAS Editor (Recording 4P)"}; - -HWND hwndTasEdit = 0; -HMENU hmenu, hrmenu; -HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull; -HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; - -// all Taseditor functional modules -TASEDIT_PROJECT project; -INPUT_HISTORY history; -PLAYBACK playback; -GREENZONE greenzone; -MARKERS markers; -BOOKMARKS bookmarks; -TASEDIT_LIST tasedit_list; -TASEDIT_SELECTION selection; +char windowCaption[] = "TAS Editor"; +extern char windowCaptions[5][30]; // enterframe function void UpdateTasEdit() @@ -81,46 +77,30 @@ void UpdateTasEdit() markers.update(); greenzone.update(); playback.update(); + recorder.update(); bookmarks.update(); selection.update(); history.update(); project.update(); - - // update window caption - if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad) - RedrawWindowCaption(); - - // update Bookmarks/Branches groupbox caption - if (TASEdit_branch_only_when_rec && old_movie_readonly != movie_readonly) - bookmarks.RedrawBookmarksCaption(); - - // update recording radio buttons if user used hotkey to switch R/W - if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad) - { - UncheckRecordingRadioButtons(); - RecheckRecordingRadioButtons(); - } - } void RedrawWindowCaption() { - char windowCaption[300]; // 260 + 30 + 1 + ... - if (movie_readonly) - strcpy(windowCaption, windowCaptions[0]); - else - strcpy(windowCaption, windowCaptions[multitrack_recording_joypad + 1]); + char windowCapt[300]; + strcpy(windowCapt, windowCaption); + if (!movie_readonly) + strcat(windowCapt, windowCaptions[recorder.multitrack_recording_joypad]); // add project name std::string projectname = project.GetProjectName(); if (!projectname.empty()) { - strcat(windowCaption, " - "); - strcat(windowCaption, projectname.c_str()); + strcat(windowCapt, " - "); + strcat(windowCapt, projectname.c_str()); } // and * if project has unsaved changes if (project.GetProjectChanged()) - strcat(windowCaption, "*"); - SetWindowText(hwndTasEdit, windowCaption); + strcat(windowCapt, "*"); + SetWindowText(hwndTasEdit, windowCapt); } void RedrawTasedit() { @@ -173,11 +153,6 @@ void RightClick(LPNMITEMACTIVATE info) RightClickMenu(info); } -void InputChangedRec() -{ - greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_RECORD, currFrameCounter, currFrameCounter)); -} - void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags) { int joy = (column_index - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS; @@ -648,45 +623,6 @@ bool Paste() return result; } -void UncheckRecordingRadioButtons() -{ - Button_SetCheck(hwndRB_RecOff, BST_UNCHECKED); - Button_SetCheck(hwndRB_RecAll, BST_UNCHECKED); - Button_SetCheck(hwndRB_Rec1P, BST_UNCHECKED); - Button_SetCheck(hwndRB_Rec2P, BST_UNCHECKED); - Button_SetCheck(hwndRB_Rec3P, BST_UNCHECKED); - Button_SetCheck(hwndRB_Rec4P, BST_UNCHECKED); -} -void RecheckRecordingRadioButtons() -{ - old_movie_readonly = movie_readonly; - old_multitrack_recording_joypad = multitrack_recording_joypad; - if (movie_readonly) - { - Button_SetCheck(hwndRB_RecOff, BST_CHECKED); - } else - { - switch(multitrack_recording_joypad) - { - case MULTITRACK_RECORDING_ALL: - Button_SetCheck(hwndRB_RecAll, BST_CHECKED); - break; - case MULTITRACK_RECORDING_1P: - Button_SetCheck(hwndRB_Rec1P, BST_CHECKED); - break; - case MULTITRACK_RECORDING_2P: - Button_SetCheck(hwndRB_Rec2P, BST_CHECKED); - break; - case MULTITRACK_RECORDING_3P: - Button_SetCheck(hwndRB_Rec3P, BST_CHECKED); - break; - case MULTITRACK_RECORDING_4P: - Button_SetCheck(hwndRB_Rec4P, BST_CHECKED); - break; - } - } -} - void OpenProject() { if (!AskSaveProject()) return; @@ -722,11 +658,7 @@ void OpenProject() std::string thisfm2name = name; thisfm2name.append(".fm2"); project.SetFM2Name(thisfm2name); - // switch to read-only mode, but first must uncheck radiobuttons explicitly - if (!movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; - UncheckRecordingRadioButtons(); - RecheckRecordingRadioButtons(); + recorder.reset(); playback.reset(); // remember to update fourscore status bool last_fourscore = currMovieData.fourscore; @@ -799,7 +731,7 @@ bool AskSaveProject() // ask saving project if (changes_found) { - int answer = MessageBox(hwndTasEdit, "Save Project changes?", "TAS Edit", MB_YESNOCANCEL); + int answer = MessageBox(hwndTasEdit, "Save Project changes?", "TAS Editor", MB_YESNOCANCEL); if(answer == IDYES) return SaveProject(); return (answer != IDCANCEL); @@ -849,19 +781,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar if (TasEdit_wndx==-32000) TasEdit_wndx=0; //Just in case if (TasEdit_wndy==-32000) TasEdit_wndy=0; SetWindowPos(hwndDlg, 0, TasEdit_wndx, TasEdit_wndy, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); - // save references to dialog items - hwndProgressbar = GetDlgItem(hwndDlg, IDC_PROGRESS1); - SendMessage(hwndProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSBAR_WIDTH)); - hwndRewind = GetDlgItem(hwndDlg, TASEDIT_REWIND); - hwndForward = GetDlgItem(hwndDlg, TASEDIT_FORWARD); - hwndRewindFull = GetDlgItem(hwndDlg, TASEDIT_REWIND_FULL); - hwndForwardFull = GetDlgItem(hwndDlg, TASEDIT_FORWARD_FULL); - hwndRB_RecOff = GetDlgItem(hwndDlg, IDC_RADIO1); - hwndRB_RecAll = GetDlgItem(hwndDlg, IDC_RADIO2); - hwndRB_Rec1P = GetDlgItem(hwndDlg, IDC_RADIO3); - hwndRB_Rec2P = GetDlgItem(hwndDlg, IDC_RADIO4); - hwndRB_Rec3P = GetDlgItem(hwndDlg, IDC_RADIO5); - hwndRB_Rec4P = GetDlgItem(hwndDlg, IDC_RADIO6); break; case WM_MOVE: { @@ -1159,6 +1078,16 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar TASEdit_bind_markers ^= 1; CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED); break; + case ID_CONFIG_USE1PFORRECORDING: + //switch "Use 1P keys for single Recordings" flag + TASEdit_use_1p_rec ^= 1; + CheckMenuItem(hmenu, ID_CONFIG_USE1PFORRECORDING, TASEdit_use_1p_rec?MF_CHECKED : MF_UNCHECKED); + break; + case ID_CONFIG_COMBINECONSECUTIVERECORDINGS: + //switch "Combine consecutive Recordings" flag + TASEdit_combine_consecutive_rec ^= 1; + CheckMenuItem(hmenu, ID_CONFIG_COMBINECONSECUTIVERECORDINGS, TASEdit_combine_consecutive_rec?MF_CHECKED : MF_UNCHECKED); + break; case ID_CONFIG_MUTETURBO: muteTurbo ^= 1; CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); @@ -1179,27 +1108,36 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case IDC_RADIO2: // switch to read+write for all, no need to recheck radiobuttons if (movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; + recorder.multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; break; case IDC_RADIO3: // switch to read+write for 1P, no need to recheck radiobuttons if (movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_1P; + recorder.multitrack_recording_joypad = MULTITRACK_RECORDING_1P; break; case IDC_RADIO4: // switch to read+write for 2P, no need to recheck radiobuttons if (movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_2P; + recorder.multitrack_recording_joypad = MULTITRACK_RECORDING_2P; break; case IDC_RADIO5: // switch to read+write for 3P, no need to recheck radiobuttons if (movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_3P; + recorder.multitrack_recording_joypad = MULTITRACK_RECORDING_3P; break; case IDC_RADIO6: // switch to read+write for 4P, no need to recheck radiobuttons if (movie_readonly) FCEUI_MovieToggleReadOnly(); - multitrack_recording_joypad = MULTITRACK_RECORDING_4P; + recorder.multitrack_recording_joypad = MULTITRACK_RECORDING_4P; + break; + case IDC_SUPERIMPOSE: + // 3 states of "Superimpose" checkbox + if (TASEdit_superimpose == BST_UNCHECKED) + TASEdit_superimpose = BST_CHECKED; + else if (TASEdit_superimpose == BST_CHECKED) + TASEdit_superimpose = BST_INDETERMINATE; + else TASEdit_superimpose = BST_UNCHECKED; + CheckDlgButton(hwndTasEdit, IDC_SUPERIMPOSE, TASEdit_superimpose); break; case ACCEL_CTRL_A: case ID_EDIT_SELECTMIDMARKERS: @@ -1301,13 +1239,16 @@ void EnterTasEdit() CheckMenuItem(hmenu, ID_VIEW_SHOW_MARKERS, TASEdit_show_markers?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_SHOWBRANCHSCREENSHOTS, TASEdit_show_branch_screenshots?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, TASEdit_jump_to_undo?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BRANCHESRESTOREFULLMOVIE, TASEdit_branch_full_movie?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BRANCHESWORKONLYWHENRECORDING, TASEdit_branch_only_when_rec?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_COMBINECONSECUTIVERECORDINGS, TASEdit_combine_consecutive_rec?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_HUDINBRANCHSCREENSHOTS, TASEdit_branch_scr_hud?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, TASEdit_enable_hot_changes?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_USE1PFORRECORDING, TASEdit_use_1p_rec?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndTasEdit,CHECK_AUTORESTORE_PLAYBACK,TASEdit_restore_position?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwndTasEdit, IDC_SUPERIMPOSE, TASEdit_superimpose); SetWindowPos(hwndTasEdit, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); // init modules @@ -1319,20 +1260,16 @@ void EnterTasEdit() FCEUI_StopMovie(); CreateCleanMovie(); playback.StartFromZero(); - } - else + } else { //use current movie to create a new project FCEUI_StopMovie(); greenzone.TryDumpIncremental(lagFlag != 0); } - // always start work from read-only mode, ready to switch to MULTITRACK_RECORDING_ALL - movie_readonly = true; - multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; - RecheckRecordingRadioButtons(); // switch to tasedit mode movieMode = MOVIEMODE_TASEDIT; // init variables + recorder.init(); tasedit_list.init(); markers.init(); project.init(); diff --git a/src/drivers/win/tasedit.h b/src/drivers/win/tasedit.h index a1ca199f..ed454db3 100644 --- a/src/drivers/win/tasedit.h +++ b/src/drivers/win/tasedit.h @@ -1,5 +1,3 @@ -#define PROGRESSBAR_WIDTH 200 - #define GREENZONE_CAPACITY_DEFAULT 10000 #define GREENZONE_CAPACITY_MIN 1 #define GREENZONE_CAPACITY_MAX 50000 @@ -8,18 +6,10 @@ #define UNDO_LEVELS_MAX 999 #define UNDO_LEVELS_DEFAULT 100 -#define AUTOSAVE_PERIOD_SCALE 60000 // = 1 minute in milliseconds #define AUTOSAVE_PERIOD_DEFAULT 10 // in minutes #define AUTOSAVE_PERIOD_MIN 0 // 0 = no autosave #define AUTOSAVE_PERIOD_MAX 60 // 1 hour -// multitracking -#define MULTITRACK_RECORDING_ALL 0 -#define MULTITRACK_RECORDING_1P 1 -#define MULTITRACK_RECORDING_2P 2 -#define MULTITRACK_RECORDING_3P 3 -#define MULTITRACK_RECORDING_4P 4 - enum ECONTEXTMENU { CONTEXTMENU_STRAY = 0, @@ -34,10 +24,7 @@ void RedrawWindowCaption(); void RedrawTasedit(); void RedrawListAndBookmarks(); void RedrawRowAndBookmark(int index); -void InputChangedRec(); void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags); -void UncheckRecordingRadioButtons(); -void RecheckRecordingRadioButtons(); void OpenProject(); bool SaveProject(); bool SaveProjectAs(); diff --git a/src/drivers/win/taseditlib/bookmark.cpp b/src/drivers/win/taseditlib/bookmark.cpp index d553a13f..f1a1aafb 100644 --- a/src/drivers/win/taseditlib/bookmark.cpp +++ b/src/drivers/win/taseditlib/bookmark.cpp @@ -1,9 +1,6 @@ //Implementation file of Bookmark class -#include "movie.h" -#include "../common.h" #include "taseditproj.h" -//#include "../tasedit.h" #include "zlib.h" extern GREENZONE greenzone; @@ -17,7 +14,6 @@ extern uint8 *XBackBuf; BOOKMARK::BOOKMARK() { - } void BOOKMARK::init() @@ -70,7 +66,7 @@ void BOOKMARK::save(EMUFILE *os) { write8le(1, os); // write parent_branch - write8le((uint8)parent_branch, os); + write32le(parent_branch, os); // write snapshot snapshot.save(os); // write savestate @@ -92,17 +88,16 @@ bool BOOKMARK::load(EMUFILE *is) if (not_empty) { // read parent_branch - if (!read8le(&tmp, is)) return true; - parent_branch = *(int8*)(&tmp); + if (!read32le(&parent_branch, is)) return true; // read snapshot if (snapshot.load(is)) return true; // read savestate int size; - if (!read32le((uint32 *)&size, is)) return true; + if (!read32le(&size, is)) return true; savestate.resize(size); if ((int)is->fread(&savestate[0], size) < size) return true; // read saved_screenshot - if (!read32le((uint32 *)&size, is)) return true; + if (!read32le(&size, is)) return true; saved_screenshot.resize(size); if ((int)is->fread(&saved_screenshot[0], size) < size) return true; } diff --git a/src/drivers/win/taseditlib/bookmarks.cpp b/src/drivers/win/taseditlib/bookmarks.cpp index 45380ce9..6500f100 100644 --- a/src/drivers/win/taseditlib/bookmarks.cpp +++ b/src/drivers/win/taseditlib/bookmarks.cpp @@ -1,8 +1,8 @@ //Implementation file of Bookmarks class #include "taseditproj.h" -#include "zlib.h" #include "utils/xstring.h" +#include "zlib.h" #pragma comment(lib, "msimg32.lib") @@ -197,7 +197,9 @@ void BOOKMARKS::init() scr_bmp = CreateDIBSection(win_hdc, scr_bmi, DIB_RGB_COLORS, (void**)&scr_ptr, 0, 0); RedrawBookmarksCaption(); + next_animation_time = 0; update(); + } void BOOKMARKS::reset() { @@ -569,7 +571,7 @@ void BOOKMARKS::save(EMUFILE *os) // write cloud time os->fwrite(cloud_time, TIME_DESC_LENGTH); // write current branch and flag of changes since it - write8le((uint8)current_branch, os); + write32le(current_branch, os); if (changes_since_current_branch) write8le((uint8)1, os); else @@ -593,8 +595,7 @@ bool BOOKMARKS::load(EMUFILE *is) if ((int)is->fread(cloud_time, TIME_DESC_LENGTH) < TIME_DESC_LENGTH) return true; // read current branch and flag of changes since it uint8 tmp; - if (!read8le(&tmp, is)) return true; - current_branch = *(int8*)(&tmp); + if (!read32le(¤t_branch, is)) return true; if (!read8le(&tmp, is)) return true; changes_since_current_branch = (tmp != 0); // read current_position time diff --git a/src/drivers/win/taseditlib/greenzone.cpp b/src/drivers/win/taseditlib/greenzone.cpp index e205a293..b0ca92c3 100644 --- a/src/drivers/win/taseditlib/greenzone.cpp +++ b/src/drivers/win/taseditlib/greenzone.cpp @@ -1,7 +1,6 @@ //Implementation file of Greenzone class #include "taseditproj.h" -#include "../tasedit.h" #include "state.h" #include "zlib.h" @@ -11,12 +10,12 @@ extern int TASEdit_greenzone_capacity; extern bool TASEdit_restore_position; extern void FCEU_printf(char *format, ...); +extern void RedrawListAndBookmarks(); char greenzone_save_id[GREENZONE_ID_LEN] = "GREENZONE"; GREENZONE::GREENZONE() { - } void GREENZONE::init() @@ -337,7 +336,7 @@ void GREENZONE::InvalidateAndCheck(int after) // redraw list even if greenzone didn't change RedrawListAndBookmarks(); } -// This version doesn't restore playback, may be used only by Branching functions! +// This version doesn't restore playback, may be used only by Branching and Recording functions! void GREENZONE::Invalidate(int after) { if (after >= 0) diff --git a/src/drivers/win/taseditlib/inputhistory.cpp b/src/drivers/win/taseditlib/inputhistory.cpp index 2cfbbad9..9aeecdd8 100644 --- a/src/drivers/win/taseditlib/inputhistory.cpp +++ b/src/drivers/win/taseditlib/inputhistory.cpp @@ -1,12 +1,12 @@ //Implementation file of Input History class (Undo feature) #include "taseditproj.h" -#include "../tasedit.h" // just for mainlist functions, later this should be deleted extern HWND hwndTasEdit; extern bool TASEdit_bind_markers; extern bool TASEdit_enable_hot_changes; extern bool TASEdit_branch_full_movie; +extern bool TASEdit_combine_consecutive_rec; LRESULT APIENTRY HistoryListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); WNDPROC hwndHistoryList_oldWndProc; @@ -234,6 +234,7 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) // create new input shanshot INPUT_SNAPSHOT inp; inp.init(currMovieData, TASEdit_enable_hot_changes); + inp.mod_type = mod_type; if (mod_type == MODTYPE_MARKER_SET || mod_type == MODTYPE_MARKER_UNSET) { // special case: changed markers, but input didn't change @@ -290,17 +291,6 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) inp.jump_frame = start; break; } - case MODTYPE_RECORD: - { - inp.jump_frame = start; - // also add info which joypads were affected - int num = (inp.input_type + 1) * 2; // hacky, only for distingushing between normal2p and fourscore - for (int i = 0; i < num; ++i) - { - if (inp.checkJoypadDiff(input_snapshots[real_pos], first_changes, i)) - strcat(inp.description, joypadCaptions[i]); - } - } } // add upper and lower frame to description char framenum[11]; @@ -333,7 +323,6 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) case MODTYPE_CLEAR: case MODTYPE_CUT: case MODTYPE_PASTE: - case MODTYPE_RECORD: inp.inheritHotChanges(&input_snapshots[real_pos]); inp.fillHotChanges(input_snapshots[real_pos], first_changes, end); break; @@ -359,6 +348,7 @@ void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot) INPUT_SNAPSHOT inp; inp.init(currMovieData, TASEdit_enable_hot_changes); // fill description: modification type + time of the Branch + inp.mod_type = mod_type; strcat(inp.description, modCaptions[mod_type]); strcat(inp.description, bookmarks.bookmarks_array[slot].snapshot.description); inp.jump_frame = first_change; @@ -384,6 +374,75 @@ void INPUT_HISTORY::RegisterBranching(int mod_type, int first_change, int slot) } AddInputSnapshotToHistory(inp); } +void INPUT_HISTORY::RegisterRecording(int frame_of_change) +{ + int real_pos = (history_start_pos + history_cursor_pos) % history_size; + INPUT_SNAPSHOT inp; + inp.init(currMovieData, TASEdit_enable_hot_changes); + inp.fillJoypadsDiff(input_snapshots[real_pos], frame_of_change); + inp.mod_type = MODTYPE_RECORD; + strcat(inp.description, modCaptions[MODTYPE_RECORD]); + char framenum[11]; + // check if current snapshot is also Recording and maybe it is consecutive recording + if (TASEdit_combine_consecutive_rec && input_snapshots[real_pos].mod_type == MODTYPE_RECORD && input_snapshots[real_pos].rec_end_frame+1 == frame_of_change && input_snapshots[real_pos].rec_joypad_diff_bits == inp.rec_joypad_diff_bits) + { + // clone this snapshot and continue chain of recorded frames + inp.jump_frame = input_snapshots[real_pos].jump_frame; + inp.rec_end_frame = frame_of_change; + // add info which joypads were affected + int num = (inp.input_type + 1) * 2; // = joypads_per_frame + uint32 current_mask = 1; + for (int i = 0; i < num; ++i) + { + if ((inp.rec_joypad_diff_bits & current_mask)) + strcat(inp.description, joypadCaptions[i]); + current_mask <<= 1; + } + // add upper and lower frame to description + _itoa(inp.jump_frame, framenum, 10); + strcat(inp.description, " "); + strcat(inp.description, framenum); + _itoa(frame_of_change, framenum, 10); + strcat(inp.description, "-"); + strcat(inp.description, framenum); + // set hotchanges + if (TASEdit_enable_hot_changes) + { + inp.copyHotChanges(&input_snapshots[real_pos]); + inp.fillHotChanges(input_snapshots[real_pos], frame_of_change, frame_of_change); + } + // replace current snapshot with this cloned snapshot and truncate history here + input_snapshots[real_pos] = inp; + history_total_items = history_cursor_pos+1; + UpdateHistoryList(); + RedrawHistoryList(); + } else + { + // not consecutive - add new snapshot to history + inp.jump_frame = inp.rec_end_frame = frame_of_change; + // add info which joypads were affected + int num = (inp.input_type + 1) * 2; // = joypads_per_frame + uint32 current_mask = 1; + for (int i = 0; i < num; ++i) + { + if ((inp.rec_joypad_diff_bits & current_mask)) + strcat(inp.description, joypadCaptions[i]); + current_mask <<= 1; + } + // add upper frame to description + _itoa(frame_of_change, framenum, 10); + strcat(inp.description, " "); + strcat(inp.description, framenum); + // set hotchanges + if (TASEdit_enable_hot_changes) + { + inp.inheritHotChanges(&input_snapshots[real_pos]); + inp.fillHotChanges(input_snapshots[real_pos], frame_of_change, frame_of_change); + } + AddInputSnapshotToHistory(inp); + } + bookmarks.ChangesMadeSinceBranch(); +} void INPUT_HISTORY::save(EMUFILE *os) { diff --git a/src/drivers/win/taseditlib/inputhistory.h b/src/drivers/win/taseditlib/inputhistory.h index a6cf6c4d..5b212053 100644 --- a/src/drivers/win/taseditlib/inputhistory.h +++ b/src/drivers/win/taseditlib/inputhistory.h @@ -64,6 +64,7 @@ public: int RegisterChanges(int mod_type, int start = 0, int end =-1); void RegisterBranching(int mod_type, int first_change, int slot); + void RegisterRecording(int frame_of_change); INPUT_SNAPSHOT& GetCurrentSnapshot(); INPUT_SNAPSHOT& GetNextToCurrentSnapshot(); diff --git a/src/drivers/win/taseditlib/inputsnapshot.cpp b/src/drivers/win/taseditlib/inputsnapshot.cpp index c84dd82f..dc623407 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.cpp +++ b/src/drivers/win/taseditlib/inputsnapshot.cpp @@ -3,7 +3,7 @@ #include "taseditproj.h" #include "zlib.h" -const int bytes_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {2, 4}; // 16bits for normal joypads, 32bits for fourscore +const int bytes_per_frame[NUM_SUPPORTED_INPUT_TYPES] = {2, 4}; // so 16bits for normal joypads, 32bits for fourscore extern void FCEU_printf(char *format, ...); @@ -150,6 +150,9 @@ void INPUT_SNAPSHOT::save(EMUFILE *os) write8le(input_type, os); if (coherent) write8le(1, os); else write8le((uint8)0, os); write32le(jump_frame, os); + write32le(rec_end_frame, os); + write32le(rec_joypad_diff_bits, os); + write32le(mod_type, os); if (has_hot_changes) write8le((uint8)1, os); else write8le((uint8)0, os); // write description int len = strlen(description); @@ -185,13 +188,16 @@ bool INPUT_SNAPSHOT::load(EMUFILE *is) if (!read8le(&tmp, is)) return true; coherent = (tmp != 0); if (!read32le(&jump_frame, is)) return true; + if (!read32le(&rec_end_frame, is)) return true; + if (!read32le(&rec_joypad_diff_bits, is)) return true; + if (!read32le(&mod_type, is)) return true; if (!read8le(&tmp, is)) return true; has_hot_changes = (tmp != 0); // read description if (!read8le(&tmp, is)) return true; if (tmp >= SNAPSHOT_DESC_MAX_LENGTH) return true; if (is->fread(&description[0], tmp) != tmp) return true; - description[tmp] = 0; // add '0' because it wasn't saved + description[tmp] = 0; // add '0' because it wasn't saved in the file // read data already_compressed = true; int comprlen; @@ -283,26 +289,31 @@ bool INPUT_SNAPSHOT::checkDiff(INPUT_SNAPSHOT& inp) return false; } -// return true if joypads differ (this function is only used by "Record" modtype) -bool INPUT_SNAPSHOT::checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy) +// fills map of bits judging on which joypads differ (this function is only used by "Record" modtype) +void INPUT_SNAPSHOT::fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame) { + rec_joypad_diff_bits = 0; + uint32 current_mask = 1; switch(input_type) { case FOURSCORE: case NORMAL_2JOYPADS: { int pos = frame * bytes_per_frame[input_type]; - if (pos < (inp.size * bytes_per_frame[input_type])) + for (int i = 0; i < bytes_per_frame[input_type]; ++i) // this should be actually joypads_per_frame[] { - if (joysticks[pos+joy] != inp.joysticks[pos+joy]) return true; - } else - { - if (joysticks[pos+joy]) return true; + if (pos < (inp.size * bytes_per_frame[input_type])) + { + if (joysticks[pos+i] != inp.joysticks[pos+i]) rec_joypad_diff_bits |= current_mask; + } else + { + if (joysticks[pos+i]) rec_joypad_diff_bits |= current_mask; + } + current_mask <<= 1; } break; } } - return false; } // return true if any difference in markers_array is found, comparing two snapshots @@ -429,6 +440,21 @@ int INPUT_SNAPSHOT::findFirstChange(MovieData& md, int start, int end) return -1; // no changes were found } + +int INPUT_SNAPSHOT::GetJoystickInfo(int frame, int joy) +{ + if (frame < 0 || frame >= size) return 0; + switch(input_type) + { + case FOURSCORE: + case NORMAL_2JOYPADS: + { + return joysticks[frame * bytes_per_frame[input_type] + joy]; + break; + } + } + return 0; +} // -------------------------------------------------------- void INPUT_SNAPSHOT::copyHotChanges(INPUT_SNAPSHOT* source_of_hotchanges, int limit_frame_of_source) { diff --git a/src/drivers/win/taseditlib/inputsnapshot.h b/src/drivers/win/taseditlib/inputsnapshot.h index d2dcfe39..c9bf00ba 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.h +++ b/src/drivers/win/taseditlib/inputsnapshot.h @@ -1,7 +1,5 @@ //Specification file for Input Snapshot class -#include - #define HOTCHANGE_BYTES_PER_JOY 4 #define SNAPSHOT_DESC_MAX_LENGTH 50 @@ -24,7 +22,7 @@ public: bool skipLoad(EMUFILE *is); bool checkDiff(INPUT_SNAPSHOT& inp); - bool checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy); + void fillJoypadsDiff(INPUT_SNAPSHOT& inp, int frame); bool checkMarkersDiff(INPUT_SNAPSHOT& inp); bool checkMarkersDiff(); @@ -33,6 +31,8 @@ public: int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1); int findFirstChange(MovieData& md, int start = 0, int end = -1); + int GetJoystickInfo(int frame, int joy); + void copyHotChanges(INPUT_SNAPSHOT* source_of_hotchanges, int limit_frame_of_source = -1); void inheritHotChanges(INPUT_SNAPSHOT* source_of_hotchanges); void inheritHotChanges_DeleteSelection(INPUT_SNAPSHOT* source_of_hotchanges); @@ -55,6 +55,9 @@ public: bool coherent; // indicates whether this state was made right after previous state int jump_frame; // for jumping when making undo + int rec_end_frame; // for consecutive Recordings + uint32 rec_joypad_diff_bits; // for consecutive Recordings + int mod_type; char description[SNAPSHOT_DESC_MAX_LENGTH]; bool has_hot_changes; diff --git a/src/drivers/win/taseditlib/markers.cpp b/src/drivers/win/taseditlib/markers.cpp index 966a8451..b263ba34 100644 --- a/src/drivers/win/taseditlib/markers.cpp +++ b/src/drivers/win/taseditlib/markers.cpp @@ -1,14 +1,12 @@ //Implementation file of Markers class #include "taseditproj.h" -//#include "../tasedit.h" #include "zlib.h" char markers_save_id[MARKERS_ID_LEN] = "MARKERS"; MARKERS::MARKERS() { - } void MARKERS::init() diff --git a/src/drivers/win/taseditlib/playback.cpp b/src/drivers/win/taseditlib/playback.cpp index 2d7afaae..3096d6e2 100644 --- a/src/drivers/win/taseditlib/playback.cpp +++ b/src/drivers/win/taseditlib/playback.cpp @@ -1,14 +1,15 @@ //Implementation file of Playback class #include "taseditproj.h" -#include "../tasedit.h" #ifdef _S9XLUA_H extern void ForceExecuteLuaFrameFunctions(); #endif -extern HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull; +extern HWND hwndTasEdit; extern void FCEU_printf(char *format, ...); +extern void RedrawListAndBookmarks(); +extern void RedrawRowAndBookmark(int index); extern bool turbo; extern MARKERS markers; @@ -23,6 +24,12 @@ PLAYBACK::PLAYBACK() void PLAYBACK::init() { + hwndProgressbar = GetDlgItem(hwndTasEdit, IDC_PROGRESS1); + SendMessage(hwndProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSBAR_WIDTH)); + hwndRewind = GetDlgItem(hwndTasEdit, TASEDIT_REWIND); + hwndForward = GetDlgItem(hwndTasEdit, TASEDIT_FORWARD); + hwndRewindFull = GetDlgItem(hwndTasEdit, TASEDIT_REWIND_FULL); + hwndForwardFull = GetDlgItem(hwndTasEdit, TASEDIT_FORWARD_FULL); reset(); } @@ -168,7 +175,6 @@ void PLAYBACK::ToggleEmulationPause() void PLAYBACK::PauseEmulation() { FCEUI_SetEmulationPaused(1); - //RedrawList(); // to show some "pale" greenzone // make some additional stuff } void PLAYBACK::UnpauseEmulation() @@ -190,16 +196,17 @@ void PLAYBACK::SeekingStop() turbo = false; PauseEmulation(); SetProgressbar(1, 1); - //RedrawList(); // to show some "pale" greenzone } void PLAYBACK::RewindFrame() { + if (pause_frame && !emu_paused) return; if (currFrameCounter > 0) jump(currFrameCounter-1); if (!pause_frame) PauseEmulation(); } void PLAYBACK::ForwardFrame() { + if (pause_frame && !emu_paused) return; jump(currFrameCounter+1); if (!pause_frame) PauseEmulation(); turbo = false; diff --git a/src/drivers/win/taseditlib/playback.h b/src/drivers/win/taseditlib/playback.h index 7a6f1748..62f878b4 100644 --- a/src/drivers/win/taseditlib/playback.h +++ b/src/drivers/win/taseditlib/playback.h @@ -1,5 +1,7 @@ //Specification file for Playback class +#define PROGRESSBAR_WIDTH 200 + #define PAUSEFRAME_BLINKING_PERIOD_SEEKING 100 #define PAUSEFRAME_BLINKING_PERIOD_PAUSED 250 @@ -36,6 +38,7 @@ public: int GetPauseFrame(); void SetProgressbar(int a, int b); + HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull; private: bool JumpToFrame(int index); diff --git a/src/drivers/win/taseditlib/recorder.cpp b/src/drivers/win/taseditlib/recorder.cpp new file mode 100644 index 00000000..98529acb --- /dev/null +++ b/src/drivers/win/taseditlib/recorder.cpp @@ -0,0 +1,161 @@ +//Implementation file of RECORDER class +#include "taseditproj.h" +#include "zlib.h" + +extern HWND hwndTasEdit; + +extern BOOKMARKS bookmarks; +extern INPUT_HISTORY history; +extern GREENZONE greenzone; + +extern void RedrawWindowCaption(); +extern bool TASEdit_branch_only_when_rec; +extern bool TASEdit_use_1p_rec; +extern int TASEdit_superimpose; + +// resources +char windowCaptions[5][30] = { " (Recording All)", + " (Recording 1P)", + " (Recording 2P)", + " (Recording 3P)", + " (Recording 4P)"}; +RECORDER::RECORDER() +{ +} + +void RECORDER::init() +{ + hwndRB_RecOff = GetDlgItem(hwndTasEdit, IDC_RADIO1); + hwndRB_RecAll = GetDlgItem(hwndTasEdit, IDC_RADIO2); + hwndRB_Rec1P = GetDlgItem(hwndTasEdit, IDC_RADIO3); + hwndRB_Rec2P = GetDlgItem(hwndTasEdit, IDC_RADIO4); + hwndRB_Rec3P = GetDlgItem(hwndTasEdit, IDC_RADIO5); + hwndRB_Rec4P = GetDlgItem(hwndTasEdit, IDC_RADIO6); + reset(); + old_multitrack_recording_joypad = multitrack_recording_joypad; + old_movie_readonly = movie_readonly; + old_joy.resize(4); + new_joy.resize(4); +} +void RECORDER::reset() +{ + movie_readonly = true; + multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; + UncheckRecordingRadioButtons(); + RecheckRecordingRadioButtons(); +} +void RECORDER::update() +{ + // update window caption if needed + if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad) + RedrawWindowCaption(); + // update Bookmarks/Branches groupbox caption + if (TASEdit_branch_only_when_rec && old_movie_readonly != movie_readonly) + bookmarks.RedrawBookmarksCaption(); + // update recording radio buttons if user used hotkey to switch R/W + if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad) + { + UncheckRecordingRadioButtons(); + RecheckRecordingRadioButtons(); + } + +} +// ------------------------------------------------------------------------------------ +void RECORDER::UncheckRecordingRadioButtons() +{ + Button_SetCheck(hwndRB_RecOff, BST_UNCHECKED); + Button_SetCheck(hwndRB_RecAll, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec1P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec2P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec3P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec4P, BST_UNCHECKED); +} +void RECORDER::RecheckRecordingRadioButtons() +{ + old_movie_readonly = movie_readonly; + old_multitrack_recording_joypad = multitrack_recording_joypad; + if (movie_readonly) + { + Button_SetCheck(hwndRB_RecOff, BST_CHECKED); + } else + { + switch(multitrack_recording_joypad) + { + case MULTITRACK_RECORDING_ALL: + Button_SetCheck(hwndRB_RecAll, BST_CHECKED); + break; + case MULTITRACK_RECORDING_1P: + Button_SetCheck(hwndRB_Rec1P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_2P: + Button_SetCheck(hwndRB_Rec2P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_3P: + Button_SetCheck(hwndRB_Rec3P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_4P: + Button_SetCheck(hwndRB_Rec4P, BST_CHECKED); + break; + } + } +} + +void RECORDER::InputChangedRec() +{ + bool changes_made = false; + // take previous values from current snapshot, new input from current movie + old_joy[0] = history.GetCurrentSnapshot().GetJoystickInfo(currFrameCounter, 0); + new_joy[0] = currMovieData.records[currFrameCounter].joysticks[0]; + old_joy[1] = history.GetCurrentSnapshot().GetJoystickInfo(currFrameCounter, 1); + new_joy[1] = currMovieData.records[currFrameCounter].joysticks[1]; + if (currMovieData.fourscore) + { + old_joy[2] = history.GetCurrentSnapshot().GetJoystickInfo(currFrameCounter, 2); + new_joy[2] = currMovieData.records[currFrameCounter].joysticks[2]; + old_joy[3] = history.GetCurrentSnapshot().GetJoystickInfo(currFrameCounter, 3); + new_joy[3] = currMovieData.records[currFrameCounter].joysticks[3]; + } + if (multitrack_recording_joypad == MULTITRACK_RECORDING_ALL) + { + int i; + if (currMovieData.fourscore) i = 3; else i = 1; + for (; i >= 0; i--) + { + // superimpose (bitwise OR) if needed + if (TASEdit_superimpose == BST_CHECKED || (TASEdit_superimpose == BST_INDETERMINATE && new_joy[i] == 0)) + new_joy[i] |= old_joy[i]; + // change this joystick + currMovieData.records[currFrameCounter].joysticks[i] = new_joy[i]; + if (new_joy[i] != old_joy[i]) + changes_made = true; + } + } else + { + int joy = multitrack_recording_joypad - 1; + // substitute targed joypad with 1p joypad + if (multitrack_recording_joypad > MULTITRACK_RECORDING_1P && TASEdit_use_1p_rec) + new_joy[joy] = new_joy[0]; + // superimpose (bitwise OR) if needed + if (TASEdit_superimpose == BST_CHECKED || (TASEdit_superimpose == BST_INDETERMINATE && new_joy[joy] == 0)) + new_joy[joy] |= old_joy[joy]; + // other joysticks should not be changed + currMovieData.records[currFrameCounter].joysticks[0] = old_joy[0]; + currMovieData.records[currFrameCounter].joysticks[1] = old_joy[1]; + if (currMovieData.fourscore) + { + currMovieData.records[currFrameCounter].joysticks[2] = old_joy[2]; + currMovieData.records[currFrameCounter].joysticks[3] = old_joy[3]; + } + // change only this joystick + currMovieData.records[currFrameCounter].joysticks[joy] = new_joy[joy]; + if (new_joy[joy] != old_joy[joy]) + changes_made = true; + } + if (changes_made) + { + history.RegisterRecording(currFrameCounter); + greenzone.Invalidate(currFrameCounter); + } +} + + diff --git a/src/drivers/win/taseditlib/recorder.h b/src/drivers/win/taseditlib/recorder.h new file mode 100644 index 00000000..b9999064 --- /dev/null +++ b/src/drivers/win/taseditlib/recorder.h @@ -0,0 +1,32 @@ +//Specification file for RECORDER class + +#define MULTITRACK_RECORDING_ALL 0 +#define MULTITRACK_RECORDING_1P 1 +#define MULTITRACK_RECORDING_2P 2 +#define MULTITRACK_RECORDING_3P 3 +#define MULTITRACK_RECORDING_4P 4 + +class RECORDER +{ +public: + RECORDER(); + void init(); + void reset(); + void update(); + + void UncheckRecordingRadioButtons(); + void RecheckRecordingRadioButtons(); + + void InputChangedRec(); + + int multitrack_recording_joypad; + HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; + +private: + int old_multitrack_recording_joypad; + bool old_movie_readonly; + + // temps + std::vector old_joy; + std::vector new_joy; +}; diff --git a/src/drivers/win/taseditlib/tasedit_list.cpp b/src/drivers/win/taseditlib/tasedit_list.cpp index 8a8935d8..43eaf866 100644 --- a/src/drivers/win/taseditlib/tasedit_list.cpp +++ b/src/drivers/win/taseditlib/tasedit_list.cpp @@ -1,15 +1,15 @@ //Implementation file of TASEDIT_LIST class #include "taseditproj.h" -//#include "../tasedit.h" #include "utils/xstring.h" -extern HWND hwndTasEdit, hwndRB_Rec3P, hwndRB_Rec4P; +extern HWND hwndTasEdit; extern char buttonNames[NUM_JOYPAD_BUTTONS][2]; extern void ColumnSet(int column); extern BOOKMARKS bookmarks; extern PLAYBACK playback; +extern RECORDER recorder; extern GREENZONE greenzone; extern INPUT_HISTORY history; extern MARKERS markers; @@ -21,7 +21,6 @@ extern bool TASEdit_show_lag_frames; extern bool TASEdit_follow_playback; extern bool TASEdit_jump_to_undo; - LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); WNDPROC hwndList_oldWndProc, hwndHeader_oldWndproc; @@ -201,8 +200,8 @@ void TASEDIT_LIST::AddFourscore() lvc.pszText = "Frame#"; ListView_InsertColumn(hwndList, colidx++, &lvc); // enable radiobuttons for 3P/4P multitracking - EnableWindow(hwndRB_Rec3P, true); - EnableWindow(hwndRB_Rec4P, true); + EnableWindow(recorder.hwndRB_Rec3P, true); + EnableWindow(recorder.hwndRB_Rec4P, true); // change eoptions FCEUI_SetInputFourscore(true); } @@ -214,8 +213,8 @@ void TASEDIT_LIST::RemoveFourscore() ListView_DeleteColumn (hwndList, i); } // disable radiobuttons for 3P/4P multitracking - EnableWindow(hwndRB_Rec3P, false); - EnableWindow(hwndRB_Rec4P, false); + EnableWindow(recorder.hwndRB_Rec3P, false); + EnableWindow(recorder.hwndRB_Rec4P, false); // change eoptions FCEUI_SetInputFourscore(false); } diff --git a/src/drivers/win/taseditlib/tasedit_sel.cpp b/src/drivers/win/taseditlib/tasedit_sel.cpp index ed3b3811..93bb1aa2 100644 --- a/src/drivers/win/taseditlib/tasedit_sel.cpp +++ b/src/drivers/win/taseditlib/tasedit_sel.cpp @@ -1,8 +1,6 @@ //Implementation file of TASEDIT_SELECTION class -#include "../common.h" #include "taseditproj.h" -//#include "../tasedit.h" char selection_save_id[SELECTION_ID_LEN] = "SELECTION"; diff --git a/src/drivers/win/taseditlib/taseditproj.cpp b/src/drivers/win/taseditlib/taseditproj.cpp index fc14907c..274a5e73 100644 --- a/src/drivers/win/taseditlib/taseditproj.cpp +++ b/src/drivers/win/taseditlib/taseditproj.cpp @@ -1,8 +1,6 @@ //Implementation file of TASEdit Project class -#include "../main.h" #include "taseditproj.h" -#include "../tasedit.h" extern MARKERS markers; extern BOOKMARKS bookmarks; @@ -13,16 +11,17 @@ extern TASEDIT_LIST tasedit_list; extern TASEDIT_SELECTION selection; extern void FCEU_printf(char *format, ...); +extern bool SaveProject(); +extern void RedrawWindowCaption(); + extern int TASEdit_autosave_period; -TASEDIT_PROJECT::TASEDIT_PROJECT() //Non parameterized constructor, loads project with default values +TASEDIT_PROJECT::TASEDIT_PROJECT() { - } void TASEDIT_PROJECT::init() { - // init new project projectName=""; fm2FileName=""; diff --git a/src/drivers/win/taseditlib/taseditproj.h b/src/drivers/win/taseditlib/taseditproj.h index fe4ec303..336da570 100644 --- a/src/drivers/win/taseditlib/taseditproj.h +++ b/src/drivers/win/taseditlib/taseditproj.h @@ -1,19 +1,22 @@ //Specification file for the TASEdit Project class - #include typedef std::set SelectionFrames; +#include #include "movie.h" #include "../common.h" #include "inputsnapshot.h" #include "inputhistory.h" #include "playback.h" +#include "recorder.h" #include "greenzone.h" #include "markers.h" #include "bookmarks.h" #include "tasedit_list.h" #include "tasedit_sel.h" +#define AUTOSAVE_PERIOD_SCALE 60000 // = 1 minute in milliseconds + class TASEDIT_PROJECT { public: diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 3af47dde..5f929e15 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -2835,7 +2835,7 @@ void UpdateMenuHotkeys() //Open TAS Edit combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MISC_OPENTASEDIT]); - combined = "&TAS Edit...\t" + combo; + combined = "&TAS Editor...\t" + combo; ChangeMenuItemText(MENU_TASEDIT, combined); //-------------------------------Debug-------------------------------------- diff --git a/src/movie.cpp b/src/movie.cpp index 232a0942..a6f874ae 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -41,8 +41,9 @@ extern void AddRecentMovieFile(const char *filename); #include "./drivers/win/taseditlib/playback.h" -extern void InputChangedRec(); +#include "./drivers/win/taseditlib/recorder.h" extern PLAYBACK playback; +extern RECORDER recorder; #endif using namespace std; @@ -994,21 +995,20 @@ void FCEUMOV_AddInputState() if(movie_readonly || turbo || pauseframe > currFrameCounter) { // do not record buttons - //reset if necessary - if(mr->command_reset()) ResetNES(); + if(mr->command_reset()) + ResetNES(); + if(mr->command_fds_insert()) + FCEU_FDSInsert(); + if(mr->command_fds_select()) + FCEU_FDSSelect(); joyports[0].load(mr); joyports[1].load(mr); - } - else + } else { // record buttons - // TODO: multitracking - joyports[0].log(mr); joyports[1].log(mr); - mr->commands = 0; - - InputChangedRec(); + recorder.InputChangedRec(); } } else #endif diff --git a/vc/vc10_fceux.vcxproj b/vc/vc10_fceux.vcxproj index 4e29fd86..cd467dda 100644 --- a/vc/vc10_fceux.vcxproj +++ b/vc/vc10_fceux.vcxproj @@ -426,6 +426,7 @@ + @@ -740,6 +741,7 @@ + diff --git a/vc/vc10_fceux.vcxproj.filters b/vc/vc10_fceux.vcxproj.filters index 66f4f317..6c236b71 100644 --- a/vc/vc10_fceux.vcxproj.filters +++ b/vc/vc10_fceux.vcxproj.filters @@ -930,6 +930,7 @@ + @@ -1379,6 +1380,7 @@ +