diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs index a0040cc626..cb889a23bb 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/FDS.cs @@ -67,7 +67,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo { byte[] buf = new byte[65500]; Buffer.BlockCopy(diskimage, 16 + side * 65500, buf, 0, 65500); - diskdrive.InsertBrokenImage(buf, true); + diskdrive.InsertBrokenImage(buf, false /*true*/); + } + + public MemoryDomain GetDiskPeeker() + { + return new MemoryDomain("FDS SIDE", diskdrive.NumBytes, Endian.Little, diskdrive.PeekData, null); } void SetIRQ() @@ -91,7 +96,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo public override void WriteEXP(int addr, byte value) { - //Console.WriteLine("W{0:x4}:{1:x2} {2:x4}", addr + 0x4000, value, NES.cpu.PC); + //if (addr == 0x0025) + // Console.WriteLine("W{0:x4}:{1:x2} {2:x4}", addr + 0x4000, value, NES.cpu.PC); if (addr >= 0x0040) { diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs index 24699c163e..09f0527ffa 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/FDS/RamAdapter.cs @@ -122,6 +122,23 @@ namespace BizHawk.Emulation.Consoles.Nintendo //File.WriteAllBytes("fdsdebug.bin", realside); } + /// + /// memorydomain debugging + /// + public int NumBytes { get { return 65500; } } + /// + /// memorydomain debugging + /// + /// + /// + public byte PeekData(int addr) + { + if (disk != null && disk.Length > addr) + return disk[addr]; + else + return 0xff; + } + // all timings are in terms of PPU cycles (@5.37mhz) int cycleswaiting = 0; @@ -142,22 +159,27 @@ namespace BizHawk.Emulation.Consoles.Nintendo void SetCycles() { + // these are mostly guesses switch (state) { - case RamAdapterState.RUNNING: - cycleswaiting = 56; //82; + case RamAdapterState.RUNNING: // matches of-quoted 96khz data transfer rate + // time to read/write one bit + cycleswaiting = 56; break; - case RamAdapterState.INSERTING: - cycleswaiting = 5000000; + case RamAdapterState.INSERTING: // 298ms + // time for the disk drive to engage on disk after inserting + cycleswaiting = 1600000; break; - case RamAdapterState.SPINUP: - cycleswaiting = 2000; + case RamAdapterState.SPINUP: // 199ms + // time for motor to spinup and start + cycleswaiting = 1070000; break; - case RamAdapterState.IDLE: + case RamAdapterState.IDLE: // irrelevant cycleswaiting = 50000; break; - case RamAdapterState.RESET: - cycleswaiting = 50000; + case RamAdapterState.RESET: // 1200ms + // time for motor to re-park after reaching end of drive + cycleswaiting = 6443100; break; } } @@ -166,7 +188,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo public void Write4024(byte value) { bytetransferflag = false; - //irq = false; //?? + writereglatch = value; } byte cached4025; @@ -190,7 +212,21 @@ namespace BizHawk.Emulation.Consoles.Nintendo if ((value & 2) != 0) transferreset = true; if ((cached4025 & 0x40) == 0 && (value & 0x40) != 0) + { lookingforendofgap = true; + + if ((value & 4) == 0) + { + // write mode: reload and go + writeregpos = 0; + writereg = writereglatch; + bytetransferflag = true; + // irq? + Console.WriteLine("FDS: Startwrite @{0} Reload {1:x2}", diskpos, writereglatch); + } + } + + irq = false; // ?? cached4025 = value; @@ -240,6 +276,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo ret &= unchecked((byte)~0x01); if (!transferreset && (state == RamAdapterState.RUNNING || state == RamAdapterState.IDLE)) ret &= unchecked((byte)~0x02); + if (disk != null && state != RamAdapterState.INSERTING && !writeprotect) + ret &= unchecked((byte)~0x04); return ret; } @@ -345,7 +383,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo if ((cached4025 & 0x80) != 0) irq = true; lastreaddiskpos = diskpos; - //Console.WriteLine("{0:x2} {1} @{2}", readreg, (cached4025 & 0x80) != 0 ? "RAISE" : " ", diskpos); + Console.WriteLine("{0:x2} {1} @{2}", readreg, (cached4025 & 0x80) != 0 ? "RAISE" : " ", diskpos); readreglatch = readreg; //} //else // when in CRC, don't send results back to user @@ -362,6 +400,52 @@ namespace BizHawk.Emulation.Consoles.Nintendo void Write() { + if (writeprotect) + { + diskpos++; + return; + } + + bool bittowrite = false; + + // the variable is named for its function in read mode; in write mode, when not set, + // write an endless stream of zeroes. + if (!lookingforendofgap) + { + bittowrite = false; + } + else + { + bittowrite = (writereg & (1 << writeregpos)) != 0; + writeregpos++; + if (writeregpos == 8) + { + writeregpos = 0; + writereg = writereglatch; + bytetransferflag = true; + if ((cached4025 & 0x80) != 0) + irq = true; + Console.WriteLine("FDS: Write @{0} Reload {1:x2}", diskpos + 1, writereglatch); + + + // it seems that after a successful CRC, the writereg is reset to 0 value. this is needed? + // TODO: actually write the CRC (2 bytes) + if ((cached4025 & 0x10) != 0) + { + Console.WriteLine("FDS: write clear CRC", readreg, diskpos); + cached4025 &= unchecked((byte)~0x10); // clear CRC reading + //writereg = 0; // don't do this + writereglatch = 0; //?? + } + + } + } + + var tmp = disk[diskpos >> 3]; + tmp &= unchecked((byte)~(1 << (diskpos & 7))); + if (bittowrite) + tmp |= (byte)(1 << (diskpos & 7)); + disk[diskpos >> 3] = tmp; diskpos++; } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index eae35aabe4..f73c696832 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -406,6 +406,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo domains.Add(WRAM); } + if (board is FDS) + { + domains.Add((board as FDS).GetDiskPeeker()); + } + memoryDomains = domains.AsReadOnly(); }