diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index d19aaa43..ab62aafc 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -71,6 +71,7 @@ extern int frameSkipAmt; extern bool TASEdit_follow_playback; extern bool TASEdit_show_lag_frames; extern bool TASEdit_restore_position; +extern bool TASEdit_show_dot; extern int TASEdit_greenzone_capacity; //window positions and sizes: @@ -292,6 +293,7 @@ static CFGSTRUCT fceuconfig[] = { AC(TASEdit_follow_playback), AC(TASEdit_show_lag_frames), AC(TASEdit_restore_position), + AC(TASEdit_show_dot), AC(TASEdit_greenzone_capacity), AC(lagCounterDisplay), AC(oldInputDisplay), diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 676e1199..2b06750a 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -403,6 +403,12 @@ void DoFCEUExit() if(exiting) //Eh, oops. I'll need to try to fix this later. return; +#ifdef WIN32 + //If user was asked to save changes in Taseditor and chose cancel, don't close FCEUX + extern bool ExitTasEdit(); + if (FCEUMOV_Mode(MOVIEMODE_TASEDIT) && !ExitTasEdit()) return; +#endif + if (CloseMemoryWatch() && AskSave()) //If user was asked to save changes in the memory watch dialog or ram watch, and chose cancel, don't close FCEUX! { if(goptions & GOO_CONFIRMEXIT) diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index d006f893..cb397166 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -221,7 +221,7 @@ BEGIN BEGIN MENUITEM "&New Project\tCtrl+N", ID_FILE_NEWPROJECT MENUITEM "&Open Project...\tCtrl+O", ID_FILE_OPENPROJECT - MENUITEM "&Save Project\tCtrl+S", ID_FILE_SAVEPROJECT, INACTIVE + MENUITEM "&Save Project\tCtrl+S", ID_FILE_SAVEPROJECT MENUITEM "S&ave Project As...\tCtrl+Shift+S", ID_FILE_SAVEPROJECTAS MENUITEM "Recent", ID_TASEDIT_FILE_RECENT MENUITEM SEPARATOR @@ -239,14 +239,12 @@ BEGIN MENUITEM "&Paste\tCtrl+V", ID_TASEDIT_PASTE MENUITEM "&Delete\tCtrl+Delete", ID_TASEDIT_DELETE MENUITEM SEPARATOR - MENUITEM "&Add Marker", ID_EDIT_ADDMARKER, INACTIVE - MENUITEM "&Remove Marker", ID_EDIT_REMOVEMARKER, INACTIVE - MENUITEM SEPARATOR MENUITEM "&Truncate\tCtrl+T", ID_EDIT_TRUNCATE END POPUP "&View" BEGIN MENUITEM "Highlight &lag frames", ID_VIEW_SHOW_LAG_FRAMES + MENUITEM "Show &dot in empty cells", ID_VIEW_SHOWDOTINEMPTYCELLS MENUITEM SEPARATOR MENUITEM "&Follow playback\tCtrl+F", ID_VIEW_FOLLOW_PLAYBACK END @@ -344,9 +342,7 @@ BEGIN MENUITEM "Insert Frame(s)", ID_CONTEXT_SELECTED_INSERTFRAMES MENUITEM "Insert number of Frames", ID_CONTEXT_SELECTED_INSERTFRAMES2 MENUITEM "Delete Frame(s)", ID_CONTEXT_SELECTED_DELETEFRAMES - MENUITEM SEPARATOR - MENUITEM "Add Marker", ID_CONTEXT_SELECTED_ADDMARKER, INACTIVE - MENUITEM "Remove Marker", ID_CONTEXT_SELECTED_REMOVEMARKER, INACTIVE + MENUITEM "Clear Frame(s)", ID_CONTEXT_SELECTED_CLEARFRAMES MENUITEM SEPARATOR MENUITEM "Truncate", ID_CONTEXT_SELECTED_TRUNCATE END @@ -1352,14 +1348,22 @@ BEGIN PUSHBUTTON ">>",TASEDIT_FORWARD_FULL,414,14,22,14,NOT WS_TABSTOP CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK, "Button",BS_AUTOCHECKBOX,328,31,105,12 - GROUPBOX "Recording input",IDC_STATIC,322,55,118,58,BS_CENTER,WS_EX_RIGHT - GROUPBOX "Editing input",IDC_STATIC,322,114,118,33,BS_CENTER,WS_EX_RIGHT + GROUPBOX "Recording input",IDC_STATIC,322,55,118,50,BS_CENTER,WS_EX_RIGHT + GROUPBOX "Editing",IDC_STATIC,322,106,118,41,BS_CENTER,WS_EX_RIGHT GROUPBOX "Bookmarks",IDC_STATIC,322,148,118,103,BS_CENTER,WS_EX_RIGHT CONTROL "",IDC_LIST3,"SysListView32",LVS_LIST | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,327,159,108,88 GROUPBOX "Project Input Logs",IDC_STATIC,322,252,118,123,BS_CENTER,WS_EX_RIGHT CONTROL "",IDC_LIST2,"SysListView32",LVS_LIST | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,327,263,108,108,WS_EX_LEFTSCROLLBAR CONTROL "",IDC_PROGRESS_BUTTON,"Button",BS_OWNERDRAW | WS_TABSTOP,326,41,110,12 CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,326,44,110,6 + CONTROL " OFF",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,328,65,29,10 + CONTROL " ON",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,328,79,29,10 + CONTROL " 1P",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,380,65,25,10 + CONTROL " 2P",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,409,65,23,10 + CONTROL " 3P",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,380,79,25,10 + CONTROL " 4P",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,409,79,23,10 + CONTROL " Superimpose",IDC_SUPERIMPOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,328,92,55,10 + CONTROL " Omit blank",IDC_OMITBLANK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,387,92,49,10 END ASSEMBLER DIALOGEX 0, 0, 202, 135 @@ -2005,12 +2009,14 @@ BEGIN "C", ACCEL_CTRL_C, VIRTKEY, CONTROL, NOINVERT VK_DELETE, ACCEL_CTRL_DELETE, VIRTKEY, CONTROL, NOINVERT "F", ACCEL_CTRL_F, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ACCEL_CTRL_INSERT, VIRTKEY, CONTROL, NOINVERT "P", ACCEL_CTRL_P, VIRTKEY, CONTROL, NOINVERT "S", ACCEL_CTRL_S, VIRTKEY, CONTROL, NOINVERT "T", ACCEL_CTRL_T, VIRTKEY, CONTROL, NOINVERT "V", ACCEL_CTRL_V, VIRTKEY, CONTROL, NOINVERT "X", ACCEL_CTRL_X, VIRTKEY, CONTROL, NOINVERT - VK_INSERT, ACCEL_CTRL_INSERT, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ACCEL_INS, VIRTKEY, NOINVERT + VK_DELETE, ACCEL_DEL, VIRTKEY, NOINVERT END IDR_RWACCELERATOR ACCELERATORS diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index e66b2cc8..af2c07ba 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -374,19 +374,22 @@ #define MEMW_EXPANDCOLLAPSE 1133 #define IDC_SOUND_RESTOREDEFAULTVOL 1133 #define IDC_BUTTON2 1134 -#define TASEDIT_FORWARD 1134 +#define TASEDIT_FORWARD 1134 #define IDC_BUTTON3 1135 #define TASEDIT_REWIND_FULL 1135 #define IDC_BUTTON4 1136 -#define TASEDIT_FORWARD_FULL 1136 +#define TASEDIT_FORWARD_FULL 1136 #define TASEDIT_REWIND2 1137 #define TASEDIT_PLAYSTOP 1137 #define IDC_RADIO1 1138 #define IDC_RADIO2 1139 #define IDC_RADIO3 1140 +#define IDC_RADIO4 1141 #define MEMW_EDIT00FORMULA 1142 +#define IDC_RADIO5 1142 #define MEMW_EDIT01FORMULA 1143 -#define IDC_PROGRESS_BUTTON 1144 +#define IDC_RADIO6 1143 +#define IDC_PROGRESS_BUTTON 1144 #define MEMW_EDIT02FORMULA 1144 #define IDC_BUTTON7 1145 #define MEMW_EDIT03FORMULA 1145 @@ -430,7 +433,9 @@ #define DEBUGAUTOLOAD 1203 #define IDC_CHEAT_PAUSEWHENACTIVE 1203 #define IDC_FULLSAVESTATES 1203 +#define IDC_SUPERIMPOSE 1203 #define IDC_VOLUMEGROUP 1204 +#define IDC_OMITBLANK 1204 #define IDC_RAMLIST 1205 #define IDC_C_SEARCH 1206 #define IDC_C_ADDCHEAT 1207 @@ -609,8 +614,6 @@ #define ID_FILE_SAVEPROJECTAS 40182 #define ID_FILE_EXPORTFM2 40183 #define ACCEL_CTRL_X 40184 -#define ID_EDIT_ADDMARKER 40186 -#define ID_EDIT_REMOVE_MARKER 40187 #define ID_TASEDIT_CUT 40188 #define ID_TASEDIT_COPY 40189 #define ID_TASEDIT_COPYTONEW 40190 @@ -632,8 +635,6 @@ #define ID_CONTEXT_SELECTED_DELETEFRAMES 40205 #define ID_SELECTED_REMOVEMARKER 40206 #define ID_CONTEXT_SELECTED_PASTETONEW 40207 -#define ID_CONTEXT_SELECTED_ADDMARKER 40208 -#define ID_CONTEXT_SELECTED_REMOVEMARKER 40209 #define ID_CONTEXT_SELECTED_BRANCH 40210 #define ID_EDIT_BRANCHCTRL 40211 #define ID_EDIT_BRANCH 40212 @@ -830,6 +831,12 @@ #define ID_AVI_DISPLAYHUD 40438 #define ID_AVI_STOPWAV 40439 #define ID_AVI_ENABLEHUDRECORDING 40440 +#define ID_VIEW_SHOWDOTINEMPTYCELLS 40441 +#define ACCEL_INS 40442 +#define ACCEL_DEL 40443 +#define ID_SELECTED_CLEARSELECTION 40445 +#define ID_CONTEXT_SELECTED_CLEARSELECTION 40446 +#define ID_CONTEXT_SELECTED_CLEARFRAMES 40447 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -839,7 +846,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 160 -#define _APS_NEXT_COMMAND_VALUE 40441 +#define _APS_NEXT_COMMAND_VALUE 40448 #define _APS_NEXT_CONTROL_VALUE 1263 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index de124956..2054d82a 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -23,9 +23,11 @@ using namespace std; //to change header font //http://forums.devx.com/archive/index.php/t-37234.html -int old_movie_readonly = -1; +bool old_project_changed; +int old_multitrack_recording_joypad, multitrack_recording_joypad; +bool old_movie_readonly; int lastCursor; -bool old_emu_paused; +bool old_emu_paused, emu_paused; int old_pauseframe; bool old_show_pauseframe, show_pauseframe; bool old_rewind_button_state, rewind_button_state; @@ -33,7 +35,12 @@ bool old_forward_button_state, forward_button_state; int button_hold_time; int seeking_start_frame = 0; bool TASEdit_focus = false; -int saved_eoptions = 0; +// saved FCEU config +int saved_eoptions; +int saved_EnableAutosave; +extern int EnableAutosave; +bool saved_compressSavestates; +extern bool compressSavestates; // vars saved in cfg file int TasEdit_wndx, TasEdit_wndy; @@ -42,13 +49,20 @@ bool TASEdit_show_lag_frames = true; bool TASEdit_restore_position = false; int TASEdit_greenzone_capacity = GREENZONE_DEFAULT_CAPACITY; extern bool muteTurbo; +bool TASEdit_show_dot = true; string tasedithelp = "{16CDE0C4-02B0-4A60-A88D-076319909A4D}"; //Name of TASEdit Help page char buttonNames[NUM_JOYPAD_BUTTONS][2] = {"A", "B", "S", "T", "U", "D", "L", "R"}; - +char windowCaptions[6][30] = { "TAS Editor", + "TAS Editor (Recording All)", + "TAS Editor (Recording 1P)", + "TAS Editor (Recording 2P)", + "TAS Editor (Recording 3P)", + "TAS Editor (Recording 4P)"}; HWND hwndTasEdit = 0; static HMENU hmenu, hrmenu; static HWND hwndList, hwndHeader, hwndProgressbar, hwndRewind, hwndForward; +static HWND hwndRB_RecOff, hwndRB_RecAll, hwndRB_Rec1P, hwndRB_Rec2P, hwndRB_Rec3P, hwndRB_Rec4P; static WNDPROC hwndHeader_oldWndproc, hwndList_oldWndProc; typedef std::set TSelectionFrames; @@ -93,8 +107,14 @@ static void GetDispInfo(NMLVDISPINFO* nmlvDispInfo) { item.pszText[0] = MovieRecord::mnemonics[bit]; item.pszText[1] = 0; - } else - item.pszText[0] = 0; + } else + { + if (TASEdit_show_dot) + { + item.pszText[0] = 46; // "." + item.pszText[1] = 0; + } else item.pszText[0] = 0; + } } break; } @@ -108,6 +128,8 @@ static void GetDispInfo(NMLVDISPINFO* nmlvDispInfo) static LONG CustomDraw(NMLVCUSTOMDRAW* msg) { + //LPNMCUSTOMDRAW + int cell_x, cell_y; switch(msg->nmcd.dwDrawStage) { @@ -119,6 +141,9 @@ static LONG CustomDraw(NMLVCUSTOMDRAW* msg) SelectObject(msg->nmcd.hdc,debugSystem->hFixedFont); cell_x = msg->iSubItem; cell_y = msg->nmcd.dwItemSpec; + + //msg->clrText = 0xFF0000; + if(cell_x > COLUMN_ICONS) { if(cell_x == COLUMN_FRAMENUM || cell_x == COLUMN_FRAMENUM2) @@ -197,21 +222,21 @@ void UpdateTasEdit() SeekingStop(); // update seeking progressbar + old_emu_paused = emu_paused; + emu_paused = (bool)FCEUI_EmulationPaused(); if (pauseframe) { SendMessage(hwndProgressbar, PBM_SETPOS, PROGRESSBAR_WIDTH * (currFrameCounter-seeking_start_frame) / (pauseframe-seeking_start_frame), 0); - } else if (old_emu_paused != (bool)FCEUI_EmulationPaused()) + } else if (old_emu_paused != emu_paused) { // emulator got paused/unpaused externally - if (old_emu_paused && !FCEUI_EmulationPaused()) + if (old_emu_paused && !emu_paused) // externally unpaused - progressbar should be empty SendMessage(hwndProgressbar, PBM_SETPOS, 0, 0); else // externally paused - progressbar should be full SendMessage(hwndProgressbar, PBM_SETPOS, PROGRESSBAR_WIDTH, 0); } - old_emu_paused = (bool)FCEUI_EmulationPaused(); - // update flashing pauseframe if (old_pauseframe != pauseframe && old_pauseframe) RedrawRow(old_pauseframe-1); old_pauseframe = pauseframe; @@ -223,6 +248,7 @@ void UpdateTasEdit() if (old_show_pauseframe != show_pauseframe) RedrawRow(pauseframe-1); UpdateList(); + //UpdateRecordingRadioButtons(); //update the cursor if(currFrameCounter != lastCursor) @@ -235,24 +261,11 @@ void UpdateTasEdit() lastCursor = currFrameCounter; } - // update window caption - if ((!old_movie_readonly) == movie_readonly) - { - old_movie_readonly = movie_readonly; - if (movie_readonly) - { - SetWindowText(hwndTasEdit, "TAS Editor"); - } else - { - SetWindowText(hwndTasEdit, "TAS Editor (Recording)"); - } - } - // update < and > buttons - if(FCEUI_EmulationPaused()) + if(emu_paused) { old_rewind_button_state = rewind_button_state; - rewind_button_state = Button_GetState(hwndRewind) & BST_PUSHED; + rewind_button_state = (bool)(Button_GetState(hwndRewind) & BST_PUSHED); if (rewind_button_state) { if (!old_rewind_button_state) @@ -265,7 +278,7 @@ void UpdateTasEdit() } } old_forward_button_state = forward_button_state; - forward_button_state = Button_GetState(hwndForward) & BST_PUSHED; + forward_button_state = (bool)(Button_GetState(hwndForward) & BST_PUSHED); if (forward_button_state) { if (!old_forward_button_state) @@ -278,6 +291,19 @@ void UpdateTasEdit() } } } + + // update window caption + if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad || old_project_changed != project.changed) + RedrawWindowCaption(); + old_project_changed = project.changed; + + // update recording radio buttons if user used hotkey to switch R/W + if (old_movie_readonly != movie_readonly || old_multitrack_recording_joypad != multitrack_recording_joypad) + { + UncheckRecordingRadioButtons(); + RecheckRecordingRadioButtons(); + } + } void UpdateList() @@ -290,6 +316,25 @@ void UpdateList() } } +void RedrawWindowCaption() +{ + char windowCaption[300]; // 260 + 30 + 1 + ... + if (movie_readonly) + strcpy(windowCaption, windowCaptions[0]); + else + strcpy(windowCaption, windowCaptions[multitrack_recording_joypad + 1]); + // add project name + std::string projectname = project.GetProjectName(); + if (!projectname.empty()) + { + strcat(windowCaption, " - "); + strcat(windowCaption, projectname.c_str()); + } + // and * if project has unsaved changes + if (project.changed) + strcat(windowCaption, "*"); + SetWindowText(hwndTasEdit, windowCaption); +} void RedrawTasedit() { InvalidateRect(hwndTasEdit,0,FALSE); @@ -395,6 +440,15 @@ void RightClick(LPNMITEMACTIVATE info) RightClickMenu(info); } +void InputChanged() +{ + // keep input log + // update hot input + + + project.changed = true; +} + void InvalidateGreenZone(int after) { if (currMovieData.greenZoneCount > after+1) @@ -486,6 +540,7 @@ void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags) //update one row currMovieData.records[row_index].toggleBit(joy,bit); } + InputChanged(); InvalidateGreenZone(row_index); } @@ -556,10 +611,10 @@ static void InsertFrames() } UpdateList(); + InputChanged(); InvalidateGreenZone(*selectionFrames.begin()); } -//delete frames at the currently selected positions. static void DeleteFrames() { //delete frames on each selection, going backwards @@ -572,6 +627,7 @@ static void DeleteFrames() if (!currMovieData.records.size()) StartFromZero(); // reduce list + InputChanged(); UpdateList(); int index = *selectionFrames.begin(); int delete_index; @@ -590,6 +646,20 @@ static void DeleteFrames() InvalidateGreenZone(index); } +static void ClearFrames() +{ + //clear input on each selection + for(TSelectionFrames::iterator it(selectionFrames.begin()); it != selectionFrames.end(); it++) + { + currMovieData.records[*it].clear(); + } + InputChanged(); + // reduce greenzone + int index = *selectionFrames.begin(); + InvalidateGreenZone(index); +} + + //the column set operation, for setting a button for a span of selected values static void ColumnSet(int column) { @@ -630,6 +700,7 @@ static void ColumnSet(int column) { currMovieData.records[*it].setBitValue(joy,button,newValue); } + InputChanged(); InvalidateGreenZone(*selectionFrames.begin()); } @@ -718,7 +789,7 @@ static void Cut() { if (Copy()) { - DeleteFrames(); + ClearFrames(); } } @@ -798,6 +869,7 @@ static bool Paste() pGlobal = strchr(pGlobal, '\n'); } + InputChanged(); InvalidateGreenZone(*selectionFrames.begin()); result = true; } @@ -809,14 +881,6 @@ static bool Paste() return result; } -void AddMarker() -{ -} -void RemoveMarker() -{ -} - - // --------------------------------------------------------------------------------- //The subclass wndproc for the listview header static LRESULT APIENTRY HeaderWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) @@ -913,13 +977,15 @@ static void InitDialog() } } // add pads 3 and 4 and frame_number2 - if (currMovieData.fourscore) AddFourscoreColumns(); + if (currMovieData.fourscore) AddFourscore(); //the initial update UpdateTasEdit(); } -void AddFourscoreColumns() + +void AddFourscore() { + // add list columns LVCOLUMN lvc; lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT; lvc.fmt = LVCFMT_CENTER; @@ -937,19 +1003,67 @@ void AddFourscoreColumns() lvc.cx = 92; lvc.pszText = "Frame#"; ListView_InsertColumn(hwndList, colidx++, &lvc); + // enable radiobuttons for 3P/4P multitracking + EnableWindow(hwndRB_Rec3P, true); + EnableWindow(hwndRB_Rec4P, true); + // change eoptions + FCEUI_SetInputFourscore(true); + + } -void RemoveFourscoreColumns() +void RemoveFourscore() { + // remove list columns for (int i = COLUMN_FRAMENUM2; i >= COLUMN_JOYPAD3_A; --i) { ListView_DeleteColumn (hwndList, i); } + // disable radiobuttons for 3P/4P multitracking + EnableWindow(hwndRB_Rec3P, false); + EnableWindow(hwndRB_Rec4P, false); + // change eoptions + FCEUI_SetInputFourscore(false); + + } -bool CheckSaveChanges() +void UncheckRecordingRadioButtons() { - //TODO: determine if project has changed, and ask to save changes - return true; + Button_SetCheck(hwndRB_RecOff, BST_UNCHECKED); + Button_SetCheck(hwndRB_RecAll, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec1P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec2P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec3P, BST_UNCHECKED); + Button_SetCheck(hwndRB_Rec4P, BST_UNCHECKED); +} +void RecheckRecordingRadioButtons() +{ + old_movie_readonly = movie_readonly; + old_multitrack_recording_joypad = multitrack_recording_joypad; + if (movie_readonly) + { + Button_SetCheck(hwndRB_RecOff, BST_CHECKED); + } else + { + switch(multitrack_recording_joypad) + { + case MULTITRACK_RECORDING_ALL: + Button_SetCheck(hwndRB_RecAll, BST_CHECKED); + break; + case MULTITRACK_RECORDING_1P: + Button_SetCheck(hwndRB_Rec1P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_2P: + Button_SetCheck(hwndRB_Rec2P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_3P: + Button_SetCheck(hwndRB_Rec3P, BST_CHECKED); + break; + case MULTITRACK_RECORDING_4P: + Button_SetCheck(hwndRB_Rec4P, BST_CHECKED); + break; + } + } } //Creates a new TASEdit Project @@ -958,18 +1072,15 @@ static void NewProject() //determine if current project changed //if so, ask to save changes //close current project - if (!CheckSaveChanges()) return; + if (!AskSaveProject()) return; //TODO: close current project instance, create a new one with a non-parameterized constructor } //Opens a new Project file -static void OpenProject() +void OpenProject() { -//TODO - //determine if current project changed - //if so, ask to save changes - //close current project + if (!AskSaveProject()) return; //If OPENFILENAME dialog successful, open up a completely new project instance and scrap the old one //Run the project Load() function to pull all info from the .tas file into this new project instance @@ -996,40 +1107,40 @@ static void OpenProject() { std::string tempstr = nameo; //Make a temporary string for filename char drv[512], dir[512], name[512], ext[512]; //For getting the filename! - if(tempstr.rfind(".tas") == std::string::npos) //If they haven't put ".tas" after it - { - tempstr.append(".tas"); //Stick it on ourselves - splitpath(tempstr.c_str(), drv, dir, name, ext); //Split the path... - std::string filename = name; //Get the filename - filename.append(ext); //Shove the extension back onto it... - project.SetProjectFile(filename); //And update the project's filename. - } else { //If they've been nice and done it for us... - splitpath(tempstr.c_str(), drv, dir, name, ext); //Split it up... - std::string filename = name; //Grab the name... - filename.append(ext); //Stick extension back on... - project.SetProjectFile(filename); //And update the project's filename. - } + if(tempstr.rfind(".tas") == std::string::npos) //If they haven't put ".tas" after it, stick it on ourselves + tempstr.append(".tas"); + splitpath(tempstr.c_str(), drv, dir, name, ext); //Split the path... + std::string filename = name; //Get the filename + filename.append(ext); //Shove the extension back onto it... + project.SetProjectFile(filename); //And update the project's filename. //Set the project's name to the ROM name project.SetProjectName(GetRomName()); //Set the fm2 name std::string thisfm2name = project.GetProjectName(); thisfm2name.append(".fm2"); project.SetFM2Name(thisfm2name); - // load project and change number of listview columns if needed + // switch to read-only mode, but first must uncheck radiobuttons explicitly + if (!movie_readonly) FCEUI_MovieToggleReadOnly(); + UncheckRecordingRadioButtons(); + RecheckRecordingRadioButtons(); + // remember to update fourscore status bool last_fourscore = currMovieData.fourscore; + // Load project project.LoadProject(project.GetProjectFile()); if (last_fourscore && !currMovieData.fourscore) - RemoveFourscoreColumns(); + RemoveFourscore(); else if (!last_fourscore && currMovieData.fourscore) - AddFourscoreColumns(); - PauseEmulation(); + AddFourscore(); + SeekingStop(); FollowPlayback(); + //UpdateTasEdit(); RedrawTasedit(); + RedrawWindowCaption(); } } // Saves current project -static void SaveProjectAs() +bool SaveProjectAs() { //Save project as new user selected filename //flag project as not changed @@ -1067,18 +1178,36 @@ static void SaveProjectAs() std::string thisfm2name = project.GetProjectName(); thisfm2name.append(".fm2"); //Setup the fm2 name project.SetFM2Name(thisfm2name); //Set the project's fm2 name - project.SaveProject(); - } - + project.saveProject(); + } else return false; + // saved successfully - remove * mark from caption + RedrawWindowCaption(); + return true; +} +bool SaveProject() +{ + if (!project.saveProject()) + return SaveProjectAs(); + else + RedrawWindowCaption(); + return true; } -//Saves current project -static void SaveProject() +// returns false if user doesn't want to exit +bool AskSaveProject() { -//TODO: determine if file exists, if not, do SaveProjectAs() -//Save work, flag project as not changed - if (!project.SaveProject()) - SaveProjectAs(); + bool changes_found = false; + if (project.changed) changes_found = true; + + // ask saving project + if (changes_found) + { + int answer = MessageBox(hwndTasEdit, "Save Project changes?", "TAS Edit", MB_YESNOCANCEL); + if(answer == IDYES) + return SaveProject(); + return (answer != IDCANCEL); + } + return true; } //Takes a selected .fm2 file and adds it to the Project inputlog @@ -1126,6 +1255,7 @@ static void Truncate() ClearSelection(); } currMovieData.truncateAt(frame+1); + InputChanged(); UpdateList(); InvalidateGreenZone(frame); } @@ -1184,11 +1314,18 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar if (TasEdit_wndx==-32000) TasEdit_wndx=0; //Just in case if (TasEdit_wndy==-32000) TasEdit_wndy=0; SetWindowPos(hwndDlg,0,TasEdit_wndx,TasEdit_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); - + // save references to dialog items hwndList = GetDlgItem(hwndDlg, IDC_LIST1); hwndProgressbar = GetDlgItem(hwndDlg, IDC_PROGRESS1); + SendMessage(hwndProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSBAR_WIDTH)); hwndRewind = GetDlgItem(hwndDlg, TASEDIT_REWIND); hwndForward = GetDlgItem(hwndDlg, TASEDIT_FORWARD); + hwndRB_RecOff = GetDlgItem(hwndDlg, IDC_RADIO1); + hwndRB_RecAll = GetDlgItem(hwndDlg, IDC_RADIO2); + hwndRB_Rec1P = GetDlgItem(hwndDlg, IDC_RADIO3); + hwndRB_Rec2P = GetDlgItem(hwndDlg, IDC_RADIO4); + hwndRB_Rec3P = GetDlgItem(hwndDlg, IDC_RADIO5); + hwndRB_Rec4P = GetDlgItem(hwndDlg, IDC_RADIO6); InitDialog(); break; @@ -1236,15 +1373,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar break; } break; - case TASEDIT_REWIND: - switch(((LPNMHDR)lParam)->code) - { - case NM_CLICK: - case NM_DBLCLK: - Tasedit_RewindFrame(); - break; - } - break; case TASEDIT_PLAYSTOP: switch(((LPNMHDR)lParam)->code) { @@ -1254,15 +1382,6 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar break; } break; - case TASEDIT_FORWARD: - switch(((LPNMHDR)lParam)->code) - { - case NM_CLICK: - case NM_DBLCLK: - Tasedit_ForwardFrame(); - break; - } - break; } break; @@ -1284,80 +1403,57 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case ID_FILE_NEWPROJECT: NewProject(); break; - case ID_FILE_OPENPROJECT: OpenProject(); break; - case ACCEL_CTRL_S: case ID_FILE_SAVEPROJECT: - SaveProject(); + SaveProject(); break; - case ID_FILE_SAVEPROJECTAS: - SaveProjectAs(); + SaveProjectAs(); break; - case ID_FILE_IMPORTFM2: Replay_LoadMovie(true); //Import(); //adelikat: Putting the play movie dialog in its place until the import concept is refined. break; - case ID_FILE_EXPORTFM2: - Export(); + Export(); break; - case ID_TASEDIT_FILE_CLOSE: ExitTasEdit(); break; - case ID_EDIT_SELECTALL: SelectAll(); break; - case ACCEL_CTRL_X: case ID_TASEDIT_CUT: Cut(); break; - case ACCEL_CTRL_C: case ID_TASEDIT_COPY: Copy(); break; - case ACCEL_CTRL_V: case ID_TASEDIT_PASTE: Paste(); break; - case ACCEL_CTRL_DELETE: case ID_TASEDIT_DELETE: case ID_CONTEXT_SELECTED_DELETEFRAMES: if (selectionFrames.size()) DeleteFrames(); break; - - case ID_EDIT_ADDMARKER: - case ID_CONTEXT_SELECTED_ADDMARKER: - AddMarker(); - break; - - case ID_EDIT_REMOVEMARKER: - case ID_CONTEXT_SELECTED_REMOVEMARKER: - RemoveMarker(); - break; - case ACCEL_CTRL_T: case ID_EDIT_TRUNCATE: case ID_CONTEXT_SELECTED_TRUNCATE: case ID_CONTEXT_STRAY_TRUNCATE: Truncate(); break; - case ID_HELP_TASEDITHELP: OpenHelpWindow(tasedithelp); //link to TASEdit in help menu break; - + case ACCEL_INS: case MENU_CONTEXT_STRAY_INSERTFRAMES: case ID_CONTEXT_SELECTED_INSERTFRAMES2: { @@ -1371,23 +1467,27 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar // insert at selection int index = *selectionFrames.begin(); currMovieData.insertEmpty(index,frames); + InputChanged(); InvalidateGreenZone(index); } else { // insert at playback cursor currMovieData.insertEmpty(currFrameCounter,frames); + InputChanged(); InvalidateGreenZone(currFrameCounter); } } } } break; - case ACCEL_CTRL_INSERT: case ID_CONTEXT_SELECTED_INSERTFRAMES: if (selectionFrames.size()) InsertFrames(); break; - + case ACCEL_DEL: + case ID_CONTEXT_SELECTED_CLEARFRAMES: + if (selectionFrames.size()) ClearFrames(); + break; case TASEDIT_REWIND_FULL: //rewinds to beginning of greenzone JumpToFrame(FindBeginningOfGreenZone(0)); @@ -1443,15 +1543,47 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar } break; } - case ID_CONFIG_MUTETURBO: muteTurbo ^= 1; CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); break; - case IDC_PROGRESS_BUTTON: if (pauseframe) SeekingStop(); break; + case IDC_RADIO1: + // switch to readonly, no need to recheck radiobuttons + if (!movie_readonly) FCEUI_MovieToggleReadOnly(); + break; + case IDC_RADIO2: + // switch to read+write for all, no need to recheck radiobuttons + if (movie_readonly) FCEUI_MovieToggleReadOnly(); + multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; + break; + case IDC_RADIO3: + // switch to read+write for 1P, no need to recheck radiobuttons + if (movie_readonly) FCEUI_MovieToggleReadOnly(); + multitrack_recording_joypad = MULTITRACK_RECORDING_1P; + break; + case IDC_RADIO4: + // switch to read+write for 2P, no need to recheck radiobuttons + if (movie_readonly) FCEUI_MovieToggleReadOnly(); + multitrack_recording_joypad = MULTITRACK_RECORDING_2P; + break; + case IDC_RADIO5: + // switch to read+write for 3P, no need to recheck radiobuttons + if (movie_readonly) FCEUI_MovieToggleReadOnly(); + multitrack_recording_joypad = MULTITRACK_RECORDING_3P; + break; + case IDC_RADIO6: + // switch to read+write for 4P, no need to recheck radiobuttons + if (movie_readonly) FCEUI_MovieToggleReadOnly(); + multitrack_recording_joypad = MULTITRACK_RECORDING_4P; + break; + case ID_VIEW_SHOWDOTINEMPTYCELLS: + TASEdit_show_dot ^= 1; + CheckMenuItem(hmenu, ID_VIEW_SHOWDOTINEMPTYCELLS, TASEdit_show_dot?MF_CHECKED : MF_UNCHECKED); + RedrawList(); + break; } break; @@ -1494,6 +1626,14 @@ void EnterTasEdit() DoPriority(); // clear "Disable speed throttling" eoptions &= ~EO_NOTHROTTLE; + // switch off autosaves + saved_EnableAutosave = EnableAutosave; + EnableAutosave = 0; + // switch on savestates compression + saved_compressSavestates = compressSavestates; + compressSavestates = true; + + UpdateCheckedMenuItems(); hmenu = GetMenu(hwndTasEdit); @@ -1503,10 +1643,12 @@ void EnterTasEdit() CheckMenuItem(hmenu, ID_VIEW_SHOW_LAG_FRAMES, TASEdit_show_lag_frames?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); SetWindowPos(hwndTasEdit,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); } - // either start new project or use current movie + project.init(); + // either start new movie or use current movie if (movieMode == MOVIEMODE_INACTIVE) { FCEUI_StopMovie(); @@ -1518,29 +1660,38 @@ void EnterTasEdit() //use current movie to create a new project FCEUI_StopMovie(); } - // set progressbar property - SendMessage(hwndProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSBAR_WIDTH)); + // always start work from read-only mode, ready to switch to MULTITRACK_RECORDING_ALL + movie_readonly = true; + multitrack_recording_joypad = MULTITRACK_RECORDING_ALL; + RecheckRecordingRadioButtons(); + movieMode = MOVIEMODE_TASEDIT; // init variables lastCursor = -1; + old_project_changed = false; old_pauseframe = 0; old_show_pauseframe = show_pauseframe = false; old_rewind_button_state = rewind_button_state = false; old_forward_button_state = forward_button_state = false; - old_emu_paused = true; + old_emu_paused = emu_paused = true; SeekingStop(); - FCEU_DispMessage("Tasedit engaged",0); - movieMode = MOVIEMODE_TASEDIT; currMovieData.TryDumpIncremental(); + FCEU_DispMessage("Tasedit engaged",0); } -void ExitTasEdit() +bool ExitTasEdit() { - if (!CheckSaveChanges()) return; + if (!AskSaveProject()) return false; + DestroyWindow(hwndTasEdit); hwndTasEdit = 0; SeekingStop(); TASEdit_focus = false; // restore "eoptions" eoptions = saved_eoptions; + // restore autosaves + EnableAutosave = saved_EnableAutosave; + // restore compression + compressSavestates = saved_compressSavestates; + DoPriority(); UpdateCheckedMenuItems(); // clear "Background TASEdit input" @@ -1551,4 +1702,5 @@ void ExitTasEdit() movieMode = MOVIEMODE_INACTIVE; FCEU_DispMessage("Tasedit disengaged",0); CreateCleanMovie(); + return true; } diff --git a/src/drivers/win/tasedit.h b/src/drivers/win/tasedit.h index 5f686a03..c1001749 100644 --- a/src/drivers/win/tasedit.h +++ b/src/drivers/win/tasedit.h @@ -9,6 +9,12 @@ #define PAUSEFRAME_BLINKING_PERIOD 100 #define PROGRESSBAR_WIDTH 200 #define HOLD_REPEAT_DELAY 250 // in milliseconds +// multitrack +#define MULTITRACK_RECORDING_ALL 0 +#define MULTITRACK_RECORDING_1P 1 +#define MULTITRACK_RECORDING_2P 2 +#define MULTITRACK_RECORDING_3P 3 +#define MULTITRACK_RECORDING_4P 4 // listview column names #define COLUMN_ICONS 0 #define COLUMN_FRAMENUM 1 @@ -62,16 +68,18 @@ // ----------------------------- void EnterTasEdit(); -void ExitTasEdit(); +bool ExitTasEdit(); void UpdateTasEdit(); void UpdateList(); +void InputChanged(); void InvalidateGreenZone(int after); bool JumpToFrame(int index); int FindBeginningOfGreenZone(int starting_index); void FollowPlayback(); void ClearSelection(); -void AddFourscoreColumns(); -void RemoveFourscoreColumns(); +void AddFourscore(); +void RemoveFourscore(); +void RedrawWindowCaption(); void RedrawTasedit(); void RedrawList(); void RedrawRow(int index); @@ -83,4 +91,12 @@ void UnpauseEmulation(); void ToggleJoypadBit(int column_index, int row_index, UINT KeyFlags); void Tasedit_RewindFrame(); void Tasedit_ForwardFrame(); -void StartFromZero(); \ No newline at end of file +void StartFromZero(); +void SwitchToReadOnly(); +void UncheckRecordingRadioButtons(); +void RecheckRecordingRadioButtons(); +void OpenProject(); +bool SaveProject(); +bool SaveProjectAs(); +bool AskSaveProject(); + diff --git a/src/drivers/win/taseditlib/taseditproj.cpp b/src/drivers/win/taseditlib/taseditproj.cpp index accc54bc..05172e4a 100644 --- a/src/drivers/win/taseditlib/taseditproj.cpp +++ b/src/drivers/win/taseditlib/taseditproj.cpp @@ -16,7 +16,7 @@ TASEDIT_PROJECT::TASEDIT_PROJECT() //Non parameterized constructor, loads projec } -void TASEDIT_PROJECT::init() //TODO: rip this out! This should be the class constructor instead +void TASEDIT_PROJECT::init() { projectName=""; fm2FileName=""; @@ -53,9 +53,10 @@ void TASEDIT_PROJECT::SetProjectFile(std::string e) projectFile = e; } -bool TASEDIT_PROJECT::SaveProject() +bool TASEDIT_PROJECT::saveProject() { std::string PFN = GetProjectFile(); + if (PFN.empty()) return false; const char* filename = PFN.c_str(); EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename,"wb"); //ofs << GetProjectName() << std::endl; diff --git a/src/drivers/win/taseditlib/taseditproj.h b/src/drivers/win/taseditlib/taseditproj.h index 2d209d6e..db4ce24c 100644 --- a/src/drivers/win/taseditlib/taseditproj.h +++ b/src/drivers/win/taseditlib/taseditproj.h @@ -60,12 +60,14 @@ public: void SetProjectFile(std::string e); //Guess what these functions are for... - bool SaveProject(); + bool saveProject(); bool LoadProject(std::string PFN); bool Export2FM2(std::string filename); //creates a fm2 out of header, comments, subtitles, and main branch input log, return false if any errors occur void AddInputLog(std::vector records, std::string fn); //Receives a vector of movie records & a filename, and saves them to disk (as .log files), and adds filename to inputlog vector + bool changed; // If there are unsaved changes. + private: std::string projectName; //The TASEdit Project's name std::string fm2FileName; //The main branch ilog file (todo rename more appropriately) @@ -76,5 +78,4 @@ private: std::vector comments; std::vector subtitles; - bool changed; // If there are unsaved changes. }; diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 712bae85..0a41fad3 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -2805,11 +2805,26 @@ void UpdateMenuHotkeys() combined = "&Cheats...\t" + combo; ChangeMenuItemText(MENU_CHEATS, combined); + //Open RAM Search + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_TOOL_OPENRAMSEARCH]); + combined = "&RAM Search...\t" + combo; + ChangeMenuItemText(ID_RAM_SEARCH, combined); + + //Open RAM Watch + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_TOOL_OPENRAMWATCH]); + combined = "&RAM Watch...\t" + combo; + ChangeMenuItemText(ID_RAM_WATCH, combined); + //Open Memory Watch combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_TOOL_OPENMEMORYWATCH]); combined = "&Memory Watch...\t" + combo; ChangeMenuItemText(MENU_MEMORY_WATCH, combined); + //Open TAS Edit + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MISC_OPENTASEDIT]); + combined = "&TAS Edit...\t" + combo; + ChangeMenuItemText(MENU_TASEDIT, combined); + //-------------------------------Debug-------------------------------------- //Open Debugger combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_TOOL_OPENDEBUGGER]); diff --git a/src/movie.cpp b/src/movie.cpp index 2b3a465a..e51a36e4 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -132,13 +132,13 @@ void MovieData::TryDumpIncremental() // if movie length is less than currFrame, pad it with empty frames if(currFrameCounter >= (int)currMovieData.records.size() || currMovieData.records.size()==0) currMovieData.insertEmpty(-1, 1 + currFrameCounter - (int)currMovieData.records.size()); + if (currFrameCounter >= (int)currMovieData.frames_flags.size()) + currMovieData.frames_flags.resize(currFrameCounter+1); //always log savestates in taseditor mode currMovieData.storeTasSavestate(currFrameCounter, Z_DEFAULT_COMPRESSION); // also log frame_flags if (currFrameCounter > 0) { - if ((int)currMovieData.frames_flags.size() <= currFrameCounter) - currMovieData.frames_flags.resize(currFrameCounter+1); // lagFlag indicates that lag was in previous frame currMovieData.frames_flags[currFrameCounter-1] = (lagFlag)?LAG_FLAG_BIT:0; }