diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index d203fc1bdf..44c76bba23 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -265,6 +265,9 @@
N64.cs
+
+ N64.cs
+
N64.cs
@@ -274,6 +277,9 @@
N64.cs
+
+ N64.cs
+
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs
index 67db75b262..b01f973138 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using BizHawk.Emulation.Common;
+using BizHawk.Emulation.Cores.Nintendo.N64.NativeApi;
namespace BizHawk.Emulation.Cores.Nintendo.N64
{
@@ -69,5 +70,35 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
}
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
+
+ private mupen64plusApi.MemoryCallback _readcb;
+ private mupen64plusApi.MemoryCallback _writecb;
+
+ private void RefreshMemoryCallbacks()
+ {
+ var mcs = MemoryCallbacks;
+
+ // we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
+ if (mcs.HasReads)
+ {
+ _readcb = delegate(uint addr) { mcs.CallRead(addr); };
+ }
+ else
+ {
+ _readcb = null;
+ }
+
+ if (mcs.HasWrites)
+ {
+ _writecb = delegate(uint addr) { mcs.CallWrite(addr); };
+ }
+ else
+ {
+ _writecb = null;
+ }
+
+ api.setReadCallback(_readcb);
+ api.setWriteCallback(_writecb);
+ }
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IInputPollable.cs
new file mode 100644
index 0000000000..14103da9d6
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IInputPollable.cs
@@ -0,0 +1,51 @@
+using BizHawk.Emulation.Common;
+
+namespace BizHawk.Emulation.Cores.Nintendo.N64
+{
+ public partial class N64 : IInputPollable
+ {
+ public int Frame { get; private set; }
+ public int LagCount { get; set; }
+
+ public bool IsLagFrame
+ {
+ get
+ {
+ if (_settings.UseMupenStyleLag)
+ {
+ return !IsVIFrame;
+ }
+
+ return !_inputProvider.LastFrameInputPolled;
+ }
+
+ internal set
+ {
+ if (_settings.UseMupenStyleLag)
+ {
+ IsVIFrame = !value;
+ }
+ else
+ {
+ _inputProvider.LastFrameInputPolled = !value;
+ }
+ }
+ }
+
+ public bool IsVIFrame
+ {
+ get
+ {
+ return _videoProvider.IsVIFrame;
+ }
+
+ internal set
+ {
+ _videoProvider.IsVIFrame = value;
+ }
+ }
+
+ // TODO: optimize managed to unmanaged using the ActiveChanged event
+ public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented] get; private set; }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs
new file mode 100644
index 0000000000..547e566477
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs
@@ -0,0 +1,104 @@
+using System;
+using System.IO;
+
+using BizHawk.Common.BufferExtensions;
+using BizHawk.Emulation.Common;
+using BizHawk.Emulation.Cores.Nintendo.N64.NativeApi;
+
+namespace BizHawk.Emulation.Cores.Nintendo.N64
+{
+ public partial class N64 : IStatable
+ {
+ public bool BinarySaveStatesPreferred { get { return true; } }
+
+ // these functions are all exact copy paste from gambatte.
+ // if something's wrong here, it's probably wrong there too
+ public void SaveStateText(TextWriter writer)
+ {
+ var temp = SaveStateBinary();
+ temp.SaveAsHexFast(writer);
+
+ // write extra copy of stuff we don't use
+ writer.WriteLine("Frame {0}", Frame);
+ }
+
+ public void LoadStateText(TextReader reader)
+ {
+ var hex = reader.ReadLine();
+ var state = new byte[hex.Length / 2];
+ state.ReadFromHexFast(hex);
+ LoadStateBinary(new BinaryReader(new MemoryStream(state)));
+ }
+
+ public void SaveStateBinary(BinaryWriter writer)
+ {
+ byte[] data = SaveStatePrivateBuff;
+ int bytes_used = api.SaveState(data);
+
+ writer.Write(bytes_used);
+ writer.Write(data, 0, bytes_used);
+
+ byte[] saveram = api.SaveSaveram();
+ writer.Write(saveram);
+ if (saveram.Length != mupen64plusApi.kSaveramSize)
+ {
+ throw new InvalidOperationException("Unexpected N64 SaveRam size");
+ }
+
+ // other variables
+ writer.Write(IsLagFrame);
+ writer.Write(LagCount);
+ writer.Write(Frame);
+ }
+
+ public void LoadStateBinary(BinaryReader reader)
+ {
+ int length = reader.ReadInt32();
+ if ((_disableExpansionSlot && length >= 16788288) || (!_disableExpansionSlot && length < 16788288))
+ {
+ throw new SavestateSizeMismatchException("Wrong N64 savestate size");
+ }
+
+ reader.Read(SaveStatePrivateBuff, 0, length);
+ byte[] data = SaveStatePrivateBuff;
+
+ api.LoadState(data);
+
+ reader.Read(SaveStatePrivateBuff, 0, mupen64plusApi.kSaveramSize);
+ api.LoadSaveram(SaveStatePrivateBuff);
+
+ // other variables
+ IsLagFrame = reader.ReadBoolean();
+ LagCount = reader.ReadInt32();
+ Frame = reader.ReadInt32();
+ }
+
+ public byte[] SaveStateBinary()
+ {
+ // WELCOME TO THE HACK ZONE
+ byte[] saveram = api.SaveSaveram();
+
+ int lenwant = 4 + SaveStatePrivateBuff.Length + saveram.Length + 1 + 4 + 4;
+ if (SaveStateBinaryPrivateBuff.Length != lenwant)
+ {
+ Console.WriteLine("Allocating new N64 private buffer size {0}", lenwant);
+ SaveStateBinaryPrivateBuff = new byte[lenwant];
+ }
+
+ var ms = new MemoryStream(SaveStateBinaryPrivateBuff);
+ var bw = new BinaryWriter(ms);
+ SaveStateBinary(bw);
+ bw.Flush();
+
+ if (ms.Length != SaveStateBinaryPrivateBuff.Length)
+ {
+ throw new Exception("Unexpected Length");
+ }
+
+ return SaveStateBinaryPrivateBuff;
+ }
+
+ private byte[] SaveStatePrivateBuff = new byte[16788288 + 1024];
+ private byte[] SaveStateBinaryPrivateBuff = new byte[0];
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs
index b43a88f5c0..3fba0fa196 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs
@@ -52,6 +52,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
public N64(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings)
{
ServiceProvider = new BasicServiceProvider(this);
+ InputCallbacks = new InputCallbackSystem();
MemoryCallbacks = new MemoryCallbackSystem();
int SaveType = 0;
@@ -254,40 +255,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
set { _inputProvider.Controller = value; }
}
- public int Frame { get; private set; }
- public int LagCount { get; set; }
-
- public bool IsLagFrame
- {
- get
- {
- if (_settings.UseMupenStyleLag)
- {
- return !IsVIFrame;
- }
-
- return !_inputProvider.LastFrameInputPolled;
- }
-
- internal set
- {
- if (_settings.UseMupenStyleLag)
- {
- IsVIFrame = !value;
- }
- else
- {
- _inputProvider.LastFrameInputPolled = !value;
- }
- }
- }
-
- public bool IsVIFrame
- {
- get { return _videoProvider.IsVIFrame; }
- internal set { _videoProvider.IsVIFrame = value; }
- }
-
public void ResetCounters()
{
Frame = 0;
@@ -296,131 +263,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
}
public bool DeterministicEmulation { get { return false; } }
-
- #region Savestates
-
- // these next 5 functions are all exact copy paste from gambatte.
- // if something's wrong here, it's probably wrong there too
- public void SaveStateText(TextWriter writer)
- {
- var temp = SaveStateBinary();
- temp.SaveAsHexFast(writer);
-
- // write extra copy of stuff we don't use
- writer.WriteLine("Frame {0}", Frame);
- }
-
- public void LoadStateText(TextReader reader)
- {
- var hex = reader.ReadLine();
- var state = new byte[hex.Length / 2];
- state.ReadFromHexFast(hex);
- LoadStateBinary(new BinaryReader(new MemoryStream(state)));
- }
-
- private byte[] SaveStatePrivateBuff = new byte[16788288 + 1024];
- public void SaveStateBinary(BinaryWriter writer)
- {
- byte[] data = SaveStatePrivateBuff;
- int bytes_used = api.SaveState(data);
-
- writer.Write(bytes_used);
- writer.Write(data, 0, bytes_used);
-
- byte[] saveram = api.SaveSaveram();
- writer.Write(saveram);
- if (saveram.Length != mupen64plusApi.kSaveramSize)
- {
- throw new InvalidOperationException("Unexpected N64 SaveRam size");
- }
-
- // other variables
- writer.Write(IsLagFrame);
- writer.Write(LagCount);
- writer.Write(Frame);
- }
-
- public void LoadStateBinary(BinaryReader reader)
- {
- int length = reader.ReadInt32();
- if ((_disableExpansionSlot && length >= 16788288) || (!_disableExpansionSlot && length < 16788288))
- {
- throw new SavestateSizeMismatchException("Wrong N64 savestate size");
- }
-
- reader.Read(SaveStatePrivateBuff, 0, length);
- byte[] data = SaveStatePrivateBuff;
-
- api.LoadState(data);
-
- reader.Read(SaveStatePrivateBuff, 0, mupen64plusApi.kSaveramSize);
- api.LoadSaveram(SaveStatePrivateBuff);
-
- // other variables
- IsLagFrame = reader.ReadBoolean();
- LagCount = reader.ReadInt32();
- Frame = reader.ReadInt32();
- }
-
- private byte[] SaveStateBinaryPrivateBuff = new byte[0];
-
- public byte[] SaveStateBinary()
- {
- // WELCOME TO THE HACK ZONE
- byte[] saveram = api.SaveSaveram();
-
- int lenwant = 4 + SaveStatePrivateBuff.Length + saveram.Length + 1 + 4 + 4;
- if (SaveStateBinaryPrivateBuff.Length != lenwant)
- {
- Console.WriteLine("Allocating new N64 private buffer size {0}", lenwant);
- SaveStateBinaryPrivateBuff = new byte[lenwant];
- }
-
- var ms = new MemoryStream(SaveStateBinaryPrivateBuff);
- var bw = new BinaryWriter(ms);
- SaveStateBinary(bw);
- bw.Flush();
-
- if (ms.Length != SaveStateBinaryPrivateBuff.Length)
- {
- throw new Exception("Unexpected Length");
- }
-
- return SaveStateBinaryPrivateBuff;
- }
-
- public bool BinarySaveStatesPreferred { get { return true; } }
-
- #endregion
-
- #region Debugging Hooks
-
- private mupen64plusApi.MemoryCallback readcb;
- private mupen64plusApi.MemoryCallback writecb;
-
- private void RefreshMemoryCallbacks()
- {
- var mcs = MemoryCallbacks;
-
- // we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
- if (mcs.HasReads)
- readcb = delegate(uint addr) { mcs.CallRead(addr); };
- else
- readcb = null;
- if (mcs.HasWrites)
- writecb = delegate(uint addr) { mcs.CallWrite(addr); };
- else
- writecb = null;
-
- api.setReadCallback(readcb);
- api.setWriteCallback(writecb);
- }
-
- private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
-
- // TODO: optimize managed to unmanaged using the ActiveChanged event
- public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } }
-
- #endregion
}
}