diff --git a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
index b69231c4aa..ffe5319495 100644
--- a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
+++ b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
@@ -1,4 +1,6 @@
using System;
+using System.Globalization;
+using System.IO;
namespace BizHawk.Emulation.CPUs.M6502
{
@@ -59,19 +61,6 @@ namespace BizHawk.Emulation.CPUs.M6502
return val;
}
- // ==== CPU State ====
-
- public byte A;
- public byte X;
- public byte Y;
- public byte P;
- public ushort PC;
- public byte S;
-
- // TODO IRQ, NMI functions
- public bool Interrupt;
- public bool NMI;
-
private const ushort NMIVector = 0xFFFA;
private const ushort ResetVector = 0xFFFC;
private const ushort BRKVector = 0xFFFE;
@@ -91,13 +80,74 @@ namespace BizHawk.Emulation.CPUs.M6502
WriteMemory((ushort)(S-- + 0x100), P);
P = oldP;
FlagI = true;
- if(type == ExceptionType.NMI)
+ if (type == ExceptionType.NMI)
PC = ReadWord(NMIVector);
else
PC = ReadWord(BRKVector);
PendingCycles -= 7;
}
+ // ==== CPU State ====
+
+ public byte A;
+ public byte X;
+ public byte Y;
+ public byte P;
+ public ushort PC;
+ public byte S;
+
+ // TODO IRQ, NMI functions
+ public bool Interrupt;
+ public bool NMI;
+
+ public void SaveStateText(TextWriter writer)
+ {
+ writer.WriteLine("[MOS6502]");
+ writer.WriteLine("A {0:X2}", A);
+ writer.WriteLine("X {0:X2}", X);
+ writer.WriteLine("Y {0:X2}", Y);
+ writer.WriteLine("P {0:X2}", P);
+ writer.WriteLine("PC {0:X4}", PC);
+ writer.WriteLine("S {0:X2}", S);
+ writer.WriteLine("NMI {0}", NMI);
+ writer.WriteLine("Interrupt {0}", Interrupt);
+ writer.WriteLine("TotalExecutedCycles {0}", TotalExecutedCycles);
+ writer.WriteLine("PendingCycles {0}", PendingCycles);
+ writer.WriteLine("[/MOS6502]\n");
+ }
+
+ public void LoadStateText(TextReader reader)
+ {
+ while (true)
+ {
+ string[] args = reader.ReadLine().Split(' ');
+ if (args[0].Trim() == "") continue;
+ if (args[0] == "[/MOS6502]") break;
+ if (args[0] == "A")
+ A = byte.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "X")
+ X = byte.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "Y")
+ Y = byte.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "P")
+ P = byte.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "PC")
+ PC = ushort.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "S")
+ S = byte.Parse(args[1], NumberStyles.HexNumber);
+ else if (args[0] == "NMI")
+ NMI = bool.Parse(args[1]);
+ else if (args[0] == "Interrupt")
+ Interrupt = bool.Parse(args[1]);
+ else if (args[0] == "TotalExecutedCycles")
+ TotalExecutedCycles = int.Parse(args[1]);
+ else if (args[0] == "PendingCycles")
+ PendingCycles = int.Parse(args[1]);
+ else
+ Console.WriteLine("Skipping unrecognized identifier " + args[0]);
+ }
+ }
+
// ==== End State ====
/// Carry Flag
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
index 4786ae45ef..59d938490a 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AxROM.cs
@@ -1,17 +1,27 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
+ //TODO - hardcode CRAM size and assert
+
//generally mapper7
+ //Battletoads
+ //Time Lord
+ //Marble Madness
+
public class AxROM : NES.NESBoardBase
{
+ //configuration
string type;
bool bus_conflict;
- byte[] cram;
int cram_mask;
int prg_mask;
+
+ //state
+ byte[] cram;
int prg;
public AxROM(string type)
@@ -81,5 +91,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
else base.WritePPU(addr,value);
}
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(prg);
+ Util.WriteByteBuffer(bw, cram);
+ }
+
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ prg = br.ReadInt32();
+ cram = Util.ReadByteBuffer(br, false);
+ }
+
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs
index e54b1e6d17..69bc3a392e 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CPROM.cs
@@ -1,12 +1,17 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
- //generally mapper3
public class CPROM : NES.NESBoardBase
{
+ //generally mapper 13
+
+ //Videomation
+
+ //state
byte[] cram;
int chr;
@@ -42,5 +47,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
cram[addr - 0x1000 + (chr << 12)] = value;
else base.WritePPU(addr,value);
}
+
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(chr);
+ Util.WriteByteBuffer(bw, cram);
+ }
+
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ chr = br.ReadInt32();
+ cram = Util.ReadByteBuffer(br, false);
+ }
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs
index bac6e6c335..f7f589bca1 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs
@@ -1,13 +1,27 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
//generally mapper3
+ //Solomon's Key
+ //Arkanoid
+ //Arkista's Ring
+ //Bump 'n' Jump
+ //Cybernoid
+
public class CxROM : NES.NESBoardBase
{
+ //configuration
string type;
+ int chr_mask;
+ bool bus_conflict;
+
+ //state
+ int chr;
+
public CxROM(string type)
{
this.type = type;
@@ -36,9 +50,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
else return base.ReadPPU(addr);
}
- int chr;
- int chr_mask;
- bool bus_conflict;
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(chr);
+ }
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ chr = br.ReadInt32();
+ }
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs
index fb50d311d3..d5396a386e 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/GxROM.cs
@@ -1,13 +1,25 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
+ //generally mapper66
+
+ //Doraemon
+ //Dragon Power
+ //Gumshoe
+ //Thunder & Lightning
+ //Super Mario Bros. + Duck Hunt
+
//should this be called GNROM? there is no other Gx anything AFAIK..
public class GxROM : NES.NESBoardBase
{
+ //configuraton
int prg_mask, chr_mask;
+
+ //state
int prg, chr;
public override void Initialize(NES.RomInfo romInfo, NES nes)
@@ -40,6 +52,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
prg = (((value>>4) & 3) & prg_mask);
}
- int mask;
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(chr);
+ bw.Write(prg);
+ }
+
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ chr = br.ReadInt32();
+ prg = br.ReadInt32();
+ }
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs
index de30bc1f37..f1ce05858f 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs
@@ -1,16 +1,23 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
//mapper 11
+ //Crystal Mines
+ //Metal Fighter
+
public class Discrete_74x377 : NES.NESBoardBase
{
+ //configuration
int prg_mask, chr_mask;
- int prg, chr;
bool bus_conflict = true;
+ //state
+ int prg, chr;
+
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
@@ -47,5 +54,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
prg = (value & 3) & prg_mask;
chr = (value >> 4) & chr_mask;
}
+
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(chr);
+ bw.Write(prg);
+ }
+
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ chr = br.ReadInt32();
+ prg = br.ReadInt32();
+ }
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
index ec9c26e4d7..50f2444c83 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
@@ -5,6 +5,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
public class NROM : NES.NESBoardBase
{
+ //configuration
+ int mask;
+
+ //state
+ //(none)
+
public override void Initialize(NES.RomInfo romInfo, NES nes)
{
base.Initialize(romInfo, nes);
@@ -16,7 +22,5 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
addr &= mask;
return RomInfo.ROM[addr];
}
-
- int mask;
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs
index b7e7b99f7c..447b54cb09 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
@@ -26,6 +27,33 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
//well, lets leave it.
}
+ public void SaveStateBinary(BinaryWriter bw)
+ {
+ bw.Write(shift_count);
+ bw.Write(shift_val);
+ bw.Write(chr_mode);
+ bw.Write(prg_mode);
+ bw.Write(prg_slot);
+ bw.Write((int)mirror);
+ bw.Write(chr_0);
+ bw.Write(chr_1);
+ bw.Write(wram_disable);
+ bw.Write(prg);
+ }
+ public void LoadStateBinary(BinaryReader br)
+ {
+ shift_count = br.ReadInt32();
+ shift_val = br.ReadInt32();
+ chr_mode = br.ReadInt32();
+ prg_mode = br.ReadInt32();
+ prg_slot = br.ReadInt32();
+ mirror = (NES.EMirrorType)br.ReadInt32();
+ chr_0 = br.ReadInt32();
+ chr_1 = br.ReadInt32();
+ wram_disable = br.ReadInt32();
+ prg = br.ReadInt32();
+ }
+
public enum Rev
{
A, B1, B2, B3
@@ -137,12 +165,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
public class SxROM : NES.NESBoardBase
{
+ //configuration
string type;
- MMC1 mmc1;
int prg_mask, chr_mask;
- byte[] cram, pram;
int cram_mask, pram_mask;
+ //state
+ byte[] cram, pram;
+ MMC1 mmc1;
public SxROM(string type)
{
@@ -184,6 +214,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
cram = new byte[RomInfo.CRAM_Size * 1024];
cram_mask = cram.Length - 1;
}
+ else cram = new byte[0];
Debug.Assert(RomInfo.PRAM_Size == 0 || RomInfo.PRAM_Size == 8);
if (RomInfo.PRAM_Size != 0)
@@ -191,6 +222,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
pram = new byte[RomInfo.CRAM_Size * 1024];
pram_mask = pram.Length - 1;
}
+ else pram = new byte[0];
if (RomInfo.CHR_Size != 0)
{
@@ -264,6 +296,21 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
}
}
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ mmc1.SaveStateBinary(bw);
+ Util.WriteByteBuffer(bw, pram);
+ Util.WriteByteBuffer(bw, cram);
+ }
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ mmc1.LoadStateBinary(br);
+ pram = Util.ReadByteBuffer(br, false);
+ cram = Util.ReadByteBuffer(br, false);
+ }
+
}
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs
index 551cb5e0bd..003af1ba6d 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs
@@ -1,15 +1,30 @@
using System;
+using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
//generally mapper2
+ //Mega Man
+ //Castlevania
+ //Contra
+ //Duck Tales
+ //Metal Gear
+
//TODO - simplify logic and handle fewer (known) cases (e.g. no IsPowerOfTwo, but rather hardcoded cases)
public class UxROM : NES.NESBoardBase
{
+ //configuration
string type;
+ int pagemask;
+ int cram_mask;
+
+ //state
+ int prg;
+ byte[] cram;
+
public UxROM(string type)
{
this.type = type;
@@ -24,6 +39,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
else throw new InvalidOperationException("Invalid UxROM type");
//guess CRAM size (this is a very confident guess!)
+ //(should these guesses be here?) (is this a guess? maybe all these boards have cram)
if (RomInfo.CRAM_Size == -1) RomInfo.CRAM_Size = 8;
cram = new byte[RomInfo.CRAM_Size * 1024];
@@ -59,9 +75,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
else base.WritePPU(addr,value);
}
- int pagemask;
- int prg;
- byte[] cram;
- int cram_mask;
+ public override void SaveStateBinary(BinaryWriter bw)
+ {
+ base.SaveStateBinary(bw);
+ bw.Write(prg);
+ Util.WriteByteBuffer(bw, cram);
+ }
+
+ public override void LoadStateBinary(BinaryReader br)
+ {
+ base.LoadStateBinary(br);
+ prg = br.ReadInt32();
+ cram = Util.ReadByteBuffer(br, false);
+ }
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
index cb419c4730..a47e496df9 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
@@ -49,6 +49,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
void WritePRAM(int addr, byte value);
void Initialize(RomInfo romInfo, NES nes);
byte[] SaveRam { get; }
+ void SaveStateBinary(BinaryWriter bw);
+ void LoadStateBinary(BinaryReader br);
};
public abstract class NESBoardBase : INESBoard
@@ -62,6 +64,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public RomInfo RomInfo { get; set; }
public NES NES { get; set; }
+ public virtual void SaveStateBinary(BinaryWriter bw)
+ {
+ for (int i = 0; i < 4; i++) bw.Write(mirroring[i]);
+ }
+ public virtual void LoadStateBinary(BinaryReader br)
+ {
+ for (int i = 0; i < 4; i++) mirroring[i] = br.ReadInt32();
+ }
+
int[] mirroring = new int[4];
protected void SetMirroring(int a, int b, int c, int d)
{
@@ -132,17 +143,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public virtual byte[] SaveRam { get { return null; } }
}
- //hardware
+ //hardware/state
protected MOS6502 cpu;
INESBoard board;
public PPU ppu;
- RomInfo romInfo;
byte[] ram;
-
- IPortDevice[] ports;
+ int cpu_accumulate;
//user configuration
int[,] palette; //TBD!!
+ IPortDevice[] ports;
+ RomInfo romInfo;
public byte ReadPPUReg(int addr)
{
@@ -299,7 +310,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ppu.FrameAdvance();
}
- int cpu_accumulate;
protected void RunCpu(int cycles)
{
if (ppu.PAL)
@@ -415,27 +425,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
set { }
}
- public void SaveStateText(TextWriter writer)
- {
- }
-
- public void LoadStateText(TextReader reader)
- {
- }
-
- public void SaveStateBinary(BinaryWriter writer)
- {
- }
-
- public void LoadStateBinary(BinaryReader reader)
- {
- }
-
- public byte[] SaveStateBinary()
- {
- return new byte[0];
- }
-
public string SystemId { get { return "NES"; } }
public IList MemoryDomains { get { return new List(); } }
public MemoryDomain MainMemory
@@ -684,6 +673,65 @@ namespace BizHawk.Emulation.Consoles.Nintendo
HardReset();
}
+
+ public void SaveStateText(TextWriter writer)
+ {
+ writer.WriteLine("[NES]");
+ byte[] lol = SaveStateBinary();
+ writer.WriteLine("blob {0}", Util.BytesToHexString(lol));
+ writer.WriteLine("[/NES]");
+ }
+
+ public void LoadStateText(TextReader reader)
+ {
+ byte[] blob = null;
+ while (true)
+ {
+ string[] args = reader.ReadLine().Split(' ');
+ if (args[0] == "blob")
+ blob = Util.HexStringToBytes(args[1]);
+ else if (args[0] == "[/NES]") break;
+ }
+ if (blob == null) throw new ArgumentException();
+ LoadStateBinary(new BinaryReader(new MemoryStream(blob)));
+ }
+
+
+ public byte[] SaveStateBinary()
+ {
+ MemoryStream ms = new MemoryStream();
+ BinaryWriter bw = new BinaryWriter(ms);
+ SaveStateBinary(bw);
+ bw.Flush();
+ return ms.ToArray();
+ }
+
+ public void SaveStateBinary(BinaryWriter bw)
+ {
+ using (var sw = new StringWriter())
+ {
+ cpu.SaveStateText(sw);
+ sw.Flush();
+ Util.WriteByteBuffer(bw, System.Text.Encoding.ASCII.GetBytes(sw.ToString()));
+ }
+ Util.WriteByteBuffer(bw,ram);
+ bw.Write(cpu_accumulate);
+ board.SaveStateBinary(bw);
+ ppu.SaveStateBinary(bw);
+ bw.Flush();
+ }
+
+ public void LoadStateBinary(BinaryReader br)
+ {
+ using (var sr = new StringReader(System.Text.Encoding.ASCII.GetString(Util.ReadByteBuffer(br, false))))
+ cpu.LoadStateText(sr);
+ ram = Util.ReadByteBuffer(br, false);
+ cpu_accumulate = br.ReadInt32();
+ board.LoadStateBinary(br);
+ ppu.LoadStateBinary(br);
+ }
+
+
}
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
index 988b0d4914..0087b9466d 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.cs
@@ -51,9 +51,50 @@ namespace BizHawk.Emulation.Consoles.Nintendo
Reset();
}
+ //state
int ppudead; //measured in frames
bool idleSynch;
+ public void SaveStateBinary(BinaryWriter bw)
+ {
+ bw.Write(ppudead);
+ bw.Write(idleSynch);
+ bw.Write((bool)Reg2002_objoverflow);
+ bw.Write((bool)Reg2002_objhit);
+ bw.Write((bool)Reg2002_vblank_active);
+ bw.Write(PPUGenLatch);
+ bw.Write(reg_2000.Value);
+ bw.Write(reg_2001.Value);
+ bw.Write(reg_2003);
+ Util.WriteByteBuffer(bw, OAM);
+ Util.WriteByteBuffer(bw, PALRAM);
+ Util.WriteByteBuffer(bw, NTARAM);
+ bw.Write(vtoggle);
+ bw.Write(VRAMBuffer);
+ ppur.SaveStateBinary(bw);
+ bw.Write(xbuf);
+ }
+
+ public void LoadStateBinary(BinaryReader br)
+ {
+ ppudead = br.ReadInt32();
+ idleSynch = br.ReadBoolean();
+ Reg2002_objoverflow = br.ReadBit();
+ Reg2002_objhit = br.ReadBit();
+ Reg2002_vblank_active = br.ReadBit();
+ PPUGenLatch = br.ReadByte();
+ reg_2000.Value = br.ReadByte();
+ reg_2001.Value = br.ReadByte();
+ reg_2003 = br.ReadByte();
+ OAM = Util.ReadByteBuffer(br,false);
+ PALRAM = Util.ReadByteBuffer(br, false);
+ NTARAM = Util.ReadByteBuffer(br, false);
+ vtoggle = br.ReadBoolean();
+ VRAMBuffer = br.ReadByte();
+ ppur.LoadStateBinary(br);
+ xbuf = br.ReadShorts(xbuf.Length);
+ }
+
public void Reset()
{
regs_reset();
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
index c093431661..ec607b8197 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.regs.cs
@@ -71,6 +71,42 @@ namespace BizHawk.Emulation.Consoles.Nintendo
reset();
}
+ public void SaveStateBinary(BinaryWriter bw)
+ {
+ bw.Write(fv);
+ bw.Write(v);
+ bw.Write(h);
+ bw.Write(vt);
+ bw.Write(ht);
+ bw.Write(_fv);
+ bw.Write(_v);
+ bw.Write(_h);
+ bw.Write(_vt);
+ bw.Write(_ht);
+ bw.Write(fh);
+ bw.Write(status.cycle);
+ bw.Write(status.end_cycle);
+ bw.Write(status.sl);
+ }
+
+ public void LoadStateBinary(BinaryReader br)
+ {
+ fv = br.ReadInt32();
+ v = br.ReadInt32();
+ h = br.ReadInt32();
+ vt = br.ReadInt32();
+ ht = br.ReadInt32();
+ _fv = br.ReadInt32();
+ _v = br.ReadInt32();
+ _h = br.ReadInt32();
+ _vt = br.ReadInt32();
+ _ht = br.ReadInt32();
+ fh = br.ReadInt32();
+ status.cycle = br.ReadInt32();
+ status.end_cycle = br.ReadInt32();
+ status.sl = br.ReadInt32();
+ }
+
//normal clocked regs. as the game can interfere with these at any time, they need to be savestated
public int fv;//3
public int v;//1
@@ -221,8 +257,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public Bit ppu_layer; //PPU layer select (should always be 0 in the NES; some Nintendo arcade boards presumably had two PPUs)
public Bit vblank_nmi_gen; //Vertical blank NMI generation (0: off; 1: on)
+
public byte Value
{
+ get
+ {
+ return (byte)(ppu.ppur._h | (ppu.ppur._v << 1) | (vram_incr32 << 2) | (obj_pattern_hi << 3) | (bg_pattern_hi << 4) | (obj_size_16 << 5) | (ppu_layer << 6) | (vblank_nmi_gen << 7));
+ }
set
{
ppu.ppur._h = value & 1;
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
index ab1f0053dd..e35895fcae 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/PPU.run.cs
@@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public byte pt_0, pt_1;
};
- public int[] xbuf = new int[256*256];
+ public short[] xbuf = new short[256*256];
void Read_bgdata(ref BGDataRecord bgdata) {
int addr = ppur.get_ntread();
@@ -68,11 +68,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
//TODO - check flashing sirens in werewolf
- int PaletteAdjustPixel(int pixel)
+ short PaletteAdjustPixel(int pixel)
{
//tack on the deemph bits
pixel |= (reg_2001.intense_red<<8)|(reg_2001.intense_green<<9)|(reg_2001.intense_blue<<10);
- return pixel;
+ return (short)pixel;
}
const int kLineTime = 341;
diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs
index 89be102a48..d5fba37bd3 100644
--- a/BizHawk.Emulation/Util.cs
+++ b/BizHawk.Emulation/Util.cs
@@ -200,6 +200,65 @@ namespace BizHawk
writer.WriteLine();
}
+ public static void SaveAsHex(this int[] buffer, TextWriter writer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ {
+ writer.Write("{0:X8}", buffer[i]);
+ }
+ writer.WriteLine();
+ }
+
+ public static void SaveAsHex(this uint[] buffer, TextWriter writer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ {
+ writer.Write("{0:X8}", buffer[i]);
+ }
+ writer.WriteLine();
+ }
+
+ public static void Write(this BinaryWriter bw, int[] buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ public static void Write(this BinaryWriter bw, uint[] buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ public static void Write(this BinaryWriter bw, short[] buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ public static void Write(this BinaryWriter bw, ushort[] buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ public static int[] ReadInts(this BinaryReader br, int num)
+ {
+ int[] ret = new int[num];
+ for (int i = 0; i < num; i++)
+ ret[i] = br.ReadInt32();
+ return ret;
+ }
+
+ public static short[] ReadShorts(this BinaryReader br, int num)
+ {
+ short[] ret = new short[num];
+ for (int i = 0; i < num; i++)
+ ret[i] = br.ReadInt16();
+ return ret;
+ }
+
+
public static void ReadFromHex(this byte[] buffer, string hex)
{
if (hex.Length % 2 != 0)
@@ -232,6 +291,22 @@ namespace BizHawk
buffer[i] = ushort.Parse(ushorthex, NumberStyles.HexNumber);
}
}
+
+ public static void ReadFromHex(this int[] buffer, BinaryWriter bw)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ public static void SaveAsHex(this uint[] buffer, BinaryWriter bw)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ bw.Write(buffer[i]);
+ }
+
+ //these don't work??? they dont get chosen by compiler
+ public static void Write(this BinaryWriter bw, Bit bit) { bw.Write((bool)bit); }
+ public static Bit ReadBit(this BinaryReader br) { return br.ReadBoolean(); }
}
public static class Colors
@@ -255,7 +330,7 @@ namespace BizHawk
//I think this is a little faster with uint than with byte
- struct Bit
+ public struct Bit
{
Bit(uint val) { this.val = val; }
uint val;
@@ -299,6 +374,7 @@ namespace BizHawk
///
/// conerts bytes to an uppercase string of hex numbers in upper case without any spacing or anything
+ /// //could be extension method
///
public static string BytesToHexString(byte[] bytes)
{
@@ -308,6 +384,57 @@ namespace BizHawk
return sb.ToString();
}
+ //could be extension method
+ public static byte[] HexStringToBytes(string str)
+ {
+ MemoryStream ms = new MemoryStream();
+ if (str.Length % 2 != 0) throw new ArgumentException();
+ int len = str.Length/2;
+ for (int i = 0; i < len; i++)
+ {
+ int d = 0;
+ for (int j = 0; j < 2; j++)
+ {
+ char c = char.ToLower(str[i * 2 + j]);
+ if (c >= '0' && c <= '9')
+ d += (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ d += (c - 'a') + 10;
+ else throw new ArgumentException();
+ if (j == 0) d <<= 4;
+ }
+ ms.WriteByte((byte)d);
+ }
+ return ms.ToArray();
+ }
+
+ //could be extension method
+ public static void WriteByteBuffer(BinaryWriter bw, byte[] data)
+ {
+ if (data == null) bw.Write(0);
+ else
+ {
+ bw.Write(data.Length);
+ bw.Write(data);
+ }
+ }
+
+ //could be extension method
+ public static byte[] ReadByteBuffer(BinaryReader br, bool return_null)
+ {
+ int len = br.ReadInt32();
+ if (len == 0 && return_null) return null;
+ byte[] ret = new byte[len];
+ int ofs = 0;
+ while (len > 0)
+ {
+ int done = br.Read(ret, ofs, len);
+ ofs += done;
+ len -= done;
+ }
+ return ret;
+ }
+
public static unsafe int memcmp(void* a, string b, int len)
{
fixed (byte* bp = System.Text.Encoding.ASCII.GetBytes(b))
diff --git a/BizHawk.MultiClient/Config.cs b/BizHawk.MultiClient/Config.cs
index 6fec656066..3a4eda5b35 100644
--- a/BizHawk.MultiClient/Config.cs
+++ b/BizHawk.MultiClient/Config.cs
@@ -35,6 +35,7 @@
public bool LimitFramerate = true;
public bool AutoMinimizeSkipping = true;
public bool DisplayVSync = false;
+ public bool RewindEnabled = true;
// Display options
public bool DisplayFPS = false;
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index 93f227f475..6def637169 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -610,7 +610,7 @@ namespace BizHawk.MultiClient
runFrame = true;
}
- if (/*Global.Config.RewindEnabled && */Global.ClientControls["Rewind"])
+ if (Global.Config.RewindEnabled && Global.ClientControls["Rewind"])
{
rewindCredits += Global.Config.SpeedPercent;
int rewindTodo = rewindCredits / 100;
@@ -629,7 +629,7 @@ namespace BizHawk.MultiClient
bool genSound = false;
if (runFrame)
{
- if(!suppressCaptureRewind) CaptureRewindState();
+ if(!suppressCaptureRewind && Global.Config.RewindEnabled) CaptureRewindState();
if (!runloop_frameadvance) genSound = true;
else if (!Global.Config.MuteFrameAdvance)
genSound = true;
diff --git a/BizHawk.MultiClient/Rewind.cs b/BizHawk.MultiClient/Rewind.cs
index e9dd1b3606..785ef4bcb7 100644
--- a/BizHawk.MultiClient/Rewind.cs
+++ b/BizHawk.MultiClient/Rewind.cs
@@ -38,6 +38,8 @@ namespace BizHawk.MultiClient
{
if (inChangeSequence == false)
{
+ if (i >= LastState.Length)
+ continue;
if (CurrentState[i] == LastState[i])
continue;
@@ -82,6 +84,8 @@ namespace BizHawk.MultiClient
{
if (inChangeSequence == false)
{
+ if (i >= LastState.Length)
+ continue;
if (CurrentState[i] == LastState[i])
continue;
diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt
index 0955d251e3..8ec551f891 100644
--- a/BizHawk.MultiClient/output/gamedb.txt
+++ b/BizHawk.MultiClient/output/gamedb.txt
@@ -2386,7 +2386,7 @@ D821FB982CE47299FDB08A027EC0B8BE Super Mario Bros - Duck Hunt (U) NES board=Gx
;GxROM 8,4 (mapper 66) ;these frequently needs to be corrected to V
ADD4E9F5ED4391A6B3FDFC5F0E300E71 Doraemon (J) NES board=GxROM;mirror=V;PRG=8;CHR=4
4E9D128C63A41C8CC20FF1114A67A2DD Dragon Power (U) NES board=GxROM;mirror=V;PRG=8;CHR=4
-8F43E7D7BD3DBDF6D8ADF3E046DE3562 Gumshoe (UE) NES board=GxROM;mirror=H;PRG=8;CHR=4
+8F43E7D7BD3DBDF6D8ADF3E046DE3562 Gumshoe (UE) NES board=GxROM;mirror=V;PRG=8;CHR=4
;GxROM 8,16 (mapper 66)
BE40E77C5532AF8E2C1EA7B96831CCEA Thunder & Lightning (U).nes NES board=GxROM;mirror=H;PRG=8;CHR=16
\ No newline at end of file