* Tasedit: no more slow seeking and no NewProject in File menu
* Tasedit: input history, undo (Ctrl-Z), redo (Ctrl-Y) * Tasedit: greenzone reduces only from the point with actual differences were found * Tasedit: history ListView, jumping to any position * Tasedit: Config->Set max Undo levels (1-999, 100) * Tasedit: View->Jump when making undo, undo hint line * Tasedit: saving/loading history to .tas file
This commit is contained in:
parent
8b9774878b
commit
fd28f4c2b0
|
@ -75,6 +75,8 @@ extern bool TASEdit_bind_markers;
|
|||
extern bool TASEdit_restore_position;
|
||||
extern bool TASEdit_show_dot;
|
||||
extern int TASEdit_greenzone_capacity;
|
||||
extern int TasEdit_undo_levels;
|
||||
extern bool TASEdit_jump_to_undo;
|
||||
|
||||
//window positions and sizes:
|
||||
extern int ChtPosX,ChtPosY;
|
||||
|
@ -299,6 +301,8 @@ static CFGSTRUCT fceuconfig[] = {
|
|||
AC(TASEdit_restore_position),
|
||||
AC(TASEdit_show_dot),
|
||||
AC(TASEdit_greenzone_capacity),
|
||||
AC(TasEdit_undo_levels),
|
||||
AC(TASEdit_jump_to_undo),
|
||||
AC(lagCounterDisplay),
|
||||
AC(oldInputDisplay),
|
||||
AC(movieSubtitles),
|
||||
|
|
|
@ -219,7 +219,6 @@ TASEDITMENU MENU
|
|||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "&New Project", ID_FILE_NEWPROJECT
|
||||
MENUITEM "&Open Project...", ID_FILE_OPENPROJECT
|
||||
MENUITEM "&Save Project\tCtrl+S", ID_FILE_SAVEPROJECT
|
||||
MENUITEM "S&ave Project As...", ID_FILE_SAVEPROJECTAS
|
||||
|
@ -245,17 +244,24 @@ BEGIN
|
|||
MENUITEM "Insert # of Frames\tInsert", ID_EDIT_INSERT
|
||||
MENUITEM "Cl&one\tShift+Ins", ID_EDIT_CLONEFRAMES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "T&runcate movie\tCtrl+T", ID_EDIT_TRUNCATE
|
||||
MENUITEM "Truncate movie\tCtrl+T", ID_EDIT_TRUNCATE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Undo\tCtrl-Z", ID_EDIT_UNDO
|
||||
MENUITEM "&Redo\tCtrl-Y", ID_EDIT_REDO
|
||||
END
|
||||
POPUP "&View"
|
||||
BEGIN
|
||||
MENUITEM "Highlight &Lag Frames", ID_VIEW_SHOW_LAG_FRAMES
|
||||
MENUITEM "Show &Markers", ID_VIEW_SHOW_MARKERS
|
||||
MENUITEM "Show &dot in empty cells", ID_VIEW_SHOWDOTINEMPTYCELLS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Follow undo context", ID_VIEW_JUMPWHENMAKINGUNDO
|
||||
END
|
||||
POPUP "&Config"
|
||||
BEGIN
|
||||
MENUITEM "Set &greenzone capacity", ID_CONFIG_SETGREENZONECAPACITY
|
||||
MENUITEM "Set max undo levels", ID_CONFIG_SETMAXUNDOLEVELS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Mute &Turbo", ID_CONFIG_MUTETURBO
|
||||
MENUITEM "&Bind Markers to Input", ID_CONFIG_BINDMARKERSTOINPUT
|
||||
END
|
||||
|
@ -341,7 +347,7 @@ BEGIN
|
|||
BEGIN
|
||||
MENUITEM "Insert # of Frames", MENU_CONTEXT_STRAY_INSERTFRAMES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "T&runcate movie", ID_CONTEXT_STRAY_TRUNCATE
|
||||
MENUITEM "Truncate movie", ID_CONTEXT_STRAY_TRUNCATE
|
||||
END
|
||||
POPUP "Selected"
|
||||
BEGIN
|
||||
|
@ -353,7 +359,7 @@ BEGIN
|
|||
MENUITEM "Insert # of Frames", ID_CONTEXT_SELECTED_INSERTFRAMES2
|
||||
MENUITEM "Cl&one", ID_SELECTED_CLONE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "T&runcate movie", ID_CONTEXT_SELECTED_TRUNCATE
|
||||
MENUITEM "Truncate movie", ID_CONTEXT_SELECTED_TRUNCATE
|
||||
END
|
||||
END
|
||||
|
||||
|
@ -1348,8 +1354,8 @@ 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,298,370
|
||||
GROUPBOX "Playback control",IDC_STATIC,310,5,118,62,BS_CENTER,WS_EX_RIGHT
|
||||
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
|
||||
|
@ -1360,12 +1366,11 @@ BEGIN
|
|||
CONTROL " Follow cursor",CHECK_FOLLOW_CURSOR,"Button",BS_AUTOCHECKBOX,315,30,105,12
|
||||
CONTROL " Auto-restore last position",CHECK_AUTORESTORE_PLAYBACK,
|
||||
"Button",BS_AUTOCHECKBOX,315,53,105,12
|
||||
GROUPBOX "Recording input",IDC_STATIC,310,68,118,48,BS_CENTER,WS_EX_RIGHT
|
||||
GROUPBOX "Editing",IDC_STATIC,310,118,118,29,BS_CENTER,WS_EX_RIGHT
|
||||
GROUPBOX "Bookmarks",IDC_STATIC,310,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,315,159,108,88
|
||||
GROUPBOX "Project Input Logs",IDC_STATIC,310,252,118,123,BS_CENTER,WS_EX_RIGHT
|
||||
CONTROL "",IDC_LIST2,"SysListView32",LVS_LIST | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER,315,263,108,108,WS_EX_LEFTSCROLLBAR
|
||||
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_STATIC,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
|
||||
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
|
||||
|
@ -1374,6 +1379,7 @@ BEGIN
|
|||
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
|
||||
END
|
||||
|
||||
ASSEMBLER DIALOGEX 0, 0, 202, 135
|
||||
|
@ -2026,6 +2032,8 @@ BEGIN
|
|||
"T", ACCEL_CTRL_T, VIRTKEY, CONTROL, NOINVERT
|
||||
"V", ACCEL_CTRL_V, VIRTKEY, CONTROL, NOINVERT
|
||||
"X", ACCEL_CTRL_X, VIRTKEY, CONTROL, NOINVERT
|
||||
"Y", ACCEL_CTRL_Y, VIRTKEY, CONTROL, NOINVERT
|
||||
"Z", ACCEL_CTRL_Z, VIRTKEY, CONTROL, NOINVERT
|
||||
VK_DELETE, ACCEL_DEL, VIRTKEY, NOINVERT
|
||||
VK_INSERT, ACCEL_INS, VIRTKEY, NOINVERT
|
||||
VK_INSERT, ACCEL_SHIFT_INS, VIRTKEY, SHIFT, NOINVERT
|
||||
|
|
|
@ -396,8 +396,8 @@
|
|||
#define IDC_BUTTON8 1146
|
||||
#define IDC_EDIT1 1147
|
||||
#define IDC_BUTTON9 1148
|
||||
#define IDC_LIST2 1149
|
||||
#define IDC_LIST3 1150
|
||||
#define IDC_HISTORYLIST 1149
|
||||
#define IDC_BOOKMARKSLIST 1150
|
||||
#define CHECK_SOUND_MUTETURBO 1179
|
||||
#define IDC_EDIT_AUTHOR 1180
|
||||
#define MEMW_STATIC 1181
|
||||
|
@ -851,6 +851,14 @@
|
|||
#define ID_EDIT_CLONEFRAMES 40460
|
||||
#define ACCEL_SHIFT_INS 40461
|
||||
#define ID_SELECTED_CLONE 40463
|
||||
#define ID_CONFIG_Q 40464
|
||||
#define ACCEL_CTRL_Z 40465
|
||||
#define ACCEL_CTRL_Y 40466
|
||||
#define ID_EDIT_UNDO 40468
|
||||
#define ID_EDIT_REDO 40469
|
||||
#define ID_CONFIG_SETMAXUNDOLEVELS 40470
|
||||
#define ID_VIEW_X 40471
|
||||
#define ID_VIEW_JUMPWHENMAKINGUNDO 40472
|
||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||
#define MW_ValueLabel2 65423
|
||||
#define MW_ValueLabel1 65426
|
||||
|
@ -860,7 +868,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 160
|
||||
#define _APS_NEXT_COMMAND_VALUE 40464
|
||||
#define _APS_NEXT_COMMAND_VALUE 40473
|
||||
#define _APS_NEXT_CONTROL_VALUE 1263
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,21 @@
|
|||
#include "movie.h"
|
||||
|
||||
#define FRAMES_TOO_FAR 60
|
||||
|
||||
#define NUM_JOYPADS 4
|
||||
#define NUM_JOYPAD_BUTTONS 8
|
||||
#define GREENZONE_DEFAULT_CAPACITY 100000
|
||||
#define GREENZONE_MIN_CAPACITY 1
|
||||
#define GREENZONE_MAX_CAPACITY 200000 // maybe even more
|
||||
#define PAUSEFRAME_BLINKING_PERIOD 100
|
||||
#define PROGRESSBAR_WIDTH 200
|
||||
#define HOLD_REPEAT_DELAY 250 // in milliseconds
|
||||
|
||||
#define GREENZONE_CAPACITY_DEFAULT 100000
|
||||
#define GREENZONE_CAPACITY_MIN 1
|
||||
#define GREENZONE_CAPACITY_MAX 200000 // maybe even more
|
||||
|
||||
#define UNDO_LEVELS_MIN 1
|
||||
#define UNDO_LEVELS_MAX 999
|
||||
#define UNDO_LEVELS_DEFAULT 100
|
||||
|
||||
#define UNDO_HINT_TIME 200
|
||||
|
||||
// multitrack
|
||||
#define MULTITRACK_RECORDING_ALL 0
|
||||
#define MULTITRACK_RECORDING_1P 1
|
||||
|
@ -54,31 +61,42 @@
|
|||
#define DIGITS_IN_FRAMENUM 7
|
||||
// listview colors
|
||||
#define NORMAL_FRAMENUM_COLOR 0xFFFFFF
|
||||
#define UNDOHINT_FRAMENUM_COLOR 0xF9DDE6
|
||||
#define MARKED_FRAMENUM_COLOR 0xC0FCFF
|
||||
#define CUR_MARKED_FRAMENUM_COLOR 0xDEF7F4
|
||||
#define CUR_FRAMENUM_COLOR 0xFCF1CE
|
||||
#define GREENZONE_FRAMENUM_COLOR 0xDDFFDD
|
||||
#define LAG_FRAMENUM_COLOR 0xDBDAFF
|
||||
#define NORMAL_INPUT_COLOR1 0xF0F0F0
|
||||
#define UNDOHINT_INPUT_COLOR1 0xF6CCDD
|
||||
#define CUR_INPUT_COLOR1 0xF7E9B2
|
||||
#define GREENZONE_INPUT_COLOR1 0xC3FFC3
|
||||
#define LAG_INPUT_COLOR1 0xCCC8EE
|
||||
#define NORMAL_INPUT_COLOR2 0xDEDEDE
|
||||
#define UNDOHINT_INPUT_COLOR2 0xE5B7CC
|
||||
#define CUR_INPUT_COLOR2 0xE4D8A8
|
||||
#define GREENZONE_INPUT_COLOR2 0xAEE2AE
|
||||
#define LAG_INPUT_COLOR2 0xB8B3E2
|
||||
|
||||
#define HISTORY_COHERENT_COLOR 0xF9DDE6
|
||||
#define HISTORY_NORMAL_COLOR 0xFFFFFF
|
||||
|
||||
// -----------------------------
|
||||
void EnterTasEdit();
|
||||
void InitDialog();
|
||||
bool ExitTasEdit();
|
||||
void UpdateTasEdit();
|
||||
void UpdateList();
|
||||
void UpdateProgressbar(int frame);
|
||||
void InputChanged();
|
||||
void UpdateHistoryList();
|
||||
void UpdateProgressbar(int a, int b);
|
||||
void InputChangedRec();
|
||||
void InvalidateGreenZone(int after);
|
||||
bool JumpToFrame(int index);
|
||||
int FindBeginningOfGreenZone(int starting_index);
|
||||
bool CheckItemVisible(int frame);
|
||||
void FollowPlayback();
|
||||
void FollowUndo();
|
||||
void FollowRedo();
|
||||
void ClearSelection();
|
||||
void ClearRowSelection(int index);
|
||||
void AddFourscore();
|
||||
|
@ -86,6 +104,7 @@ void RemoveFourscore();
|
|||
void RedrawWindowCaption();
|
||||
void RedrawTasedit();
|
||||
void RedrawList();
|
||||
void RedrawHistoryList();
|
||||
void RedrawRow(int index);
|
||||
void SeekingStart(int finish_frame);
|
||||
void SeekingStop();
|
||||
|
@ -108,3 +127,13 @@ void SelectMidMarkers();
|
|||
void CloneFrames();
|
||||
void InsertFrames();
|
||||
void DeleteFrames();
|
||||
void ClearFrames(bool cut = false);
|
||||
void ColumnSet(int column);
|
||||
bool Copy();
|
||||
void Cut();
|
||||
bool Paste();
|
||||
void Truncate();
|
||||
void HistoryGetDispInfo(NMLVDISPINFO* nmlvDispInfo);
|
||||
LONG HistoryCustomDraw(NMLVCUSTOMDRAW* msg);
|
||||
void HistoryClick(LPNMITEMACTIVATE info);
|
||||
|
||||
|
|
|
@ -0,0 +1,600 @@
|
|||
//Implementation file of Input History and Input Snapshot classes (for Undo feature)
|
||||
|
||||
#include "movie.h"
|
||||
#include "inputhistory.h"
|
||||
#include "zlib.h"
|
||||
|
||||
extern void FCEU_printf(char *format, ...);
|
||||
extern void RedrawHistoryList();
|
||||
extern void UpdateHistoryList();
|
||||
extern void UpdateProgressbar(int a, int b);
|
||||
|
||||
char modCaptions[23][12] = {"Init",
|
||||
"Change",
|
||||
"Set",
|
||||
"Unset",
|
||||
"Insert",
|
||||
"Delete",
|
||||
"Truncate",
|
||||
"Clear",
|
||||
"Cut",
|
||||
"Paste",
|
||||
"PasteInsert",
|
||||
"Clone",
|
||||
"Record",
|
||||
"Branch0",
|
||||
"Branch1",
|
||||
"Branch2",
|
||||
"Branch3",
|
||||
"Branch4",
|
||||
"Branch5",
|
||||
"Branch6",
|
||||
"Branch7",
|
||||
"Branch8",
|
||||
"Branch9"};
|
||||
char joypadCaptions[4][5] = {"(1P)", "(2P)", "(3P)", "(4P)"};
|
||||
|
||||
INPUT_SNAPSHOT::INPUT_SNAPSHOT()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::init(MovieData& md)
|
||||
{
|
||||
// retrieve input data from movie data
|
||||
size = md.getNumRecords();
|
||||
fourscore = md.fourscore;
|
||||
int num = (fourscore)?4:2;
|
||||
joysticks.resize(num*size); // it's much faster to have this format [joy + frame << JOY_POWER] than have [frame][joy]
|
||||
hot_changes.resize(num*size * HOTCHANGE_BYTES_PER_JOY);
|
||||
int pos = 0;
|
||||
if (fourscore)
|
||||
{
|
||||
for (int frame = 0; frame < size; ++frame)
|
||||
{
|
||||
joysticks[pos++] = 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];
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int frame = 0; frame < size; ++frame)
|
||||
{
|
||||
joysticks[pos++] = md.records[frame].joysticks[0];
|
||||
joysticks[pos++] = md.records[frame].joysticks[1];
|
||||
}
|
||||
}
|
||||
coherent = true;
|
||||
// save time to description
|
||||
time_t raw_time;
|
||||
time(&raw_time);
|
||||
struct tm * timeinfo = localtime(&raw_time);
|
||||
strftime(description, 10, "%H:%M:%S ", timeinfo);
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::toMovie(MovieData& md, int start)
|
||||
{
|
||||
// write input data to movie data
|
||||
md.records.resize(size);
|
||||
md.frames_flags.resize(size);
|
||||
if (fourscore)
|
||||
{
|
||||
int pos = start << 2;
|
||||
for (int frame = start; frame < size; ++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++];
|
||||
}
|
||||
} else
|
||||
{
|
||||
int pos = start << 1;
|
||||
for (int frame = start; frame < size; ++frame)
|
||||
{
|
||||
md.records[frame].joysticks[0] = joysticks[pos++];
|
||||
md.records[frame].joysticks[1] = joysticks[pos++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::save(EMUFILE *os)
|
||||
{
|
||||
// write vars
|
||||
write32le(size, os);
|
||||
if (fourscore) write8le(4, os); else write8le((uint8)0, os);
|
||||
if (coherent) write8le(1, os); else write8le((uint8)0, os);
|
||||
write32le(jump_frame, os);
|
||||
// write description
|
||||
int len = strlen(description);
|
||||
write8le(len, os);
|
||||
os->fwrite(&description[0], len);
|
||||
// compress and save joysticks data
|
||||
len = joysticks.size();
|
||||
int comprlen = (len>>9)+12 + len;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
int e = compress(cbuf.data(), (uLongf*)&comprlen,(uint8*)joysticks.data(),len);
|
||||
// write size
|
||||
write32le(comprlen, os);
|
||||
os->fwrite(cbuf.data(), comprlen);
|
||||
// compress and save hot_changes data
|
||||
len = hot_changes.size();
|
||||
comprlen = (len>>9)+12 + len;
|
||||
std::vector<uint8> cbuf2(comprlen);
|
||||
e = compress(cbuf2.data(),(uLongf*)&comprlen,(uint8*)hot_changes.data(),len);
|
||||
// write size
|
||||
write32le(comprlen, os);
|
||||
os->fwrite(cbuf2.data(), comprlen);
|
||||
}
|
||||
bool INPUT_SNAPSHOT::load(EMUFILE *is)
|
||||
{
|
||||
int len;
|
||||
uint8 tmp;
|
||||
// read vars
|
||||
if (!read32le(&size, is)) return false;
|
||||
if (!read8le(&tmp, is)) return false;
|
||||
fourscore = (tmp != 0);
|
||||
if (!read8le(&tmp, is)) return false;
|
||||
coherent = (tmp != 0);
|
||||
if (!read32le(&jump_frame, is)) return false;
|
||||
// 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;
|
||||
description[tmp] = 0; // add '0' because it wasn't saved
|
||||
// read and uncompress joysticks data
|
||||
len = (fourscore)?4*size:2*size;
|
||||
joysticks.resize(len);
|
||||
// read size
|
||||
int comprlen;
|
||||
if (!read32le(&comprlen, is)) return false;
|
||||
if (comprlen <= 0 || comprlen > len) return false;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
if (is->fread(cbuf.data(),comprlen) != comprlen) return false;
|
||||
int e = uncompress((uint8*)joysticks.data(),(uLongf*)&len,cbuf.data(),comprlen);
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) return false;
|
||||
// read and uncompress hot_changes data
|
||||
len = (fourscore) ? 4*size*HOTCHANGE_BYTES_PER_JOY : 2*size*HOTCHANGE_BYTES_PER_JOY;
|
||||
hot_changes.resize(len);
|
||||
// read size
|
||||
if (!read32le(&comprlen, is)) return false;
|
||||
if (comprlen <= 0 || comprlen > len) return false;
|
||||
std::vector<uint8> cbuf2(comprlen);
|
||||
if (is->fread(cbuf2.data(),comprlen) != comprlen) return false;
|
||||
e = uncompress(hot_changes.data(),(uLongf*)&len,cbuf.data(),comprlen);
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) return false;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
// read description
|
||||
if (!read8le(&tmp1, is)) return false;
|
||||
if (is->fseek(tmp1, SEEK_CUR) != 0) return false;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// return true if any difference is found
|
||||
bool INPUT_SNAPSHOT::checkDiff(INPUT_SNAPSHOT& inp)
|
||||
{
|
||||
if (size != inp.size) return true;
|
||||
if (findFirstChange(inp) >= 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if joypads differ
|
||||
bool INPUT_SNAPSHOT::checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy)
|
||||
{
|
||||
if (fourscore)
|
||||
{
|
||||
int pos = frame << 2;
|
||||
if (pos < (inp.size << 2))
|
||||
{
|
||||
if (joysticks[pos+joy] != inp.joysticks[pos+joy]) return true;
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos+joy]) return true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
int pos = frame << 1;
|
||||
if (pos < (inp.size << 1))
|
||||
{
|
||||
if (joysticks[pos+joy] != inp.joysticks[pos+joy]) return true;
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos+joy]) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// return number of first frame of difference
|
||||
int INPUT_SNAPSHOT::findFirstChange(INPUT_SNAPSHOT& inp, int start, int end)
|
||||
{
|
||||
// search for differences to the specified end (or to size)
|
||||
if (end < 0 || end >= size) end = size-1;
|
||||
|
||||
if (fourscore)
|
||||
{
|
||||
int inp_end = inp.size << 2;
|
||||
end = (end << 2) + 3;
|
||||
for (int pos = start << 2; pos <= end; ++pos)
|
||||
{
|
||||
// if found different byte, or found emptiness in inp when there's non-zero value here
|
||||
if (pos < inp_end)
|
||||
{
|
||||
if (joysticks[pos] != inp.joysticks[pos]) return (pos >> 2);
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos]) return (pos >> 2);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
int inp_end = inp.size << 1;
|
||||
end = (end << 1) + 1;
|
||||
for (int pos = start << 1; pos <= end; ++pos)
|
||||
{
|
||||
// if found different byte, or found emptiness in inp when there's non-zero value here
|
||||
if (pos < inp_end)
|
||||
{
|
||||
if (joysticks[pos] != inp.joysticks[pos]) return (pos >> 1);
|
||||
} else
|
||||
{
|
||||
if (joysticks[pos]) return (pos >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if current size is less then previous return size-1 as the frame of difference
|
||||
if (size < inp.size) return size-1;
|
||||
|
||||
return -1; // no changes were found
|
||||
}
|
||||
int INPUT_SNAPSHOT::findFirstChange(MovieData& md)
|
||||
{
|
||||
// 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;
|
||||
|
||||
if (fourscore)
|
||||
{
|
||||
for (int frame = 0, pos = 0; 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;
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int frame = 0, pos = 0; frame <= end; ++frame)
|
||||
{
|
||||
if (joysticks[pos++] != md.records[frame].joysticks[0]) return frame;
|
||||
if (joysticks[pos++] != md.records[frame].joysticks[1]) return frame;
|
||||
}
|
||||
}
|
||||
// if sizes differ, return last frame from the lesser of them
|
||||
if (size != md.getNumRecords()) return end;
|
||||
|
||||
return -1; // no changes were found
|
||||
}
|
||||
|
||||
void INPUT_SNAPSHOT::SetMaxHotChange(int frame, int absolute_button)
|
||||
{
|
||||
if (frame < 0 || frame >= size) return;
|
||||
// set max value (15) to the button hotness
|
||||
if (fourscore)
|
||||
{
|
||||
// 32 buttons, 16bytes
|
||||
if (absolute_button & 1)
|
||||
// odd buttons (B, T, D, R) - set upper 4 bits of the byte
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] &= 0xF0;
|
||||
else
|
||||
// even buttons (A, S, U, L) - set lower 4 bits of the byte
|
||||
hot_changes[(frame << 4) | (absolute_button >> 1)] &= 0x0F;
|
||||
} else
|
||||
{
|
||||
// 16 buttons, 8bytes
|
||||
if (absolute_button & 1)
|
||||
// odd buttons (B, T, D, R) - set upper 4 bits of the byte
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] &= 0xF0;
|
||||
else
|
||||
// even buttons (A, S, U, L) - set lower 4 bits of the byte
|
||||
hot_changes[(frame << 3) | (absolute_button >> 1)] &= 0x0F;
|
||||
}
|
||||
}
|
||||
int INPUT_SNAPSHOT::GetHotChangeInfo(int frame, int absolute_button)
|
||||
{
|
||||
if (frame < 0 || frame >= size) return 0;
|
||||
if (absolute_button < 0 || absolute_button > 31) return 0;
|
||||
|
||||
uint8 val;
|
||||
if (fourscore)
|
||||
// 32 buttons, 16bytes
|
||||
val = hot_changes[(frame << 4) + (absolute_button >> 1)];
|
||||
else
|
||||
// 16 buttons, 8bytes
|
||||
val = hot_changes[(frame << 3) + (absolute_button >> 1)];
|
||||
|
||||
if (absolute_button & 1)
|
||||
// odd buttons (B, T, D, R) - upper 4 bits of the byte
|
||||
return val >> 4;
|
||||
else
|
||||
// even buttons (A, S, U, L) - lower 4 bits of the byte
|
||||
return val & 15;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
INPUT_HISTORY::INPUT_HISTORY()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void INPUT_HISTORY::init(int new_size)
|
||||
{
|
||||
history_size = new_size + 1;
|
||||
// clear snapshots history
|
||||
history_total_items = 0;
|
||||
input_snapshots.resize(history_size);
|
||||
history_start_pos = 0;
|
||||
history_cursor_pos = -1;
|
||||
// create initial snapshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
inp.init(currMovieData);
|
||||
strcat(inp.description, modCaptions[0]);
|
||||
inp.jump_frame = -1;
|
||||
AddInputSnapshotToHistory(inp);
|
||||
}
|
||||
void INPUT_HISTORY::free()
|
||||
{
|
||||
input_snapshots.resize(0);
|
||||
}
|
||||
|
||||
// returns frame of first input change (for greenzone invalidation)
|
||||
int INPUT_HISTORY::jump(int new_pos)
|
||||
{
|
||||
if (new_pos < 0) new_pos = 0; else if (new_pos >= history_total_items) new_pos = history_total_items-1;
|
||||
// if nothing is done, do not invalidate greenzone
|
||||
if (new_pos == history_cursor_pos) return -1;
|
||||
|
||||
// make jump
|
||||
history_cursor_pos = new_pos;
|
||||
int real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
|
||||
int first_change = input_snapshots[real_pos].findFirstChange(currMovieData);
|
||||
if (first_change < 0) return -1; // if somehow there's no changes
|
||||
|
||||
// update current movie
|
||||
input_snapshots[real_pos].toMovie(currMovieData, first_change);
|
||||
RedrawHistoryList();
|
||||
return first_change;
|
||||
}
|
||||
int INPUT_HISTORY::undo()
|
||||
{
|
||||
return jump(history_cursor_pos - 1);
|
||||
}
|
||||
int INPUT_HISTORY::redo()
|
||||
{
|
||||
return jump(history_cursor_pos + 1);
|
||||
}
|
||||
// ----------------------------
|
||||
INPUT_SNAPSHOT& INPUT_HISTORY::GetCurrentSnapshot()
|
||||
{
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
}
|
||||
INPUT_SNAPSHOT& INPUT_HISTORY::GetNextToCurrentSnapshot()
|
||||
{
|
||||
if (history_cursor_pos < history_total_items)
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos + 1) % history_size];
|
||||
else
|
||||
return input_snapshots[(history_start_pos + history_cursor_pos) % history_size];
|
||||
}
|
||||
int INPUT_HISTORY::GetCursorPos()
|
||||
{
|
||||
return history_cursor_pos;
|
||||
}
|
||||
int INPUT_HISTORY::GetTotalItems()
|
||||
{
|
||||
return history_total_items;
|
||||
}
|
||||
char* INPUT_HISTORY::GetItemDesc(int pos)
|
||||
{
|
||||
return input_snapshots[(history_start_pos + pos) % history_size].description;
|
||||
}
|
||||
bool INPUT_HISTORY::GetItemCoherence(int pos)
|
||||
{
|
||||
return input_snapshots[(history_start_pos + pos) % history_size].coherent;
|
||||
}
|
||||
// ----------------------------
|
||||
void INPUT_HISTORY::AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp)
|
||||
{
|
||||
// history uses conveyor of snapshots (vector with fixed size) to aviod resizing which is awfully expensive with such large objects as INPUT_SNAPSHOT
|
||||
int real_pos;
|
||||
if (history_cursor_pos+1 >= history_size)
|
||||
{
|
||||
// reached the end of available history_size - move history_start_pos (thus deleting older snapshot)
|
||||
history_cursor_pos = history_size-1;
|
||||
history_start_pos = (history_start_pos + 1) % history_size;
|
||||
} else
|
||||
{
|
||||
// didn't reach the end of history yet
|
||||
history_cursor_pos++;
|
||||
if (history_cursor_pos < history_total_items)
|
||||
{
|
||||
// overwrite old snapshot
|
||||
real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
// compare with the snapshot we're going to overwrite, if it's different then break the chain of coherent snapshots
|
||||
if (input_snapshots[real_pos].checkDiff(inp))
|
||||
{
|
||||
for (int i = history_cursor_pos+1; i < history_total_items; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
input_snapshots[real_pos].coherent = false;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// add new smapshot
|
||||
history_total_items = history_cursor_pos+1;
|
||||
UpdateHistoryList();
|
||||
}
|
||||
}
|
||||
// write snapshot
|
||||
real_pos = (history_start_pos + history_cursor_pos) % history_size;
|
||||
input_snapshots[real_pos] = inp;
|
||||
RedrawHistoryList();
|
||||
}
|
||||
|
||||
// returns frame of first actual change
|
||||
int INPUT_HISTORY::RegisterInputChanges(int mod_type, int start, int end)
|
||||
{
|
||||
// create new input shanshot
|
||||
INPUT_SNAPSHOT inp;
|
||||
inp.init(currMovieData);
|
||||
// check if there are 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);
|
||||
if (first_changes >= 0)
|
||||
{
|
||||
// differences found
|
||||
// fade old hot_changes by 1
|
||||
|
||||
// highlight new hot changes
|
||||
|
||||
// fill description
|
||||
strcat(inp.description, modCaptions[mod_type]);
|
||||
switch (mod_type)
|
||||
{
|
||||
case MODTYPE_CHANGE:
|
||||
case MODTYPE_SET:
|
||||
case MODTYPE_UNSET:
|
||||
case MODTYPE_TRUNCATE:
|
||||
case MODTYPE_CLEAR:
|
||||
case MODTYPE_CUT:
|
||||
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;
|
||||
}
|
||||
case MODTYPE_INSERT:
|
||||
case MODTYPE_DELETE:
|
||||
case MODTYPE_PASTE:
|
||||
case MODTYPE_PASTEINSERT:
|
||||
case MODTYPE_CLONE:
|
||||
{
|
||||
// for these changes user prefers to see frame of attempted change (selection beginning), not frame of actual differences
|
||||
inp.jump_frame = start;
|
||||
break;
|
||||
}
|
||||
case MODTYPE_RECORD:
|
||||
{
|
||||
// add info which joypads were affected
|
||||
int num = (inp.fourscore)?4:2;
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
if (inp.checkJoypadDiff(input_snapshots[real_pos], first_changes, i))
|
||||
strcat(inp.description, joypadCaptions[i]);
|
||||
}
|
||||
inp.jump_frame = start;
|
||||
}
|
||||
}
|
||||
// add upper and lower frame to description
|
||||
char framenum[11];
|
||||
_itoa(start, framenum, 10);
|
||||
strcat(inp.description, " ");
|
||||
strcat(inp.description, framenum);
|
||||
if (end > start)
|
||||
{
|
||||
_itoa(end, framenum, 10);
|
||||
strcat(inp.description, "-");
|
||||
strcat(inp.description, framenum);
|
||||
}
|
||||
AddInputSnapshotToHistory(inp);
|
||||
}
|
||||
return first_changes;
|
||||
}
|
||||
// ----------------------------
|
||||
void INPUT_HISTORY::save(EMUFILE *os)
|
||||
{
|
||||
int real_pos, last_tick = 0;
|
||||
// write vars
|
||||
write32le(history_cursor_pos, os);
|
||||
write32le(history_total_items, os);
|
||||
// write snapshots starting from history_start_pos
|
||||
for (int i = 0; i < history_total_items; ++i)
|
||||
{
|
||||
real_pos = (history_start_pos + i) % history_size;
|
||||
input_snapshots[real_pos].save(os);
|
||||
UpdateProgressbar(i, history_total_items);
|
||||
}
|
||||
}
|
||||
void INPUT_HISTORY::load(EMUFILE *is)
|
||||
{
|
||||
int i = -1;
|
||||
INPUT_SNAPSHOT inp;
|
||||
// delete old snapshots
|
||||
input_snapshots.resize(history_size);
|
||||
// read vars
|
||||
if (!read32le((uint32 *)&history_cursor_pos, is)) goto error;
|
||||
if (!read32le((uint32 *)&history_total_items, is)) goto error;
|
||||
history_start_pos = 0;
|
||||
// read snapshots
|
||||
int total = history_total_items;
|
||||
if (history_total_items > history_size)
|
||||
{
|
||||
// user can't afford that much undo levels, skip some snapshots
|
||||
int num_snapshots_to_skip = history_total_items - history_size;
|
||||
// first try to skip snapshots over history_cursor_pos (future snapshots), because "redo" is less important than "undo"
|
||||
int num_redo_snapshots = history_total_items-1 - history_cursor_pos;
|
||||
if (num_snapshots_to_skip >= num_redo_snapshots)
|
||||
{
|
||||
// skip all redo snapshots
|
||||
history_total_items = history_cursor_pos+1;
|
||||
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;
|
||||
total -= num_snapshots_to_skip;
|
||||
history_cursor_pos -= num_snapshots_to_skip;
|
||||
}
|
||||
history_total_items -= num_snapshots_to_skip;
|
||||
}
|
||||
// load snapshots
|
||||
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;
|
||||
UpdateProgressbar(i, history_total_items);
|
||||
}
|
||||
// skip redo snapshots if needed
|
||||
for (; i < total; ++i)
|
||||
if (!inp.skipLoad(is)) goto error;
|
||||
|
||||
return;
|
||||
error:
|
||||
// couldn't load full history - reset it
|
||||
FCEU_printf("Error loading history\n");
|
||||
init(history_size-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
//Specification file for Input History and Input Snapshot classes
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define HOTCHANGE_BYTES_PER_JOY 4
|
||||
#define SNAPSHOT_DESC_MAX_LENGTH 50
|
||||
|
||||
#define MODTYPE_INIT 0
|
||||
#define MODTYPE_CHANGE 1
|
||||
#define MODTYPE_SET 2
|
||||
#define MODTYPE_UNSET 3
|
||||
#define MODTYPE_INSERT 4
|
||||
#define MODTYPE_DELETE 5
|
||||
#define MODTYPE_TRUNCATE 6
|
||||
#define MODTYPE_CLEAR 7
|
||||
#define MODTYPE_CUT 8
|
||||
#define MODTYPE_PASTE 9
|
||||
#define MODTYPE_PASTEINSERT 10
|
||||
#define MODTYPE_CLONE 11
|
||||
#define MODTYPE_RECORD 12
|
||||
#define MODTYPE_BRANCH_0 13
|
||||
#define MODTYPE_BRANCH_1 14
|
||||
#define MODTYPE_BRANCH_2 15
|
||||
#define MODTYPE_BRANCH_3 16
|
||||
#define MODTYPE_BRANCH_4 17
|
||||
#define MODTYPE_BRANCH_5 18
|
||||
#define MODTYPE_BRANCH_6 19
|
||||
#define MODTYPE_BRANCH_7 20
|
||||
#define MODTYPE_BRANCH_8 21
|
||||
#define MODTYPE_BRANCH_9 22
|
||||
|
||||
class INPUT_SNAPSHOT
|
||||
{
|
||||
public:
|
||||
INPUT_SNAPSHOT();
|
||||
void init(MovieData& md);
|
||||
void toMovie(MovieData& md, int start = 0);
|
||||
|
||||
void save(EMUFILE *os);
|
||||
bool load(EMUFILE *is);
|
||||
bool skipLoad(EMUFILE *is);
|
||||
|
||||
bool checkDiff(INPUT_SNAPSHOT& inp);
|
||||
bool checkJoypadDiff(INPUT_SNAPSHOT& inp, int frame, int joy);
|
||||
int findFirstChange(INPUT_SNAPSHOT& inp, int start = 0, int end = -1);
|
||||
int findFirstChange(MovieData& md);
|
||||
|
||||
void SetMaxHotChange(int frame, int absolute_button);
|
||||
int GetHotChangeInfo(int frame, int absolute_button);
|
||||
|
||||
int size; // in frames
|
||||
bool fourscore;
|
||||
std::vector<uint8> joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ...
|
||||
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
|
||||
|
||||
bool coherent; // indicates whether this state was made by inputchange of previous state
|
||||
int jump_frame; // for jumping when making undo
|
||||
char description[SNAPSHOT_DESC_MAX_LENGTH];
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class INPUT_HISTORY
|
||||
{
|
||||
public:
|
||||
INPUT_HISTORY();
|
||||
void init(int new_size);
|
||||
void free();
|
||||
|
||||
void save(EMUFILE *os);
|
||||
void load(EMUFILE *is);
|
||||
|
||||
int undo();
|
||||
int redo();
|
||||
int jump(int new_pos);
|
||||
|
||||
void AddInputSnapshotToHistory(INPUT_SNAPSHOT &inp);
|
||||
|
||||
int RegisterInputChanges(int mod_type, int start = 0, int end =-1);
|
||||
|
||||
int InputChanged(int start, int end);
|
||||
int InputInserted(int start);
|
||||
int InputDeleted(int start);
|
||||
|
||||
INPUT_SNAPSHOT& GetCurrentSnapshot();
|
||||
INPUT_SNAPSHOT& GetNextToCurrentSnapshot();
|
||||
int GetCursorPos();
|
||||
int GetTotalItems();
|
||||
char* GetItemDesc(int pos);
|
||||
bool GetItemCoherence(int pos);
|
||||
|
||||
private:
|
||||
std::vector<INPUT_SNAPSHOT> input_snapshots;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
||||
int history_total_items;
|
||||
int history_size;
|
||||
|
||||
};
|
||||
|
|
@ -3,21 +3,23 @@
|
|||
//Contains all the TASEDit project and all files/settings associated with it
|
||||
//Also contains all methods for manipulating the project files/settings, and saving them to disk
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../main.h"
|
||||
#include "taseditproj.h"
|
||||
#include "movie.h"
|
||||
|
||||
TASEDIT_PROJECT::TASEDIT_PROJECT() //Non parameterized constructor, loads project with default values
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TASEDIT_PROJECT::init()
|
||||
void TASEDIT_PROJECT::init(INPUT_HISTORY* history_ptr)
|
||||
{
|
||||
// keep references to other Taseditor objects
|
||||
history = history_ptr;
|
||||
//greenzone = greenzone_ptr;
|
||||
//bookmarks_bookmarks_ptr;
|
||||
|
||||
projectName="";
|
||||
fm2FileName="";
|
||||
projectFile="";
|
||||
|
@ -66,6 +68,8 @@ bool TASEDIT_PROJECT::saveProject()
|
|||
ofs->fputc('\0'); // TODO: Add main branch name.
|
||||
currMovieData.dumpGreenzone(ofs);
|
||||
|
||||
history->save(ofs);
|
||||
|
||||
delete ofs;
|
||||
|
||||
changed=false;
|
||||
|
@ -86,12 +90,18 @@ bool TASEDIT_PROJECT::LoadProject(std::string PFN)
|
|||
|
||||
char branchname;
|
||||
branchname = ifs.fgetc(); // TODO: Add main branch name.
|
||||
|
||||
// try to load greenzone
|
||||
if (!currMovieData.loadGreenzone(&ifs))
|
||||
{
|
||||
// there was some error while loading greenzone - reset playback to frame 0
|
||||
poweron(true);
|
||||
currFrameCounter = 0;
|
||||
}
|
||||
changed=false;
|
||||
// try to load history
|
||||
history->load(&ifs);
|
||||
|
||||
changed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
//All notes are added to teh right columns
|
||||
//All ilog files are listed in the input log list
|
||||
|
||||
#include <string>
|
||||
#include "movie.h"
|
||||
#include "inputhistory.h"
|
||||
|
||||
//The notes feature, displays user notes in the notes column
|
||||
struct TASENote
|
||||
|
@ -48,7 +48,7 @@ class TASEDIT_PROJECT
|
|||
{
|
||||
public:
|
||||
TASEDIT_PROJECT();
|
||||
void init();
|
||||
void init(INPUT_HISTORY* history_ptr);
|
||||
|
||||
std::string GetProjectName();
|
||||
void SetProjectName(std::string e);
|
||||
|
@ -59,14 +59,13 @@ public:
|
|||
std::string GetProjectFile();
|
||||
void SetProjectFile(std::string e);
|
||||
|
||||
//Guess what these functions are for...
|
||||
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<MovieRecord> 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.
|
||||
// public vars
|
||||
bool changed;
|
||||
|
||||
private:
|
||||
std::string projectName; //The TASEdit Project's name
|
||||
|
@ -78,4 +77,6 @@ private:
|
|||
std::vector<std::string> comments;
|
||||
std::vector<std::string> subtitles;
|
||||
|
||||
// references to other important objects of Taseditor
|
||||
INPUT_HISTORY* history;
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "./drivers/win/window.h"
|
||||
extern void AddRecentMovieFile(const char *filename);
|
||||
|
||||
extern void UpdateProgressbar(int frame);
|
||||
extern void UpdateProgressbar(int a, int b);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -598,7 +598,7 @@ int MovieData::dumpGreenzone(EMUFILE *os)
|
|||
{
|
||||
int start = os->ftell();
|
||||
int frame, size;
|
||||
int last_tick = PROGRESSBAR_UPDATE_MIN;
|
||||
int last_tick = 0;
|
||||
// write size
|
||||
write32le(greenZoneCount, os);
|
||||
write32le(currFrameCounter, os);
|
||||
|
@ -609,7 +609,7 @@ int MovieData::dumpGreenzone(EMUFILE *os)
|
|||
// update TASEditor progressbar from time to time
|
||||
if (frame / PROGRESSBAR_UPDATE_RATE > last_tick)
|
||||
{
|
||||
UpdateProgressbar(frame);
|
||||
UpdateProgressbar(frame, greenZoneCount);
|
||||
last_tick = frame / PROGRESSBAR_UPDATE_RATE;
|
||||
}
|
||||
#endif
|
||||
|
@ -622,7 +622,7 @@ int MovieData::dumpGreenzone(EMUFILE *os)
|
|||
// write savestate
|
||||
size = savestates[frame].size();
|
||||
write32le(size, os);
|
||||
os->fwrite(&savestates[frame][0], size);
|
||||
os->fwrite(savestates[frame].data(), size);
|
||||
|
||||
}
|
||||
// write -1 as eof for greenzone
|
||||
|
@ -637,7 +637,7 @@ bool MovieData::loadGreenzone(EMUFILE *is)
|
|||
clearGreenzone();
|
||||
frames_flags.resize(records.size());
|
||||
int frame = 0, prev_frame = 0, size = 0;
|
||||
int last_tick = PROGRESSBAR_UPDATE_MIN;
|
||||
int last_tick = 0;
|
||||
// read size
|
||||
if (read32le((uint32 *)&size, is))
|
||||
{
|
||||
|
@ -660,7 +660,7 @@ bool MovieData::loadGreenzone(EMUFILE *is)
|
|||
// update TASEditor progressbar from time to time
|
||||
if (frame / PROGRESSBAR_UPDATE_RATE > last_tick)
|
||||
{
|
||||
UpdateProgressbar(frame);
|
||||
UpdateProgressbar(frame, greenZoneCount);
|
||||
last_tick = frame / PROGRESSBAR_UPDATE_RATE;
|
||||
}
|
||||
#endif
|
||||
|
@ -674,7 +674,7 @@ bool MovieData::loadGreenzone(EMUFILE *is)
|
|||
{
|
||||
// load savestate
|
||||
savestates[frame].resize(size);
|
||||
if ((int)is->fread((char*)&savestates[frame][0],size) < size) break;
|
||||
if ((int)is->fread(savestates[frame].data(),size) < size) break;
|
||||
prev_frame = frame; // successfully read one greenzone frame info
|
||||
} else
|
||||
{
|
||||
|
@ -691,6 +691,7 @@ bool MovieData::loadGreenzone(EMUFILE *is)
|
|||
} else
|
||||
{
|
||||
// there was some error while reading greenzone
|
||||
FCEU_printf("Error loading greenzone\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -774,6 +775,7 @@ static void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size)
|
|||
numRecords=movieData.loadFrameCount;
|
||||
|
||||
movieData.records.resize(numRecords);
|
||||
movieData.frames_flags.resize(numRecords);
|
||||
for(int i=0;i<numRecords;i++)
|
||||
{
|
||||
movieData.records[i].parseBinary(&movieData,fp);
|
||||
|
@ -845,6 +847,7 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
|
|||
if (stopAfterHeader) return true;
|
||||
int currcount = movieData.records.size();
|
||||
movieData.records.resize(currcount+1);
|
||||
movieData.frames_flags.resize(currcount+1);
|
||||
int preparse = fp->ftell();
|
||||
movieData.records[currcount].parse(&movieData, fp);
|
||||
int postparse = fp->ftell();
|
||||
|
@ -1208,18 +1211,14 @@ void FCEUMOV_AddInputState()
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: check if input actually changed
|
||||
InputChanged();
|
||||
// record buttons
|
||||
if (currMovieData.greenZoneCount>currFrameCounter+1)
|
||||
{
|
||||
InvalidateGreenZone(currFrameCounter);
|
||||
}
|
||||
// TODO: multitracking
|
||||
|
||||
joyports[0].log(mr);
|
||||
joyports[1].log(mr);
|
||||
mr->commands = 0;
|
||||
|
||||
InputChangedRec(); // TODO: don't call function explicitly, taseditor should catch changes in UpdateTasedit function
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#define LAG_FLAG_BIT 1
|
||||
#define MARKER_FLAG_BIT 2
|
||||
|
||||
#define PROGRESSBAR_UPDATE_RATE 3000 // in frames of greenzone
|
||||
#define PROGRESSBAR_UPDATE_MIN 6000 / PROGRESSBAR_UPDATE_RATE
|
||||
#define PROGRESSBAR_UPDATE_RATE 2000 // in frames of greenzone
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
|
|
@ -418,6 +418,7 @@
|
|||
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.xdc</XMLDocumentationFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\tasedit.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\inputhistory.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\texthook.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\throttle.cpp" />
|
||||
<ClCompile Include="..\src\drivers\win\timing.cpp" />
|
||||
|
@ -729,6 +730,7 @@
|
|||
<ClInclude Include="..\src\drivers\win\sound.h" />
|
||||
<ClInclude Include="..\src\drivers\win\state.h" />
|
||||
<ClInclude Include="..\src\drivers\win\tasedit.h" />
|
||||
<ClInclude Include="..\src\drivers\win\taseditlib\inputhistory.h" />
|
||||
<ClInclude Include="..\src\drivers\win\texthook.h" />
|
||||
<ClInclude Include="..\src\drivers\win\throttle.h" />
|
||||
<ClInclude Include="..\src\drivers\win\timing.h" />
|
||||
|
@ -851,6 +853,7 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)auxlib.lua;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<None Include="..\src\pputile.inc" />
|
||||
<None Include="ClassDiagram1.cd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -907,6 +907,7 @@
|
|||
<ClCompile Include="..\src\boards\onebus.cpp">
|
||||
<Filter>boards</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drivers\win\taseditlib\inputhistory.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\cart.h">
|
||||
|
@ -1351,6 +1352,7 @@
|
|||
<ClInclude Include="..\src\drivers\common\nes_ntsc_impl.h">
|
||||
<Filter>drivers\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drivers\win\taseditlib\inputhistory.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\src\drivers\win\res.rc">
|
||||
|
@ -1368,6 +1370,7 @@
|
|||
<Filter>drivers\win\res</Filter>
|
||||
</None>
|
||||
<None Include="..\src\pputile.inc" />
|
||||
<None Include="ClassDiagram1.cd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\src\auxlib.lua" />
|
||||
|
|
Loading…
Reference in New Issue