diff --git a/BizHawk.Client.Common/config/PathEntry.cs b/BizHawk.Client.Common/config/PathEntry.cs
index de9f552a3e..b17ca54f68 100644
--- a/BizHawk.Client.Common/config/PathEntry.cs
+++ b/BizHawk.Client.Common/config/PathEntry.cs
@@ -71,7 +71,7 @@ namespace BizHawk.Client.Common
 				// we have the system, but not the type.  don't attempt to add an unknown type
 				return null;
 			}
-			
+
 			// we don't have anything for the system in question.  add a set of stock paths
 			var systempath = PathManager.RemoveInvalidFileSystemChars(system) + "_INTERIM";
 			var systemdisp = system + " (INTERIM)";
@@ -154,6 +154,8 @@ namespace BizHawk.Client.Common
 					new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "Watch (.wch)", Path = ".", Ordinal = 7 },
 					new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "A/V Dumps", Path = ".", Ordinal = 8 },
 					new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "Debug Logs", Path = ".", Ordinal = 9 },
+					new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "Macros", Path = Path.Combine(".", "Movies", "Macros"), Ordinal = 10 },
+					new PathEntry { System = "Global_NULL", SystemDisplayName="Global", Type = "TAStudio states", Path = Path.Combine(".", "Movies", "TAStudio states"), Ordinal = 11 },
 
 					new PathEntry { System = "INTV", SystemDisplayName="Intellivision", Type = "Base", Path = Path.Combine(".", "Intellivision"), Ordinal = 0 },
 					new PathEntry { System = "INTV", SystemDisplayName="Intellivision", Type = "ROM", Path = ".", Ordinal = 1 },
diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
index 50fee2cf01..68e4270188 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs
@@ -91,7 +91,8 @@ namespace BizHawk.Client.Common
 			{
 				return new TasMovieRecord
 				{
-					State = StateManager[index],
+					// State = StateManager[index],
+					HasState = StateManager.HasState(index),
 					LogEntry = GetInputLogEntry(index),
 					Lagged = LagLog[index + 1],
 					WasLagged = LagLog.History(index + 1)
diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs b/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs
index ec588f31ba..8aeb697ea6 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs
@@ -5,14 +5,14 @@ namespace BizHawk.Client.Common
 {
 	public class TasMovieRecord
 	{
-		public KeyValuePair<int, byte[]> State { get; set; }
+		// public KeyValuePair<int, byte[]> State { get; set; }
 		public bool? Lagged { get; set; }
 		public bool? WasLagged { get; set; }
 		public string LogEntry { get; set; }
 
-		public bool HasState
-		{
-			get { return State.Value.Any(); }
-		}
+		public bool HasState { get; set; }
+		//{
+		//	get { return State.Value.Any(); }
+		//}
 	}
 }
diff --git a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs
index b44fe44870..dc9fb75bf5 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs
@@ -26,9 +26,16 @@ namespace BizHawk.Client.Common
 		}
 
 		private readonly SortedList<int, byte[]> States = new SortedList<int, byte[]>();
+		private string statePath
+		{
+			get
+			{
+				return PathManager.MakeAbsolutePath(Global.Config.PathEntries["Global", "TAStudio states"].Path, null);
+			}
+		}
 
 		private readonly TasMovie _movie;
-		private int _expectedStateSize = 0;
+		private ulong _expectedStateSize = 0;
 
 		private int _minFrequency = VersionInfo.DeveloperBuild ? 2 : 1;
 		private const int _maxFrequency = 16;
@@ -36,7 +43,7 @@ namespace BizHawk.Client.Common
 		{
 			get
 			{
-				var freq = _expectedStateSize / 65536;
+				int freq = (int)(_expectedStateSize / 65536);
 
 				if (freq < _minFrequency)
 				{
@@ -54,7 +61,7 @@ namespace BizHawk.Client.Common
 		private int _lastCapture = 0;
 
 		private int maxStates
-		{ get { return Settings.Cap / _expectedStateSize; } }
+		{ get { return (int)(Settings.Cap / _expectedStateSize); } }
 
 		public TasStateManager(TasMovie movie)
 		{
@@ -62,18 +69,20 @@ namespace BizHawk.Client.Common
 
 			Settings = new TasStateManagerSettings(Global.Config.DefaultTasProjSettings);
 
-			var cap = Settings.Cap;
-
 			int limit = 0;
 
-			_expectedStateSize = Core.SaveStateBinary().Length;
+			_expectedStateSize = (ulong)Core.SaveStateBinary().Length;
 
 			if (_expectedStateSize > 0)
 			{
-				limit = cap / _expectedStateSize;
+				limit = maxStates;
 			}
 
 			States = new SortedList<int, byte[]>(limit);
+			if (Directory.Exists(statePath))
+				Directory.Delete(statePath, true); // To delete old files that may still exist.
+			Directory.CreateDirectory(statePath);
+			accessed = new List<int>();
 		}
 
 		public TasStateManagerSettings Settings { get; set; }
@@ -94,12 +103,15 @@ namespace BizHawk.Client.Common
 
 				if (States.ContainsKey(frame))
 				{
+					// if (States[frame] == null) // Get from file
+					StateAccessed(frame);
 					return new KeyValuePair<int, byte[]>(frame, States[frame]);
 				}
 
 				return new KeyValuePair<int, byte[]>(-1, new byte[0]);
 			}
 		}
+		private List<int> accessed;
 
 		public byte[] InitialState
 		{
@@ -146,20 +158,7 @@ namespace BizHawk.Client.Common
 
 			if (shouldCapture)
 			{
-				var state = (byte[])Core.SaveStateBinary().Clone();
-
-				if (States.ContainsKey(frame))
-				{
-					States[frame] = state;
-				}
-				else
-				{
-					Used += state.Length;
-					MaybeRemoveState(); // Remove before adding so this state won't be removed.
-
-					States.Add(frame, state);
-				}
-
+				SetState(frame, (byte[])Core.SaveStateBinary().Clone());
 				_lastCapture = frame;
 			}
 		}
@@ -167,38 +166,44 @@ namespace BizHawk.Client.Common
 		private void MaybeRemoveState()
 		{
 			int shouldRemove = -1;
-			if (Used >= Settings.Cap)
-				shouldRemove = _movie.StartsFromSavestate ? 0 : 1;
-			if (shouldRemove != -1) // Which one to remove?
+			if (Used + DiskUsed > Settings.CapTotal)
+				shouldRemove = StateToRemove();
+			if (shouldRemove != -1)
 			{
-				int markerSkips = maxStates / 3;
-
-				shouldRemove--;
-				do
-				{
-					shouldRemove++;
-
-					// No need to have two savestates with only lag frames between them.
-					for (int i = shouldRemove + 1; i < States.Count - 1; i++)
-					{
-						if (AllLag(States.ElementAt(i).Key, States.ElementAt(i + 1).Key))
-						{
-							shouldRemove = i;
-							break;
-						}
-					}
-
-					// Keep marker states
-					markerSkips--;
-					if (markerSkips < 0)
-						shouldRemove = _movie.StartsFromSavestate ? 0 : 1;
-				} while (_movie.Markers.IsMarker(States.ElementAt(shouldRemove).Key + 1) && markerSkips > -1);
-				int element = States.ElementAt(shouldRemove).Key;
-
-				// Remove
-				Used -= States.ElementAt(shouldRemove).Value.Length;
-				States.RemoveAt(shouldRemove);
+				RemoveState(States.ElementAt(shouldRemove).Key);
 			}
+
+			if (Used > Settings.Cap)
+			{
+				MoveStateToDisk(accessed.Last());
+			}
+		}
+		private int StateToRemove()
+		{
+			int markerSkips = maxStates / 3;
+
+			int shouldRemove = _movie.StartsFromSavestate ? -1 : 0;
+			do
+			{
+				shouldRemove++;
+
+				// No need to have two savestates with only lag frames between them.
+				for (int i = shouldRemove + 1; i < States.Count - 1; i++)
+				{
+					if (AllLag(States.ElementAt(i).Key, States.ElementAt(i + 1).Key))
+					{
+						shouldRemove = i;
+						break;
+					}
+				}
+
+				// Keep marker states
+				markerSkips--;
+				if (markerSkips < 0)
+					shouldRemove = _movie.StartsFromSavestate ? 0 : 1;
+			} while (_movie.Markers.IsMarker(States.ElementAt(shouldRemove).Key + 1) && markerSkips > -1);
+
+			return shouldRemove;
 		}
 		private bool AllLag(int from, int upTo)
 		{
@@ -218,6 +223,75 @@ namespace BizHawk.Client.Common
 			return true;
 		}
 
+		private void MoveStateToDisk(int index)
+		{
+			// Save
+			string path = Path.Combine(statePath, index.ToString());
+			File.WriteAllBytes(path, States[index]);
+			DiskUsed += _expectedStateSize;
+
+			// Remove from RAM
+			Used -= (ulong)States[index].Length;
+			States[index] = null;
+		}
+		private void MoveStateToMemory(int index)
+		{
+			// Load
+			string path = Path.Combine(statePath, index.ToString());
+			byte[] loadData = File.ReadAllBytes(path);
+			DiskUsed -= _expectedStateSize;
+
+			// States list
+			Used += (ulong)loadData.Length;
+			States[index] = loadData;
+
+			File.Delete(path);
+		}
+		private void SetState(int frame, byte[] state)
+		{
+			if (States.ContainsKey(frame))
+			{
+				States[frame] = state;
+				MaybeRemoveState(); // Also does moving to disk
+			}
+			else
+			{
+				Used += (ulong)state.Length;
+				MaybeRemoveState(); // Remove before adding so this state won't be removed.
+
+				States.Add(frame, state);
+			}
+			StateAccessed(frame);
+		}
+		private void RemoveState(int index)
+		{
+			if (States[index] == null)
+			{
+				DiskUsed -= _expectedStateSize; // Disk length?
+				string path = Path.Combine(statePath, index.ToString());
+				File.Delete(path);
+			}
+			else
+				Used -= (ulong)States[index].Length;
+			States.RemoveAt(States.IndexOfKey(index));
+
+			accessed.Remove(index);
+		}
+		private void StateAccessed(int index)
+		{
+			bool removed = accessed.Remove(index);
+			accessed.Add(index);
+
+			if (States[index] == null)
+			{
+				MoveStateToDisk(accessed[0]);
+				MoveStateToMemory(index);
+			}
+
+			if (!removed && accessed.Count > (int)(Used / _expectedStateSize))
+				accessed.RemoveAt(0);
+		}
+
 		public bool HasState(int frame)
 		{
 			if (_movie.StartsFromSavestate && frame == 0)
@@ -245,7 +319,10 @@ namespace BizHawk.Client.Common
 					.ToList();
 				foreach (var state in statesToRemove)
 				{
-					Used -= state.Value.Length;
+					if (state.Value == null)
+						DiskUsed -= _expectedStateSize; // Length??
+					else
+						Used -= (ulong)state.Value.Length;
 					States.Remove(state.Key);
 				}
 
@@ -280,7 +357,7 @@ namespace BizHawk.Client.Common
 				if (power.Value.Length > 0)
 				{
 					States.Add(0, power.Value);
-					Used = power.Value.Length;
+					Used = (ulong)power.Value.Length;
 					_lastCapture = 0;
 				}
 				else
@@ -293,9 +370,28 @@ namespace BizHawk.Client.Common
 
 		public void Save(BinaryWriter bw)
 		{
+			List<int> noSave = new List<int>();
+			if (Used + DiskUsed > (ulong)Settings.DiskSaveCapacitymb * 1024 * 1024)
+			{
+				ulong saveUsed = Used + DiskUsed;
+				do
+				{
+					int index = StateToRemove();
+					noSave.Add(index);
+					if (States.ElementAt(index).Value == null)
+						saveUsed -= _expectedStateSize;
+					else
+						saveUsed -= (ulong)States.ElementAt(index).Value.Length;
+				} while (saveUsed > (ulong)Settings.DiskSaveCapacitymb * 1024 * 1024);
+			}
+
 			bw.Write(States.Count);
 			foreach (var kvp in States)
 			{
+				if (noSave.Contains(kvp.Key))
+					continue;
+
+				StateAccessed(kvp.Key);
 				bw.Write(kvp.Key);
 				bw.Write(kvp.Value.Length);
 				bw.Write(kvp.Value);
@@ -313,8 +409,9 @@ namespace BizHawk.Client.Common
 					int frame = br.ReadInt32();
 					int len = br.ReadInt32();
 					byte[] data = br.ReadBytes(len);
-					States.Add(frame, data);
-					Used += len;
+					SetState(frame, data);
+					//States.Add(frame, data);
+					//Used += len;
 				}
 			}
 		}
@@ -323,12 +420,7 @@ namespace BizHawk.Client.Common
 		{
 			var s = States.LastOrDefault(state => state.Key < frame);
 
-			if (s.Value == null && _movie.StartsFromSavestate)
-			{
-				return new KeyValuePair<int, byte[]>(0, _movie.BinarySavestate);
-			}
-
-			return s;
+			return this[s.Key];
 		}
 
 		// Map:
@@ -338,7 +430,12 @@ namespace BizHawk.Client.Common
 		// 4 bytes - length of savestate
 		// 0 - n savestate
 
-		private int Used
+		private ulong Used
+		{
+			get;
+			set;
+		}
+		private ulong DiskUsed
 		{
 			get;
 			set;
diff --git a/BizHawk.Client.Common/movie/tasproj/TasStateManagerSettings.cs b/BizHawk.Client.Common/movie/tasproj/TasStateManagerSettings.cs
index eb044ea6fe..2ccd8ba8fa 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasStateManagerSettings.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasStateManagerSettings.cs
@@ -10,43 +10,73 @@ namespace BizHawk.Client.Common
 	{
 		public TasStateManagerSettings()
 		{
-			SaveStateHistory = true;
+			DiskSaveCapacitymb = 512;
 			Capacitymb = 512;
+			DiskCapacitymb = 512;
 		}
 
 		public TasStateManagerSettings(TasStateManagerSettings settings)
 		{
-			SaveStateHistory = settings.SaveStateHistory;
+			DiskSaveCapacitymb = settings.DiskSaveCapacitymb;
 			Capacitymb = settings.Capacitymb;
+			DiskCapacitymb = settings.DiskCapacitymb;
 		}
 
 		/// <summary>
-		/// Whether or not to save greenzone information to disk
+		/// Whether or not to save state history information to disk
 		/// </summary>
 		[DisplayName("Save History")]
 		[Description("Whether or not to use savestate history")]
-		public bool SaveStateHistory { get; set; }
+		public bool SaveStateHistory { get { return DiskSaveCapacitymb != 0; } }
 
 		/// <summary>
-		/// The total amount of memory to devote to greenzone in megabytes
+		/// The size limit to use when saving the tas project to disk.
 		/// </summary>
-		[DisplayName("Capacity (in megabytes))")]
-		[Description("The size limit of the state history buffer.  When this limit is reached it will start removing previous savestates")]
+		[DisplayName("Save Capacity (in megabytes)")]
+		[Description("The size limit to use when saving the tas project to disk.")]
+		public int DiskSaveCapacitymb { get; set; }
+
+		/// <summary>
+		/// The total amount of memory to devote to state history in megabytes
+		/// </summary>
+		[DisplayName("Capacity (in megabytes)")]
+		[Description("The size limit of the state history buffer.  When this limit is reached it will start moving to disk.")]
 		public int Capacitymb { get; set; }
 
+		/// <summary>
+		/// The total amount of disk space to devote to state history in megabytes
+		/// </summary>
+		[DisplayName("Disk Capacity (in megabytes)")]
+		[Description("The size limit of the state history buffer on the disk.  When this limit is reached it will start removing previous savestates")]
+		public int DiskCapacitymb { get; set; }
+
+		/// <summary>
+		/// The total state capacity in bytes.
+		/// </summary>
 		[JsonIgnore]
 		[Browsable(false)]
-		public int Cap
+		public ulong CapTotal
 		{
-			get { return Capacitymb * 1024 * 1024; }
+			get { return (ulong)(Capacitymb + DiskCapacitymb) * 1024UL * 1024UL; }
+		}
+
+		/// <summary>
+		/// The memory state capacity in bytes.
+		/// </summary>
+		[JsonIgnore]
+		[Browsable(false)]
+		public ulong Cap
+		{
+			get { return (ulong)Capacitymb * 1024UL * 1024UL; }
 		}
 
 		public override string ToString()
 		{
 			StringBuilder sb = new StringBuilder();
 
-			sb.AppendLine(SaveStateHistory.ToString());
+			sb.AppendLine(DiskSaveCapacitymb.ToString());
 			sb.AppendLine(Capacitymb.ToString());
+			sb.AppendLine(DiskCapacitymb.ToString());
 
 			return sb.ToString();
 		}
@@ -55,9 +85,22 @@ namespace BizHawk.Client.Common
 		{
 			if (!string.IsNullOrWhiteSpace(settings))
 			{
-				var lines = settings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
-				SaveStateHistory = bool.Parse(lines[0]);
+				string[] lines = settings.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
 				Capacitymb = int.Parse(lines[1]);
+				int refCapacity;
+				if (!int.TryParse(lines[0], out refCapacity))
+				{
+					if (bool.Parse(lines[0]))
+						DiskSaveCapacitymb = Capacitymb;
+					else
+						DiskSaveCapacitymb = 0;
+				}
+				else
+					DiskSaveCapacitymb = refCapacity;
+				if (lines.Length > 2)
+					DiskCapacitymb = int.Parse(lines[2]);
+				else
+					DiskCapacitymb = 512;
 			}
 		}
 	}
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index c348a2e11e..dbf3eeca5b 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -513,6 +513,10 @@ namespace BizHawk.Client.EmuHawk
 				components.Dispose();
 			}
 
+			// Do not keep TAStudio's disk save states. TODO: This might not be a good place to put this.
+			if (Directory.Exists(PathManager.MakeAbsolutePath(Global.Config.PathEntries["Global", "TAStudio states"].Path, null)))
+				Directory.Delete(PathManager.MakeAbsolutePath(Global.Config.PathEntries["Global", "TAStudio states"].Path, null), true);
+
 			base.Dispose(disposing);
 		}
 
diff --git a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
index 3e2528f54d..b86a8986fc 100644
--- a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
+++ b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs
@@ -219,20 +219,32 @@ namespace BizHawk.Client.EmuHawk
 
 		private static string SuggestedFolder()
 		{
-			return PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null) +
-				"\\Macros";
+			return PathManager.MakeAbsolutePath(Path.Combine(
+				Global.Config.PathEntries["Global", "Macros"].Path,
+				Global.Game.Name), null);
 		}
 		#endregion
 
 		public static void SaveMacroAs(MovieZone macro)
 		{
 			SaveFileDialog dialog = new SaveFileDialog();
+			bool create = false;
+			if (!Directory.Exists(SuggestedFolder()))
+			{
+				Directory.CreateDirectory(SuggestedFolder());
+				create = true;
+			}
 			dialog.InitialDirectory = SuggestedFolder();
+			// Create directory?
 			dialog.Filter = "Movie Macros (*.bk2m)|*.bk2m|All Files|*.*";
 
 			DialogResult result = dialog.ShowHawkDialog();
 			if (result != DialogResult.OK)
+			{
+				if (create)
+					Directory.Delete(dialog.InitialDirectory);
 				return;
+			}
 
 			macro.Save(dialog.FileName);
 			Global.Config.RecentMacros.Add(dialog.FileName);
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.Designer.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.Designer.cs
index 4f867c58b1..596e905a9a 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.Designer.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.Designer.cs
@@ -38,22 +38,31 @@ namespace BizHawk.Client.EmuHawk
 			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StateHistorySettingsForm));
 			this.CancelBtn = new System.Windows.Forms.Button();
 			this.OkBtn = new System.Windows.Forms.Button();
-			this.SaveStateHistoryCheckbox = new System.Windows.Forms.CheckBox();
-			this.CapacityNumeric = new System.Windows.Forms.NumericUpDown();
+			this.MemCapacityNumeric = new System.Windows.Forms.NumericUpDown();
 			this.label1 = new System.Windows.Forms.Label();
 			this.label2 = new System.Windows.Forms.Label();
 			this.label3 = new System.Windows.Forms.Label();
 			this.SavestateSizeLabel = new System.Windows.Forms.Label();
 			this.label4 = new System.Windows.Forms.Label();
 			this.NumStatesLabel = new System.Windows.Forms.Label();
-			((System.ComponentModel.ISupportInitialize)(this.CapacityNumeric)).BeginInit();
+			this.DiskCapacityNumeric = new System.Windows.Forms.NumericUpDown();
+			this.label5 = new System.Windows.Forms.Label();
+			this.label6 = new System.Windows.Forms.Label();
+			this.SaveCapacityNumeric = new System.Windows.Forms.NumericUpDown();
+			this.label7 = new System.Windows.Forms.Label();
+			this.label8 = new System.Windows.Forms.Label();
+			this.label9 = new System.Windows.Forms.Label();
+			this.NumSaveStatesLabel = new System.Windows.Forms.Label();
+			((System.ComponentModel.ISupportInitialize)(this.MemCapacityNumeric)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.DiskCapacityNumeric)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.SaveCapacityNumeric)).BeginInit();
 			this.SuspendLayout();
 			// 
 			// CancelBtn
 			// 
 			this.CancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
 			this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
-			this.CancelBtn.Location = new System.Drawing.Point(236, 96);
+			this.CancelBtn.Location = new System.Drawing.Point(216, 113);
 			this.CancelBtn.Name = "CancelBtn";
 			this.CancelBtn.Size = new System.Drawing.Size(60, 23);
 			this.CancelBtn.TabIndex = 0;
@@ -64,7 +73,7 @@ namespace BizHawk.Client.EmuHawk
 			// OkBtn
 			// 
 			this.OkBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-			this.OkBtn.Location = new System.Drawing.Point(170, 96);
+			this.OkBtn.Location = new System.Drawing.Point(150, 113);
 			this.OkBtn.Name = "OkBtn";
 			this.OkBtn.Size = new System.Drawing.Size(60, 23);
 			this.OkBtn.TabIndex = 1;
@@ -72,43 +81,33 @@ namespace BizHawk.Client.EmuHawk
 			this.OkBtn.UseVisualStyleBackColor = true;
 			this.OkBtn.Click += new System.EventHandler(this.OkBtn_Click);
 			// 
-			// SaveGreenzoneCheckbox
+			// MemCapacityNumeric
 			// 
-			this.SaveStateHistoryCheckbox.AutoSize = true;
-			this.SaveStateHistoryCheckbox.Location = new System.Drawing.Point(13, 20);
-			this.SaveStateHistoryCheckbox.Name = "SaveGreenzoneCheckbox";
-			this.SaveStateHistoryCheckbox.Size = new System.Drawing.Size(234, 17);
-			this.SaveStateHistoryCheckbox.TabIndex = 2;
-			this.SaveStateHistoryCheckbox.Text = "Save savestate history information in proj file";
-			this.SaveStateHistoryCheckbox.UseVisualStyleBackColor = true;
-			// 
-			// CapacityNumeric
-			// 
-			this.CapacityNumeric.Location = new System.Drawing.Point(13, 67);
-			this.CapacityNumeric.Maximum = new decimal(new int[] {
+			this.MemCapacityNumeric.Location = new System.Drawing.Point(12, 26);
+			this.MemCapacityNumeric.Maximum = new decimal(new int[] {
             1024,
             0,
             0,
             0});
-			this.CapacityNumeric.Minimum = new decimal(new int[] {
+			this.MemCapacityNumeric.Minimum = new decimal(new int[] {
             1,
             0,
             0,
             0});
-			this.CapacityNumeric.Name = "CapacityNumeric";
-			this.CapacityNumeric.Size = new System.Drawing.Size(48, 20);
-			this.CapacityNumeric.TabIndex = 3;
-			this.CapacityNumeric.Value = new decimal(new int[] {
+			this.MemCapacityNumeric.Name = "MemCapacityNumeric";
+			this.MemCapacityNumeric.Size = new System.Drawing.Size(55, 20);
+			this.MemCapacityNumeric.TabIndex = 3;
+			this.MemCapacityNumeric.Value = new decimal(new int[] {
             512,
             0,
             0,
             0});
-			this.CapacityNumeric.ValueChanged += new System.EventHandler(this.CapacityNumeric_ValueChanged);
+			this.MemCapacityNumeric.ValueChanged += new System.EventHandler(this.CapacityNumeric_ValueChanged);
 			// 
 			// label1
 			// 
 			this.label1.AutoSize = true;
-			this.label1.Location = new System.Drawing.Point(61, 70);
+			this.label1.Location = new System.Drawing.Point(67, 29);
 			this.label1.Name = "label1";
 			this.label1.Size = new System.Drawing.Size(21, 13);
 			this.label1.TabIndex = 4;
@@ -117,16 +116,16 @@ namespace BizHawk.Client.EmuHawk
 			// label2
 			// 
 			this.label2.AutoSize = true;
-			this.label2.Location = new System.Drawing.Point(13, 50);
+			this.label2.Location = new System.Drawing.Point(12, 9);
 			this.label2.Name = "label2";
-			this.label2.Size = new System.Drawing.Size(99, 13);
+			this.label2.Size = new System.Drawing.Size(88, 13);
 			this.label2.TabIndex = 5;
-			this.label2.Text = "Savestate Capacity";
+			this.label2.Text = "Memory Capacity";
 			// 
 			// label3
 			// 
 			this.label3.AutoSize = true;
-			this.label3.Location = new System.Drawing.Point(127, 50);
+			this.label3.Location = new System.Drawing.Point(126, 9);
 			this.label3.Name = "label3";
 			this.label3.Size = new System.Drawing.Size(79, 13);
 			this.label3.TabIndex = 6;
@@ -135,7 +134,7 @@ namespace BizHawk.Client.EmuHawk
 			// SavestateSizeLabel
 			// 
 			this.SavestateSizeLabel.AutoSize = true;
-			this.SavestateSizeLabel.Location = new System.Drawing.Point(209, 50);
+			this.SavestateSizeLabel.Location = new System.Drawing.Point(208, 9);
 			this.SavestateSizeLabel.Name = "SavestateSizeLabel";
 			this.SavestateSizeLabel.Size = new System.Drawing.Size(25, 13);
 			this.SavestateSizeLabel.TabIndex = 7;
@@ -144,7 +143,7 @@ namespace BizHawk.Client.EmuHawk
 			// label4
 			// 
 			this.label4.AutoSize = true;
-			this.label4.Location = new System.Drawing.Point(122, 70);
+			this.label4.Location = new System.Drawing.Point(9, 89);
 			this.label4.Name = "label4";
 			this.label4.Size = new System.Drawing.Size(84, 13);
 			this.label4.TabIndex = 8;
@@ -153,36 +152,145 @@ namespace BizHawk.Client.EmuHawk
 			// NumStatesLabel
 			// 
 			this.NumStatesLabel.AutoSize = true;
-			this.NumStatesLabel.Location = new System.Drawing.Point(209, 70);
+			this.NumStatesLabel.Location = new System.Drawing.Point(96, 89);
 			this.NumStatesLabel.Name = "NumStatesLabel";
 			this.NumStatesLabel.Size = new System.Drawing.Size(25, 13);
 			this.NumStatesLabel.TabIndex = 9;
 			this.NumStatesLabel.Text = "1kb";
 			// 
-			// GreenzoneSettingsForm
+			// DiskCapacityNumeric
+			// 
+			this.DiskCapacityNumeric.Location = new System.Drawing.Point(12, 66);
+			this.DiskCapacityNumeric.Maximum = new decimal(new int[] {
+            65536,
+            0,
+            0,
+            0});
+			this.DiskCapacityNumeric.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+			this.DiskCapacityNumeric.Name = "DiskCapacityNumeric";
+			this.DiskCapacityNumeric.Size = new System.Drawing.Size(55, 20);
+			this.DiskCapacityNumeric.TabIndex = 3;
+			this.DiskCapacityNumeric.Value = new decimal(new int[] {
+            512,
+            0,
+            0,
+            0});
+			this.DiskCapacityNumeric.ValueChanged += new System.EventHandler(this.CapacityNumeric_ValueChanged);
+			// 
+			// label5
+			// 
+			this.label5.AutoSize = true;
+			this.label5.Location = new System.Drawing.Point(67, 69);
+			this.label5.Name = "label5";
+			this.label5.Size = new System.Drawing.Size(21, 13);
+			this.label5.TabIndex = 4;
+			this.label5.Text = "mb";
+			// 
+			// label6
+			// 
+			this.label6.AutoSize = true;
+			this.label6.Location = new System.Drawing.Point(12, 49);
+			this.label6.Name = "label6";
+			this.label6.Size = new System.Drawing.Size(72, 13);
+			this.label6.TabIndex = 5;
+			this.label6.Text = "Disk Capacity";
+			// 
+			// SaveCapacityNumeric
+			// 
+			this.SaveCapacityNumeric.Location = new System.Drawing.Point(158, 66);
+			this.SaveCapacityNumeric.Maximum = new decimal(new int[] {
+            65536,
+            0,
+            0,
+            0});
+			this.SaveCapacityNumeric.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+			this.SaveCapacityNumeric.Name = "SaveCapacityNumeric";
+			this.SaveCapacityNumeric.Size = new System.Drawing.Size(55, 20);
+			this.SaveCapacityNumeric.TabIndex = 3;
+			this.SaveCapacityNumeric.Value = new decimal(new int[] {
+            512,
+            0,
+            0,
+            0});
+			this.SaveCapacityNumeric.ValueChanged += new System.EventHandler(this.SaveCapacityNumeric_ValueChanged);
+			// 
+			// label7
+			// 
+			this.label7.AutoSize = true;
+			this.label7.Location = new System.Drawing.Point(213, 69);
+			this.label7.Name = "label7";
+			this.label7.Size = new System.Drawing.Size(21, 13);
+			this.label7.TabIndex = 4;
+			this.label7.Text = "mb";
+			// 
+			// label8
+			// 
+			this.label8.AutoSize = true;
+			this.label8.Location = new System.Drawing.Point(158, 49);
+			this.label8.Name = "label8";
+			this.label8.Size = new System.Drawing.Size(112, 13);
+			this.label8.TabIndex = 5;
+			this.label8.Text = "Project Save Capacity";
+			// 
+			// label9
+			// 
+			this.label9.AutoSize = true;
+			this.label9.Location = new System.Drawing.Point(155, 89);
+			this.label9.Name = "label9";
+			this.label9.Size = new System.Drawing.Size(84, 13);
+			this.label9.TabIndex = 8;
+			this.label9.Text = "Max num states:";
+			// 
+			// NumSaveStatesLabel
+			// 
+			this.NumSaveStatesLabel.AutoSize = true;
+			this.NumSaveStatesLabel.Location = new System.Drawing.Point(242, 89);
+			this.NumSaveStatesLabel.Name = "NumSaveStatesLabel";
+			this.NumSaveStatesLabel.Size = new System.Drawing.Size(25, 13);
+			this.NumSaveStatesLabel.TabIndex = 9;
+			this.NumSaveStatesLabel.Text = "1kb";
+			// 
+			// StateHistorySettingsForm
 			// 
 			this.AcceptButton = this.OkBtn;
 			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
 			this.CancelButton = this.CancelBtn;
-			this.ClientSize = new System.Drawing.Size(308, 131);
+			this.ClientSize = new System.Drawing.Size(288, 148);
+			this.Controls.Add(this.NumSaveStatesLabel);
 			this.Controls.Add(this.NumStatesLabel);
+			this.Controls.Add(this.label9);
 			this.Controls.Add(this.label4);
 			this.Controls.Add(this.SavestateSizeLabel);
 			this.Controls.Add(this.label3);
+			this.Controls.Add(this.label8);
+			this.Controls.Add(this.label7);
+			this.Controls.Add(this.label6);
+			this.Controls.Add(this.label5);
+			this.Controls.Add(this.SaveCapacityNumeric);
 			this.Controls.Add(this.label2);
+			this.Controls.Add(this.DiskCapacityNumeric);
 			this.Controls.Add(this.label1);
-			this.Controls.Add(this.CapacityNumeric);
-			this.Controls.Add(this.SaveStateHistoryCheckbox);
+			this.Controls.Add(this.MemCapacityNumeric);
 			this.Controls.Add(this.OkBtn);
 			this.Controls.Add(this.CancelBtn);
 			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
 			this.MinimumSize = new System.Drawing.Size(225, 165);
-			this.Name = "GreenzoneSettingsForm";
+			this.Name = "StateHistorySettingsForm";
 			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
 			this.Text = "Savestate History Settings";
 			this.Load += new System.EventHandler(this.StateHistorySettings_Load);
-			((System.ComponentModel.ISupportInitialize)(this.CapacityNumeric)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.MemCapacityNumeric)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.DiskCapacityNumeric)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.SaveCapacityNumeric)).EndInit();
 			this.ResumeLayout(false);
 			this.PerformLayout();
 
@@ -190,13 +298,20 @@ namespace BizHawk.Client.EmuHawk
 
 		private Button CancelBtn;
 		private Button OkBtn;
-		private CheckBox SaveStateHistoryCheckbox;
-		private NumericUpDown CapacityNumeric;
+		private NumericUpDown MemCapacityNumeric;
 		private Label label1;
 		private Label label2;
 		private Label label3;
 		private Label SavestateSizeLabel;
 		private Label label4;
 		private Label NumStatesLabel;
+		private NumericUpDown DiskCapacityNumeric;
+		private Label label5;
+		private Label label6;
+		private NumericUpDown SaveCapacityNumeric;
+		private Label label7;
+		private Label label8;
+		private Label label9;
+		private Label NumSaveStatesLabel;
 	}
 }
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs
index 003b5c9947..2bccac30a1 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs
@@ -29,24 +29,33 @@ namespace BizHawk.Client.EmuHawk
 		{
 			_stateSizeMb = Statable.SaveStateBinary().Length / (decimal)1024 / (decimal)1024;
 
-			SaveStateHistoryCheckbox.Checked = Settings.SaveStateHistory;
-			CapacityNumeric.Value = Settings.Capacitymb == 0 ? 1 : Settings.Capacitymb < CapacityNumeric.Maximum ?
-				Settings.Capacitymb :
-				CapacityNumeric.Maximum;
+			if (Environment.Is64BitProcess) // ?
+				MemCapacityNumeric.Maximum = 1024 * 8;
+			else
+				MemCapacityNumeric.Maximum = 1024;
+
+			MemCapacityNumeric.Value = Settings.Capacitymb == 0 ? 1 : Settings.Capacitymb < MemCapacityNumeric.Maximum ?
+				Settings.Capacitymb : MemCapacityNumeric.Maximum;
+			DiskCapacityNumeric.Value = Settings.DiskCapacitymb == 0 ? 1 : Settings.DiskCapacitymb < MemCapacityNumeric.Maximum ?
+				Settings.DiskCapacitymb : MemCapacityNumeric.Maximum;
+			SaveCapacityNumeric.Value = Settings.DiskSaveCapacitymb == 0 ? 1 : Settings.DiskSaveCapacitymb < MemCapacityNumeric.Maximum ?
+				Settings.DiskSaveCapacitymb : MemCapacityNumeric.Maximum;
 
 			SavestateSizeLabel.Text = Math.Round(_stateSizeMb, 2).ToString() + " mb";
 			CapacityNumeric_ValueChanged(null, null);
+			SaveCapacityNumeric_ValueChanged(null, null);
 		}
 
-		private ulong MaxStatesInCapacity
+		private int MaxStatesInCapacity
 		{
-			get { return (ulong)Math.Floor(CapacityNumeric.Value / _stateSizeMb);  }
+			get { return (int)Math.Floor((MemCapacityNumeric.Value + DiskCapacityNumeric.Value) / _stateSizeMb); }
 		}
 
 		private void OkBtn_Click(object sender, EventArgs e)
 		{
-			Settings.SaveStateHistory = SaveStateHistoryCheckbox.Checked;
-			Settings.Capacitymb = (int)CapacityNumeric.Value;
+			Settings.Capacitymb = (int)MemCapacityNumeric.Value;
+			Settings.DiskCapacitymb = (int)DiskCapacityNumeric.Value;
+			Settings.DiskSaveCapacitymb = (int)SaveCapacityNumeric.Value;
 			DialogResult = DialogResult.OK;
 			Close();
 		}
@@ -59,7 +68,14 @@ namespace BizHawk.Client.EmuHawk
 
 		private void CapacityNumeric_ValueChanged(object sender, EventArgs e)
 		{
+			// TODO: Setting space for 2.6 (2) states in memory and 2.6 (2) on disk results in 5 total.
+			// Easy to fix the display, but the way TasStateManager works the total used actually is 5.
 			NumStatesLabel.Text = MaxStatesInCapacity.ToString();
 		}
+
+		private void SaveCapacityNumeric_ValueChanged(object sender, EventArgs e)
+		{
+			NumSaveStatesLabel.Text = ((int)Math.Floor(SaveCapacityNumeric.Value / _stateSizeMb)).ToString();
+		}
 	}
 }
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/InputRoll.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/InputRoll.cs
index e65593e80b..18b317495e 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/InputRoll.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/InputRoll.cs
@@ -39,7 +39,7 @@ namespace BizHawk.Client.EmuHawk
 		// Hiding lag frames (Mainly intended for < 60fps play.)
 		public int LagFramesToHide { get; set; }
 		public bool HideWasLagFrames { get; set; }
-		private int[] lagFrames = new int[100]; // Large enough value that it shouldn't ever need resizing.
+		private byte[] lagFrames = new byte[100]; // Large enough value that it shouldn't ever need resizing.
 
 		private IntPtr RotatedFont;
 		private Font NormalFont;
@@ -1606,7 +1606,8 @@ namespace BizHawk.Client.EmuHawk
 					} while (lagFrames[0] != 0 && VBar.Value != 0 && VBar.Value != VBar.Maximum);
 				}
 
-				OnMouseMove(new MouseEventArgs(System.Windows.Forms.MouseButtons.None, 0, _currentX.Value, _currentY.Value, 0));
+				if (_currentX != null)
+					OnMouseMove(new MouseEventArgs(System.Windows.Forms.MouseButtons.None, 0, _currentX.Value, _currentY.Value, 0));
 				Refresh();
 			}
 		}
@@ -2211,7 +2212,7 @@ namespace BizHawk.Client.EmuHawk
 				{
 					fCount++;
 				} while (QueryFrameLag(FirstVisibleRow + fCount, HideWasLagFrames) && count + fCount < LagFramesToHide);
-				lagFrames[0] = fCount;
+				lagFrames[0] = (byte)fCount;
 			}
 			else
 				lagFrames[0] = 0;
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
index 617004b27d..6e482edc82 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
@@ -120,6 +120,9 @@ namespace BizHawk.Client.EmuHawk
 
 		private void saveSelectionToMacroToolStripMenuItem_Click(object sender, EventArgs e)
 		{
+			if (TasView.LastSelectedIndex == CurrentTasMovie.InputLogLength)
+				TasView.SelectRow(CurrentTasMovie.InputLogLength, false);
+
 			if (!TasView.SelectedRows.Any())
 				return;
 
diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs
index 5ed025ca4a..550b83f5cf 100644
--- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs
+++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs
@@ -43,7 +43,7 @@ namespace BizHawk.Client.EmuHawk
 					if (CurrentTasMovie[goToFrame].HasState) // Go back 1 frame and emulate to get the display (we don't store that)
 					{
 						CurrentTasMovie.SwitchToPlay();
-						LoadState(CurrentTasMovie[goToFrame].State);
+						LoadState(CurrentTasMovie.TasStateManager[frame]); // STATE ACCESS
 
 						if (frame > 0) // We can't emulate up to frame 0!
 						{
@@ -71,7 +71,7 @@ namespace BizHawk.Client.EmuHawk
 						if (CurrentTasMovie[goToFrame].HasState) // Can we go directly there?
 						{
 							CurrentTasMovie.SwitchToPlay();
-							LoadState(CurrentTasMovie[goToFrame].State);
+							LoadState(CurrentTasMovie.TasStateManager[frame]); // STATE ACCESS
 							Emulator.FrameAdvance(true);
 							GlobalWin.DisplayManager.NeedsToPaint = true;
 
@@ -99,7 +99,7 @@ namespace BizHawk.Client.EmuHawk
 					// no reason to loadstate when we can emulate a frame instead
 					if (frame - Emulator.Frame != 1)
 					{
-						LoadState(CurrentTasMovie[CurrentTasMovie.TasStateManager.LastEmulatedFrame].State);
+						LoadState(CurrentTasMovie.TasStateManager[CurrentTasMovie.TasStateManager.LastEmulatedFrame]); // STATE ACCESS
 					}
 
 					if (frame != Emulator.Frame) // If we aren't already at our destination, seek