diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDC.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDC.cs
index 2446067b72..60582674a8 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDC.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDC.cs
@@ -164,6 +164,12 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
///
private bool ND;
+ ///
+ /// In lieu of actual timing, this will count status reads in execution phase
+ /// where the CPU hasnt actually read any bytes
+ ///
+ private int OverrunCounter;
+
///
/// Signs that the the controller is ready
///
@@ -644,7 +650,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
LastSectorDataReadByte = ExecBuffer[index];
- ExecCounter--;
+ OverrunCounter--;
+ ExecCounter--;
break;
@@ -1064,7 +1071,9 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
LastSectorDataReadByte = ExecBuffer[index];
+ OverrunCounter--;
ExecCounter--;
+
break;
//----------------------------------------
@@ -1397,7 +1406,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
LastSectorDataReadByte = ExecBuffer[index];
- ExecCounter--;
+ OverrunCounter--;
+ ExecCounter--;
break;
@@ -3095,6 +3105,18 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
SetBit(MSR_EXM, ref StatusMain);
SetBit(MSR_CB, ref StatusMain);
+ // overrun detection
+ OverrunCounter++;
+ if (OverrunCounter >= 64)
+ {
+ // CPU has read the status register 64 times without reading the data register
+ // switch the current command into result phase
+ ActivePhase = Phase.Result;
+
+ // reset the overun counter
+ OverrunCounter = 0;
+ }
+
break;
case Phase.Result:
SetBit(MSR_DIO, ref StatusMain);
@@ -3226,25 +3248,15 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
CommCounter = 0;
ResCounter = 0;
- // controller is expecting the first command byte
- BitArray bi = new BitArray(new byte[] { cmdByte });
+ // get the first 4 bytes
+ byte cByte = (byte)(cmdByte & 0x0f);
- // save command flags
- // skip
- CMD_FLAG_SK = bi[5];
- // multitrack
- CMD_FLAG_MT = bi[7];
- // MFM mode
- CMD_FLAG_MF = bi[6];
+ // get MT, MD and SK states
+ CMD_FLAG_MT = cmdByte.Bit(7);
+ CMD_FLAG_MF = cmdByte.Bit(6);
+ CMD_FLAG_SK = cmdByte.Bit(5);
- // remove flags from command byte
- bi[5] = false;
- bi[6] = false;
- bi[7] = false;
-
- byte[] bytes = new byte[1];
- bi.CopyTo(bytes, 0);
- cmdByte = bytes[0];
+ cmdByte = cByte;
// lookup the command
var cmd = CommandList.Where(a => a.CommandCode == cmdByte).FirstOrDefault();
@@ -3261,6 +3273,25 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// check validity of command byte flags
// if a flag is set but not valid for this command then it is invalid
+ bool invalid = false;
+
+ if (!ActiveCommand.MT)
+ if (CMD_FLAG_MT)
+ invalid = true;
+ if (!ActiveCommand.MF)
+ if (CMD_FLAG_MF)
+ invalid = true;
+ if (!ActiveCommand.SK)
+ if (CMD_FLAG_SK)
+ invalid = true;
+
+ if (invalid)
+ {
+ // command byte included spurious bit 5,6 or 7 flags
+ CMDIndex = CommandList.Count() - 1;
+ }
+
+ /*
if ((CMD_FLAG_MF && !ActiveCommand.MF) ||
(CMD_FLAG_MT && !ActiveCommand.MT) ||
(CMD_FLAG_SK && !ActiveCommand.SK))
@@ -3268,6 +3299,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// command byte included spurious bit 5,6 or 7 flags
CMDIndex = CommandList.Count() - 1;
}
+ */
}
CommCounter = 0;
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs
index d3ff9519cb..f2e6d3e67d 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs
@@ -22,9 +22,47 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
public string outputfile = @"D:\Dropbox\Dropbox\_Programming\TASVideos\BizHawk\output\zxhawkio-" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".csv";
- public string outputString = "STATUS,WRITE,READ\r\n";
+ public string outputString = "STATUS,WRITE,READ,CODE,MT,MF,SK,CMDCNT,RESCNT,EXECCNT,EXECLEN\r\n";
public bool writeDebug = false;
+ /*
+ * Status read
+ * Data write
+ * Data read
+ * CMD code
+ * CMD string
+ * MT flag
+ * MK flag
+ * SK flag
+ * */
+ private string[] workingArr = new string[3];
+
+ private void BuildCSVLine()
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 3; i++)
+ {
+ sb.Append(workingArr[i]);
+ sb.Append(",");
+ workingArr[i] = "";
+ }
+
+ sb.Append(ActiveCommand.CommandCode).Append(",");
+
+ sb.Append(CMD_FLAG_MT).Append(",");
+ sb.Append(CMD_FLAG_MF).Append(",");
+ sb.Append(CMD_FLAG_SK).Append(",");
+
+ sb.Append(CommCounter).Append(",");
+ sb.Append(ResCounter).Append(",");
+ sb.Append(ExecCounter).Append(",");
+ sb.Append(ExecLength);
+
+ sb.Append("\r\n");
+
+ outputString += sb.ToString();
+ }
+
///
/// Device responds to an IN instruction
///
@@ -40,7 +78,12 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// Z80 is trying to read from the data register
data = ReadDataRegister();
if (writeDebug)
- outputString += ",," + data + "\r\n";
+ {
+ workingArr[2] = data.ToString();
+ //outputString += ",," + data + "," + ActiveCommand.CommandCode + "\r\n";
+ BuildCSVLine();
+ }
+
return true;
}
@@ -50,7 +93,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// this can happen at any time
data = ReadMainStatus();
if (writeDebug)
- outputString += data + ",,\r\n";
+ {
+ //outputString += data + ",,," + ActiveCommand.CommandCode + "\r\n";
+ workingArr[0] = data.ToString();
+ BuildCSVLine();
+ //System.IO.File.WriteAllText(outputfile, outputString);
+ }
+
return true;
}
@@ -73,8 +122,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
WriteDataRegister((byte)data);
if (writeDebug)
{
- outputString += "," + data + ",\r\n";
- System.IO.File.WriteAllText(outputfile, outputString);
+ //outputString += "," + data + ",," + ActiveCommand.CommandCode + "\r\n";
+ workingArr[1] = data.ToString();
+ BuildCSVLine();
+ //System.IO.File.WriteAllText(outputfile, outputString);
}
return true;
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs
index 07c64c9f45..9d52641d6f 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs
@@ -202,6 +202,16 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// is this a lag frame?
Spectrum.IsLagFrame = !InputRead;
+
+ // FDC debug
+ /*
+ if (UPDDiskDevice != null && UPDDiskDevice.writeDebug)
+ {
+ // only write UPD log every second
+ if (FrameCount % 10 == 0)
+ System.IO.File.WriteAllText(UPDDiskDevice.outputfile, UPDDiskDevice.outputString);
+ }
+ */
}
#endregion
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs
index 8e0ebc642b..60627fc01b 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs
@@ -171,6 +171,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
Protection = ProtectionType.PaulOwens;
}
+ else if (DetectHexagon(ref weakArr))
+ {
+ Protection = ProtectionType.Hexagon;
+ }
}
///
@@ -180,6 +184,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
///
public bool DetectSpeedlock(ref int[] weak)
{
+ // SPEEDLOCK NOTES (-asni 2018-05-01)
+ // ---------------------------------
+ // Speedlock is one of the more common +3 disk protections and there are a few different versions
+ // Usually, track 0 sector 1 (ID 2) has data CRC errors that result in certain bytes returning a different value every time they are read
+ // Speedlock will generally read this track a number of times during the load process
+ // and if the correct bytes are not different between reads, the load fails
+
// always must have track 0 containing 9 sectors
if (DiskTracks[0].Sectors.Length != 9)
return false;
@@ -232,7 +243,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
}
///
- /// Detect speedlock weak sector
+ /// Detect Alkatraz
///
///
///
@@ -265,7 +276,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
}
///
- /// Detect speedlock weak sector
+ /// Detect Paul Owens
///
///
///
@@ -291,6 +302,41 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
return true;
}
+
+ ///
+ /// Detect Hexagon copy protection
+ ///
+ ///
+ ///
+ public bool DetectHexagon(ref int[] weak)
+ {
+ if (DiskTracks[0].Sectors.Length != 10 || DiskTracks[0].Sectors[8].ActualDataByteLength != 512)
+ return false;
+
+ // check for Hexagon ident in sector 8
+ string ident = Encoding.ASCII.GetString(DiskTracks[0].Sectors[8].SectorData, 0, DiskTracks[0].Sectors[8].SectorData.Length);
+ if (ident.ToUpper().Contains("GON DISK PROT"))
+ return true;
+
+ // hexagon protection may not be labelled as such
+ var track = DiskTracks[1];
+ var sector = track.Sectors[0];
+
+ if (sector.SectorSize == 6 && sector.Status1 == 0x20 && sector.Status2 == 0x60)
+ {
+ if (track.Sectors.Length == 1)
+ return true;
+ }
+
+
+ // Hexagon Copy Protection Notes (-asni 2018-05-01)
+ // ---------------------------------------------------
+ //
+ //
+
+ return false;
+ }
+
/*
///
/// Should be run at the end of the ParseDisk process