* Taseditor: cleanup of InputLog

This commit is contained in:
ansstuff 2012-11-07 15:15:13 +00:00
parent 802f73b989
commit 41b11e53c6
4 changed files with 128 additions and 404 deletions

View File

@ -960,7 +960,7 @@ int HISTORY::RegisterLuaChanges(const char* name, int start, bool InsertionDelet
} else } else
{ {
hotchanges_snapshot.inputlog.has_hot_changes = true; hotchanges_snapshot.inputlog.has_hot_changes = true;
hotchanges_snapshot.inputlog.hot_changes.resize(joysticks_per_frame[snap.inputlog.input_type] * hotchanges_snapshot.inputlog.size * HOTCHANGE_BYTES_PER_JOY); hotchanges_snapshot.inputlog.Init_HotChanges();
} }
// insert/delete frames in hotchanges_snapshot, so that it will be the same size as the snap // insert/delete frames in hotchanges_snapshot, so that it will be the same size as the snap
taseditor_lua.InsertDelete_rows_to_Snaphot(hotchanges_snapshot); taseditor_lua.InsertDelete_rows_to_Snaphot(hotchanges_snapshot);

View File

@ -39,50 +39,22 @@ void INPUTLOG::init(MovieData& md, bool hotchanges, int force_input_type)
input_type = GetInputType(md); input_type = GetInputType(md);
else else
input_type = force_input_type; input_type = force_input_type;
int num_joys = joysticks_per_frame[input_type];
// retrieve Input data from movie data // retrieve Input data from movie data
size = md.getNumRecords(); size = md.getNumRecords();
joysticks.resize(BYTES_PER_JOYSTICK * joysticks_per_frame[input_type] * size); // it's much faster to have this format than have [frame][joy] or other structures joysticks.resize(BYTES_PER_JOYSTICK * num_joys * size); // it's much faster to have this format than have [frame][joy] or other structures
commands.resize(size); // commands take 1 byte per frame commands.resize(size); // commands take 1 byte per frame
if (has_hot_changes) if (has_hot_changes)
hot_changes.resize(joysticks_per_frame[input_type] * size * HOTCHANGE_BYTES_PER_JOY); Init_HotChanges();
// fill Input vector // fill Input vector
int pos = 0; int joy;
switch(input_type) for (int frame = 0; frame < size; ++frame)
{ {
case INPUT_TYPE_FOURSCORE: for (joy = num_joys - 1; joy >= 0; joy--)
{ joysticks[frame * num_joys * BYTES_PER_JOYSTICK + joy * BYTES_PER_JOYSTICK] = md.records[frame].joysticks[joy];
for (int frame = 0; frame < size; ++frame) commands[frame] = md.records[frame].commands;
{
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];
commands[frame] = md.records[frame].commands;
}
break;
}
case INPUT_TYPE_2P:
{
for (int frame = 0; frame < size; ++frame)
{
joysticks[pos++] = md.records[frame].joysticks[0];
joysticks[pos++] = md.records[frame].joysticks[1];
commands[frame] = md.records[frame].commands;
}
break;
}
case INPUT_TYPE_1P:
{
for (int frame = 0; frame < size; ++frame)
{
joysticks[pos++] = md.records[frame].joysticks[0];
commands[frame] = md.records[frame].commands;
}
break;
}
} }
already_compressed = false; already_compressed = false;
} }
@ -91,42 +63,13 @@ void INPUTLOG::toMovie(MovieData& md, int start, int end)
if (end < 0 || end >= size) end = size - 1; if (end < 0 || end >= size) end = size - 1;
// write Input data to movie data // write Input data to movie data
md.records.resize(end + 1); md.records.resize(end + 1);
switch(input_type) int num_joys = joysticks_per_frame[input_type];
int joy;
for (int frame = start; frame <= end; ++frame)
{ {
case INPUT_TYPE_FOURSCORE: for (joy = num_joys - 1; joy >= 0; joy--)
{ md.records[frame].joysticks[joy] = joysticks[frame * num_joys * BYTES_PER_JOYSTICK + joy * BYTES_PER_JOYSTICK];
int pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; md.records[frame].commands = commands[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 INPUT_TYPE_2P:
{
int pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type];
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;
}
case INPUT_TYPE_1P:
{
int pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type];
for (int frame = start; frame <= end; ++frame)
{
md.records[frame].joysticks[0] = joysticks[pos++];
md.records[frame].commands = commands[frame];
}
break;
}
} }
} }
@ -265,25 +208,13 @@ uint32 INPUTLOG::fillJoypadsDiff(INPUTLOG& their_log, int frame)
{ {
uint32 joypad_diff_bits = 0; uint32 joypad_diff_bits = 0;
uint32 current_mask = 1; uint32 current_mask = 1;
switch(input_type) if (frame < their_log.size)
{ {
case INPUT_TYPE_FOURSCORE: for (int joy = 0; joy < joysticks_per_frame[input_type]; ++joy)
case INPUT_TYPE_2P:
case INPUT_TYPE_1P:
{ {
int pos = frame * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; if (GetJoystickInfo(frame, joy) != their_log.GetJoystickInfo(frame, joy))
for (int i = 0; i < BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; ++i) joypad_diff_bits |= current_mask;
{ current_mask <<= 1;
if (pos < (their_log.size * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]))
{
if (joysticks[pos+i] != their_log.joysticks[pos+i]) joypad_diff_bits |= current_mask;
} else
{
if (joysticks[pos+i]) joypad_diff_bits |= current_mask;
}
current_mask <<= 1;
}
break;
} }
} }
return joypad_diff_bits; return joypad_diff_bits;
@ -291,82 +222,20 @@ uint32 INPUTLOG::fillJoypadsDiff(INPUTLOG& their_log, int frame)
// return number of first frame of difference between two InputLogs // return number of first frame of difference between two InputLogs
int INPUTLOG::findFirstChange(INPUTLOG& their_log, int start, int end) int INPUTLOG::findFirstChange(INPUTLOG& their_log, int start, int end)
{ {
// if these two InputLogs have different input_type (abnormal situation) then refuse to search and return the beginning
if (their_log.input_type != input_type)
return start;
// search for differences to the specified end (or to the end of this InputLog) // search for differences to the specified end (or to the end of this InputLog)
if (end < 0 || end >= size) end = size-1; if (end < 0 || end >= size) end = size-1;
int their_log_end = their_log.size; int their_log_end = their_log.size;
switch(input_type)
int joy;
int num_joys = joysticks_per_frame[input_type];
for (int frame = start; frame <= end; ++frame)
{ {
case INPUT_TYPE_FOURSCORE: for (joy = num_joys - 1; joy >= 0; joy--)
{ if (GetJoystickInfo(frame, joy) != their_log.GetJoystickInfo(frame, joy)) return frame;
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame) if (GetCommandsInfo(frame) != their_log.GetCommandsInfo(frame)) return frame;
{
// return the frame if found different byte, or found emptiness in their_log when there's non-zero value here
if (frame < their_log_end)
{
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (commands[frame] != their_log.commands[frame]) return frame;
} else
{
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 INPUT_TYPE_2P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame)
{
// return the frame if found different byte, or found emptiness in their_log when there's non-zero value here
if (frame < their_log_end)
{
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (commands[frame] != their_log.commands[frame]) return frame;
} else
{
if (joysticks[pos++]) return frame;
if (joysticks[pos++]) return frame;
if (commands[frame]) return frame;
}
}
break;
}
case INPUT_TYPE_1P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame)
{
// return the frame if found different byte, or found emptiness in their_log when there's non-zero value here
if (frame < their_log_end)
{
if (joysticks[pos] != their_log.joysticks[pos]) return frame;
pos++;
if (commands[frame] != their_log.commands[frame]) return frame;
} else
{
if (joysticks[pos++]) return frame;
if (commands[frame]) return frame;
}
}
break;
}
} }
// no difference was found
// if my_size is less then their_size, return last frame + 1 (= size) as the frame of difference // if my_size is less then their_size, return last frame + 1 (= size) as the frame of difference
if (size < their_log_end) return size; if (size < their_log_end) return size;
// no changes were found // no changes were found
@ -375,70 +244,41 @@ int INPUTLOG::findFirstChange(INPUTLOG& their_log, int start, int end)
// return number of first frame of difference between this InputLog and MovieData // return number of first frame of difference between this InputLog and MovieData
int INPUTLOG::findFirstChange(MovieData& md, int start, int end) int INPUTLOG::findFirstChange(MovieData& md, int start, int end)
{ {
// search for differences to the specified end (or to the end of this InputLog / to the end of the movie) // search for differences to the specified end (or to the end of this InputLog / to the end of the movie data)
if (end < 0 || end >= size) end = size-1; if (end < 0 || end >= size) end = size - 1;
if (end >= md.getNumRecords()) end = md.getNumRecords()-1; if (end >= md.getNumRecords()) end = md.getNumRecords() - 1;
switch(input_type) int joy;
int num_joys = joysticks_per_frame[input_type];
for (int frame = start; frame <= end; ++frame)
{ {
case INPUT_TYPE_FOURSCORE: for (joy = num_joys - 1; joy >= 0; joy--)
{ if (GetJoystickInfo(frame, joy) != md.records[frame].joysticks[joy]) return frame;
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame) if (GetCommandsInfo(frame) != md.records[frame].commands) return 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 INPUT_TYPE_2P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_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;
}
case INPUT_TYPE_1P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame)
{
if (joysticks[pos++] != md.records[frame].joysticks[0]) return frame;
if (commands[frame] != md.records[frame].commands) return frame;
}
break;
}
} }
// no difference was found
// if sizes differ, return last frame + 1 from the lesser of them // if sizes differ, return last frame + 1 from the lesser of them
if (size < md.getNumRecords() && end >= size-1) if (size < md.getNumRecords() && end >= size - 1)
return size; return size;
else if (size > md.getNumRecords() && end >= md.getNumRecords()-1) else if (size > md.getNumRecords() && end >= md.getNumRecords() - 1)
return md.getNumRecords(); return md.getNumRecords();
return -1; // no changes were found return -1;
} }
int INPUTLOG::GetJoystickInfo(int frame, int joy) int INPUTLOG::GetJoystickInfo(int frame, int joy)
{ {
if (frame < 0 || frame >= size) return 0; if (frame < 0 || frame >= size)
switch(input_type) return 0;
{ if (joy > joysticks_per_frame[input_type])
case INPUT_TYPE_FOURSCORE: return 0;
case INPUT_TYPE_2P: return joysticks[frame * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type] + joy];
case INPUT_TYPE_1P:
{
return joysticks[frame * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type] + joy];
}
}
return 0;
} }
int INPUTLOG::GetCommandsInfo(int frame) int INPUTLOG::GetCommandsInfo(int frame)
{ {
if (frame < 0 || frame >= size) return 0; if (frame < 0 || frame >= size)
return 0;
return commands[frame]; return commands[frame];
} }
@ -456,7 +296,7 @@ void INPUTLOG::insertFrames(int at, int frames)
// fill new hotchanges with max value // fill new hotchanges with max value
int lower_limit = joysticks_per_frame[input_type] * (size - frames) * HOTCHANGE_BYTES_PER_JOY; int lower_limit = joysticks_per_frame[input_type] * (size - frames) * HOTCHANGE_BYTES_PER_JOY;
for (int i = hot_changes.size() - 1; i >= lower_limit; i--) for (int i = hot_changes.size() - 1; i >= lower_limit; i--)
hot_changes[i] = 0xFF; hot_changes[i] = BYTE_VALUE_CONTAINING_MAX_HOTCHANGES;
} }
} else } else
{ {
@ -470,7 +310,7 @@ void INPUTLOG::insertFrames(int at, int frames)
{ {
// insert X bytes of hot_changes // insert X bytes of hot_changes
bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
hot_changes.insert(hot_changes.begin() + (at * bytes), frames * bytes, 0xFF); hot_changes.insert(hot_changes.begin() + (at * bytes), frames * bytes, BYTE_VALUE_CONTAINING_MAX_HOTCHANGES);
} }
} }
// data was changed // data was changed
@ -493,24 +333,26 @@ void INPUTLOG::eraseFrame(int frame)
// data was changed // data was changed
already_compressed = false; already_compressed = false;
} }
// -------------------------------------------------------- // -----------------------------------------------------------------------------------------------
void INPUTLOG::Init_HotChanges()
{
hot_changes.resize(joysticks_per_frame[input_type] * size * HOTCHANGE_BYTES_PER_JOY);
}
void INPUTLOG::copyHotChanges(INPUTLOG* source_of_hotchanges, int limit_frame_of_source) void INPUTLOG::copyHotChanges(INPUTLOG* source_of_hotchanges, int limit_frame_of_source)
{ {
// copy hot changes from source InputLog // copy hot changes from source InputLog
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type) if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
{ {
int min = hot_changes.size(); int frames_to_copy = source_of_hotchanges->size;
if (min > (int)source_of_hotchanges->hot_changes.size()) if (frames_to_copy > size)
min = source_of_hotchanges->hot_changes.size(); frames_to_copy = size;
// special case for Branches: if limit_frame if specified, then copy only hotchanges from 0 to limit_frame // special case for Branches: if limit_frame if specified, then copy only hotchanges from 0 to limit_frame
if (limit_frame_of_source >= 0) if (limit_frame_of_source >= 0 && frames_to_copy > limit_frame_of_source)
{ frames_to_copy = limit_frame_of_source;
if (min > limit_frame_of_source * joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY)
min = limit_frame_of_source * joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
}
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], min); int bytes_to_copy = frames_to_copy * joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], bytes_to_copy);
} }
} }
void INPUTLOG::inheritHotChanges(INPUTLOG* source_of_hotchanges) void INPUTLOG::inheritHotChanges(INPUTLOG* source_of_hotchanges)
@ -518,31 +360,31 @@ void INPUTLOG::inheritHotChanges(INPUTLOG* source_of_hotchanges)
// copy hot changes from source InputLog and fade them // copy hot changes from source InputLog and fade them
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type) if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
{ {
int min = hot_changes.size(); int frames_to_copy = source_of_hotchanges->size;
if (min > (int)source_of_hotchanges->hot_changes.size()) if (frames_to_copy > size)
min = source_of_hotchanges->hot_changes.size(); frames_to_copy = size;
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], min); int bytes_to_copy = frames_to_copy * joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
memcpy(&hot_changes[0], &source_of_hotchanges->hot_changes[0], bytes_to_copy);
FadeHotChanges(); FadeHotChanges();
} }
} }
void INPUTLOG::inheritHotChanges_DeleteSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset) void INPUTLOG::inheritHotChanges_DeleteSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset)
{ {
// copy hot changes from source InputLog, but omit deleted frames (which are represented by current selection) // copy hot changes from source InputLog, but omit deleted frames (which are represented by the "frameset")
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type) if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
{ {
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
int frame = 0, pos = 0, source_pos = 0; int frame = 0, pos = 0, source_pos = 0;
int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size(); int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size();
SelectionFrames::iterator it(frameset->begin()); SelectionFrames::iterator it(frameset->begin());
SelectionFrames::iterator current_selection_end(frameset->end()); SelectionFrames::iterator frameset_end(frameset->end());
while (pos < this_size && source_pos < source_size) while (pos < this_size && source_pos < source_size)
{ {
if (it != current_selection_end && frame == *it) if (it != frameset_end && frame == *it)
{ {
// this frame is selected
it++;
// omit the frame // omit the frame
it++;
source_pos += bytes; source_pos += bytes;
} else } else
{ {
@ -558,9 +400,9 @@ void INPUTLOG::inheritHotChanges_DeleteSelection(INPUTLOG* source_of_hotchanges,
} }
void INPUTLOG::inheritHotChanges_InsertSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset) void INPUTLOG::inheritHotChanges_InsertSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset)
{ {
// copy hot changes from source InputLog, but insert filled lines for inserted frames (which are represented by current selection) // copy hot changes from source InputLog, but insert filled lines for inserted frames (which are represented by the "frameset")
SelectionFrames::iterator it(frameset->begin()); SelectionFrames::iterator it(frameset->begin());
SelectionFrames::iterator current_selection_end(frameset->end()); SelectionFrames::iterator frameset_end(frameset->end());
if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type) if (source_of_hotchanges && source_of_hotchanges->has_hot_changes && source_of_hotchanges->input_type == input_type)
{ {
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
@ -568,16 +410,16 @@ void INPUTLOG::inheritHotChanges_InsertSelection(INPUTLOG* source_of_hotchanges,
int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size(); int this_size = hot_changes.size(), source_size = source_of_hotchanges->hot_changes.size();
while (pos < this_size) while (pos < this_size)
{ {
if (it != current_selection_end && frame == *it) if (it != frameset_end && frame == *it)
{ {
// this frame is selected // omit the frame
it++; it++;
region_len++; region_len++;
// set filled line to the frame // set filled line to the frame
memset(&hot_changes[pos], 0xFF, bytes); memset(&hot_changes[pos], BYTE_VALUE_CONTAINING_MAX_HOTCHANGES, bytes);
} else if (source_pos < source_size) } else if (source_pos < source_size)
{ {
// this frame is not selected // this frame should be copied
frame -= region_len; frame -= region_len;
region_len = 0; region_len = 0;
// copy hotchanges of this frame // copy hotchanges of this frame
@ -590,21 +432,21 @@ void INPUTLOG::inheritHotChanges_InsertSelection(INPUTLOG* source_of_hotchanges,
} }
} else } else
{ {
// no old data, just fill selected lines // no old data, just fill "frameset" lines
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
int frame = 0, region_len = 0, pos = 0; int frame = 0, region_len = 0, pos = 0;
int this_size = hot_changes.size(); int this_size = hot_changes.size();
while (pos < this_size) while (pos < this_size)
{ {
if (it != current_selection_end && frame == *it) if (it != frameset_end && frame == *it)
{ {
// this frame is selected // this frame is selected
it++; it++;
region_len++; region_len++;
// set filled line to the frame // set filled line to the frame
memset(&hot_changes[pos], 0xFF, bytes); memset(&hot_changes[pos], BYTE_VALUE_CONTAINING_MAX_HOTCHANGES, bytes);
// exit loop when all frames in the Selection are handled // exit loop when all frames in the Selection are handled
if (it == current_selection_end) break; if (it == frameset_end) break;
} else } else
{ {
// this frame is not selected // this frame is not selected
@ -661,11 +503,11 @@ void INPUTLOG::inheritHotChanges_InsertNum(INPUTLOG* source_of_hotchanges, int s
FadeHotChanges(); FadeHotChanges();
} }
// fill the gap with max_hot lines on frames from "start" to "start+frames" // fill the gap with max_hot lines on frames from "start" to "start+frames"
memset(&hot_changes[bytes * start], 0xFF, bytes * frames); memset(&hot_changes[bytes * start], BYTE_VALUE_CONTAINING_MAX_HOTCHANGES, bytes * frames);
} }
void INPUTLOG::inheritHotChanges_PasteInsert(INPUTLOG* source_of_hotchanges, SelectionFrames* inserted_set) void INPUTLOG::inheritHotChanges_PasteInsert(INPUTLOG* source_of_hotchanges, SelectionFrames* inserted_set)
{ {
// copy hot changes from source InputLog and insert filled lines for inserted frames (which are represented by inserted_set) // copy hot changes from source InputLog and insert filled lines for inserted frames (which are represented by "inserted_set")
int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY; int bytes = joysticks_per_frame[input_type] * HOTCHANGE_BYTES_PER_JOY;
int frame = 0, pos = 0; int frame = 0, pos = 0;
int this_size = hot_changes.size(); int this_size = hot_changes.size();
@ -683,7 +525,7 @@ void INPUTLOG::inheritHotChanges_PasteInsert(INPUTLOG* source_of_hotchanges, Sel
// this frame was inserted // this frame was inserted
it++; it++;
// set filled line to the frame // set filled line to the frame
memset(&hot_changes[pos], 0xFF, bytes); memset(&hot_changes[pos], BYTE_VALUE_CONTAINING_MAX_HOTCHANGES, bytes);
} else if (source_pos < source_size) } else if (source_pos < source_size)
{ {
// copy hotchanges of this frame // copy hotchanges of this frame
@ -704,7 +546,7 @@ void INPUTLOG::inheritHotChanges_PasteInsert(INPUTLOG* source_of_hotchanges, Sel
// this frame was inserted // this frame was inserted
it++; it++;
// set filled line to the frame // set filled line to the frame
memset(&hot_changes[pos], 0xFF, bytes); memset(&hot_changes[pos], BYTE_VALUE_CONTAINING_MAX_HOTCHANGES, bytes);
pos += bytes; pos += bytes;
// exit loop when all inserted_set frames are handled // exit loop when all inserted_set frames are handled
if (it == inserted_set_end) break; if (it == inserted_set_end) break;
@ -719,95 +561,17 @@ void INPUTLOG::inheritHotChanges_PasteInsert(INPUTLOG* source_of_hotchanges, Sel
} }
void INPUTLOG::fillHotChanges(INPUTLOG& their_log, int start, int end) void INPUTLOG::fillHotChanges(INPUTLOG& their_log, int start, int end)
{ {
// if these two InputLogs have different input_type (abnormal situation) then refuse to compare
if (their_log.input_type != input_type)
return;
// compare InputLogs to the specified end (or to the end of this InputLog) // compare InputLogs to the specified end (or to the end of this InputLog)
if (end < 0 || end >= size) end = size-1; if (end < 0 || end >= size) end = size-1;
int their_log_end = their_log.size; uint8 my_joy, their_joy;
switch(input_type) for (int joy = joysticks_per_frame[input_type] - 1; joy >= 0; joy--)
{ {
case INPUT_TYPE_FOURSCORE: for (int frame = start; frame <= end; ++frame)
{ {
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame) my_joy = GetJoystickInfo(frame, joy);
{ their_joy = their_log.GetJoystickInfo(frame, joy);
// consider changed if found different byte, or found emptiness in their_log when there's non-zero value here if (my_joy != their_joy)
if (frame < their_log_end) SetMaxHotChange_Bits(frame, joy, my_joy ^ their_joy);
{
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 1, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 2, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 3, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
} else
{
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos]);
pos++;
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 1, joysticks[pos]);
pos++;
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 2, joysticks[pos]);
pos++;
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 3, joysticks[pos]);
pos++;
}
}
break;
}
case INPUT_TYPE_2P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame)
{
// consider changed if found different byte, or found emptiness in their_log when there's non-zero value here
if (frame < their_log_end)
{
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 1, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
} else
{
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos]);
pos++;
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 1, joysticks[pos]);
pos++;
}
}
break;
}
case INPUT_TYPE_1P:
{
for (int frame = start, pos = start * BYTES_PER_JOYSTICK * joysticks_per_frame[input_type]; frame <= end; ++frame)
{
// consider changed if found different byte, or found emptiness in their_log when there's non-zero value here
if (frame < their_log_end)
{
if (joysticks[pos] != their_log.joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos] ^ their_log.joysticks[pos]);
pos++;
} else
{
if (joysticks[pos])
SetMaxHotChange_Bits(frame, 0, joysticks[pos]);
pos++;
}
}
break;
} }
} }
} }
@ -816,53 +580,21 @@ void INPUTLOG::SetMaxHotChange_Bits(int frame, int joypad, uint8 joy_bits)
{ {
uint8 mask = 1; uint8 mask = 1;
// check all 8 buttons and set max hot_changes for bits that are set // check all 8 buttons and set max hot_changes for bits that are set
for (int i = 0; i < 8; ++i) for (int i = 0; i < BUTTONS_PER_JOYSTICK; ++i)
{ {
if (joy_bits & mask) if (joy_bits & mask)
SetMaxHotChange(frame, joypad * 8 + i); SetMaxHotChange(frame, joypad * BUTTONS_PER_JOYSTICK + i);
mask <<= 1; mask <<= 1;
} }
} }
void INPUTLOG::SetMaxHotChange(int frame, int absolute_button) void INPUTLOG::SetMaxHotChange(int frame, int absolute_button)
{ {
if (frame < 0 || frame >= size || !has_hot_changes) return; if (frame < 0 || frame >= size || !has_hot_changes) return;
// set max value (15) to the button hotness // set max value to the button hotness
switch(input_type) if (absolute_button & 1)
{ hot_changes[frame * (HOTCHANGE_BYTES_PER_JOY * joysticks_per_frame[input_type]) + (absolute_button >> 1)] |= BYTE_VALUE_CONTAINING_MAX_HOTCHANGE_HI;
case INPUT_TYPE_FOURSCORE: else
{ hot_changes[frame * (HOTCHANGE_BYTES_PER_JOY * joysticks_per_frame[input_type]) + (absolute_button >> 1)] |= BYTE_VALUE_CONTAINING_MAX_HOTCHANGE_LO;
// 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;
break;
}
case INPUT_TYPE_2P:
{
// 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;
break;
}
case INPUT_TYPE_1P:
{
// 8 buttons = 4bytes
if (absolute_button & 1)
// odd buttons (B, T, D, R) - set upper 4 bits of the byte
hot_changes[(frame << 2) | (absolute_button >> 1)] |= 0xF0;
else
// even buttons (A, S, U, L) - set lower 4 bits of the byte
hot_changes[(frame << 2) | (absolute_button >> 1)] |= 0x0F;
break;
}
}
} }
void INPUTLOG::FadeHotChanges(int start_byte, int end_byte) void INPUTLOG::FadeHotChanges(int start_byte, int end_byte)
@ -874,11 +606,11 @@ void INPUTLOG::FadeHotChanges(int start_byte, int end_byte)
{ {
if (hot_changes[i]) if (hot_changes[i])
{ {
hi_half = hot_changes[i] >> 4; hi_half = hot_changes[i] >> HOTCHANGE_BITS_PER_VALUE;
low_half = hot_changes[i] & 15; low_half = hot_changes[i] & HOTCHANGE_BITMASK;
if (hi_half) hi_half--; if (hi_half) hi_half--;
if (low_half) low_half--; if (low_half) low_half--;
hot_changes[i] = (hi_half << 4) | low_half; hot_changes[i] = (hi_half << HOTCHANGE_BITS_PER_VALUE) | low_half;
} }
} }
} }
@ -888,34 +620,13 @@ int INPUTLOG::GetHotChangeInfo(int frame, int absolute_button)
if (!has_hot_changes || frame < 0 || frame >= size || absolute_button < 0 || absolute_button >= NUM_JOYPAD_BUTTONS * joysticks_per_frame[input_type]) if (!has_hot_changes || frame < 0 || frame >= size || absolute_button < 0 || absolute_button >= NUM_JOYPAD_BUTTONS * joysticks_per_frame[input_type])
return 0; return 0;
uint8 val; uint8 val = hot_changes[frame * (HOTCHANGE_BYTES_PER_JOY * joysticks_per_frame[input_type]) + (absolute_button >> 1)];
switch(input_type)
{
case INPUT_TYPE_FOURSCORE:
{
// 32 buttons, 16bytes
val = hot_changes[(frame << 4) + (absolute_button >> 1)];
break;
}
case INPUT_TYPE_2P:
{
// 16 buttons, 8bytes
val = hot_changes[(frame << 3) + (absolute_button >> 1)];
break;
}
case INPUT_TYPE_1P:
{
// 8 buttons, 4bytes
val = hot_changes[(frame << 2) + (absolute_button >> 1)];
break;
}
}
if (absolute_button & 1) if (absolute_button & 1)
// odd buttons (B, T, D, R) - upper 4 bits of the byte // odd buttons (B, T, D, R) take upper 4 bits of the byte
return val >> 4; return val >> HOTCHANGE_BITS_PER_VALUE;
else else
// even buttons (A, S, U, L) - lower 4 bits of the byte // even buttons (A, S, U, L) take lower 4 bits of the byte
return val & 15; return val & HOTCHANGE_BITMASK;
} }

View File

@ -9,8 +9,17 @@ enum Input_types
NUM_SUPPORTED_INPUT_TYPES NUM_SUPPORTED_INPUT_TYPES
}; };
#define BYTES_PER_JOYSTICK 1 // 1 byte per 1 joystick (8 buttons) #define BUTTONS_PER_JOYSTICK 8
#define HOTCHANGE_BYTES_PER_JOY 4 // 4 bytes per 8 buttons #define BYTES_PER_JOYSTICK 1 // 1 byte per 1 joystick (8 buttons)
#define HOTCHANGE_BITS_PER_VALUE 4 // any HotChange value takes 4 bits
#define HOTCHANGE_BITMASK 0xF // "1111"
#define HOTCHANGE_MAX_VALUE 0xF // "1111" max
#define HOTCHANGE_VALUES_PER_BYTE 2 // hence 2 HotChange values fit into 1 byte
#define BYTE_VALUE_CONTAINING_MAX_HOTCHANGES ((HOTCHANGE_MAX_VALUE << HOTCHANGE_BITS_PER_VALUE) | HOTCHANGE_MAX_VALUE) // "0xFF"
#define BYTE_VALUE_CONTAINING_MAX_HOTCHANGE_HI (HOTCHANGE_MAX_VALUE << HOTCHANGE_BITS_PER_VALUE) // "0xF0"
#define BYTE_VALUE_CONTAINING_MAX_HOTCHANGE_LO HOTCHANGE_MAX_VALUE // "0x0F"
#define HOTCHANGE_BYTES_PER_JOY (BYTES_PER_JOYSTICK * HOTCHANGE_BITS_PER_VALUE) // 4 bytes per 8 buttons
class INPUTLOG class INPUTLOG
{ {
@ -26,7 +35,7 @@ public:
void compress_data(); void compress_data();
bool Get_already_compressed(); bool Get_already_compressed();
uint32 INPUTLOG::fillJoypadsDiff(INPUTLOG& their_log, int frame); uint32 fillJoypadsDiff(INPUTLOG& their_log, int frame);
int findFirstChange(INPUTLOG& their_log, int start = 0, int end = -1); int findFirstChange(INPUTLOG& their_log, int start = 0, int end = -1);
int findFirstChange(MovieData& md, int start = 0, int end = -1); int findFirstChange(MovieData& md, int start = 0, int end = -1);
@ -36,6 +45,8 @@ public:
void insertFrames(int at, int frames); void insertFrames(int at, int frames);
void eraseFrame(int frame); void eraseFrame(int frame);
void Init_HotChanges();
void copyHotChanges(INPUTLOG* source_of_hotchanges, int limit_frame_of_source = -1); void copyHotChanges(INPUTLOG* source_of_hotchanges, int limit_frame_of_source = -1);
void inheritHotChanges(INPUTLOG* source_of_hotchanges); void inheritHotChanges(INPUTLOG* source_of_hotchanges);
void inheritHotChanges_DeleteSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset); void inheritHotChanges_DeleteSelection(INPUTLOG* source_of_hotchanges, SelectionFrames* frameset);
@ -58,9 +69,9 @@ public:
bool has_hot_changes; bool has_hot_changes;
// not saved data // not saved data
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
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> joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ...
std::vector<uint8> commands; // Format: commands-for-frame0, commands-for-frame1, ... std::vector<uint8> commands; // Format: commands-for-frame0, commands-for-frame1, ...
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
private: private:

View File

@ -1577,6 +1577,8 @@ bool PIANO_ROLL::CheckIfTheresAnyIconAtFrame(int frame)
return true; return true;
if (frame == playback.GetLostPosition()) if (frame == playback.GetLostPosition())
return true; return true;
if (frame == playback.GetPauseFrame())
return true;
if (bookmarks.FindBookmarkAtFrame(frame) >= 0) if (bookmarks.FindBookmarkAtFrame(frame) >= 0)
return true; return true;
return false; return false;