ZXHawk: Implemented CPU overrun detection within the FDC. This appears to have sorted more Alkatraz protected games AND N=6 (hexagon protection) sectors
This commit is contained in:
parent
462d66c549
commit
e977826c5e
|
@ -164,6 +164,12 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
private bool ND;
|
||||
|
||||
/// <summary>
|
||||
/// In lieu of actual timing, this will count status reads in execution phase
|
||||
/// where the CPU hasnt actually read any bytes
|
||||
/// </summary>
|
||||
private int OverrunCounter;
|
||||
|
||||
/// <summary>
|
||||
/// Signs that the the controller is ready
|
||||
/// </summary>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Device responds to an IN instruction
|
||||
/// </summary>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -171,6 +171,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
{
|
||||
Protection = ProtectionType.PaulOwens;
|
||||
}
|
||||
else if (DetectHexagon(ref weakArr))
|
||||
{
|
||||
Protection = ProtectionType.Hexagon;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -180,6 +184,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// <returns></returns>
|
||||
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
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detect speedlock weak sector
|
||||
/// Detect Alkatraz
|
||||
/// </summary>
|
||||
/// <param name="weak"></param>
|
||||
/// <returns></returns>
|
||||
|
@ -265,7 +276,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detect speedlock weak sector
|
||||
/// Detect Paul Owens
|
||||
/// </summary>
|
||||
/// <param name="weak"></param>
|
||||
/// <returns></returns>
|
||||
|
@ -291,6 +302,41 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detect Hexagon copy protection
|
||||
/// </summary>
|
||||
/// <param name="weak"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Should be run at the end of the ParseDisk process
|
||||
|
|
Loading…
Reference in New Issue