BizHawk/BizHawk.Client.Common/movie/MovieLog.cs

247 lines
4.8 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
2013-10-25 00:59:34 +00:00
using System.IO;
2013-10-28 00:44:01 +00:00
using System.Linq;
2013-10-25 00:59:34 +00:00
namespace BizHawk.Client.Common
{
// TODO: what is this object really trying to accomplish? COnsider making it a collection (ICollection, IEnumerable perhaps)
2013-10-25 00:59:34 +00:00
/// <summary>
/// Represents the controller key presses of a movie
/// </summary>
public class MovieLog : IEnumerable<string>
2013-10-25 00:59:34 +00:00
{
public IEnumerator<string> GetEnumerator()
{
return _movieRecords.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
2013-10-25 00:59:34 +00:00
#region Properties
public byte[] InitState { get; private set; }
public int StateCount
{
get
{
return _state_records.Count;
}
}
public int Length
{
get
{
return _movieRecords.Count;
2013-10-25 00:59:34 +00:00
}
}
public int StateFirstIndex
{
get
{
return (_state_records.Count == 0) ? -1 : _state_records[0].Index;
}
}
public int StateLastIndex
{
get
{
return (_state_records.Count == 0) ? -1 : _state_records[_state_records.Count - 1].Index;
}
}
public int StateSizeInBytes
{
get
{
2013-10-28 00:44:01 +00:00
return _state_records.Any() ? StateCount * _state_records[0].State.Length : 0;
2013-10-25 00:59:34 +00:00
}
}
#endregion
#region Public Methods
public void Clear()
{
_movieRecords.Clear();
2013-10-25 00:59:34 +00:00
_state_records.Clear();
}
public void ClearStates()
{
_state_records.Clear();
}
public void AppendFrame(string frame)
{
_movieRecords.Add(frame);
2013-10-25 00:59:34 +00:00
}
public void AddState(byte[] state)
{
if (Global.Emulator.Frame == 0)
{
InitState = state;
}
2013-10-25 00:59:34 +00:00
if (Global.Emulator.Frame < StateFirstIndex)
{
_state_records.Clear();
_state_records.Add(new StateRecord(Global.Emulator.Frame, state));
}
2013-10-25 00:59:34 +00:00
if (Global.Emulator.Frame > StateLastIndex)
{
if (StateSizeInBytes + state.Length > MAXSTATERECORDSIZE)
{
// Discard the oldest state to save space.
_state_records.RemoveAt(0);
}
2013-10-25 00:59:34 +00:00
_state_records.Add(new StateRecord(Global.Emulator.Frame,state));
}
}
public void SetFrameAt(int frameNum, string frame)
{
if (frameNum < StateLastIndex && (frameNum < StateFirstIndex || frame != _movieRecords[frameNum]))
2013-10-25 00:59:34 +00:00
{
TruncateStates(frameNum + 1);
2013-10-25 00:59:34 +00:00
}
if (_movieRecords.Count > frameNum)
2013-10-25 00:59:34 +00:00
{
_movieRecords[frameNum] = frame;
2013-10-25 00:59:34 +00:00
}
else
{
_movieRecords.Add(frame);
2013-10-25 00:59:34 +00:00
}
}
public void AddFrameAt(int frame, string record)
{
_movieRecords.Insert(frame, record);
2013-10-25 00:59:34 +00:00
if (frame <= StateLastIndex)
{
if (frame <= StateFirstIndex)
{
_state_records.Clear();
}
else
{
_state_records.RemoveRange(frame - StateFirstIndex, StateLastIndex - frame + 1);
}
}
}
public byte[] GetState(int frame)
{
return _state_records[frame - StateFirstIndex].State;
}
public void DeleteFrame(int frame)
{
_movieRecords.RemoveAt(frame);
2013-10-25 00:59:34 +00:00
if (frame <= StateLastIndex)
{
if (frame <= StateFirstIndex)
{
_state_records.Clear();
}
else
{
_state_records.RemoveRange(frame - StateFirstIndex, StateLastIndex - frame + 1);
}
}
}
public void TruncateStates(int frame)
{
if (frame >= 0)
{
if (frame < StateFirstIndex)
{
_state_records.Clear();
}
else if (frame <= StateLastIndex)
{
_state_records.RemoveRange(frame - StateFirstIndex, StateLastIndex - frame + 1);
}
}
}
2013-10-28 00:44:01 +00:00
public string this[int frame]
2013-10-25 00:59:34 +00:00
{
2013-10-28 00:44:01 +00:00
get
2013-10-25 00:59:34 +00:00
{
return _movieRecords[frame];
2013-10-25 00:59:34 +00:00
}
}
public void TruncateMovie(int frame)
{
if (frame < _movieRecords.Count)
2013-10-25 00:59:34 +00:00
{
_movieRecords.RemoveRange(frame, _movieRecords.Count - frame);
2013-10-25 00:59:34 +00:00
TruncateStates(frame);
}
}
public bool FrameLagged(int frame)
{
if (frame >= StateFirstIndex && frame <= StateLastIndex && frame <= _state_records.Count)
{
if (frame < _state_records.Count)
{
return _state_records[frame].Lagged;
}
else
{
return false;
}
}
else
{
return false;
}
}
#endregion
#region private fields
private sealed class StateRecord
2013-10-25 00:59:34 +00:00
{
public StateRecord(int index, byte[] state)
{
Index = index;
State = state;
Lagged = Global.Emulator.IsLagFrame;
}
2013-10-28 00:44:01 +00:00
public int Index { get; private set; }
public byte[] State { get; private set; }
public bool Lagged { get; private set; }
2013-10-25 00:59:34 +00:00
}
private readonly List<string> _movieRecords = new List<string>();
2013-10-25 00:59:34 +00:00
private readonly List<StateRecord> _state_records = new List<StateRecord>();
// TODO: Make this size limit configurable by the user
private const int MAXSTATERECORDSIZE = 512 * 1024 * 1024; //To limit memory usage.
2013-10-25 00:59:34 +00:00
#endregion
}
}