1. Fixed tastudio memory leak. This was accomplished by dropping the oldest saved stats after hitting a size limit (1 GB).
2. Changed StopOnEnd to StopOnFrame. This expands the functionality so that you can tell the emulator to run and then stop at a predetermined point. 3. Expanded the functionality of RewindToFrame to handle more cases. Now you can go back or even forward to a frame and it handles the execution and greenzone appropriately. 4. Due to the change in structure some code was changed to check the index of the first and last saved states in the greenzone rather than relying on the size of the saved state list. 5. Changed the list of saved states in the movie log from a list of byte[] to a list of structures (the structure has an int for the index and byte[] for the state). 6. Saved an init state in the movie log. This is used to go back to the beginning if the beginning of the movie is no longer in the list of saved states. 7. Expanded the AddState and SetFrameAt logic in the movie log to account for the fact that the size of the saved state list is now capped. 8. Fixed a bug in the log interpretation for SMS. 9. Fixed a bug in the sms virtual controller, buttons 1 and 2 were hooked to the wrong objects. 10. Fixed the tastudio listview to show lag as pink.
This commit is contained in:
parent
4435b58c0b
commit
a6ced95e07
|
@ -32,7 +32,8 @@ namespace BizHawk.MultiClient
|
|||
public bool PressRewind = false;
|
||||
public bool FastForward = false;
|
||||
public bool TurboFastForward = false;
|
||||
public bool StopOnEnd = true;
|
||||
public int StopOnFrame = -1;
|
||||
public bool RestoreReadWriteOnStop = false;
|
||||
public bool UpdateFrame = false;
|
||||
|
||||
//avi/wav state
|
||||
|
@ -1892,16 +1893,22 @@ namespace BizHawk.MultiClient
|
|||
session.LatchInputFromPlayer(Global.MovieInputSourceAdapter);
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.Mode == MOVIEMODE.PLAY)
|
||||
if (-1 != StopOnFrame && StopOnFrame == Global.Emulator.Frame + 1)
|
||||
{
|
||||
if (Global.MovieSession.Movie.LogLength() == Global.Emulator.Frame + 1 && true == StopOnEnd)
|
||||
if(StopOnFrame == Global.MovieSession.Movie.LogLength())
|
||||
{
|
||||
if (true == Global.MovieSession.Movie.TastudioOn)
|
||||
{
|
||||
StopOnEnd = false;
|
||||
}
|
||||
Global.MovieSession.Movie.SetMovieFinished();
|
||||
}
|
||||
if (true == Global.MovieSession.Movie.TastudioOn)
|
||||
{
|
||||
PauseEmulator();
|
||||
StopOnFrame = -1;
|
||||
}
|
||||
if(true == RestoreReadWriteOnStop)
|
||||
{
|
||||
Global.MovieSession.Movie.Mode = MOVIEMODE.RECORD;
|
||||
RestoreReadWriteOnStop = false;
|
||||
}
|
||||
}
|
||||
if (Global.MovieSession.Movie.Mode == MOVIEMODE.FINISHED)
|
||||
{
|
||||
|
@ -1998,7 +2005,6 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
//The other tool updates are earlier, TAStudio needs to be later so it can display the latest
|
||||
//frame of execution in its list view.
|
||||
Global.MovieSession.Movie.CheckValidity();
|
||||
TAStudio1.UpdateValues();
|
||||
}
|
||||
|
||||
|
|
|
@ -80,14 +80,6 @@ namespace BizHawk.MultiClient
|
|||
return Frames;
|
||||
}
|
||||
|
||||
public int StateLength()
|
||||
{
|
||||
if (Loaded)
|
||||
return Log.StateLength();
|
||||
else
|
||||
return Frames;
|
||||
}
|
||||
|
||||
public void UpdateFileName(string filename)
|
||||
{
|
||||
this.Filename = filename;
|
||||
|
@ -118,27 +110,71 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
if (frame <= Global.Emulator.Frame)
|
||||
{
|
||||
//frame-1 because we need to go back an extra frame and then run a frame, otherwise the display doesn't get updated.
|
||||
Global.Emulator.LoadStateBinary(new BinaryReader(new MemoryStream(Log.GetState(frame - 1))));
|
||||
Global.MainForm.UpdateFrame = true;
|
||||
if (frame <= Log.StateFirstIndex())
|
||||
{
|
||||
//Global.MainForm.LoadRom(Global.MainForm.CurrentlyOpenRom,false);
|
||||
Global.Emulator.LoadStateBinary(new BinaryReader(new MemoryStream(Log.GetInitState())));
|
||||
Global.MainForm.TAStudio1.UpdateValues();
|
||||
if (true == Global.MainForm.EmulatorPaused && 0 != frame)
|
||||
{
|
||||
Global.MainForm.StopOnFrame = frame;
|
||||
Global.MainForm.UnpauseEmulator();
|
||||
}
|
||||
if (MOVIEMODE.RECORD == Mode)
|
||||
{
|
||||
Mode = MOVIEMODE.PLAY;
|
||||
Global.MainForm.RestoreReadWriteOnStop = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == frame)
|
||||
{
|
||||
//Global.MainForm.LoadRom(Global.MainForm.CurrentlyOpenRom, false);
|
||||
Global.Emulator.LoadStateBinary(new BinaryReader(new MemoryStream(Log.GetInitState())));
|
||||
//Global.MainForm.StopOnFrame = frame;
|
||||
Global.MainForm.TAStudio1.UpdateValues();
|
||||
}
|
||||
else
|
||||
{
|
||||
//frame-1 because we need to go back an extra frame and then run a frame, otherwise the display doesn't get updated.
|
||||
Global.Emulator.LoadStateBinary(new BinaryReader(new MemoryStream(Log.GetState(frame - 1))));
|
||||
Global.MainForm.UpdateFrame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.MainForm.StopOnFrame = frame;
|
||||
Global.MainForm.UnpauseEmulator();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteFrame(int frame)
|
||||
{
|
||||
RewindToFrame(frame);
|
||||
if (frame <= StateLastIndex())
|
||||
{
|
||||
if (frame <= StateFirstIndex())
|
||||
{
|
||||
RewindToFrame(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RewindToFrame(frame);
|
||||
}
|
||||
}
|
||||
Log.DeleteFrame(frame);
|
||||
Global.MainForm.TAStudio1.UpdateValues();
|
||||
}
|
||||
|
||||
public int ValidStateCount()
|
||||
public int StateFirstIndex()
|
||||
{
|
||||
return Log.ValidStateCount();
|
||||
return Log.StateFirstIndex();
|
||||
}
|
||||
|
||||
public void CheckValidity()
|
||||
public int StateLastIndex()
|
||||
{
|
||||
Log.CheckValidity();
|
||||
return Log.StateLastIndex();
|
||||
}
|
||||
|
||||
public void ClearSaveRAM()
|
||||
|
@ -186,6 +222,7 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
ClearSaveRAM();
|
||||
Mode = MOVIEMODE.PLAY;
|
||||
Global.MainForm.StopOnFrame = LogLength();
|
||||
}
|
||||
|
||||
public void ResumeRecording()
|
||||
|
@ -207,6 +244,7 @@ namespace BizHawk.MultiClient
|
|||
MnemonicsGenerator mg = new MnemonicsGenerator();
|
||||
|
||||
mg.SetSource(source);
|
||||
|
||||
Log.SetFrameAt(frameNum, mg.GetControllersAsMnemonic());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,24 @@ namespace BizHawk.MultiClient
|
|||
public class MovieLog
|
||||
{
|
||||
//TODO: Insert(int frame) not useful for convenctional tasing but TAStudio will want it
|
||||
|
||||
private struct StateRecordStruct
|
||||
{
|
||||
public StateRecordStruct(int index, byte[] state)
|
||||
{
|
||||
this.index = index;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
List<string> MovieRecords = new List<string>();
|
||||
public int index;
|
||||
public byte[] state;
|
||||
}
|
||||
|
||||
private List<byte[]> StateRecords = new List<byte[]>();
|
||||
private List<string> MovieRecords = new List<string>();
|
||||
private List<StateRecordStruct> StateRecords = new List<StateRecordStruct>();
|
||||
private byte[] InitState;
|
||||
//TODO: Make this size limit configurable by the user
|
||||
private int MaxStateRecordSize = 1024 * 1024 * 1024; //To limit memory usage.
|
||||
|
||||
public MovieLog()
|
||||
{
|
||||
|
@ -26,11 +40,26 @@ namespace BizHawk.MultiClient
|
|||
return MovieRecords.Count;
|
||||
}
|
||||
|
||||
public int StateLength()
|
||||
public int StateFirstIndex()
|
||||
{
|
||||
return (0 == StateRecords.Count) ? -1 : StateRecords[0].index;
|
||||
}
|
||||
|
||||
public int StateLastIndex()
|
||||
{
|
||||
return (0 == StateRecords.Count) ? -1 : StateRecords[StateRecords.Count-1].index;
|
||||
}
|
||||
|
||||
public int StateSizeInFrames()
|
||||
{
|
||||
return StateRecords.Count;
|
||||
}
|
||||
|
||||
public int StateSizeInBytes()
|
||||
{
|
||||
return (0 == StateRecords.Count) ? 0 : StateRecords.Count * StateRecords[0].state.Length;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
MovieRecords.Clear();
|
||||
|
@ -44,14 +73,33 @@ namespace BizHawk.MultiClient
|
|||
|
||||
public void AddState(byte[] state)
|
||||
{
|
||||
if (Global.Emulator.Frame >= StateRecords.Count)
|
||||
if (0 == Global.Emulator.Frame)
|
||||
{
|
||||
StateRecords.Add(state);
|
||||
InitState = state;
|
||||
}
|
||||
if (Global.Emulator.Frame < StateFirstIndex())
|
||||
{
|
||||
StateRecords.Clear();
|
||||
StateRecords.Add(new StateRecordStruct(Global.Emulator.Frame, state));
|
||||
}
|
||||
if (Global.Emulator.Frame > StateLastIndex())
|
||||
{
|
||||
if (StateSizeInBytes() + state.Length > MaxStateRecordSize)
|
||||
{
|
||||
// Discard the oldest state to save space.
|
||||
StateRecords.RemoveAt(0);
|
||||
}
|
||||
StateRecords.Add(new StateRecordStruct(Global.Emulator.Frame,state));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFrameAt(int frameNum, string frame)
|
||||
{
|
||||
if (frameNum < StateLastIndex() && (frameNum < StateFirstIndex() || frame != GetFrame(frameNum)))
|
||||
{
|
||||
TruncateStates(frameNum+1);
|
||||
}
|
||||
|
||||
if (MovieRecords.Count > frameNum)
|
||||
MovieRecords[frameNum] = frame;
|
||||
else
|
||||
|
@ -61,42 +109,44 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
MovieRecords.Insert(frameNum, frame);
|
||||
|
||||
if (frameNum <= StateRecords.Count - 1)
|
||||
if (frameNum <= StateLastIndex())
|
||||
{
|
||||
StateRecords.RemoveRange(frameNum, StateRecords.Count - frameNum);
|
||||
if (frameNum <= StateFirstIndex())
|
||||
{
|
||||
StateRecords.Clear();
|
||||
Global.MovieSession.Movie.RewindToFrame(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
StateRecords.RemoveRange(frameNum - StateFirstIndex(), StateLastIndex() - frameNum + 1);
|
||||
Global.MovieSession.Movie.RewindToFrame(frameNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckValidity()
|
||||
{
|
||||
byte[] state = Global.Emulator.SaveStateBinary();
|
||||
if (Global.Emulator.Frame < StateRecords.Count && !state.SequenceEqual((byte[])StateRecords[Global.Emulator.Frame]))
|
||||
{
|
||||
TruncateStates(Global.Emulator.Frame);
|
||||
}
|
||||
}
|
||||
|
||||
public int CapturedStateCount()
|
||||
{
|
||||
return StateRecords.Count;
|
||||
}
|
||||
|
||||
public int ValidStateCount()
|
||||
{
|
||||
return StateRecords.Count;
|
||||
}
|
||||
|
||||
public byte[] GetState(int frame)
|
||||
{
|
||||
return StateRecords[frame];
|
||||
return StateRecords[frame-StateFirstIndex()].state;
|
||||
}
|
||||
|
||||
public byte[] GetInitState()
|
||||
{
|
||||
return InitState;
|
||||
}
|
||||
|
||||
public void DeleteFrame(int frame)
|
||||
{
|
||||
MovieRecords.RemoveAt(frame);
|
||||
if (frame < StateRecords.Count)
|
||||
if (frame <= StateLastIndex())
|
||||
{
|
||||
StateRecords.RemoveAt(frame);
|
||||
if (frame <= StateFirstIndex())
|
||||
{
|
||||
StateRecords.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
StateRecords.RemoveRange(frame - StateFirstIndex(), StateLastIndex() - frame + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,19 +155,18 @@ namespace BizHawk.MultiClient
|
|||
StateRecords.Clear();
|
||||
}
|
||||
|
||||
public void TruncateFrames(int frame)
|
||||
{
|
||||
if (frame >= 0 && frame < MovieLength())
|
||||
{
|
||||
MovieRecords.RemoveRange(frame, MovieLength() - frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void TruncateStates(int frame)
|
||||
{
|
||||
if (frame >= 0 && frame < StateLength())
|
||||
if (frame >= 0)
|
||||
{
|
||||
StateRecords.RemoveRange(frame, StateLength() - frame);
|
||||
if (frame < StateFirstIndex())
|
||||
{
|
||||
StateRecords.Clear();
|
||||
}
|
||||
else if (frame <= StateLastIndex())
|
||||
{
|
||||
StateRecords.RemoveRange(frame - StateFirstIndex(), StateLastIndex() - frame+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
Global.MovieSession.Movie.TastudioOn = false;
|
||||
Global.MovieSession.Movie.ClearStates();
|
||||
|
||||
Global.MainForm.StopOnEnd = true;
|
||||
Global.MainForm.StopOnFrame = Global.MovieSession.Movie.LogLength();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
|
|
@ -70,9 +70,9 @@ namespace BizHawk.MultiClient
|
|||
case "SMS":
|
||||
case "GG":
|
||||
case "SG":
|
||||
Pads[0].SetButtons(str.Substring(0, 6));
|
||||
Pads[1].SetButtons(str.Substring(7, 6));
|
||||
Pads[2].SetButtons(str.Substring(14, 2));
|
||||
Pads[0].SetButtons(str.Substring(1, 6));
|
||||
Pads[1].SetButtons(str.Substring(8, 6));
|
||||
Pads[2].SetButtons(str.Substring(15, 2));
|
||||
break;
|
||||
case "PCE":
|
||||
case "SGX":
|
||||
|
@ -104,9 +104,13 @@ namespace BizHawk.MultiClient
|
|||
|
||||
private void TASView_QueryItemBkColor(int index, int column, ref Color color)
|
||||
{
|
||||
if (index < Global.MovieSession.Movie.ValidStateCount())
|
||||
if (0 == index && 0 == Global.MovieSession.Movie.StateFirstIndex())
|
||||
color = Color.LightGreen; //special case for frame 0. Normally we need to go back an extra frame, but for frame 0 we can reload the rom.
|
||||
if (index > Global.MovieSession.Movie.StateFirstIndex() && index <= Global.MovieSession.Movie.StateLastIndex())
|
||||
color = Color.LightGreen;
|
||||
else if ("" != Global.MovieSession.Movie.GetInputFrame(index) && Global.MovieSession.Movie.GetInputFrame(index)[1] == 'L')
|
||||
if ("" != Global.MovieSession.Movie.GetInputFrame(index) &&
|
||||
Global.COMMANDS[Global.MovieInputSourceAdapter.Type.Name].ContainsKey("Lag") &&
|
||||
Global.MovieSession.Movie.GetInputFrame(index)[1] == Global.COMMANDS[Global.MovieInputSourceAdapter.Type.Name]["Lag"][0])
|
||||
color = Color.Pink;
|
||||
if (index == Global.Emulator.Frame)
|
||||
{
|
||||
|
@ -131,7 +135,7 @@ namespace BizHawk.MultiClient
|
|||
private void DisplayList()
|
||||
{
|
||||
TASView.ItemCount = Global.MovieSession.Movie.LogLength();
|
||||
if (Global.MovieSession.Movie.LogLength() == Global.Emulator.Frame && Global.MovieSession.Movie.StateLength() == Global.Emulator.Frame)
|
||||
if (Global.MovieSession.Movie.LogLength() == Global.Emulator.Frame && Global.MovieSession.Movie.StateLastIndex() == Global.Emulator.Frame - 1)
|
||||
{
|
||||
//If we're at the end of the movie add one to show the cursor as a blank frame
|
||||
TASView.ItemCount++;
|
||||
|
@ -158,7 +162,7 @@ namespace BizHawk.MultiClient
|
|||
|
||||
Global.MovieSession.Movie.TastudioOn = true;
|
||||
|
||||
Global.MainForm.StopOnEnd = false;
|
||||
Global.MainForm.StopOnFrame = -1;
|
||||
|
||||
LoadConfigSettings();
|
||||
ReadOnlyCheckBox.Checked = Global.MainForm.ReadOnly;
|
||||
|
@ -367,11 +371,11 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
if (true == this.FastFowardToEnd.Checked)
|
||||
{
|
||||
Global.MainForm.StopOnEnd = false;
|
||||
Global.MainForm.StopOnFrame = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.MainForm.StopOnEnd = true;
|
||||
Global.MainForm.StopOnFrame = Global.MovieSession.Movie.LogLength();
|
||||
}
|
||||
|
||||
this.FastFowardToEnd.Checked ^= true;
|
||||
|
@ -490,7 +494,6 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
Global.MovieSession.Movie.InsertFrame(Global.MovieSession.Movie.GetInputFrame(list[index]), (int)list[index]);
|
||||
}
|
||||
Global.MovieSession.Movie.RewindToFrame(TASView.selectedItem);
|
||||
}
|
||||
|
||||
private void Delete_Click(object sender, EventArgs e)
|
||||
|
@ -498,7 +501,7 @@ namespace BizHawk.MultiClient
|
|||
ListView.SelectedIndexCollection list = TASView.SelectedIndices;
|
||||
for (int index = 0; index < list.Count; index++)
|
||||
{
|
||||
Global.MovieSession.Movie.DeleteFrame(TASView.selectedItem);
|
||||
Global.MovieSession.Movie.DeleteFrame(list[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,9 +168,9 @@ namespace BizHawk.MultiClient
|
|||
else if (sender == PR)
|
||||
Global.StickyXORAdapter.SetSticky(Controller + " Right", PR.Checked);
|
||||
else if (sender == B1)
|
||||
Global.StickyXORAdapter.SetSticky(Controller + " B1", B3.Checked);
|
||||
Global.StickyXORAdapter.SetSticky(Controller + " B1", B1.Checked);
|
||||
else if (sender == B2)
|
||||
Global.StickyXORAdapter.SetSticky(Controller + " B2", B4.Checked);
|
||||
Global.StickyXORAdapter.SetSticky(Controller + " B2", B2.Checked);
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
|
|
Loading…
Reference in New Issue