diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs
index a37c230a4b..c66a58d0b6 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs
@@ -15,15 +15,73 @@ namespace BizHawk.Emulation.Consoles.Nintendo
[NES.INESBoardImplCancel]
public class FDS : NES.NESBoardBase
{
- ///
- /// fds bios image; should be 8192 bytes
- ///
+ #region configuration
+ /// FDS bios image; should be 8192 bytes
public byte[] biosrom;
-
- ///
- /// .fds disk image
- ///
+ /// .FDS disk image
byte[] diskimage;
+ #endregion
+
+ #region state
+ RamAdapter diskdrive;
+ FDSAudio audio;
+ /// 0-2, how many ppu cycles since audio was last triggered
+ int audioclock;
+ /// currently loaded side of the .FDS image, 0 based
+ int? currentside = null;
+ /// collection of diffs (as provided by the RamAdapter) for each side in the .FDS image
+ byte[][] diskdiffs;
+
+ bool _diskirq;
+ bool _timerirq;
+
+ /// disk io ports enabled; see 4023.0
+ bool diskenable = false;
+ /// sound io ports enabled; see 4023.1
+ bool soundenable = false;
+ /// read on 4033, write on 4026
+ byte reg4026;
+
+ /// timer reload
+ int timerlatch;
+ /// timer current value
+ int timervalue;
+ /// 4022.0,1
+ byte timerreg;
+ #endregion
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.BeginSection("FDS");
+ ser.BeginSection("RamAdapter");
+ diskdrive.SyncState(ser);
+ ser.EndSection();
+ ser.BeginSection("audio");
+ audio.SyncState(ser);
+ ser.EndSection();
+ ser.Sync("audioclock", ref audioclock);
+ {
+ // silly little hack
+ int tmp = currentside != null ? (int)currentside : 1234567;
+ ser.Sync("currentside", ref tmp);
+ currentside = tmp == 1234567 ? null : (int?)tmp;
+ }
+ for (int i = 0; i < NumSides; i++)
+ ser.Sync("diskdiffs" + i, ref diskdiffs[i], false);
+ ser.Sync("_timerirq", ref _timerirq);
+ ser.Sync("_diskirq", ref _diskirq);
+ ser.Sync("diskenable", ref diskenable);
+ ser.Sync("soundenable", ref soundenable);
+ ser.Sync("reg4026", ref reg4026);
+ ser.Sync("timerlatch", ref timerlatch);
+ ser.Sync("timervalue", ref timervalue);
+ ser.Sync("timerreg", ref timerreg);
+ ser.EndSection();
+
+ SetIRQ();
+ }
+
///
/// should only be called once, before emulation begins
@@ -35,11 +93,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
diskdiffs = new byte[NumSides][];
}
-
- RamAdapter diskdrive;
- FDSAudio audio;
- int audioclock;
-
// as we have [INESBoardImplCancel], this will only be called with an fds disk image
public override bool Configure(NES.EDetectionOrigin origin)
{
@@ -56,21 +109,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
audio = new FDSAudio();
InsertSide(0);
-
- // set mirroring
-
+ // set mirroring??
return true;
}
// with a bit of change, these methods could work with a better disk format
- public int NumSides
- {
- get
- {
- return diskimage[4];
- }
- }
+ public int NumSides { get { return diskimage[4]; } }
public void Eject()
{
@@ -84,6 +129,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public void InsertSide(int side)
{
+ if (side >= NumSides)
+ throw new ArgumentOutOfRangeException();
byte[] buf = new byte[65500];
Buffer.BlockCopy(diskimage, 16 + side * 65500, buf, 0, 65500);
diskdrive.InsertBrokenImage(buf, false /*true*/);
@@ -92,10 +139,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
currentside = side;
}
- int? currentside = null;
-
- byte[][] diskdiffs;
-
public byte[] ReadSaveRam()
{
// update diff for currently loaded disk first!
@@ -169,20 +212,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
IRQSignal = _diskirq || _timerirq;
}
- bool _diskirq;
- bool _timerirq;
bool diskirq { get { return _diskirq; } set { _diskirq = value; SetIRQ(); } }
bool timerirq { get { return _timerirq; } set { _timerirq = value; SetIRQ(); } }
- bool diskenable = false;
- bool soundenable = false;
- int timerlatch;
- int timervalue;
- byte timerreg;
- byte reg4026;
public override void WriteEXP(int addr, byte value)
{
@@ -268,7 +303,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
if (diskenable)
{
ret = reg4026;
- ret &= 0x80; // set battery flag
+ // uncomment to set low battery flag
+ // ret &= 0x7f;
}
break;
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDSAudio.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDSAudio.cs
index f823bd25d2..2ca361c585 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDSAudio.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDSAudio.cs
@@ -8,6 +8,53 @@ namespace BizHawk.Emulation.Consoles.Nintendo
// http://wiki.nesdev.com/w/index.php/FDS_audio
public class FDSAudio
{
+ public void SyncState(Serializer ser)
+ {
+ // no need to sync the DCFilter or the samplebuff
+ ser.Sync("waveram", ref waveram, false);
+ ser.Sync("waverampos", ref waverampos);
+
+ ser.Sync("volumespd", ref volumespd);
+ ser.Sync("r4080_6", ref r4080_6);
+ ser.Sync("r4080_7", ref r4080_7);
+
+ ser.Sync("frequency", ref frequency);
+ ser.Sync("r4083_6", ref r4083_6);
+ ser.Sync("r4083_7", ref r4083_7);
+
+ ser.Sync("sweepspd", ref sweepspd);
+ ser.Sync("r4084_6", ref r4084_6);
+ ser.Sync("r4084_7", ref r4084_7);
+
+ ser.Sync("sweepbias", ref sweepbias);
+
+ ser.Sync("modfreq", ref modfreq);
+ ser.Sync("r4087_7", ref r4087_7);
+
+ ser.Sync("modtable", ref modtable, false);
+ ser.Sync("modtablepos", ref modtablepos);
+
+ ser.Sync("mastervol_num", ref mastervol_num);
+ ser.Sync("mastervol_den", ref mastervol_den);
+ ser.Sync("waveram_writeenable", ref waveram_writeenable);
+
+ ser.Sync("envspeed", ref envspeed);
+
+ ser.Sync("volumeclock", ref volumeclock);
+ ser.Sync("sweepclock", ref sweepclock);
+ ser.Sync("modclock", ref modclock);
+ ser.Sync("mainclock", ref mainclock);
+
+ ser.Sync("modoutput", ref modoutput);
+
+ ser.Sync("volumegain", ref volumegain);
+ ser.Sync("sweepgain", ref sweepgain);
+
+ ser.Sync("waveramoutput", ref waveramoutput);
+
+ ser.Sync("latchedoutput", ref latchedoutput);
+ }
+
//4040:407f
byte[] waveram = new byte[64];
int waverampos;
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs
index 4f423b1723..83d0296df6 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs
@@ -11,6 +11,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
///
public class RamAdapter
{
+ #region fix broken images
+
static void WriteBlock(Stream dest, byte[] data, int pregap)
{
for (int i = 0; i < pregap - 1; i++)
@@ -87,6 +89,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return tmp;
}
+ #endregion
+
+ #region crc
+
///
/// advance a 16 bit CRC register with 1 new input bit. x.25 standard
///
@@ -118,6 +124,41 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return crc;
}
+ #endregion
+
+ public void SyncState(Serializer ser)
+ {
+ ser.Sync("originaldisk", ref originaldisk, false);
+ ser.Sync("disk", ref disk, false);
+ ser.Sync("diskpos", ref diskpos);
+ ser.Sync("disksize", ref disksize);
+ ser.Sync("writeprotect", ref writeprotect);
+
+ ser.Sync("cycleswaiting", ref cycleswaiting);
+ {
+ int tmp = (int)state;
+ ser.Sync("state", ref tmp);
+ state = (RamAdapterState)tmp;
+ }
+ ser.Sync("cached4025", ref cached4025);
+ ser.Sync("irq", ref irq);
+ ser.Sync("transferreset", ref transferreset);
+
+ ser.Sync("crc", ref crc);
+ ser.Sync("writecomputecrc", ref writecomputecrc);
+
+ ser.Sync("readreg", ref readreg);
+ ser.Sync("writereg", ref writereg);
+ ser.Sync("readregpos", ref readregpos);
+ ser.Sync("writeregpos", ref writeregpos);
+ ser.Sync("readreglatch", ref readreglatch);
+ ser.Sync("writereglatch", ref writereglatch);
+
+ ser.Sync("bytetransferflag", ref bytetransferflag);
+ ser.Sync("lookingforendofgap", ref lookingforendofgap);
+ }
+
+ #region state
/// the original contents of this disk when it was loaded. for virtual saveram diff
byte[] originaldisk = null;
/// currently loaded disk side (ca 65k bytes)
@@ -129,6 +170,38 @@ namespace BizHawk.Emulation.Consoles.Nintendo
/// true if current disk is writeprotected
bool writeprotect = true;
+ /// ppu cycles until next action
+ int cycleswaiting = 0;
+ /// physical state of the drive
+ RamAdapterState state = RamAdapterState.IDLE;
+
+ /// cached 4025 write; can be modified internally by some things
+ byte cached4025;
+ /// can be raised on byte transfer complete
+ public bool irq;
+ /// true if 4025.1 is set to true
+ bool transferreset = false;
+
+ ///
+ /// 16 bit CRC register. in normal operation, will become all 0 on finishing a read (see x.25 spec for more details)
+ ///
+ ushort crc = 0;
+ /// true if data being written to disk is currently being computed in CRC
+ bool writecomputecrc; // this has to be latched because the "flush CRC" call comes in the middle of a byte, of course
+
+ // read and write shift regs, with bit positions and latched values for reload
+ byte readreg;
+ byte writereg;
+ int readregpos;
+ int writeregpos;
+ byte readreglatch;
+ byte writereglatch;
+
+ bool bytetransferflag;
+ bool lookingforendofgap = false;
+
+ #endregion
+
///
/// eject the loaded disk
///
@@ -221,11 +294,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
// all timings are in terms of PPU cycles (@5.37mhz)
- ///
- /// ppu cycles until next action
- ///
- int cycleswaiting = 0;
-
enum RamAdapterState
{
/// moving over the disk
@@ -239,10 +307,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
/// nothing happening
IDLE,
};
- ///
- /// physical state of the drive
- ///
- RamAdapterState state = RamAdapterState.IDLE;
///
/// set cycleswaiting param after a state change
@@ -285,23 +349,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//Console.WriteLine("!!4024:{0:x2}", value);
}
- ///
- /// cached 4025 write; can be modified internally by some things
- ///
- byte cached4025;
-
- ///
- /// can be raised on byte transfer complete
- ///
- public bool irq;
-
- /// true if 4025.1 is set to true
- bool transferreset = false;
-
- ///
- /// 16 bit CRC register. in normal operation, will become all 0 on finishing a read (see x.25 spec for more details)
- ///
- ushort crc = 0;
///
/// control reg
@@ -374,11 +421,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return ret;
}
- ///
- /// DEBUG ONLY
- ///
- int lastreaddiskpos;
-
///
/// more status stuff
///
@@ -463,22 +505,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
}
- // read and write shift regs, with bit positions and latched values for reload
- byte readreg;
- byte writereg;
- int readregpos;
- int writeregpos;
- byte readreglatch;
- byte writereglatch;
-
- bool bytetransferflag;
-
- bool lookingforendofgap = false;
-
- ///
- /// true if data being written to disk is currently being computed in CRC
- ///
- bool writecomputecrc; // this has to be latched because the "flush CRC" call comes in the middle of a byte, of course
void Read()
{
@@ -516,7 +542,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
bytetransferflag = true;
if ((cached4025 & 0x80) != 0)
irq = true;
- lastreaddiskpos = diskpos;
+ //lastreaddiskpos = diskpos;
//Console.WriteLine("{0:x2} {1} @{2}", readreg, (cached4025 & 0x80) != 0 ? "RAISE" : " ", diskpos);
readreglatch = readreg;