diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index a47c6013..09f8ef4d 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -72,6 +72,7 @@ extern bool TASEdit_follow_playback; extern bool TASEdit_show_lag_frames; extern bool TASEdit_show_markers; extern bool TASEdit_bind_markers; +extern bool TASEdit_branch_full_movie; extern bool TASEdit_restore_position; extern bool TASEdit_show_dot; extern int TASEdit_greenzone_capacity; @@ -298,6 +299,7 @@ static CFGSTRUCT fceuconfig[] = { AC(TASEdit_show_lag_frames), AC(TASEdit_show_markers), AC(TASEdit_bind_markers), + AC(TASEdit_branch_full_movie), AC(TASEdit_restore_position), AC(TASEdit_show_dot), AC(TASEdit_greenzone_capacity), diff --git a/src/drivers/win/mapinput.cpp b/src/drivers/win/mapinput.cpp index a776c48d..b0a471ad 100644 --- a/src/drivers/win/mapinput.cpp +++ b/src/drivers/win/mapinput.cpp @@ -71,9 +71,10 @@ static struct { EMUCMD_OPENROM, SCAN_O | CMD_KEY_CTRL, }, { EMUCMD_CLOSEROM, SCAN_W | CMD_KEY_CTRL, }, { EMUCMD_RELOADROM, SCAN_R | CMD_KEY_CTRL | CMD_KEY_SHIFT , }, - { EMUCMD_MISC_UNDOREDOSAVESTATE, SCAN_Z | CMD_KEY_CTRL, }, - { EMUCMD_MISC_TOGGLEFULLSCREEN, SCAN_ENTER | CMD_KEY_ALT, }, - { EMUCMD_TASEDIT_REWIND, SCAN_GRAVE, }, + { EMUCMD_MISC_UNDOREDOSAVESTATE, SCAN_Z | CMD_KEY_CTRL, }, + { EMUCMD_MISC_TOGGLEFULLSCREEN, SCAN_ENTER | CMD_KEY_ALT, }, + { EMUCMD_TASEDIT_REWIND, SCAN_GRAVE, }, + { EMUCMD_RERECORD_DISPLAY_TOGGLE, SCAN_M, }, }; #define NUM_DEFAULT_MAPPINGS (sizeof(DefaultCommandMapping)/sizeof(DefaultCommandMapping[0])) diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 3bd2e5c6..1982b487 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -129,7 +129,7 @@ BEGIN MENUITEM "&Lag Counter", MENU_DISPLAY_LAGCOUNTER MENUITEM "&Frame Counter", ID_DISPLAY_FRAMECOUNTER MENUITEM "&Rerecord Counter", ID_DISPLAY_RERECORDCOUNTER - MENUITEM "Movie status icon", ID_DISPLAY_MOVIESTATUSICON + MENUITEM "&Movie status icon", ID_DISPLAY_MOVIESTATUSICON MENUITEM SEPARATOR MENUITEM "Graphics: &BG", MENU_DISPLAY_BG MENUITEM "Graphics: &OBJ", MENU_DISPLAY_OBJ @@ -264,6 +264,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO MENUITEM "&Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT + MENUITEM "Branches restore entire Movie", ID_CONFIG_BRANCHESRESTOREFULLMOVIE END POPUP "&Help" BEGIN @@ -1348,38 +1349,38 @@ BEGIN EDITTEXT IDC_LABEL_NEWPPUUSED,76,166,155,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP END -TASEDIT DIALOGEX 0, 0, 433, 381 +TASEDIT DIALOGEX 0, 0, 438, 380 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | 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,6,5,299,370 - GROUPBOX " Playback ",IDC_STATIC,310,5,118,62,BS_CENTER,WS_EX_RIGHT - PUSHBUTTON "<<",TASEDIT_REWIND_FULL,314,14,22,14,NOT WS_TABSTOP - PUSHBUTTON "<",TASEDIT_REWIND,336,14,22,14,NOT WS_TABSTOP - PUSHBUTTON "||",TASEDIT_PLAYSTOP,358,14,22,14,NOT WS_TABSTOP - PUSHBUTTON ">",TASEDIT_FORWARD,380,14,22,14,NOT WS_TABSTOP - PUSHBUTTON ">>",TASEDIT_FORWARD_FULL,402,14,22,14,NOT WS_TABSTOP - CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW | WS_TABSTOP,314,42,110,10 - CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,314,44,110,6 - CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,315,30,105,12 + GROUPBOX " Playback ",IDC_STATIC,310,5,123,62,BS_CENTER,WS_EX_RIGHT + PUSHBUTTON "<<",TASEDIT_REWIND_FULL,314,14,23,14,NOT WS_TABSTOP + PUSHBUTTON "<",TASEDIT_REWIND,337,14,23,14,NOT WS_TABSTOP + PUSHBUTTON "||",TASEDIT_PLAYSTOP,360,14,23,14,NOT WS_TABSTOP + PUSHBUTTON ">",TASEDIT_FORWARD,383,14,23,14,NOT WS_TABSTOP + PUSHBUTTON ">>",TASEDIT_FORWARD_FULL,406,14,23,14,NOT WS_TABSTOP + CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW | WS_TABSTOP,314,42,116,10 + CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,314,44,115,6 + CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,316,30,105,12 CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK, - "Button",BS_AUTOCHECKBOX,315,53,105,12 - GROUPBOX " Recording ",IDC_STATIC,310,68,118,48,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Editing ",IDC_STATIC,310,118,118,38,BS_CENTER,WS_EX_RIGHT - GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,310,158,118,101,BS_CENTER,WS_EX_RIGHT - CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,168,108,86 - CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,271,108,100 + "Button",BS_AUTOCHECKBOX,316,53,105,12 + GROUPBOX " Recording ",IDC_STATIC,310,68,123,48,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Editing ",IDC_STATIC,310,118,123,38,BS_CENTER,WS_EX_RIGHT + GROUPBOX " Bookmarks ",IDC_BOOKMARKS_BOX,310,158,123,103,BS_CENTER,WS_EX_RIGHT + CONTROL "",IDC_BOOKMARKSLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,168,113,89 + CONTROL "",IDC_HISTORYLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOLABELWRAP | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,273,113,99 CONTROL " OFF",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,316,78,29,10 CONTROL " ON",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,316,91,29,10 - CONTROL " 1P",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,368,78,25,10 - CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,397,78,23,10 - CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,368,91,25,10 - CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,397,91,23,10 - CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,316,104,55,10 - CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,375,104,49,10 - GROUPBOX " History ",IDC_STATIC,310,261,118,114,BS_CENTER,WS_EX_RIGHT + CONTROL " 1P",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,373,78,25,10 + CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,402,78,23,10 + CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,373,91,25,10 + CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,402,91,23,10 + CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX,316,104,56,10 + CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX,377,104,51,10 + GROUPBOX " History ",IDC_STATIC,310,263,123,113,BS_CENTER,WS_EX_RIGHT END ASSEMBLER DIALOGEX 0, 0, 202, 135 @@ -1887,8 +1888,9 @@ BEGIN "TASEDIT", DIALOG BEGIN LEFTMARGIN, 7 + RIGHTMARGIN, 436 TOPMARGIN, 5 - BOTTOMMARGIN, 375 + BOTTOMMARGIN, 374 END "ASSEMBLER", DIALOG @@ -2060,6 +2062,16 @@ END // IDB_TE_ARROW BITMAP "res/te_arrow.bmp" +IDB_BITMAP0 BITMAP "res\\te_0.bmp" +IDB_BITMAP1 BITMAP "res\\te_1.bmp" +IDB_BITMAP2 BITMAP "res\\te_2.bmp" +IDB_BITMAP3 BITMAP "res\\te_3.bmp" +IDB_BITMAP4 BITMAP "res\\te_4.bmp" +IDB_BITMAP5 BITMAP "res\\te_5.bmp" +IDB_BITMAP6 BITMAP "res\\te_6.bmp" +IDB_BITMAP7 BITMAP "res\\te_7.bmp" +IDB_BITMAP8 BITMAP "res\\te_8.bmp" +IDB_BITMAP9 BITMAP "res\\te_9.bmp" #endif // Английский (США) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/drivers/win/res/te_0.bmp b/src/drivers/win/res/te_0.bmp new file mode 100644 index 00000000..6b9052ca Binary files /dev/null and b/src/drivers/win/res/te_0.bmp differ diff --git a/src/drivers/win/res/te_1.bmp b/src/drivers/win/res/te_1.bmp new file mode 100644 index 00000000..447feb43 Binary files /dev/null and b/src/drivers/win/res/te_1.bmp differ diff --git a/src/drivers/win/res/te_2.bmp b/src/drivers/win/res/te_2.bmp new file mode 100644 index 00000000..28ad61dd Binary files /dev/null and b/src/drivers/win/res/te_2.bmp differ diff --git a/src/drivers/win/res/te_3.bmp b/src/drivers/win/res/te_3.bmp new file mode 100644 index 00000000..1894d65c Binary files /dev/null and b/src/drivers/win/res/te_3.bmp differ diff --git a/src/drivers/win/res/te_4.bmp b/src/drivers/win/res/te_4.bmp new file mode 100644 index 00000000..77365321 Binary files /dev/null and b/src/drivers/win/res/te_4.bmp differ diff --git a/src/drivers/win/res/te_5.bmp b/src/drivers/win/res/te_5.bmp new file mode 100644 index 00000000..19f97223 Binary files /dev/null and b/src/drivers/win/res/te_5.bmp differ diff --git a/src/drivers/win/res/te_6.bmp b/src/drivers/win/res/te_6.bmp new file mode 100644 index 00000000..c34537ef Binary files /dev/null and b/src/drivers/win/res/te_6.bmp differ diff --git a/src/drivers/win/res/te_7.bmp b/src/drivers/win/res/te_7.bmp new file mode 100644 index 00000000..ff6bf9cc Binary files /dev/null and b/src/drivers/win/res/te_7.bmp differ diff --git a/src/drivers/win/res/te_8.bmp b/src/drivers/win/res/te_8.bmp new file mode 100644 index 00000000..ac01171b Binary files /dev/null and b/src/drivers/win/res/te_8.bmp differ diff --git a/src/drivers/win/res/te_9.bmp b/src/drivers/win/res/te_9.bmp new file mode 100644 index 00000000..f6c95cb8 Binary files /dev/null and b/src/drivers/win/res/te_9.bmp differ diff --git a/src/drivers/win/res/te_arrow.bmp b/src/drivers/win/res/te_arrow.bmp index 9ccc5a4e..1ef873ea 100644 Binary files a/src/drivers/win/res/te_arrow.bmp and b/src/drivers/win/res/te_arrow.bmp differ diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 1ad63110..acfecd52 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -159,6 +159,16 @@ #define IDD_PROMPT 157 #define IDR_RWACCELERATOR 158 #define IDD_LUA 159 +#define IDB_BITMAP0 163 +#define IDB_BITMAP1 164 +#define IDB_BITMAP2 165 +#define IDB_BITMAP3 166 +#define IDB_BITMAP4 167 +#define IDB_BITMAP5 168 +#define IDB_BITMAP6 169 +#define IDB_BITMAP7 170 +#define IDB_BITMAP8 171 +#define IDB_BITMAP9 172 #define MENU_RESET 200 #define BUTTON_ROMS 200 #define TXT_PAD1 200 @@ -860,6 +870,7 @@ #define ID_CONFIG_SETMAXUNDOLEVELS 40470 #define ID_VIEW_X 40471 #define ID_VIEW_JUMPWHENMAKINGUNDO 40472 +#define ID_CONFIG_BRANCHESRESTOREFULLMOVIE 40473 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -868,8 +879,8 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 160 -#define _APS_NEXT_COMMAND_VALUE 40473 +#define _APS_NEXT_RESOURCE_VALUE 173 +#define _APS_NEXT_COMMAND_VALUE 40474 #define _APS_NEXT_CONTROL_VALUE 1265 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index 9616e11a..db237c4b 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -37,6 +37,7 @@ bool TASEdit_follow_playback = true; bool TASEdit_show_lag_frames = true; bool TASEdit_show_markers = true; bool TASEdit_bind_markers = true; +bool TASEdit_branch_full_movie = true; bool TASEdit_restore_position = false; int TASEdit_greenzone_capacity = GREENZONE_CAPACITY_DEFAULT; extern bool muteTurbo; @@ -52,7 +53,8 @@ char windowCaptions[6][30] = { "TAS Editor", "TAS Editor (Recording 2P)", "TAS Editor (Recording 3P)", "TAS Editor (Recording 4P)"}; -char bookmarksCaption[2][23] = { " Bookmarks ", " Bookmarks / Branches " }; +// hot changes color table +COLORREF hot_changes_colors[16] = { 0x0, 0x41f2c, 0x62a3b, 0x7344a, 0x93f59, 0xb4968, 0xc5477, 0xe5e86, 0xf6995, 0x1174a4, 0x127eb3, 0x1489c2, 0x1693d1, 0x179ee0, 0x19a8ef, 0x1bb4ff }; HWND hwndTasEdit = 0; HMENU hmenu, hrmenu; @@ -65,6 +67,7 @@ WNDPROC hwndBookmarksList_oldWndProc; HWND hwndProgressbar, hwndRewind, hwndForward, hwndRewindFull, hwndForwardFull; HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; +HFONT hMainListFont; typedef std::set TSelectionFrames; static TSelectionFrames selectionFrames; @@ -79,6 +82,7 @@ INPUT_HISTORY history; PLAYBACK playback; GREENZONE greenzone; MARKERS markers; +BOOKMARKS bookmarks; void GetDispInfo(NMLVDISPINFO* nmlvDispInfo) { @@ -88,11 +92,20 @@ void GetDispInfo(NMLVDISPINFO* nmlvDispInfo) switch(item.iSubItem) { case COLUMN_ICONS: - if(item.iImage == I_IMAGECALLBACK && item.iItem == currFrameCounter) - item.iImage = 0; - else - item.iImage = -1; - break; + { + if(item.iImage == I_IMAGECALLBACK) + { + item.iImage = bookmarks.FindBookmarkAtFrame(item.iItem); + if (item.iImage < 0) + { + if (item.iItem == currFrameCounter) + item.iImage = ARROW_IMAGE_ID; + else + item.iImage = -1; + } + } + break; + } case COLUMN_FRAMENUM: case COLUMN_FRAMENUM2: { @@ -129,11 +142,6 @@ void GetDispInfo(NMLVDISPINFO* nmlvDispInfo) } } -#define CDDS_SUBITEMPREPAINT (CDDS_SUBITEM | CDDS_ITEMPREPAINT) -#define CDDS_SUBITEMPOSTPAINT (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT) -#define CDDS_SUBITEMPREERASE (CDDS_SUBITEM | CDDS_ITEMPREERASE) -#define CDDS_SUBITEMPOSTERASE (CDDS_SUBITEM | CDDS_ITEMPOSTERASE) - LONG CustomDraw(NMLVCUSTOMDRAW* msg) { int cell_x, cell_y; @@ -144,7 +152,6 @@ LONG CustomDraw(NMLVCUSTOMDRAW* msg) case CDDS_ITEMPREPAINT: return CDRF_NOTIFYSUBITEMDRAW; case CDDS_SUBITEMPREPAINT: - SelectObject(msg->nmcd.hdc,debugSystem->hFixedFont); cell_x = msg->iSubItem; cell_y = msg->nmcd.dwItemSpec; @@ -152,6 +159,7 @@ LONG CustomDraw(NMLVCUSTOMDRAW* msg) if(cell_x > COLUMN_ICONS) { + SelectObject(msg->nmcd.hdc, hMainListFont); if(cell_x == COLUMN_FRAMENUM || cell_x == COLUMN_FRAMENUM2) { // frame number @@ -255,7 +263,6 @@ LONG CustomDraw(NMLVCUSTOMDRAW* msg) } else msg->clrTextBk = NORMAL_INPUT_COLOR2; } } - return CDRF_DODEFAULT; default: return CDRF_DODEFAULT; } @@ -270,6 +277,7 @@ void UpdateTasEdit() greenzone.update(); playback.update(); + bookmarks.update(); history.update(); // update window caption @@ -279,7 +287,7 @@ void UpdateTasEdit() // update Bookmarks/Branches groupbox caption if (old_movie_readonly != movie_readonly) - RedrawBookmarksCaption(); + 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) @@ -335,21 +343,19 @@ void RedrawWindowCaption() strcat(windowCaption, "*"); SetWindowText(hwndTasEdit, windowCaption); } -void RedrawBookmarksCaption() -{ - SetWindowText(hwndBookmarks, bookmarksCaption[(movie_readonly)?0:1]); -} void RedrawTasedit() { - InvalidateRect(hwndTasEdit,0,FALSE); + InvalidateRect(hwndTasEdit, 0, FALSE); } void RedrawList() { - InvalidateRect(hwndList,0,FALSE); + InvalidateRect(hwndList, 0, FALSE); + bookmarks.RedrawBookmarksList(); } void RedrawRow(int index) { - ListView_RedrawItems(hwndList,index,index); + ListView_RedrawItems(hwndList, index, index); + bookmarks.RedrawChangedBookmarks(index); } enum ECONTEXTMENU @@ -402,7 +408,7 @@ void RightClick(LPNMITEMACTIVATE info) void InputChangedRec() { - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_RECORD, currFrameCounter, currFrameCounter)); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_RECORD, currFrameCounter, currFrameCounter)); } void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags) @@ -416,15 +422,15 @@ void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags) { currMovieData.records[*it].toggleBit(joy,bit); } - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_CHANGE, *selectionFrames.begin(), *selectionFrames.rbegin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CHANGE, *selectionFrames.begin(), *selectionFrames.rbegin())); } else { //update one row currMovieData.records[row_index].toggleBit(joy,bit); if (currMovieData.records[row_index].checkBit(joy,bit)) - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_SET, row_index, row_index)); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, row_index, row_index)); else - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_UNSET, row_index, row_index)); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, row_index, row_index)); } } @@ -440,7 +446,6 @@ void SingleClick(LPNMITEMACTIVATE info) // click on the "icons" column - jump to the frame ClearSelection(); playback.jump(row_index); - RedrawList(); } else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) { // click on the "frame number" column - set marker if clicked with Alt @@ -476,7 +481,6 @@ void DoubleClick(LPNMITEMACTIVATE info) // double click sends playback to the frame ClearSelection(); playback.jump(row_index); - RedrawList(); } else if(column_index >= COLUMN_JOYPAD1_A && column_index <= COLUMN_JOYPAD4_R) { ToggleJoypadBit(column_index, row_index, info->uKeyFlags); @@ -506,7 +510,7 @@ void CloneFrames() } else frames++; } UpdateList(); - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_CLONE, *selectionFrames.begin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLONE, *selectionFrames.begin())); } void InsertFrames() @@ -533,7 +537,7 @@ void InsertFrames() } else frames++; } UpdateList(); - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_INSERT, *selectionFrames.begin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, *selectionFrames.begin())); } void DeleteFrames() @@ -556,10 +560,10 @@ void DeleteFrames() int result = history.RegisterChanges(MODTYPE_DELETE, start_index); if (result >= 0) { - greenzone.InvalidateGreenZone(result); + greenzone.InvalidateAndCheck(result); } else if (greenzone.greenZoneCount >= currMovieData.getNumRecords()) { - greenzone.InvalidateGreenZone(currMovieData.getNumRecords()-1); + greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1); } else RedrawList(); } @@ -571,9 +575,9 @@ void ClearFrames(bool cut) currMovieData.records[*it].clear(); } if (cut) - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_CUT, *selectionFrames.begin(), *selectionFrames.rbegin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CUT, *selectionFrames.begin(), *selectionFrames.rbegin())); else - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_CLEAR, *selectionFrames.begin(), *selectionFrames.rbegin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_CLEAR, *selectionFrames.begin(), *selectionFrames.rbegin())); } void Truncate() @@ -591,10 +595,10 @@ void Truncate() int result = history.RegisterChanges(MODTYPE_TRUNCATE, frame+1); if (result >= 0) { - greenzone.InvalidateGreenZone(result); + greenzone.InvalidateAndCheck(result); } else if (greenzone.greenZoneCount >= currMovieData.getNumRecords()) { - greenzone.InvalidateGreenZone(currMovieData.getNumRecords()-1); + greenzone.InvalidateAndCheck(currMovieData.getNumRecords()-1); } else RedrawList(); } } @@ -651,9 +655,9 @@ void ColumnSet(int column) for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++) currMovieData.records[*it].setBitValue(joy,button,newValue); if (newValue) - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_SET, *selectionFrames.begin(), *selectionFrames.rbegin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_SET, *selectionFrames.begin(), *selectionFrames.rbegin())); else - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_UNSET, *selectionFrames.begin(), *selectionFrames.rbegin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_UNSET, *selectionFrames.begin(), *selectionFrames.rbegin())); } } @@ -890,7 +894,7 @@ bool Paste() pGlobal = strchr(pGlobal, '\n'); } - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_PASTE, *selectionFrames.begin())); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_PASTE, *selectionFrames.begin())); result = true; } @@ -902,7 +906,7 @@ bool Paste() } // --------------------------------------------------------------------------------- //The subclass wndproc for the listview header -LRESULT APIENTRY HeaderWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) +LRESULT APIENTRY HeaderWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { @@ -924,18 +928,18 @@ LRESULT APIENTRY HeaderWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) } return true; } - return CallWindowProc(hwndHeader_oldWndproc,hWnd,msg,wParam,lParam); + return CallWindowProc(hwndHeader_oldWndproc, hWnd, msg, wParam, lParam); } //The subclass wndproc for the listview -LRESULT APIENTRY ListWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) +LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { - case WM_CHAR: - case WM_KILLFOCUS: - return 0; - case WM_NOTIFY: + case WM_CHAR: + case WM_KILLFOCUS: + return 0; + case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { @@ -946,22 +950,53 @@ LRESULT APIENTRY ListWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) } break; } - + case WM_SYSKEYDOWN: + { + if (wParam == VK_F10) + return 0; + break; + } } - return CallWindowProc(hwndList_oldWndProc,hWnd,msg,wParam,lParam); + return CallWindowProc(hwndList_oldWndProc, hWnd, msg, wParam, lParam); +} + +LRESULT APIENTRY BookmarksListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SETFOCUS: + case WM_KILLFOCUS: + return 0; + case WM_SYSKEYDOWN: + { + if (wParam == VK_F10) + return 0; + break; + } + } + return CallWindowProc(hwndBookmarksList_oldWndProc, hWnd, msg, wParam, lParam); } LRESULT APIENTRY HistoryListWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { - case WM_CHAR: - case WM_KEYDOWN: - case WM_KEYUP: - case WM_KILLFOCUS: - return 0; + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_KILLFOCUS: + return 0; + case WM_SYSKEYDOWN: + { + if (wParam == VK_F10) + return 0; + break; + } } - return CallWindowProc(hwndList_oldWndProc,hWnd,msg,wParam,lParam); + return CallWindowProc(hwndHistoryList_oldWndProc, hWnd, msg, wParam, lParam); } void AddFourscore() @@ -1102,7 +1137,7 @@ void OpenProject() FollowPlayback(); RedrawTasedit(); RedrawWindowCaption(); - RedrawBookmarksCaption(); + bookmarks.RedrawBookmarksCaption(); } } @@ -1256,8 +1291,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar switch(uMsg) { case WM_PAINT: - { - } break; case WM_INITDIALOG: if (TasEdit_wndx==-32000) TasEdit_wndx=0; //Just in case @@ -1336,6 +1369,23 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar */ } break; + case IDC_BOOKMARKSLIST: + switch(((LPNMHDR)lParam)->code) + { + case NM_CUSTOMDRAW: + SetWindowLong(hwndDlg, DWL_MSGRESULT, bookmarks.CustomDraw((NMLVCUSTOMDRAW*)lParam)); + return TRUE; + case LVN_GETDISPINFO: + bookmarks.GetDispInfo((NMLVDISPINFO*)lParam); + break; + case NM_CLICK: + case NM_DBLCLK: + bookmarks.LeftClick((LPNMITEMACTIVATE)lParam); + break; + case NM_RCLICK: + bookmarks.RightClick((LPNMITEMACTIVATE)lParam); + } + break; case IDC_HISTORYLIST: switch(((LPNMHDR)lParam)->code) { @@ -1350,7 +1400,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case NM_RCLICK: history.Click((LPNMITEMACTIVATE)lParam); break; - } break; case TASEDIT_PLAYSTOP: @@ -1447,14 +1496,14 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar currMovieData.insertEmpty(index, frames); if (TASEdit_bind_markers) markers.insertEmpty(index, frames); - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_INSERT, index)); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, index)); } else { // insert at playback cursor currMovieData.insertEmpty(currFrameCounter, frames); if (TASEdit_bind_markers) markers.insertEmpty(currFrameCounter, frames); - greenzone.InvalidateGreenZone(history.RegisterChanges(MODTYPE_INSERT, currFrameCounter)); + greenzone.InvalidateAndCheck(history.RegisterChanges(MODTYPE_INSERT, currFrameCounter)); } } } @@ -1547,7 +1596,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar history.init(TasEdit_undo_levels); // hot changes were cleared, so update list RedrawList(); - //RedrawUndoList(); } } break; @@ -1561,6 +1609,11 @@ 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_BRANCHESRESTOREFULLMOVIE: + //switch "Branches restore entire Movie" flag + TASEdit_branch_full_movie ^= 1; + CheckMenuItem(hmenu, ID_CONFIG_BRANCHESRESTOREFULLMOVIE, TASEdit_branch_full_movie?MF_CHECKED : MF_UNCHECKED); + break; case IDC_PROGRESS_BUTTON: // click on progressbar - stop seeking if (playback.pauseframe) playback.SeekingStop(); @@ -1612,7 +1665,7 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar { UpdateList(); FollowUndo(); - greenzone.InvalidateGreenZone(result); + greenzone.InvalidateAndCheck(result); } break; } @@ -1624,13 +1677,19 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar { UpdateList(); FollowUndo(); - greenzone.InvalidateGreenZone(result); + greenzone.InvalidateAndCheck(result); } break; } } break; + case WM_SYSKEYDOWN: + { + if (wParam == VK_F10) + return 0; + break; + } default: break; @@ -1766,6 +1825,7 @@ void EnterTasEdit() CheckMenuItem(hmenu, ID_VIEW_SHOW_MARKERS, TASEdit_show_markers?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, TASEdit_jump_to_undo?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_BINDMARKERSTOINPUT, TASEdit_bind_markers?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_BRANCHESRESTOREFULLMOVIE, TASEdit_branch_full_movie?MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndTasEdit,CHECK_AUTORESTORE_PLAYBACK,TASEdit_restore_position?BST_CHECKED:BST_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_VIEW_SHOWDOTINEMPTYCELLS, TASEdit_show_dot?MF_CHECKED : MF_UNCHECKED); @@ -1793,20 +1853,58 @@ void EnterTasEdit() RecheckRecordingRadioButtons(); movieMode = MOVIEMODE_TASEDIT; - //prepare the main listview - ListView_SetExtendedListViewStyleEx(hwndList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); - //subclass the header + // create font for main listview + hMainListFont = CreateFont(13, 8, /*Height,Width*/ + 0, 0, /*escapement,orientation*/ + FW_REGULAR, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/ + ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/ + DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/ + "Courier"); /*font name*/ + + // prepare the main listview + ListView_SetExtendedListViewStyleEx(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + // subclass the header hwndHeader = ListView_GetHeader(hwndList); - hwndHeader_oldWndproc = (WNDPROC)SetWindowLong(hwndHeader,GWL_WNDPROC,(LONG)HeaderWndProc); - //subclass the whole listview - hwndList_oldWndProc = (WNDPROC)SetWindowLong(hwndList,GWL_WNDPROC,(LONG)ListWndProc); - //setup images for the listview - HIMAGELIST himglist = ImageList_Create(8,12,ILC_COLOR8 | ILC_MASK,1,1); - HBITMAP bmp = LoadBitmap(fceu_hInstance,MAKEINTRESOURCE(IDB_TE_ARROW)); + hwndHeader_oldWndproc = (WNDPROC)SetWindowLong(hwndHeader, GWL_WNDPROC, (LONG)HeaderWndProc); + // subclass the whole listview + hwndList_oldWndProc = (WNDPROC)SetWindowLong(hwndList, GWL_WNDPROC, (LONG)ListWndProc); + // setup images for the listview + HIMAGELIST himglist = ImageList_Create(9, 13, ILC_COLOR8 | ILC_MASK, 1, 1); + HBITMAP bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP0)); ImageList_AddMasked(himglist, bmp, 0xFF00FF); DeleteObject(bmp); - ListView_SetImageList(hwndList,himglist,LVSIL_SMALL); - //setup columns + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP2)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP3)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP4)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP5)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP6)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP7)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP8)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_BITMAP9)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + bmp = LoadBitmap(fceu_hInstance, MAKEINTRESOURCE(IDB_TE_ARROW)); + ImageList_AddMasked(himglist, bmp, 0xFF00FF); + DeleteObject(bmp); + ListView_SetImageList(hwndList, himglist, LVSIL_SMALL); + // setup columns LVCOLUMN lvc; int colidx=0; // icons column @@ -1816,7 +1914,7 @@ void EnterTasEdit() // frame number column lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT; lvc.fmt = LVCFMT_CENTER; - lvc.cx = 75; + lvc.cx = 74; lvc.pszText = "Frame#"; ListView_InsertColumn(hwndList, colidx++, &lvc); // pads columns @@ -1834,10 +1932,30 @@ void EnterTasEdit() if (currMovieData.fourscore) AddFourscore(); UpdateList(); - //prepare the history listview - ListView_SetExtendedListViewStyleEx(hwndHistoryList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); - //subclass the whole listview - hwndHistoryList_oldWndProc = (WNDPROC)SetWindowLong(hwndHistoryList,GWL_WNDPROC,(LONG)HistoryListWndProc); + // prepare bookmarks listview + ListView_SetExtendedListViewStyleEx(hwndBookmarksList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + // subclass the listview + hwndBookmarksList_oldWndProc = (WNDPROC)SetWindowLong(hwndBookmarksList, GWL_WNDPROC, (LONG)BookmarksListWndProc); + // setup same images for the listview + ListView_SetImageList(hwndBookmarksList, himglist, LVSIL_SMALL); + // setup columns + // icons column + lvc.mask = LVCF_WIDTH; + lvc.cx = 13; + ListView_InsertColumn(hwndBookmarksList, 0, &lvc); + // jump_frame column + lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT; + lvc.fmt = LVCFMT_CENTER; + lvc.cx = 72; + ListView_InsertColumn(hwndBookmarksList, 1, &lvc); + // time column + lvc.cx = 82; + ListView_InsertColumn(hwndBookmarksList, 2, &lvc); + + // prepare the history listview + ListView_SetExtendedListViewStyleEx(hwndHistoryList, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + // subclass the listview + hwndHistoryList_oldWndProc = (WNDPROC)SetWindowLong(hwndHistoryList, GWL_WNDPROC, (LONG)HistoryListWndProc); lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT; lvc.cx = 200; lvc.fmt = LVCFMT_LEFT; @@ -1846,8 +1964,10 @@ void EnterTasEdit() // init variables markers.init(); project.init(); + bookmarks.init(); history.init(TasEdit_undo_levels); - SetFocus(hwndHistoryList); + SetFocus(hwndHistoryList); // to show darkblue cursor + SetFocus(hwndList); FCEU_DispMessage("Tasedit engaged",0); } } @@ -1872,6 +1992,7 @@ bool ExitTasEdit() // release memory markers.free(); greenzone.clearGreenzone(); + bookmarks.free(); history.free(); playback.SeekingStop(); diff --git a/src/drivers/win/tasedit.h b/src/drivers/win/tasedit.h index 7c749a0f..a8098d87 100644 --- a/src/drivers/win/tasedit.h +++ b/src/drivers/win/tasedit.h @@ -1,4 +1,7 @@ - +#define CDDS_SUBITEMPREPAINT (CDDS_SUBITEM | CDDS_ITEMPREPAINT) +#define CDDS_SUBITEMPOSTPAINT (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT) +#define CDDS_SUBITEMPREERASE (CDDS_SUBITEM | CDDS_ITEMPREERASE) +#define CDDS_SUBITEMPOSTERASE (CDDS_SUBITEM | CDDS_ITEMPOSTERASE) #define NUM_JOYPADS 4 #define NUM_JOYPAD_BUTTONS 8 @@ -55,9 +58,10 @@ #define COLUMN_JOYPAD4_R 33 #define COLUMN_FRAMENUM2 34 #define DIGITS_IN_FRAMENUM 7 +#define ARROW_IMAGE_ID 10 // listview colors #define NORMAL_FRAMENUM_COLOR 0xFFFFFF -#define NORMAL_INPUT_COLOR1 0xF0F0F0 +#define NORMAL_INPUT_COLOR1 0xEDEDED #define NORMAL_INPUT_COLOR2 0xDEDEDE #define GREENZONE_FRAMENUM_COLOR 0xDDFFDD @@ -110,7 +114,6 @@ void ClearRowSelection(int index); void AddFourscore(); void RemoveFourscore(); void RedrawWindowCaption(); -void RedrawBookmarksCaption(); void RedrawTasedit(); void RedrawList(); void RedrawRow(int index); diff --git a/src/drivers/win/taseditlib/bookmark.cpp b/src/drivers/win/taseditlib/bookmark.cpp new file mode 100644 index 00000000..b5ff9c9e --- /dev/null +++ b/src/drivers/win/taseditlib/bookmark.cpp @@ -0,0 +1,85 @@ +//Implementation file of Bookmark class + +#include "movie.h" +#include "../common.h" +#include "taseditproj.h" +//#include "../tasedit.h" +#include "zlib.h" + +extern GREENZONE greenzone; + +BOOKMARK::BOOKMARK() +{ + +} + +void BOOKMARK::init() +{ + not_empty = false; + flash_type = flash_phase = 0; + snapshot.jump_frame = -1; +} + +void BOOKMARK::set() +{ + snapshot.init(currMovieData, false); + snapshot.jump_frame = currFrameCounter; + savestate = greenzone.savestates[currFrameCounter]; + //screenshots + + not_empty = true; + flash_phase = FLASH_PHASE_MAX; + flash_type = FLASH_TYPE_SET; +} + +void BOOKMARK::jump() +{ + flash_phase = FLASH_PHASE_MAX; + flash_type = FLASH_TYPE_JUMP; +} + +void BOOKMARK::unleash() +{ + flash_phase = FLASH_PHASE_MAX; + flash_type = FLASH_TYPE_UNLEASH; +} + +void BOOKMARK::save(EMUFILE *os) +{ + if (not_empty) + { + write8le(1, os); + snapshot.save(os); + // write savestate + int size = savestate.size(); + write32le(size, os); + os->fwrite(&savestate[0], size); + //write screenshots (current, saved) + + } else write8le((uint8)0, os); +} +// returns true if couldn't load +bool BOOKMARK::load(EMUFILE *is) +{ + uint8 tmp; + if (!read8le(&tmp, is)) return true; + not_empty = tmp != 0; + if (not_empty) + { + if (snapshot.load(is)) return true; + // read savestate + int size; + if (!read32le((uint32 *)&size, is)) return true; + savestate.resize(size); + if ((int)is->fread(&savestate[0], size) < size) return true; + //read screenshots (current, saved) + + } + // all ok + flash_type = flash_phase = 0; + return false; +} +// ---------------------------------------------------------- + + + diff --git a/src/drivers/win/taseditlib/bookmark.h b/src/drivers/win/taseditlib/bookmark.h new file mode 100644 index 00000000..1de48bec --- /dev/null +++ b/src/drivers/win/taseditlib/bookmark.h @@ -0,0 +1,31 @@ +//Specification file for Bookmark class + +#define FLASH_PHASE_MAX 11 +#define FLASH_TYPE_SET 0 +#define FLASH_TYPE_JUMP 1 +#define FLASH_TYPE_UNLEASH 2 + +class BOOKMARK +{ +public: + BOOKMARK(); + void init(); + + void set(); + void jump(); + void unleash(); + + void save(EMUFILE *os); + bool load(EMUFILE *is); + + bool not_empty; + int flash_phase; + int flash_type; + INPUT_SNAPSHOT snapshot; + std::vector savestate; + std::vector current_screenshot; + std::vector saved_screenshot; + +private: + +}; diff --git a/src/drivers/win/taseditlib/bookmarks.cpp b/src/drivers/win/taseditlib/bookmarks.cpp new file mode 100644 index 00000000..36397fef --- /dev/null +++ b/src/drivers/win/taseditlib/bookmarks.cpp @@ -0,0 +1,404 @@ +//Implementation file of Bookmarks class + +#include "movie.h" +#include "../common.h" +#include "taseditproj.h" +#include "../tasedit.h" +#include "zlib.h" +#include "utils/xstring.h" + +char bookmarks_save_id[BOOKMARKS_ID_LEN] = "BOOKMARKS"; +char bookmarksCaption[2][23] = { " Bookmarks ", " Bookmarks / Branches " }; + +// color tables for flashing when saving/loading bookmarks +COLORREF bookmark_flash_colors[3][FLASH_PHASE_MAX+1] = { + // set + 0x122330, 0x1b3541, 0x254753, 0x2e5964, 0x376b75, 0x417e87, 0x4a8f97, 0x53a1a8, 0x5db3b9, 0x66c5cb, 0x70d7dc, 0x79e9ed, + // jump + 0x382309, 0x3c350e, 0x404814, 0x455a19, 0x486c1e, 0x4d7f23, 0x519128, 0x55a32d, 0x5ab532, 0x5ec837, 0x62da3c, 0x66ec41, + // unleash + 0x320d23, 0x341435, 0x361b48, 0x38215a, 0x39286c, 0x3b2f7f, 0x3c3691, 0x3e3ca3, 0x4043b5, 0x414ac8, 0x4351da, 0x4457ec }; + +extern PLAYBACK playback; +extern GREENZONE greenzone; +extern TASEDIT_PROJECT project; +extern INPUT_HISTORY history; +extern MARKERS markers; + +extern HWND hwndBookmarks; +extern HWND hwndBookmarksList; +extern bool TASEdit_show_lag_frames; +extern bool TASEdit_bind_markers; +extern bool TASEdit_branch_full_movie; + +BOOKMARKS::BOOKMARKS() +{ + +} + +void BOOKMARKS::init() +{ + free(); + bookmarks_array.resize(TOTAL_BOOKMARKS); + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + bookmarks_array[i].init(); + } + ListView_SetItemCountEx(hwndBookmarksList, TOTAL_BOOKMARKS, LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL); + + // create font + hBookmarksFont = CreateFont(13, 8, /*Height,Width*/ + 0, 0, /*escapement,orientation*/ + FW_REGULAR, FALSE, FALSE, FALSE, /*weight, italic, underline, strikeout*/ + ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_MASK, /*charset, precision, clipping*/ + DEFAULT_QUALITY, DEFAULT_PITCH, /*quality, and pitch*/ + "Courier"); /*font name*/ + + check_flash_shedule = clock() + BOOKMARKS_FLASH_TICK; + RedrawBookmarksList(); +} +void BOOKMARKS::free() +{ + bookmarks_array.resize(0); + +} + +void BOOKMARKS::update() +{ + // once per 50 milliseconds fade bookmark flashes + if (clock() > check_flash_shedule) + { + check_flash_shedule = clock() + BOOKMARKS_FLASH_TICK; + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + if (bookmarks_array[i].flash_phase) + { + bookmarks_array[i].flash_phase--; + RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS); + } + } + } +} + +void BOOKMARKS::set(int slot) +{ + if (slot < 0 || slot >= TOTAL_BOOKMARKS) return; + int previous_frame = bookmarks_array[slot].snapshot.jump_frame; + bookmarks_array[slot].set(); + if (previous_frame >= 0 && previous_frame != currFrameCounter) + RedrawRow(previous_frame); + RedrawRow(currFrameCounter); + + RedrawBookmarksRow((slot + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS); + +} + +void BOOKMARKS::jump(int slot) +{ + if (slot < 0 || slot >= TOTAL_BOOKMARKS) return; + if (bookmarks_array[slot].not_empty) + { + int frame = bookmarks_array[slot].snapshot.jump_frame; + playback.jump(frame); + if (playback.pauseframe) + FollowPauseframe(); + else + FollowPlayback(); + bookmarks_array[slot].jump(); + } +} + +void BOOKMARKS::unleash(int slot) +{ + if (movie_readonly) + { + jump(slot); + return; + } + if (slot < 0 || slot >= TOTAL_BOOKMARKS) return; + if (!bookmarks_array[slot].not_empty) return; + int jump_frame = bookmarks_array[slot].snapshot.jump_frame; + + // revert movie to the input_snapshot state + if (TASEdit_branch_full_movie) + { + // update Markers + bool markers_changed = false; + if (TASEdit_bind_markers) + { + if (bookmarks_array[slot].snapshot.checkMarkersDiff()) + { + bookmarks_array[slot].snapshot.toMarkers(); + project.changed = true; + markers_changed = true; + } + } + // update current movie + int first_change = bookmarks_array[slot].snapshot.findFirstChange(currMovieData); + if (first_change >= 0) + { + // restore entire movie + currMovieData.records.resize(bookmarks_array[slot].snapshot.size); + bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change); + UpdateList(); + history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description); + greenzone.Invalidate(first_change); + bookmarks_array[slot].unleash(); + } else if (markers_changed) + { + history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description); + RedrawList(); + bookmarks_array[slot].unleash(); + } else + { + // didn't restore anything + bookmarks_array[slot].jump(); + } + } else + { + // update Markers + bool markers_changed = false; + if (TASEdit_bind_markers) + { + if (bookmarks_array[slot].snapshot.checkMarkersDiff(jump_frame)) + { + bookmarks_array[slot].snapshot.copyToMarkers(jump_frame-1); + project.changed = true; + markers_changed = true; + } + } + // update current movie + int first_change = bookmarks_array[slot].snapshot.findFirstChange(currMovieData, 0, jump_frame); + if (first_change >= 0 && first_change < jump_frame) + { + // restore movie up to and not including bookmarked frame (imitating old TASing method) + if (currMovieData.getNumRecords() <= jump_frame) currMovieData.records.resize(jump_frame+1); // but if old movie is shorter, include last frame as blank frame + bookmarks_array[slot].snapshot.toMovie(currMovieData, first_change, jump_frame-1); + UpdateList(); + history.RegisterBranch(MODTYPE_BRANCH_0 + slot, first_change, bookmarks_array[slot].snapshot.description); + greenzone.Invalidate(first_change); + bookmarks_array[slot].unleash(); + } else if (markers_changed) + { + history.RegisterBranch(MODTYPE_BRANCH_MARKERS_0 + slot, first_change, bookmarks_array[slot].snapshot.description); + RedrawList(); + bookmarks_array[slot].unleash(); + } else + { + // didn't restore anything + bookmarks_array[slot].jump(); + } + } + + // if greenzone reduced so much that we can't jump immediately - substitute target frame greenzone with our savestate + if (greenzone.greenZoneCount <= jump_frame || greenzone.savestates[jump_frame].empty()) + { + // clear old savestates: from current end of greenzone to new end of greenzone + for (int i = greenzone.greenZoneCount; i < jump_frame; ++i) + greenzone.ClearSavestate(i); + // restore savestate for immediate jump + greenzone.savestates[jump_frame] = bookmarks_array[slot].savestate; + // and move greenzone end to this new position + if (greenzone.greenZoneCount <= jump_frame) greenzone.greenZoneCount = jump_frame+1; + } + + // jump to the target (bookmarked frame) + playback.jump(jump_frame); +} + +void BOOKMARKS::save(EMUFILE *os) +{ + // write "BOOKMARKS" string + os->fwrite(bookmarks_save_id, BOOKMARKS_ID_LEN); + // write all 10 bookmarks + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + bookmarks_array[i].save(os); + } +} +// returns true if couldn't load +bool BOOKMARKS::load(EMUFILE *is) +{ + // read "BOOKMARKS" string + char save_id[BOOKMARKS_ID_LEN]; + if ((int)is->fread(save_id, BOOKMARKS_ID_LEN) < BOOKMARKS_ID_LEN) return true; + if (strcmp(bookmarks_save_id, save_id)) return true; // string is not valid + // read all 10 bookmarks + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + if (bookmarks_array[i].load(is)) return true; + } + // all ok + check_flash_shedule = clock() + BOOKMARKS_FLASH_TICK; + return false; +} +// ---------------------------------------------------------- +void BOOKMARKS::RedrawBookmarksCaption() +{ + SetWindowText(hwndBookmarks, bookmarksCaption[(movie_readonly)?0:1]); + RedrawBookmarksList(); +} +void BOOKMARKS::RedrawBookmarksList() +{ + InvalidateRect(hwndBookmarksList, 0, FALSE); +} +void BOOKMARKS::RedrawChangedBookmarks(int frame) +{ + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + if (bookmarks_array[i].snapshot.jump_frame == frame) + RedrawBookmarksRow((i + TOTAL_BOOKMARKS - 1) % TOTAL_BOOKMARKS); + } +} +void BOOKMARKS::RedrawBookmarksRow(int index) +{ + ListView_RedrawItems(hwndBookmarksList, index, index); +} + +void BOOKMARKS::GetDispInfo(NMLVDISPINFO* nmlvDispInfo) +{ + LVITEM& item = nmlvDispInfo->item; + if(item.mask & LVIF_TEXT) + { + switch(item.iSubItem) + { + case BOOKMARKS_COLUMN_ICON: + { + item.iImage = (item.iItem + 1) % TOTAL_BOOKMARKS; + break; + } + case BOOKMARKS_COLUMN_FRAME: + { + if (bookmarks_array[(item.iItem + 1) % TOTAL_BOOKMARKS].not_empty) + U32ToDecStr(item.pszText, bookmarks_array[(item.iItem + 1) % TOTAL_BOOKMARKS].snapshot.jump_frame, DIGITS_IN_FRAMENUM); + break; + } + case BOOKMARKS_COLUMN_TIME: + { + if (bookmarks_array[(item.iItem + 1) % TOTAL_BOOKMARKS].not_empty) + strcpy(item.pszText, bookmarks_array[(item.iItem + 1) % TOTAL_BOOKMARKS].snapshot.description); + } + break; + } + } +} + +LONG BOOKMARKS::CustomDraw(NMLVCUSTOMDRAW* msg) +{ + int cell_x, cell_y; + switch(msg->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: + return CDRF_NOTIFYITEMDRAW; + case CDDS_ITEMPREPAINT: + return CDRF_NOTIFYSUBITEMDRAW; + case CDDS_SUBITEMPREPAINT: + cell_x = msg->iSubItem; + cell_y = (msg->nmcd.dwItemSpec + 1) % TOTAL_BOOKMARKS; + + // flash with text color when needed + if (bookmarks_array[cell_y].flash_phase) + msg->clrText = bookmark_flash_colors[bookmarks_array[cell_y].flash_type][bookmarks_array[cell_y].flash_phase]; + + if (cell_x == BOOKMARKS_COLUMN_FRAME || (movie_readonly && cell_x == BOOKMARKS_COLUMN_TIME)) + { + if (bookmarks_array[cell_y].not_empty) + { + // frame number + SelectObject(msg->nmcd.hdc, hBookmarksFont); + int frame = bookmarks_array[cell_y].snapshot.jump_frame; + if (frame == currFrameCounter || frame == playback.GetPauseFrame()) + { + // current frame + msg->clrTextBk = CUR_FRAMENUM_COLOR; + } else if (frame < greenzone.greenZoneCount) + { + if (!greenzone.savestates[frame].empty()) + { + if (TASEdit_show_lag_frames && greenzone.lag_history[frame]) + msg->clrTextBk = LAG_FRAMENUM_COLOR; + else + msg->clrTextBk = GREENZONE_FRAMENUM_COLOR; + } else if ((!greenzone.savestates[frame & EVERY16TH].empty() && (int)greenzone.savestates.size() > (frame | 0xF) + 1 && !greenzone.savestates[(frame | 0xF) + 1].empty()) + || (!greenzone.savestates[frame & EVERY8TH].empty() && (int)greenzone.savestates.size() > (frame | 0x7) + 1 && !greenzone.savestates[(frame | 0x7) + 1].empty()) + || (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty()) + || (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty())) + { + if (TASEdit_show_lag_frames && greenzone.lag_history[frame]) + msg->clrTextBk = PALE_LAG_FRAMENUM_COLOR; + else + msg->clrTextBk = PALE_GREENZONE_FRAMENUM_COLOR; + } else msg->clrTextBk = NORMAL_FRAMENUM_COLOR; + } else msg->clrTextBk = NORMAL_FRAMENUM_COLOR; + } else msg->clrTextBk = 0xFFFFFF; // empty bookmark + } else if (cell_x == BOOKMARKS_COLUMN_TIME) + { + if (bookmarks_array[cell_y].not_empty) + { + // frame number + SelectObject(msg->nmcd.hdc, hBookmarksFont); + int frame = bookmarks_array[cell_y].snapshot.jump_frame; + if (frame == currFrameCounter || frame == playback.GetPauseFrame()) + { + // current frame + msg->clrTextBk = CUR_INPUT_COLOR1; + } else if (frame < greenzone.greenZoneCount) + { + if (!greenzone.savestates[frame].empty()) + { + if (TASEdit_show_lag_frames && greenzone.lag_history[frame]) + msg->clrTextBk = LAG_INPUT_COLOR1; + else + msg->clrTextBk = GREENZONE_INPUT_COLOR1; + } else if ((!greenzone.savestates[frame & EVERY16TH].empty() && (int)greenzone.savestates.size() > (frame | 0xF) + 1 && !greenzone.savestates[(frame | 0xF) + 1].empty()) + || (!greenzone.savestates[frame & EVERY8TH].empty() && (int)greenzone.savestates.size() > (frame | 0x7) + 1 && !greenzone.savestates[(frame | 0x7) + 1].empty()) + || (!greenzone.savestates[frame & EVERY4TH].empty() && (int)greenzone.savestates.size() > (frame | 0x3) + 1 && !greenzone.savestates[(frame | 0x3) + 1].empty()) + || (!greenzone.savestates[frame & EVERY2ND].empty() && !greenzone.savestates[(frame | 0x1) + 1].empty())) + { + if (TASEdit_show_lag_frames && greenzone.lag_history[frame]) + msg->clrTextBk = PALE_LAG_INPUT_COLOR1; + else + msg->clrTextBk = PALE_GREENZONE_INPUT_COLOR1; + } else msg->clrTextBk = NORMAL_INPUT_COLOR1; + } else msg->clrTextBk = NORMAL_INPUT_COLOR1; + } else msg->clrTextBk = 0xFFFFFF; // empty bookmark + } + default: + return CDRF_DODEFAULT; + } +} + +void BOOKMARKS::LeftClick(LPNMITEMACTIVATE info) +{ + int cell_x = info->iSubItem; + int cell_y = info->iItem; + if (cell_y >= 0 && cell_x >= 0) + { + if (cell_x <= BOOKMARKS_COLUMN_FRAME || movie_readonly) + jump((cell_y + 1) % TOTAL_BOOKMARKS); + else if (cell_x == BOOKMARKS_COLUMN_TIME && !movie_readonly) + unleash((cell_y + 1) % TOTAL_BOOKMARKS); + //RedrawBookmarksList(); + } + // remove selection + ListView_SetItemState(hwndBookmarksList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED); +} +void BOOKMARKS::RightClick(LPNMITEMACTIVATE info) +{ + int cell_y = info->iItem; + if (cell_y >= 0) + set((cell_y + 1) % TOTAL_BOOKMARKS); + // remove selection + ListView_SetItemState(hwndBookmarksList, -1, 0, LVIS_FOCUSED|LVIS_SELECTED); +} + +int BOOKMARKS::FindBookmarkAtFrame(int frame) +{ + for (int i = 0; i < TOTAL_BOOKMARKS; ++i) + { + if (bookmarks_array[i].snapshot.jump_frame == frame) return i; + } + return -1; +} + + diff --git a/src/drivers/win/taseditlib/bookmarks.h b/src/drivers/win/taseditlib/bookmarks.h new file mode 100644 index 00000000..5d5bf3c7 --- /dev/null +++ b/src/drivers/win/taseditlib/bookmarks.h @@ -0,0 +1,49 @@ +//Specification file for Bookmarks class + +#include "bookmark.h" + +#define TOTAL_BOOKMARKS 10 + +#define BOOKMARKS_FLASH_TICK 50 // in milliseconds + +// listview columns +#define BOOKMARKS_COLUMN_ICON 0 +#define BOOKMARKS_COLUMN_FRAME 1 +#define BOOKMARKS_COLUMN_TIME 2 + +#define BOOKMARKS_ID_LEN 10 + +class BOOKMARKS +{ +public: + BOOKMARKS(); + void init(); + void free(); + void update(); + + void save(EMUFILE *os); + bool load(EMUFILE *is); + + void set(int slot); + void jump(int slot); + void unleash(int slot); + + void GetDispInfo(NMLVDISPINFO* nmlvDispInfo); + LONG CustomDraw(NMLVCUSTOMDRAW* msg); + void LeftClick(LPNMITEMACTIVATE info); + void RightClick(LPNMITEMACTIVATE info); + + int FindBookmarkAtFrame(int frame); + + void RedrawBookmarksCaption(); + void RedrawBookmarksList(); + void RedrawChangedBookmarks(int frame); + void RedrawBookmarksRow(int index); + + std::vector bookmarks_array; + +private: + HFONT hBookmarksFont; + int check_flash_shedule; + +}; diff --git a/src/drivers/win/taseditlib/greenzone.cpp b/src/drivers/win/taseditlib/greenzone.cpp index 67ae72bb..7f7ec6d2 100644 --- a/src/drivers/win/taseditlib/greenzone.cpp +++ b/src/drivers/win/taseditlib/greenzone.cpp @@ -91,7 +91,8 @@ void GREENZONE::storeTasSavestate(int frame) void GREENZONE::GreenzoneCleaning() { int i = currFrameCounter - TASEdit_greenzone_capacity; - if (i < 0) goto none_changed; + bool changed = false; + if (i < 0) goto finish; int limit; // 2x of 1/2 limit = i - 2 * TASEdit_greenzone_capacity; @@ -99,7 +100,10 @@ void GREENZONE::GreenzoneCleaning() for (; i > limit; i--) { if ((i & 0x1) && !savestates[i].empty()) + { ClearSavestate(i); + changed = true; + } } if (i < 0) goto finish; // 4x of 1/4 @@ -108,7 +112,10 @@ void GREENZONE::GreenzoneCleaning() for (; i > limit; i--) { if ((i & 0x3) && !savestates[i].empty()) + { ClearSavestate(i); + changed = true; + } } if (i < 0) goto finish; // 8x of 1/8 @@ -117,7 +124,10 @@ void GREENZONE::GreenzoneCleaning() for (; i > limit; i--) { if ((i & 0x7) && !savestates[i].empty()) + { ClearSavestate(i); + changed = true; + } } if (i < 0) goto finish; // 16x of 1/16 @@ -126,17 +136,22 @@ void GREENZONE::GreenzoneCleaning() for (; i > limit; i--) { if ((i & 0xF) && !savestates[i].empty()) + { ClearSavestate(i); + changed = true; + } } // clear all remaining for (; i >= 0; i--) { if (!savestates[i].empty()) + { ClearSavestate(i); + changed = true; + } } finish: - RedrawList(); -none_changed: + if (changed) RedrawList(); // shedule next cleaning next_cleaning_time = clock() + TIME_BETWEEN_CLEANINGS; } @@ -298,7 +313,8 @@ error: return true; } -void GREENZONE::InvalidateGreenZone(int after) +// invalidate and restore playback +void GREENZONE::InvalidateAndCheck(int after) { if (after >= 0) { @@ -320,6 +336,21 @@ void GREENZONE::InvalidateGreenZone(int after) // redraw list even if greenzone didn't change RedrawList(); } +// This version doesn't restore playback, may be used only by Branching functions! +void GREENZONE::Invalidate(int after) +{ + if (after >= 0) + { + project.changed = true; + if (greenZoneCount > after+1) + { + greenZoneCount = after+1; + currMovieData.rerecordCount++; + } + } + // redraw list even if greenzone didn't change + RedrawList(); +} int GREENZONE::FindBeginningOfGreenZone(int starting_index) { diff --git a/src/drivers/win/taseditlib/greenzone.h b/src/drivers/win/taseditlib/greenzone.h index 5c6727f6..d2eb0bf6 100644 --- a/src/drivers/win/taseditlib/greenzone.h +++ b/src/drivers/win/taseditlib/greenzone.h @@ -25,7 +25,8 @@ public: void GreenzoneCleaning(); void ClearSavestate(int index); - void InvalidateGreenZone(int after); + void InvalidateAndCheck(int after); + void Invalidate(int after); int FindBeginningOfGreenZone(int starting_index = 0); diff --git a/src/drivers/win/taseditlib/inputhistory.cpp b/src/drivers/win/taseditlib/inputhistory.cpp index 55ca34cb..31df056d 100644 --- a/src/drivers/win/taseditlib/inputhistory.cpp +++ b/src/drivers/win/taseditlib/inputhistory.cpp @@ -13,34 +13,45 @@ extern bool TASEdit_bind_markers; extern PLAYBACK playback; extern GREENZONE greenzone; extern TASEDIT_PROJECT project; +extern MARKERS markers; char history_save_id[HISTORY_ID_LEN] = "HISTORY"; -char modCaptions[26][12] = {"Init", - "Change", - "Set", - "Unset", - "Insert", - "Delete", - "Truncate", - "Clear", - "Cut", - "Paste", - "PasteInsert", - "Clone", - "Record", - "Import", - "Branch0", - "Branch1", - "Branch2", - "Branch3", - "Branch4", - "Branch5", - "Branch6", - "Branch7", - "Branch8", - "Branch9", - "Mark Set", - "Mark Unset"}; +char modCaptions[36][20] = {" Init", + " Change", + " Set", + " Unset", + " Insert", + " Delete", + " Truncate", + " Clear", + " Cut", + " Paste", + " PasteInsert", + " Clone", + " Record", + " Import", + " Branch0 to ", + " Branch1 to ", + " Branch2 to ", + " Branch3 to ", + " Branch4 to ", + " Branch5 to ", + " Branch6 to ", + " Branch7 to ", + " Branch8 to ", + " Branch9 to ", + " Marker Branch0 to ", + " Marker Branch1 to ", + " Marker Branch2 to ", + " Marker Branch3 to ", + " Marker Branch4 to ", + " Marker Branch5 to ", + " Marker Branch6 to ", + " Marker Branch7 to ", + " Marker Branch8 to ", + " Marker Branch9 to ", + " Marker Set", + " Marker Unset"}; char joypadCaptions[4][5] = {"(1P)", "(2P)", "(3P)", "(4P)"}; INPUT_HISTORY::INPUT_HISTORY() @@ -62,7 +73,7 @@ void INPUT_HISTORY::init(int new_size) history_cursor_pos = -1; // create initial snapshot INPUT_SNAPSHOT inp; - inp.init(currMovieData); + inp.init(currMovieData, true); strcat(inp.description, modCaptions[0]); inp.jump_frame = -1; AddInputSnapshotToHistory(inp); @@ -117,21 +128,28 @@ int INPUT_HISTORY::jump(int new_pos) show_undo_hint = true; // update markers + bool markers_changed = false; if (TASEdit_bind_markers) { if (input_snapshots[real_pos].checkMarkersDiff()) { input_snapshots[real_pos].toMarkers(); project.changed = true; + markers_changed = true; } } // update current movie int first_change = input_snapshots[real_pos].findFirstChange(currMovieData); if (first_change >= 0) + { + currMovieData.records.resize(input_snapshots[real_pos].size); input_snapshots[real_pos].toMovie(currMovieData, first_change); - else + } else if (markers_changed) + { + markers.update(); RedrawList(); + } return first_change; } @@ -183,16 +201,17 @@ void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp) RedrawHistoryList(); } + // returns frame of first actual change int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) { // create new input shanshot INPUT_SNAPSHOT inp; - inp.init(currMovieData); + inp.init(currMovieData, true); if (mod_type == MODTYPE_MARKER_SET || mod_type == MODTYPE_MARKER_UNSET) { // special case: changed markers, but input didn't change - // fill description + // fill description: strcat(inp.description, modCaptions[mod_type]); inp.jump_frame = start; // add the frame to description @@ -210,6 +229,7 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) return -1; } else { + // all other types of modification: // check if there are input differences from latest snapshot int real_pos = (history_start_pos + history_cursor_pos) % history_size; int first_changes = inp.findFirstChange(input_snapshots[real_pos], start, end); @@ -220,7 +240,7 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) // highlight new hot changes - // fill description + // fill description: strcat(inp.description, modCaptions[mod_type]); switch (mod_type) { @@ -231,11 +251,6 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) case MODTYPE_CLEAR: case MODTYPE_CUT: case MODTYPE_IMPORT: - case MODTYPE_BRANCH_0: case MODTYPE_BRANCH_1: - case MODTYPE_BRANCH_2: case MODTYPE_BRANCH_3: - case MODTYPE_BRANCH_4: case MODTYPE_BRANCH_5: - case MODTYPE_BRANCH_6: case MODTYPE_BRANCH_7: - case MODTYPE_BRANCH_8: case MODTYPE_BRANCH_9: { inp.jump_frame = first_changes; break; @@ -278,6 +293,17 @@ int INPUT_HISTORY::RegisterChanges(int mod_type, int start, int end) return first_changes; } } +void INPUT_HISTORY::RegisterBranch(int mod_type, int first_change, char* branch_creation_time) +{ + // create new input shanshot + INPUT_SNAPSHOT inp; + inp.init(currMovieData, true); + // fill description: + strcat(inp.description, modCaptions[mod_type]); + strcat(inp.description, branch_creation_time); + inp.jump_frame = first_change; + AddInputSnapshotToHistory(inp); +} void INPUT_HISTORY::save(EMUFILE *os) { @@ -326,7 +352,7 @@ bool INPUT_HISTORY::load(EMUFILE *is) num_snapshots_to_skip -= num_redo_snapshots; // and still need to skip some undo snapshots for (i = 0; i < num_snapshots_to_skip; ++i) - if (!inp.skipLoad(is)) goto error; + if (inp.skipLoad(is)) goto error; total -= num_snapshots_to_skip; history_cursor_pos -= num_snapshots_to_skip; } @@ -336,12 +362,12 @@ bool INPUT_HISTORY::load(EMUFILE *is) for (i = 0; i < history_total_items; ++i) { // skip snapshots if current history_size is less then history_total_items - if (!input_snapshots[i].load(is)) goto error; + if (input_snapshots[i].load(is)) goto error; playback.SetProgressbar(i, history_total_items); } // skip redo snapshots if needed for (; i < total; ++i) - if (!inp.skipLoad(is)) goto error; + if (inp.skipLoad(is)) goto error; // init vars undo_hint_pos = old_undo_hint_pos = undo_hint_time = -1; @@ -374,7 +400,6 @@ LONG INPUT_HISTORY::CustomDraw(NMLVCUSTOMDRAW* msg) msg->clrTextBk = HISTORY_COHERENT_COLOR; else msg->clrTextBk = HISTORY_NORMAL_COLOR; - return CDRF_DODEFAULT; } default: return CDRF_DODEFAULT; @@ -393,7 +418,7 @@ void INPUT_HISTORY::Click(LPNMITEMACTIVATE info) { UpdateList(); FollowUndo(); - greenzone.InvalidateGreenZone(result); + greenzone.InvalidateAndCheck(result); return; } } diff --git a/src/drivers/win/taseditlib/inputhistory.h b/src/drivers/win/taseditlib/inputhistory.h index 49350366..3531b6d2 100644 --- a/src/drivers/win/taseditlib/inputhistory.h +++ b/src/drivers/win/taseditlib/inputhistory.h @@ -26,8 +26,18 @@ #define MODTYPE_BRANCH_7 21 #define MODTYPE_BRANCH_8 22 #define MODTYPE_BRANCH_9 23 -#define MODTYPE_MARKER_SET 24 -#define MODTYPE_MARKER_UNSET 25 +#define MODTYPE_BRANCH_MARKERS_0 24 +#define MODTYPE_BRANCH_MARKERS_1 25 +#define MODTYPE_BRANCH_MARKERS_2 26 +#define MODTYPE_BRANCH_MARKERS_3 27 +#define MODTYPE_BRANCH_MARKERS_4 28 +#define MODTYPE_BRANCH_MARKERS_5 29 +#define MODTYPE_BRANCH_MARKERS_6 30 +#define MODTYPE_BRANCH_MARKERS_7 31 +#define MODTYPE_BRANCH_MARKERS_8 32 +#define MODTYPE_BRANCH_MARKERS_9 33 +#define MODTYPE_MARKER_SET 34 +#define MODTYPE_MARKER_UNSET 35 #define HISTORY_COHERENT_COLOR 0xF9DDE6 #define HISTORY_NORMAL_COLOR 0xFFFFFF @@ -53,6 +63,7 @@ public: void AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp); int RegisterChanges(int mod_type, int start = 0, int end =-1); + void RegisterBranch(int mod_type, int first_change, char* branch_creation_time); int InputChanged(int start, int end); int InputInserted(int start); diff --git a/src/drivers/win/taseditlib/inputsnapshot.cpp b/src/drivers/win/taseditlib/inputsnapshot.cpp index be06cd40..fcdf86d2 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.cpp +++ b/src/drivers/win/taseditlib/inputsnapshot.cpp @@ -16,14 +16,17 @@ INPUT_SNAPSHOT::INPUT_SNAPSHOT() } -void INPUT_SNAPSHOT::init(MovieData& md) +void INPUT_SNAPSHOT::init(MovieData& md, bool hotchanges) { + has_hot_changes = hotchanges; already_compressed = false; // retrieve input data from movie data size = md.getNumRecords(); input_type = (md.fourscore)?1:0; joysticks.resize(bytes_per_frame[input_type] * size); // it's much faster to have this format than have [frame][joy] or other structures - hot_changes.resize(bytes_per_frame[input_type] * size * HOTCHANGE_BYTES_PER_JOY); + commands.resize(size); + if (has_hot_changes) + hot_changes.resize(bytes_per_frame[input_type] * size * HOTCHANGE_BYTES_PER_JOY); // fill input vector int pos = 0; switch(input_type) @@ -36,6 +39,7 @@ void INPUT_SNAPSHOT::init(MovieData& md) joysticks[pos++] = md.records[frame].joysticks[1]; joysticks[pos++] = md.records[frame].joysticks[2]; joysticks[pos++] = md.records[frame].joysticks[3]; + commands[frame] = md.records[frame].commands; } break; } @@ -45,6 +49,7 @@ void INPUT_SNAPSHOT::init(MovieData& md) { joysticks[pos++] = md.records[frame].joysticks[0]; joysticks[pos++] = md.records[frame].joysticks[1]; + commands[frame] = md.records[frame].commands; } break; } @@ -57,39 +62,49 @@ void INPUT_SNAPSHOT::init(MovieData& md) time_t raw_time; time(&raw_time); struct tm * timeinfo = localtime(&raw_time); - strftime(description, 10, "%H:%M:%S ", timeinfo); + strftime(description, 10, "%H:%M:%S", timeinfo); } - +// copy all stored markers to Markers void INPUT_SNAPSHOT::toMarkers() { markers.markers_array = markers_array; } - -void INPUT_SNAPSHOT::toMovie(MovieData& md, int start) +// copy some stored markers to Markers manually, from Frame 0 to end frame (including end frame) +void INPUT_SNAPSHOT::copyToMarkers(int end) { + if (markers.markers_array.size() <= end) markers.markers_array.resize(end+1); + for (int i = end; i >= 0; i--) + markers.markers_array[i] = markers_array[i]; +} + + +void INPUT_SNAPSHOT::toMovie(MovieData& md, int start, int end) +{ + if (end < 0) end = size-1; // write input data to movie data - md.records.resize(size); switch(input_type) { case FOURSCORE: { int pos = start * bytes_per_frame[input_type]; - for (int frame = start; frame < size; ++frame) + for (int frame = start; frame <= end; ++frame) { md.records[frame].joysticks[0] = joysticks[pos++]; md.records[frame].joysticks[1] = joysticks[pos++]; md.records[frame].joysticks[2] = joysticks[pos++]; md.records[frame].joysticks[3] = joysticks[pos++]; + md.records[frame].commands = commands[frame]; } break; } case NORMAL_2JOYPADS: { int pos = start * bytes_per_frame[input_type]; - for (int frame = start; frame < size; ++frame) + for (int frame = start; frame <= end; ++frame) { md.records[frame].joysticks[0] = joysticks[pos++]; md.records[frame].joysticks[1] = joysticks[pos++]; + md.records[frame].commands = commands[frame]; } break; } @@ -104,12 +119,21 @@ void INPUT_SNAPSHOT::compress_data() joysticks_compressed.resize(comprlen); compress(&joysticks_compressed[0], &comprlen, &joysticks[0], len); joysticks_compressed.resize(comprlen); - // compress hot_changes - len = hot_changes.size(); + // compress commands + len = commands.size(); comprlen = (len>>9)+12 + len; - hot_changes_compressed.resize(comprlen); - compress(&hot_changes_compressed[0], &comprlen, &hot_changes[0], len); - hot_changes_compressed.resize(comprlen); + commands_compressed.resize(comprlen); + compress(&commands_compressed[0], &comprlen, &commands[0], len); + commands_compressed.resize(comprlen); + if (has_hot_changes) + { + // compress hot_changes + len = hot_changes.size(); + comprlen = (len>>9)+12 + len; + hot_changes_compressed.resize(comprlen); + compress(&hot_changes_compressed[0], &comprlen, &hot_changes[0], len); + hot_changes_compressed.resize(comprlen); + } // compress markers len = markers_array.size(); comprlen = (len>>9)+12 + len; @@ -127,6 +151,7 @@ void INPUT_SNAPSHOT::save(EMUFILE *os) write8le(input_type, os); if (coherent) write8le(1, os); else write8le((uint8)0, os); write32le(jump_frame, os); + if (has_hot_changes) write8le((uint8)1, os); else write8le((uint8)0, os); // write description int len = strlen(description); write8le(len, os); @@ -137,28 +162,37 @@ void INPUT_SNAPSHOT::save(EMUFILE *os) // save joysticks data write32le(joysticks_compressed.size(), os); os->fwrite(&joysticks_compressed[0], joysticks_compressed.size()); - // save hot_changes data - write32le(hot_changes_compressed.size(), os); - os->fwrite(&hot_changes_compressed[0], hot_changes_compressed.size()); + // save commands data + write32le(commands_compressed.size(), os); + os->fwrite(&commands_compressed[0], commands_compressed.size()); + if (has_hot_changes) + { + // save hot_changes data + write32le(hot_changes_compressed.size(), os); + os->fwrite(&hot_changes_compressed[0], hot_changes_compressed.size()); + } // save markers data write32le(markers_array_compressed.size(), os); os->fwrite(&markers_array_compressed[0], markers_array_compressed.size()); } +// returns true if couldn't load bool INPUT_SNAPSHOT::load(EMUFILE *is) { int len; uint8 tmp; // read vars - if (!read32le(&size, is)) return false; - if (!read8le(&tmp, is)) return false; + if (!read32le(&size, is)) return true; + if (!read8le(&tmp, is)) return true; input_type = tmp; - if (!read8le(&tmp, is)) return false; + if (!read8le(&tmp, is)) return true; coherent = (tmp != 0); - if (!read32le(&jump_frame, is)) return false; + if (!read32le(&jump_frame, is)) return true; + if (!read8le(&tmp, is)) return true; + has_hot_changes = (tmp != 0); // read description - if (!read8le(&tmp, is)) return false; - if (tmp < 0 || tmp >= SNAPSHOT_DESC_MAX_LENGTH) return false; - if (is->fread(&description[0], tmp) != tmp) return false; + if (!read8le(&tmp, is)) return true; + if (tmp < 0 || 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 // read data already_compressed = true; @@ -168,55 +202,77 @@ bool INPUT_SNAPSHOT::load(EMUFILE *is) destlen = size * bytes_per_frame[input_type]; joysticks.resize(destlen); // read size - if (!read32le(&comprlen, is)) return false; - if (comprlen <= 0) return false; + if (!read32le(&comprlen, is)) return true; + if (comprlen <= 0) return true; joysticks_compressed.resize(comprlen); - if (is->fread(&joysticks_compressed[0], comprlen) != comprlen) return false; + if (is->fread(&joysticks_compressed[0], comprlen) != comprlen) return true; int e = uncompress(&joysticks[0], &destlen, &joysticks_compressed[0], comprlen); - if (e != Z_OK && e != Z_BUF_ERROR) return false; - // read and uncompress hot_changes data - destlen = size * bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; - hot_changes.resize(destlen); + if (e != Z_OK && e != Z_BUF_ERROR) return true; + // read and uncompress commands data + destlen = size; + commands.resize(destlen); // read size - if (!read32le(&comprlen, is)) return false; - if (comprlen <= 0) return false; - hot_changes_compressed.resize(comprlen); - if (is->fread(&hot_changes_compressed[0], comprlen) != comprlen) return false; - e = uncompress(&hot_changes[0], &destlen, &hot_changes_compressed[0], comprlen); - if (e != Z_OK && e != Z_BUF_ERROR) return false; + if (!read32le(&comprlen, is)) return true; + if (comprlen <= 0) return true; + commands_compressed.resize(comprlen); + if (is->fread(&commands_compressed[0], comprlen) != comprlen) return true; + e = uncompress(&commands[0], &destlen, &commands_compressed[0], comprlen); + if (e != Z_OK && e != Z_BUF_ERROR) return true; + if (has_hot_changes) + { + // read and uncompress hot_changes data + destlen = size * bytes_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; + hot_changes.resize(destlen); + // read size + if (!read32le(&comprlen, is)) return true; + if (comprlen <= 0) return true; + hot_changes_compressed.resize(comprlen); + if (is->fread(&hot_changes_compressed[0], comprlen) != comprlen) return true; + e = uncompress(&hot_changes[0], &destlen, &hot_changes_compressed[0], comprlen); + if (e != Z_OK && e != Z_BUF_ERROR) return true; + } // read and uncompress markers data destlen = size; markers_array.resize(destlen); // read size - if (!read32le(&comprlen, is)) return false; - if (comprlen <= 0) return false; + if (!read32le(&comprlen, is)) return true; + if (comprlen <= 0) return true; markers_array_compressed.resize(comprlen); - if (is->fread(&markers_array_compressed[0], comprlen) != comprlen) return false; + if (is->fread(&markers_array_compressed[0], comprlen) != comprlen) return true; e = uncompress(&markers_array[0], &destlen, &markers_array_compressed[0], comprlen); - if (e != Z_OK && e != Z_BUF_ERROR) return false; - - return true; + if (e != Z_OK && e != Z_BUF_ERROR) return true; + return false; } bool INPUT_SNAPSHOT::skipLoad(EMUFILE *is) { int tmp; uint8 tmp1; // read vars - if (!read32le(&tmp, is)) return false; - if (!read8le(&tmp1, is)) return false; - if (!read8le(&tmp1, is)) return false; - if (!read32le(&tmp, is)) return false; + if (!read32le(&tmp, is)) return true; + if (!read8le(&tmp1, is)) return true; + if (!read8le(&tmp1, is)) return true; + if (!read32le(&tmp, is)) return true; + if (!read8le(&tmp1, is)) return true; // read description - if (!read8le(&tmp1, is)) return false; - if (tmp1 < 0 || tmp1 >= SNAPSHOT_DESC_MAX_LENGTH) return false; - if (is->fseek(tmp1, SEEK_CUR) != 0) return false; + if (!read8le(&tmp1, is)) return true; + if (tmp1 < 0 || tmp1 >= SNAPSHOT_DESC_MAX_LENGTH) return true; + if (is->fseek(tmp1, SEEK_CUR) != 0) return true; // read joysticks data - if (!read32le(&tmp, is)) return false; - if (is->fseek(tmp, SEEK_CUR) != 0) return false; - // read hot_changes data - if (!read32le(&tmp, is)) return false; - if (is->fseek(tmp, SEEK_CUR) != 0) return false; - return true; + if (!read32le(&tmp, is)) return true; + if (is->fseek(tmp, SEEK_CUR) != 0) return true; + // read commands data + if (!read32le(&tmp, is)) return true; + if (is->fseek(tmp, SEEK_CUR) != 0) return true; + if (has_hot_changes) + { + // read hot_changes data + if (!read32le(&tmp, is)) return true; + if (is->fseek(tmp, SEEK_CUR) != 0) return true; + } + // read markers data + if (!read32le(&tmp, is)) return true; + if (is->fseek(tmp, SEEK_CUR) != 0) return true; + return false; } // return true if any difference is found @@ -229,7 +285,7 @@ bool INPUT_SNAPSHOT::checkDiff(INPUT_SNAPSHOT& inp) return false; } -// return true if joypads differ +// return true if joypads differ (this function is only used by "Record" modtype) bool INPUT_SNAPSHOT::checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy) { switch(input_type) @@ -251,7 +307,7 @@ bool INPUT_SNAPSHOT::checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy) return false; } -// return true if any difference in markers_array is found +// return true if any difference in markers_array is found, comparing two snapshots bool INPUT_SNAPSHOT::checkMarkersDiff(INPUT_SNAPSHOT& inp) { if (size != inp.size) return true; @@ -267,64 +323,106 @@ bool INPUT_SNAPSHOT::checkMarkersDiff() if ((markers_array[i] - markers.markers_array[i]) & MARKER_FLAG_BIT) return true; return false; } +// return true only when difference is found before end frame (not including end frame) +bool INPUT_SNAPSHOT::checkMarkersDiff(int end) +{ + if (markers_array.size() != markers.markers_array.size() && (markers_array.size()-1 < end || markers.markers_array.size()-1 < end)) return true; + for (int i = end-1; i >= 0; i--) + if ((markers_array[i] - markers.markers_array[i]) & MARKER_FLAG_BIT) return true; + return false; +} -// return number of first frame of difference +// return number of first frame of difference between two snapshots int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end) { - // search for differences to the specified end (or to size) + // search for differences to the specified end (or to the end of this snapshot) if (end < 0 || end >= size) end = size-1; + int inp_end = inp.size; switch(input_type) { case FOURSCORE: - case NORMAL_2JOYPADS: { - int inp_end = inp.size * bytes_per_frame[input_type]; - end = ((end + 1) * bytes_per_frame[input_type]) - 1; - for (int pos = start * bytes_per_frame[input_type]; pos <= end; ++pos) + for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame) { - // if found different byte, or found emptiness in inp when there's non-zero value here - if (pos < inp_end) + // return the frame if found different byte, or found emptiness in inp when there's non-zero value here + if (frame < inp_end) { - if (joysticks[pos] != inp.joysticks[pos]) return (pos / bytes_per_frame[input_type]); + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (commands[frame] != inp.commands[frame]) return frame; } else { - if (joysticks[pos]) return (pos / bytes_per_frame[input_type]); + if (joysticks[pos++]) return frame; + if (joysticks[pos++]) return frame; + if (joysticks[pos++]) return frame; + if (joysticks[pos++]) return frame; + if (commands[frame]) return frame; + } + } + break; + } + case NORMAL_2JOYPADS: + { + for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame) + { + // return the frame if found different byte, or found emptiness in inp when there's non-zero value here + if (frame < inp_end) + { + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (joysticks[pos] != inp.joysticks[pos]) return frame; + pos++; + if (commands[frame] != inp.commands[frame]) return frame; + } else + { + if (joysticks[pos++]) return frame; + if (joysticks[pos++]) return frame; + if (commands[frame]) return frame; } } break; } } - // if current size is less then previous return size-1 as the frame of difference + // if current size is less then previous, return size-1 as the frame of difference if (size < inp.size) return size-1; // no changes were found return -1; } -int INPUT_SNAPSHOT::findFirstChange(MovieData& md) +// return number of first frame of difference between this input_snapshot and MovieData +int INPUT_SNAPSHOT::findFirstChange(MovieData& md, int start, int end) { - // search for differences from the beginning to the end of movie (or to size) - int end = md.getNumRecords()-1; - if (end >= size) end = size-1; + // search for differences to the specified end (or to the end of this snapshot / to the end of the movie) + if (end < 0 || end >= size) end = size-1; + if (end >= md.getNumRecords()) end = md.getNumRecords()-1; switch(input_type) { case FOURSCORE: { - for (int frame = 0, pos = 0; frame <= end; ++frame) + for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame) { if (joysticks[pos++] != md.records[frame].joysticks[0]) return frame; if (joysticks[pos++] != md.records[frame].joysticks[1]) return frame; if (joysticks[pos++] != md.records[frame].joysticks[2]) return frame; if (joysticks[pos++] != md.records[frame].joysticks[3]) return frame; + if (commands[frame] != md.records[frame].commands) return frame; } break; } case NORMAL_2JOYPADS: { - for (int frame = 0, pos = 0; frame <= end; ++frame) + for (int frame = start, pos = start * bytes_per_frame[input_type]; frame <= end; ++frame) { if (joysticks[pos++] != md.records[frame].joysticks[0]) return frame; if (joysticks[pos++] != md.records[frame].joysticks[1]) return frame; + if (commands[frame] != md.records[frame].commands) return frame; } break; } @@ -337,7 +435,7 @@ int INPUT_SNAPSHOT::findFirstChange(MovieData& md) void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button) { - if (frame < 0 || frame >= size) return; + if (frame < 0 || frame >= size || !has_hot_changes) return; // set max value (15) to the button hotness switch(input_type) { @@ -367,7 +465,7 @@ void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button) } int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button) { - if (frame < 0 || frame >= size) return 0; + if (frame < 0 || frame >= size || !has_hot_changes) return 0; if (absolute_button < 0 || absolute_button > 31) return 0; uint8 val; @@ -395,3 +493,4 @@ int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button) return val & 15; } + diff --git a/src/drivers/win/taseditlib/inputsnapshot.h b/src/drivers/win/taseditlib/inputsnapshot.h index 237a1e3b..eeff4ae7 100644 --- a/src/drivers/win/taseditlib/inputsnapshot.h +++ b/src/drivers/win/taseditlib/inputsnapshot.h @@ -13,10 +13,11 @@ class INPUT_SNAPSHOT { public: INPUT_SNAPSHOT(); - void init(MovieData& md); + void init(MovieData& md, bool hotchanges); - void toMovie(MovieData& md, int start = 0); + void toMovie(MovieData& md, int start = 0, int end = -1); void toMarkers(); + void copyToMarkers(int end); void save(EMUFILE *os); bool load(EMUFILE *is); @@ -27,9 +28,10 @@ public: bool checkMarkersDiff(INPUT_SNAPSHOT& inp); bool checkMarkersDiff(); + bool checkMarkersDiff(int end); int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1); - int findFirstChange(MovieData& md); + int findFirstChange(MovieData& md, int start = 0, int end = -1); void SetMaxHotChange(int frame, int absolute_button); int GetHotChangeInfo(int frame, int absolute_button); @@ -37,6 +39,7 @@ public: int size; // in frames int input_type; // 0=normal, 1=fourscore, in future may support other input types std::vector joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ... + std::vector commands; // Format: commands-for-frame0, commands-for-frame1, ... std::vector hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ... std::vector markers_array; // just a copy of markers.markers_array @@ -49,8 +52,10 @@ private: bool already_compressed; // to compress only once std::vector joysticks_compressed; + std::vector commands_compressed; std::vector hot_changes_compressed; std::vector markers_array_compressed; + bool has_hot_changes; }; diff --git a/src/drivers/win/taseditlib/markers.cpp b/src/drivers/win/taseditlib/markers.cpp index 325a3d01..6851b7ae 100644 --- a/src/drivers/win/taseditlib/markers.cpp +++ b/src/drivers/win/taseditlib/markers.cpp @@ -25,7 +25,7 @@ void MARKERS::free() void MARKERS::update() { - if (markers_array.size() < currMovieData.getNumRecords()) + if ((int)markers_array.size() < currMovieData.getNumRecords()) markers_array.resize(currMovieData.getNumRecords()); } diff --git a/src/drivers/win/taseditlib/playback.cpp b/src/drivers/win/taseditlib/playback.cpp index 142ed54f..6d0f6859 100644 --- a/src/drivers/win/taseditlib/playback.cpp +++ b/src/drivers/win/taseditlib/playback.cpp @@ -171,7 +171,7 @@ void PLAYBACK::ToggleEmulationPause() void PLAYBACK::PauseEmulation() { FCEUI_SetEmulationPaused(1); - RedrawList(); // to show some "pale" greenzone + //RedrawList(); // to show some "pale" greenzone // make some additional stuff } void PLAYBACK::UnpauseEmulation() @@ -193,19 +193,17 @@ void PLAYBACK::SeekingStop() turbo = false; PauseEmulation(); SetProgressbar(1, 1); - RedrawList(); // to show some "pale" greenzone + //RedrawList(); // to show some "pale" greenzone } void PLAYBACK::RewindFrame() { if (currFrameCounter > 0) jump(currFrameCounter-1); - FollowPlayback(); } void PLAYBACK::ForwardFrame() { jump(currFrameCounter+1); turbo = false; - FollowPlayback(); } void PLAYBACK::RewindFull() { @@ -220,7 +218,6 @@ void PLAYBACK::RewindFull() else if (currFrameCounter > 0) jump(0); } - FollowPlayback(); } void PLAYBACK::ForwardFull() { @@ -236,7 +233,6 @@ void PLAYBACK::ForwardFull() else if (currFrameCounter < last_frame) jump(last_frame); } - FollowPlayback(); } void PLAYBACK::StartFromZero() @@ -249,7 +245,10 @@ void PLAYBACK::StartFromZero() void PLAYBACK::jump(int frame) { if (JumpToFrame(frame)) + { ForceExecuteLuaFrameFunctions(); + FollowPlayback(); + } } void PLAYBACK::restorePosition() { @@ -262,12 +261,12 @@ void PLAYBACK::restorePosition() bool PLAYBACK::JumpToFrame(int index) { // Returns true if a jump to the frame is made, false if started seeking outside greenzone or if nothing's done - if (index<0) return false; + if (index < 0) return false; if (index >= greenzone.greenZoneCount) { // handle jump outside greenzone - if (JumpToFrame(greenzone.greenZoneCount-1)) + if (currFrameCounter == greenzone.greenZoneCount-1 || JumpToFrame(greenzone.greenZoneCount-1)) // seek from the end of greenzone SeekingStart(index+1); return false; @@ -275,7 +274,6 @@ bool PLAYBACK::JumpToFrame(int index) /* Handle jumps inside greenzone. */ if (greenzone.loadTasSavestate(index)) { - currFrameCounter = index; turbo = false; // if playback was seeking, pause emulation right here if (pauseframe) SeekingStop(); diff --git a/src/drivers/win/taseditlib/taseditproj.cpp b/src/drivers/win/taseditlib/taseditproj.cpp index 7137d865..ed5b814c 100644 --- a/src/drivers/win/taseditlib/taseditproj.cpp +++ b/src/drivers/win/taseditlib/taseditproj.cpp @@ -4,6 +4,7 @@ #include "taseditproj.h" extern MARKERS markers; +extern BOOKMARKS bookmarks; extern GREENZONE greenzone; extern PLAYBACK playback; extern INPUT_HISTORY history; @@ -46,6 +47,7 @@ bool TASEDIT_PROJECT::saveProject() currMovieData.dump(ofs, true); markers.save(ofs); + bookmarks.save(ofs); greenzone.save(ofs); history.save(ofs); @@ -77,6 +79,15 @@ bool TASEDIT_PROJECT::LoadProject(std::string PFN) FCEU_printf("Error loading markers\n"); markers.init(); } else + { + // try to load bookmarks + error = bookmarks.load(&ifs); + } + if (error) + { + FCEU_printf("Error loading bookmarks\n"); + bookmarks.init(); + } else { // try to load greenzone error = greenzone.load(&ifs); diff --git a/src/drivers/win/taseditlib/taseditproj.h b/src/drivers/win/taseditlib/taseditproj.h index 7c3e85ed..eff9c796 100644 --- a/src/drivers/win/taseditlib/taseditproj.h +++ b/src/drivers/win/taseditlib/taseditproj.h @@ -6,6 +6,7 @@ #include "playback.h" #include "greenzone.h" #include "markers.h" +#include "bookmarks.h" class TASEDIT_PROJECT { diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 002dbdb5..576a2fa1 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -1810,7 +1810,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) UpdateCheckedMenuItems(); break; case MENU_DISPLAY_LAGCOUNTER: - lagCounterDisplay ^= 1; + LagCounterToggle(); UpdateCheckedMenuItems(); break; case ID_DISPLAY_FRAMECOUNTER: @@ -1818,7 +1818,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) UpdateCheckedMenuItems(); break; case ID_DISPLAY_RERECORDCOUNTER: - rerecord_display ^= 1; + FCEUI_MovieToggleRerecordDisplay(); UpdateCheckedMenuItems(); break; case ID_DISPLAY_MOVIESTATUSICON: @@ -2791,7 +2791,17 @@ void UpdateMenuHotkeys() combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE]); combined = "&Frame Counter\t" + combo; ChangeMenuItemText(ID_DISPLAY_FRAMECOUNTER, combined); - + + //Rerecord Counter + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_RERECORD_DISPLAY_TOGGLE]); + combined = "&Rerecord Counter\t" + combo; + ChangeMenuItemText(ID_DISPLAY_RERECORDCOUNTER, combined); + + //Movie status icon + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE]); + combined = "&Movie status icon\t" + combo; + ChangeMenuItemText(ID_DISPLAY_MOVIESTATUSICON, combined); + //Graphics: BG combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MISC_DISPLAY_BG_TOGGLE]); combined = "Graphics: &BG\t" + combo; diff --git a/src/input.cpp b/src/input.cpp index cebf7cea..64fefff6 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -52,7 +52,10 @@ #include "drivers/win/window.h" #include "drivers/win/ntview.h" +#include "./drivers/win/taseditlib/inputsnapshot.h" +#include "./drivers/win/taseditlib/bookmarks.h" extern bool Tasedit_rewind_now; +extern BOOKMARKS bookmarks; #endif // WIN32 //it is easier to declare these input drivers extern here than include a bunch of files @@ -620,7 +623,6 @@ static void CommandSoundAdjust(void); static void CommandUsePreset(void); static void BackgroundDisplayToggle(void); static void ObjectDisplayToggle(void); -static void LagCounterToggle(void); static void ViewSlots(void); static void LaunchTasEdit(void); static void LaunchMemoryWatch(void); @@ -667,52 +669,52 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_SPEED_TURBO, EMUCMDTYPE_SPEED, FCEUD_TurboOn, FCEUD_TurboOff, 0, "Turbo", EMUCMDFLAG_TASEDIT }, { EMUCMD_SPEED_TURBO_TOGGLE, EMUCMDTYPE_SPEED, FCEUD_TurboToggle, 0, 0, "Turbo Toggle", EMUCMDFLAG_TASEDIT }, - { EMUCMD_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", 0 }, - { EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", 0 }, - { EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", 0 }, - { EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", 0 }, - { EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", 0 }, - { EMUCMD_SAVE_SLOT_5, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 5", 0 }, - { EMUCMD_SAVE_SLOT_6, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 6", 0 }, - { EMUCMD_SAVE_SLOT_7, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 7", 0 }, - { EMUCMD_SAVE_SLOT_8, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 8", 0 }, - { EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", 0 }, + { EMUCMD_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_5, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 5", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_6, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 6", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_7, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 7", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_8, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 8", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", EMUCMDFLAG_TASEDIT }, { EMUCMD_SAVE_SLOT_NEXT, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Next Savestate Slot", 0 }, { EMUCMD_SAVE_SLOT_PREV, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Previous Savestate Slot", 0 }, { EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", 0 }, { EMUCMD_SAVE_STATE_AS, EMUCMDTYPE_STATE, FCEUD_SaveStateAs, 0, 0, "Save State As...", 0 }, - { EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", 0 }, - { EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", 0 }, - { EMUCMD_SAVE_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 2", 0 }, - { EMUCMD_SAVE_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 3", 0 }, - { EMUCMD_SAVE_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 4", 0 }, - { EMUCMD_SAVE_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 5", 0 }, - { EMUCMD_SAVE_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 6", 0 }, - { EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", 0 }, - { EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", 0 }, - { EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", 0 }, + { EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 2", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 3", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 4", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 5", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 6", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", EMUCMDFLAG_TASEDIT }, + { EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", EMUCMDFLAG_TASEDIT }, { EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", 0 }, { EMUCMD_LOAD_STATE_FROM, EMUCMDTYPE_STATE, FCEUD_LoadStateFrom, 0, 0, "Load State From...", 0 }, - { EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", 0 }, - { EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", 0 }, - { EMUCMD_LOAD_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 2", 0 }, - { EMUCMD_LOAD_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 3", 0 }, - { EMUCMD_LOAD_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 4", 0 }, - { EMUCMD_LOAD_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 5", 0 }, - { EMUCMD_LOAD_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 6", 0 }, - { EMUCMD_LOAD_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 7", 0 }, - { EMUCMD_LOAD_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 8", 0 }, - { EMUCMD_LOAD_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 9", 0 }, + { EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 2", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 3", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 4", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 5", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 6", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 7", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 8", EMUCMDFLAG_TASEDIT }, + { EMUCMD_LOAD_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 9", EMUCMDFLAG_TASEDIT }, - { EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...",0 }, - { EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Play Movie From...", }, - { EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", 0 }, + { EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 }, + { EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Play Movie From...", 0 }, + { EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", EMUCMDFLAG_TASEDIT }, { EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 }, { EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDIT }, - { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Frame Display Toggle", EMUCMDFLAG_TASEDIT }, + { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDIT }, { EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", EMUCMDFLAG_TASEDIT }, - { EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", 0 }, + { EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDIT }, #ifdef _S9XLUA_H { EMUCMD_SCRIPT_RELOAD, EMUCMDTYPE_MISC, FCEU_ReloadLuaCode, 0, 0, "Reload current Lua script", 0 }, @@ -773,6 +775,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0}, { EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0}, { EMUCMD_TASEDIT_REWIND, EMUCMDTYPE_TOOL, TaseditRewindOn, TaseditRewindOff, 0, "Rewind Frame (Tasedit-only)", EMUCMDFLAG_TASEDIT}, + { EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay, 0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDIT }, }; #define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0])) @@ -829,37 +832,61 @@ static void ViewSlots(void) static void CommandSelectSaveSlot(void) { - if(execcmd <= EMUCMD_SAVE_SLOT_9) - FCEUI_SelectState(execcmd-EMUCMD_SAVE_SLOT_0, 1); - else if(execcmd == EMUCMD_SAVE_SLOT_NEXT) - FCEUI_SelectStateNext(1); - else if(execcmd == EMUCMD_SAVE_SLOT_PREV) - FCEUI_SelectStateNext(-1); + if (FCEUMOV_Mode(MOVIEMODE_TASEDIT)) + { +#ifdef WIN32 + bookmarks.jump(execcmd - EMUCMD_SAVE_SLOT_0); +#endif + } else + { + if(execcmd <= EMUCMD_SAVE_SLOT_9) + FCEUI_SelectState(execcmd - EMUCMD_SAVE_SLOT_0, 1); + else if(execcmd == EMUCMD_SAVE_SLOT_NEXT) + FCEUI_SelectStateNext(1); + else if(execcmd == EMUCMD_SAVE_SLOT_PREV) + FCEUI_SelectStateNext(-1); + } } static void CommandStateSave(void) { - // FCEU_PrintError("execcmd=%d, EMUCMD_SAVE_STATE_SLOT_0=%d, EMUCMD_SAVE_STATE_SLOT_9=%d", execcmd,EMUCMD_SAVE_STATE_SLOT_0,EMUCMD_SAVE_STATE_SLOT_9); - if(execcmd >= EMUCMD_SAVE_STATE_SLOT_0 && execcmd <= EMUCMD_SAVE_STATE_SLOT_9) + if (FCEUMOV_Mode(MOVIEMODE_TASEDIT)) { - int oldslot=FCEUI_SelectState(execcmd-EMUCMD_SAVE_STATE_SLOT_0, 0); - FCEUI_SaveState(0); - FCEUI_SelectState(oldslot, 0); +#ifdef WIN32 + bookmarks.set(execcmd - EMUCMD_SAVE_STATE_SLOT_0); +#endif + } else + { + // FCEU_PrintError("execcmd=%d, EMUCMD_SAVE_STATE_SLOT_0=%d, EMUCMD_SAVE_STATE_SLOT_9=%d", execcmd,EMUCMD_SAVE_STATE_SLOT_0,EMUCMD_SAVE_STATE_SLOT_9); + if(execcmd >= EMUCMD_SAVE_STATE_SLOT_0 && execcmd <= EMUCMD_SAVE_STATE_SLOT_9) + { + int oldslot=FCEUI_SelectState(execcmd-EMUCMD_SAVE_STATE_SLOT_0, 0); + FCEUI_SaveState(0); + FCEUI_SelectState(oldslot, 0); + } + else + FCEUI_SaveState(0); } - else - FCEUI_SaveState(0); } static void CommandStateLoad(void) { - if(execcmd >= EMUCMD_LOAD_STATE_SLOT_0 && execcmd <= EMUCMD_LOAD_STATE_SLOT_9) + if (FCEUMOV_Mode(MOVIEMODE_TASEDIT)) { - int oldslot=FCEUI_SelectState(execcmd-EMUCMD_LOAD_STATE_SLOT_0, 0); - FCEUI_LoadState(0); - FCEUI_SelectState(oldslot, 0); +#ifdef WIN32 + bookmarks.unleash(execcmd - EMUCMD_LOAD_STATE_SLOT_0); +#endif + } else + { + if(execcmd >= EMUCMD_LOAD_STATE_SLOT_0 && execcmd <= EMUCMD_LOAD_STATE_SLOT_9) + { + int oldslot=FCEUI_SelectState(execcmd-EMUCMD_LOAD_STATE_SLOT_0, 0); + FCEUI_LoadState(0); + FCEUI_SelectState(oldslot, 0); + } + else + FCEUI_LoadState(0); } - else - FCEUI_LoadState(0); } static void CommandSoundAdjust(void) @@ -902,7 +929,7 @@ void LagCounterReset() lagCounter = 0; } -static void LagCounterToggle(void) +void LagCounterToggle(void) { lagCounterDisplay ^= 1; } diff --git a/src/input.h b/src/input.h index b32b7fdb..a2b69d4b 100644 --- a/src/input.h +++ b/src/input.h @@ -5,6 +5,8 @@ #include "git.h" +void LagCounterToggle(void); + class MovieRecord; //MBG TODO - COMBINE THESE INPUTC AND INPUTCFC @@ -229,9 +231,10 @@ enum EMUCMD EMUCMD_TOOL_RAMSEARCHEQ, EMUCMD_TOOL_RAMSEARCHNE, EMUCMD_TOOL_OPENNTVIEW, + EMUCMD_TASEDIT_REWIND, //----------------------------- //keep adding these in order of newness or else the hotkey binding configs will get messed up... - EMUCMD_TASEDIT_REWIND, + EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMD_MAX }; diff --git a/src/movie.cpp b/src/movie.cpp index ccd1237e..232a0942 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -40,9 +40,9 @@ #include "./drivers/win/window.h" extern void AddRecentMovieFile(const char *filename); +#include "./drivers/win/taseditlib/playback.h" extern void InputChangedRec(); -extern int TASEdit_greenzone_capacity; -extern bool TASEdit_bind_markers; +extern PLAYBACK playback; #endif using namespace std; @@ -1409,6 +1409,11 @@ void FCEUI_MovieToggleFrameDisplay(void) frame_display=!frame_display; } +void FCEUI_MovieToggleRerecordDisplay() +{ + rerecord_display ^= 1; +} + void FCEUI_ToggleInputDisplay(void) { switch(input_display) @@ -1488,7 +1493,13 @@ void FCEUI_MovieToggleReadOnly() void FCEUI_MoviePlayFromBeginning(void) { - if (movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_TASEDIT) + if (movieMode == MOVIEMODE_TASEDIT) + { + movie_readonly = true; +#ifdef WIN32 + playback.jump(0); +#endif + } else if (movieMode != MOVIEMODE_INACTIVE) { if (currMovieData.savestate.empty()) { diff --git a/src/movie.h b/src/movie.h index a0197475..3c0d52b9 100644 --- a/src/movie.h +++ b/src/movie.h @@ -270,6 +270,7 @@ int FCEUI_GetMovieLength(); int FCEUI_GetMovieRerecordCount(); std::string FCEUI_GetMovieName(void); void FCEUI_MovieToggleFrameDisplay(); +void FCEUI_MovieToggleRerecordDisplay(); void FCEUI_ToggleInputDisplay(void); void LoadSubtitles(MovieData &); diff --git a/vc/vc10_fceux.vcxproj b/vc/vc10_fceux.vcxproj index 788a9775..27aac60e 100644 --- a/vc/vc10_fceux.vcxproj +++ b/vc/vc10_fceux.vcxproj @@ -418,6 +418,8 @@ $(IntDir)%(Filename)1.xdc + + @@ -839,8 +841,19 @@ + + + + + + + + + + + @@ -858,6 +871,16 @@ + + + + + + + + + + diff --git a/vc/vc10_fceux.vcxproj.filters b/vc/vc10_fceux.vcxproj.filters index b1f18a8b..8e1795e0 100644 --- a/vc/vc10_fceux.vcxproj.filters +++ b/vc/vc10_fceux.vcxproj.filters @@ -912,6 +912,8 @@ + + @@ -1375,6 +1377,27 @@ + + + + + + + + + + + + + + + + + + + + +