These changes are TAStudio related.

1. Added a list of save states to the movie log.
2. Added corresponding support functions for the save states.
3. Added double click to the list view to load a previous frame.
4. Added a context menu to the list view with insert and delete.
5. Fixed some issues with the green zone of valid state history.
6. Fixed an input bug that I had unwittingly created, as well as issues with the nes log format.
This commit is contained in:
phillip.grimsrud 2012-06-01 05:49:26 +00:00
parent 986774f5ee
commit d6479e5613
9 changed files with 597 additions and 454 deletions

View File

@ -33,6 +33,7 @@ namespace BizHawk.MultiClient
public bool FastForward = false;
public bool TurboFastForward = false;
public bool StopOnEnd = false;
public bool UpdateFrame = false;
//avi/wav state
IVideoWriter CurrAviWriter = null;
@ -1797,6 +1798,12 @@ namespace BizHawk.MultiClient
if (Global.MovieSession.Movie.Mode == MOVIEMODE.RECORD)
Global.MovieSession.Movie.Mode = MOVIEMODE.PLAY;
}
if (true == UpdateFrame)
{
runFrame = true;
if (Global.MovieSession.Movie.Mode == MOVIEMODE.RECORD)
Global.MovieSession.Movie.Mode = MOVIEMODE.PLAY;
}
bool genSound = false;
if (runFrame)
@ -1830,6 +1837,8 @@ namespace BizHawk.MultiClient
}
if (!suppressCaptureRewind && Global.Config.RewindEnabled) CaptureRewindState();
Global.MovieSession.Movie.CaptureState();
if (!runloop_frameadvance) genSound = true;
else if (!Global.Config.MuteFrameAdvance)
genSound = true;
@ -1924,6 +1933,12 @@ namespace BizHawk.MultiClient
Global.MovieSession.Movie.Mode = MOVIEMODE.RECORD;
PressRewind = false;
}
if (true == UpdateFrame)
{
if (ReturnToRecording)
Global.MovieSession.Movie.Mode = MOVIEMODE.RECORD;
UpdateFrame = false;
}
if (genSound)
{
@ -1960,6 +1975,7 @@ 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.
TAStudio1.UpdateValues();
Global.MovieSession.Movie.CheckValidity();
}
private unsafe Image MakeScreenshotImage()

View File

@ -396,7 +396,7 @@ namespace BizHawk.MultiClient
if (ControlType == "NES Controller")
{
if (mnemonic.Length < 2) return;
Force("Reset", mnemonic[1] != '.' && mnemonic[1] != 'r' && mnemonic[1] != 'l');
Force("Reset", mnemonic[1] != '.' && mnemonic[1] != '0' && mnemonic[1] != 'l');
}
if (ControlType == "SMS Controller" || ControlType == "TI83 Controller")
{

View File

@ -89,6 +89,39 @@ namespace BizHawk.MultiClient
Mode = MOVIEMODE.INACTIVE;
}
public void CaptureState()
{
byte[] state = Global.Emulator.SaveStateBinary();
Log.AddState(state);
}
public void RewindToFrame(int frame)
{
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;
}
}
public void DeleteFrame(int frame)
{
RewindToFrame(frame);
Log.DeleteFrame(frame);
Global.MainForm.TAStudio1.UpdateValues();
}
public int LastValidState()
{
return Log.LastValidState();
}
public void CheckValidity()
{
Log.CheckValidity();
}
public void ClearSaveRAM()
{
string x = PathManager.SaveRamPath(Global.Game);
@ -174,7 +207,9 @@ namespace BizHawk.MultiClient
public void InsertFrame(string record, int frame)
{
Log.SetFrameAt(frame, record);
Log.AddFrameAt(record,frame);
Global.MainForm.TAStudio1.UpdateValues();
}
public void WriteMovie()

View File

@ -15,6 +15,9 @@ namespace BizHawk.MultiClient
List<string> MovieRecords = new List<string>();
private List<byte[]> StateList = new List<byte[]>();
private int StateLastValidIndex = -1;
public MovieLog()
{
//Should this class initialize with an empty string to MovieRecords so that first frame is index 1?
@ -35,6 +38,16 @@ namespace BizHawk.MultiClient
{
MovieRecords.Add(frame);
}
public void AddState(byte[] state)
{
if (Global.Emulator.Frame >= StateList.Count)
{
StateList.Add(state);
StateLastValidIndex = Global.Emulator.Frame;
}
}
public void SetFrameAt(int frameNum, string frame)
{
if (MovieRecords.Count > frameNum)
@ -45,6 +58,52 @@ namespace BizHawk.MultiClient
public void AddFrameAt(string frame, int frameNum)
{
MovieRecords.Insert(frameNum, frame);
if (frameNum <= StateList.Count - 1)
{
StateList.RemoveRange(frameNum, StateList.Count - frameNum);
}
if (StateLastValidIndex >= frameNum)
{
StateLastValidIndex = frameNum - 1;
}
}
public void CheckValidity()
{
byte[] state = Global.Emulator.SaveStateBinary();
if (Global.Emulator.Frame < StateList.Count && (null == StateList[Global.Emulator.Frame] || !state.SequenceEqual((byte[])StateList[Global.Emulator.Frame])))
{
StateLastValidIndex = Global.Emulator.Frame;
}
}
public int CapturedStateCount()
{
return StateList.Count;
}
public int LastValidState()
{
return StateLastValidIndex;
}
public byte[] GetState(int frame)
{
return StateList[frame];
}
public void DeleteFrame(int frame)
{
MovieRecords.RemoveAt(frame);
if (frame < StateList.Count)
{
StateList.RemoveAt(frame);
}
if (StateLastValidIndex > frame)
{
StateLastValidIndex = frame;
}
}
public void Truncate(int frame)

View File

@ -54,6 +54,14 @@
this.updatePadsOnMovePlaybackToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.restoreWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ReadOnlyCheckBox = new System.Windows.Forms.CheckBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.InsertOneFrame = new System.Windows.Forms.ToolStripMenuItem();
this.SelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.ControllerBox = new System.Windows.Forms.GroupBox();
this.ControllersContext = new System.Windows.Forms.ContextMenuStrip(this.components);
this.clearToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStrip1 = new ToolStripEx();
this.RewindToBeginning = new System.Windows.Forms.ToolStripButton();
this.RewindButton = new System.Windows.Forms.ToolStripButton();
@ -64,22 +72,14 @@
this.FastFowardToEnd = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
this.StopButton = new System.Windows.Forms.ToolStripButton();
this.ReadOnlyCheckBox = new System.Windows.Forms.CheckBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.insertFrameToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ControllerBox = new System.Windows.Forms.GroupBox();
this.ControllersContext = new System.Windows.Forms.ContextMenuStrip(this.components);
this.clearToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.TASView = new BizHawk.VirtualListView();
this.Frame = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.Log = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.DeleteFrames = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.ControllersContext.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// menuStrip1
@ -269,6 +269,69 @@
this.restoreWindowToolStripMenuItem.Text = "Restore Default Settings";
this.restoreWindowToolStripMenuItem.Click += new System.EventHandler(this.restoreWindowToolStripMenuItem_Click);
//
// ReadOnlyCheckBox
//
this.ReadOnlyCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
this.ReadOnlyCheckBox.AutoSize = true;
this.ReadOnlyCheckBox.BackColor = System.Drawing.SystemColors.Control;
this.ReadOnlyCheckBox.Image = global::BizHawk.MultiClient.Properties.Resources.ReadOnly;
this.ReadOnlyCheckBox.ImageAlign = System.Drawing.ContentAlignment.BottomRight;
this.ReadOnlyCheckBox.Location = new System.Drawing.Point(12, 27);
this.ReadOnlyCheckBox.Name = "ReadOnlyCheckBox";
this.ReadOnlyCheckBox.Size = new System.Drawing.Size(22, 22);
this.ReadOnlyCheckBox.TabIndex = 3;
this.toolTip1.SetToolTip(this.ReadOnlyCheckBox, "Read-only");
this.ReadOnlyCheckBox.UseVisualStyleBackColor = false;
this.ReadOnlyCheckBox.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.InsertOneFrame,
this.DeleteFrames,
this.SelectAll});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(157, 70);
//
// InsertOneFrame
//
this.InsertOneFrame.Name = "InsertOneFrame";
this.InsertOneFrame.Size = new System.Drawing.Size(156, 22);
this.InsertOneFrame.Text = "Insert Frame";
this.InsertOneFrame.Click += new System.EventHandler(this.InsertOneFrame_Click);
//
// SelectAll
//
this.SelectAll.Enabled = false;
this.SelectAll.Name = "SelectAll";
this.SelectAll.Size = new System.Drawing.Size(156, 22);
this.SelectAll.Text = "Select All";
//
// ControllerBox
//
this.ControllerBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.ControllerBox.ContextMenuStrip = this.ControllersContext;
this.ControllerBox.Location = new System.Drawing.Point(300, 55);
this.ControllerBox.Name = "ControllerBox";
this.ControllerBox.Size = new System.Drawing.Size(367, 197);
this.ControllerBox.TabIndex = 4;
this.ControllerBox.TabStop = false;
this.ControllerBox.Text = "Controllers";
//
// ControllersContext
//
this.ControllersContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.clearToolStripMenuItem1});
this.ControllersContext.Name = "ControllersContext";
this.ControllersContext.Size = new System.Drawing.Size(136, 26);
//
// clearToolStripMenuItem1
//
this.clearToolStripMenuItem1.Name = "clearToolStripMenuItem1";
this.clearToolStripMenuItem1.Size = new System.Drawing.Size(135, 22);
this.clearToolStripMenuItem1.Text = "&Clear Holds";
this.clearToolStripMenuItem1.Click += new System.EventHandler(this.clearToolStripMenuItem1_Click);
//
// toolStrip1
//
this.toolStrip1.ClickThrough = true;
@ -381,72 +444,6 @@
this.StopButton.Text = "Stop Movie";
this.StopButton.Click += new System.EventHandler(this.StopButton_Click);
//
// ReadOnlyCheckBox
//
this.ReadOnlyCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
this.ReadOnlyCheckBox.AutoSize = true;
this.ReadOnlyCheckBox.BackColor = System.Drawing.SystemColors.Control;
this.ReadOnlyCheckBox.Image = global::BizHawk.MultiClient.Properties.Resources.ReadOnly;
this.ReadOnlyCheckBox.ImageAlign = System.Drawing.ContentAlignment.BottomRight;
this.ReadOnlyCheckBox.Location = new System.Drawing.Point(12, 27);
this.ReadOnlyCheckBox.Name = "ReadOnlyCheckBox";
this.ReadOnlyCheckBox.Size = new System.Drawing.Size(22, 22);
this.ReadOnlyCheckBox.TabIndex = 3;
this.toolTip1.SetToolTip(this.ReadOnlyCheckBox, "Read-only");
this.ReadOnlyCheckBox.UseVisualStyleBackColor = false;
this.ReadOnlyCheckBox.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.insertFrameToolStripMenuItem1,
this.toolStripSeparator5,
this.selectAllToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(140, 54);
//
// insertFrameToolStripMenuItem1
//
this.insertFrameToolStripMenuItem1.Name = "insertFrameToolStripMenuItem1";
this.insertFrameToolStripMenuItem1.Size = new System.Drawing.Size(139, 22);
this.insertFrameToolStripMenuItem1.Text = "Insert Frame";
//
// toolStripSeparator5
//
this.toolStripSeparator5.Name = "toolStripSeparator5";
this.toolStripSeparator5.Size = new System.Drawing.Size(136, 6);
//
// selectAllToolStripMenuItem
//
this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem";
this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(139, 22);
this.selectAllToolStripMenuItem.Text = "Select All";
//
// ControllerBox
//
this.ControllerBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.ControllerBox.ContextMenuStrip = this.ControllersContext;
this.ControllerBox.Location = new System.Drawing.Point(300, 55);
this.ControllerBox.Name = "ControllerBox";
this.ControllerBox.Size = new System.Drawing.Size(367, 197);
this.ControllerBox.TabIndex = 4;
this.ControllerBox.TabStop = false;
this.ControllerBox.Text = "Controllers";
//
// ControllersContext
//
this.ControllersContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.clearToolStripMenuItem1});
this.ControllersContext.Name = "ControllersContext";
this.ControllersContext.Size = new System.Drawing.Size(136, 26);
//
// clearToolStripMenuItem1
//
this.clearToolStripMenuItem1.Name = "clearToolStripMenuItem1";
this.clearToolStripMenuItem1.Size = new System.Drawing.Size(135, 22);
this.clearToolStripMenuItem1.Text = "&Clear Holds";
this.clearToolStripMenuItem1.Click += new System.EventHandler(this.clearToolStripMenuItem1_Click);
//
// TASView
//
this.TASView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -455,6 +452,7 @@
this.TASView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.Frame,
this.Log});
this.TASView.ContextMenuStrip = this.contextMenuStrip1;
this.TASView.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.TASView.FullRowSelect = true;
this.TASView.GridLines = true;
@ -466,6 +464,8 @@
this.TASView.TabIndex = 1;
this.TASView.UseCompatibleStateImageBehavior = false;
this.TASView.View = System.Windows.Forms.View.Details;
this.TASView.SelectedIndexChanged += new System.EventHandler(this.TASView_SelectedIndexChanged);
this.TASView.DoubleClick += new System.EventHandler(this.TASView_DoubleClick);
//
// Frame
//
@ -476,6 +476,13 @@
this.Log.Text = "Log";
this.Log.Width = 201;
//
// DeleteFrames
//
this.DeleteFrames.Name = "DeleteFrames";
this.DeleteFrames.Size = new System.Drawing.Size(156, 22);
this.DeleteFrames.Text = "Delete Frame(s)";
this.DeleteFrames.Click += new System.EventHandler(this.DeleteFrames_Click);
//
// TAStudio
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -494,10 +501,10 @@
this.Load += new System.EventHandler(this.TAStudio_Load);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.contextMenuStrip1.ResumeLayout(false);
this.ControllersContext.ResumeLayout(false);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -537,9 +544,8 @@
private System.Windows.Forms.ToolStripButton FastFowardToEnd;
private System.Windows.Forms.ToolStripMenuItem insertFrameToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem insertFrameToolStripMenuItem1;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
private System.Windows.Forms.ToolStripMenuItem selectAllToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem InsertOneFrame;
private System.Windows.Forms.ToolStripMenuItem SelectAll;
private System.Windows.Forms.GroupBox ControllerBox;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
private System.Windows.Forms.ToolStripButton StopButton;
@ -551,5 +557,6 @@
private System.Windows.Forms.ToolStripMenuItem clearToolStripMenuItem1;
private System.Windows.Forms.ToolStripButton FastForward;
private System.Windows.Forms.ToolStripButton TurboFastForward;
private System.Windows.Forms.ToolStripMenuItem DeleteFrames;
}
}

View File

@ -24,6 +24,7 @@ namespace BizHawk.MultiClient
//Dynamic virtualpad system based on platform
//ensureVisible when recording
//Allow hotkeys when TAStudio has focus
//Reduce the memory footprint with compression and or dropping frames and rerunning them when requested.
int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired
int defaultHeight;
@ -103,10 +104,14 @@ namespace BizHawk.MultiClient
private void TASView_QueryItemBkColor(int index, int column, ref Color color)
{
if (index < Global.MainForm.RewindBufferCount())
if (index <= Global.MovieSession.Movie.LastValidState())
color = Color.LightGreen;
else if (Global.MovieSession.Movie.GetInputFrame(index)[1] == 'L')
color = Color.Pink;
if (index == Global.Emulator.Frame)
{
color = Color.LightBlue;
}
}
private void TASView_QueryItemText(int index, int column, out string text)
@ -308,7 +313,7 @@ namespace BizHawk.MultiClient
private void RewindButton_Click(object sender, EventArgs e)
{
Global.MainForm.PressRewind = true;
Global.MovieSession.Movie.RewindToFrame(Global.Emulator.Frame - 1);
}
private void PauseButton_Click(object sender, EventArgs e)
@ -445,5 +450,26 @@ namespace BizHawk.MultiClient
this.FastFowardToEnd.Checked = false;
}
}
private void TASView_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void TASView_DoubleClick(object sender, EventArgs e)
{
Global.MovieSession.Movie.RewindToFrame(TASView.selectedItem);
}
private void InsertOneFrame_Click(object sender, EventArgs e)
{
Global.MovieSession.Movie.InsertFrame(Global.MovieSession.Movie.GetInputFrame(TASView.selectedItem), TASView.selectedItem);
Global.MovieSession.Movie.RewindToFrame(TASView.selectedItem);
}
private void DeleteFrames_Click(object sender, EventArgs e)
{
Global.MovieSession.Movie.DeleteFrame(TASView.selectedItem);
}
}
}

View File

@ -120,9 +120,6 @@
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>324, 17</value>
</metadata>
@ -132,6 +129,9 @@
<metadata name="ControllersContext.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>571, 17</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

View File

@ -155,13 +155,13 @@ namespace BizHawk.MultiClient
public override string GetMnemonic()
{
StringBuilder input = new StringBuilder("");
input.Append(PR.Checked ? "R" : ".");
input.Append(PL.Checked ? "L" : ".");
input.Append(PD.Checked ? "D" : ".");
input.Append(PU.Checked ? "U" : ".");
input.Append(PD.Checked ? "D" : ".");
input.Append(PL.Checked ? "L" : ".");
input.Append(PR.Checked ? "R" : ".");
input.Append(B2.Checked ? "S" : ".");
input.Append(B1.Checked ? "s" : ".");
input.Append(B2.Checked ? "S" : ".");
input.Append(B3.Checked ? "B" : ".");
input.Append(B4.Checked ? "A" : ".");
input.Append("|");

View File

@ -96,7 +96,7 @@ namespace BizHawk.MultiClient
public override void SetButtons(string buttons)
{
if (buttons.Length < 1) return;
if (buttons[0] == '.' || buttons[0] == 'l')
if (buttons[0] == '.' || buttons[0] == 'l' || buttons[0] == '0')
{
B2.Checked = false;
}