ZXHawk: implemented +2a/+3 floating bus (confirmed working with 2017 release of 'A Yankee in Iraq')

This commit is contained in:
Asnivor 2018-06-13 11:53:05 +01:00
parent 7ce55e6601
commit 373db35805
11 changed files with 87 additions and 19 deletions

View File

@ -62,6 +62,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// </summary> /// </summary>
public ushort lastPortAddr; public ushort lastPortAddr;
/// <summary>
/// If true, the next read memory operation has been contended
/// </summary>
public bool NextMemReadContended;
#endregion #endregion
#region Methods #region Methods
@ -87,6 +92,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (cont > 0) if (cont > 0)
{ {
_cpu.TotalExecutedCycles += cont; _cpu.TotalExecutedCycles += cont;
NextMemReadContended = true;
} }
} }
} }
@ -393,7 +399,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
ser.BeginSection("CPUMonitor"); ser.BeginSection("CPUMonitor");
ser.Sync("", ref lastPortAddr); ser.Sync("lastPortAddr", ref lastPortAddr);
ser.Sync("NextMemReadContended", ref NextMemReadContended);
ser.EndSection(); ser.EndSection();
} }

View File

@ -50,7 +50,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// Signs that all paging is disabled /// Signs that all paging is disabled
/// If this is TRUE, then 128k and above machines need a hard reset before paging is allowed again /// If this is TRUE, then 128k and above machines need a hard reset before paging is allowed again
/// </summary> /// </summary>
protected bool PagingDisabled; public bool PagingDisabled;
/// <summary> /// <summary>
/// Index of the currently paged ROM /// Index of the currently paged ROM
@ -87,6 +87,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// </summary> /// </summary>
protected int PagingConfiguration; protected int PagingConfiguration;
/// <summary>
/// The last byte that was read after contended cycles
/// </summary>
public byte LastContendedReadByte;
#endregion #endregion
#region Memory Related Methods #region Memory Related Methods

View File

@ -357,11 +357,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ser.Sync("PagingConfiguration", ref PagingConfiguration); ser.Sync("PagingConfiguration", ref PagingConfiguration);
ser.Sync("ROMhigh", ref ROMhigh); ser.Sync("ROMhigh", ref ROMhigh);
ser.Sync("ROMlow", ref ROMlow); ser.Sync("ROMlow", ref ROMlow);
ser.Sync("LastContendedReadByte", ref LastContendedReadByte);
KeyboardDevice.SyncState(ser); KeyboardDevice.SyncState(ser);
BuzzerDevice.SyncState(ser); BuzzerDevice.SyncState(ser);
TapeBuzzer.SyncState(ser); TapeBuzzer.SyncState(ser);
ULADevice.SyncState(ser); ULADevice.SyncState(ser);
CPUMon.SyncState(ser);
if (AYDevice != null) if (AYDevice != null)
{ {

View File

@ -667,12 +667,31 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
} }
} }
/// <summary>
/// Generates the port lookup table for +2a/+3 allowed floating bus ports
/// </summary>
public void GenerateP3PortTable()
{
List<ushort> table = new List<ushort>();
for (int i = 0; i < 0x1000; i++)
{
ushort r = (ushort)(1 + (4 * i));
if (r > 4093)
break;
table.Add(r);
}
Plus3FBPortTable = table.ToArray();
}
private ushort[] Plus3FBPortTable = new ushort[1];
/// <summary> /// <summary>
/// Returns floating bus value (if available) /// Returns floating bus value (if available)
/// </summary> /// </summary>
/// <param name="tstate"></param> /// <param name="tstate"></param>
/// <returns></returns> /// <returns></returns>
public void ReadFloatingBus(int tstate, ref int result) public void ReadFloatingBus(int tstate, ref int result, ushort port)
{ {
tstate += FloatingBusOffset; tstate += FloatingBusOffset;
if (tstate >= RenderingTable.Renderer.Length) if (tstate >= RenderingTable.Renderer.Length)
@ -688,13 +707,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
case MachineType.ZXSpectrum48: case MachineType.ZXSpectrum48:
case MachineType.ZXSpectrum128: case MachineType.ZXSpectrum128:
case MachineType.ZXSpectrum128Plus2: case MachineType.ZXSpectrum128Plus2:
/*
if (item.FloatingBusAddress > 0)
{
result = _machine.FetchScreenMemory(item.FloatingBusAddress);
//result = 0x00;
}
*/
switch (item.RAction) switch (item.RAction)
{ {
case RenderTable.RenderAction.BorderAndFetchByte1: case RenderTable.RenderAction.BorderAndFetchByte1:
@ -708,15 +721,46 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
result = _machine.FetchScreenMemory(item.AttributeAddress); result = _machine.FetchScreenMemory(item.AttributeAddress);
break; break;
default: default:
//result = _machine.FetchScreenMemory(fetchA2);
break; break;
} }
break; break;
case MachineType.ZXSpectrum128Plus2a: case MachineType.ZXSpectrum128Plus2a:
case MachineType.ZXSpectrum128Plus3: case MachineType.ZXSpectrum128Plus3:
// http://sky.relative-path.com/zx/floating_bus.html
if (_machine.PagingDisabled)
{
result = 0xff;
break;
}
// check whether fb is found on this port
ushort pLook = Array.Find(Plus3FBPortTable, s => s == port);
if (pLook == 0)
{
result = 0xff;
break;
}
// floating bus on +2a/+3 always returns a byte with Bit0 set
switch (item.RAction)
{
case RenderTable.RenderAction.BorderAndFetchByte1:
case RenderTable.RenderAction.Shift1AndFetchByte2:
case RenderTable.RenderAction.Shift2AndFetchByte1:
result = (byte)(_machine.FetchScreenMemory(item.ByteAddress) | 0x01);
break;
case RenderTable.RenderAction.BorderAndFetchAttribute1:
case RenderTable.RenderAction.Shift1AndFetchAttribute2:
case RenderTable.RenderAction.Shift2AndFetchAttribute1:
result = (byte)(_machine.FetchScreenMemory(item.AttributeAddress) | 0x01);
break;
default:
result = (byte)(_machine.LastContendedReadByte | 0x01);
break;
}
break; break;
} }
} }

View File

@ -32,7 +32,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// -asni (2018-06-08) - need this to pass the final portread tests from fusetest.tap // -asni (2018-06-08) - need this to pass the final portread tests from fusetest.tap
// get the floating bus value // get the floating bus value
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result); ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
// use this to set the paging registers // use this to set the paging registers
WritePort(port, (byte)result); WritePort(port, (byte)result);
// return the floating bus value // return the floating bus value
@ -71,7 +71,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed) if (!deviceAddressed)
{ {
// If this is an unused port the floating memory bus should be returned // If this is an unused port the floating memory bus should be returned
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result); ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
} }
return (byte)result; return (byte)result;

View File

@ -358,6 +358,12 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public override byte ReadMemory(ushort addr) public override byte ReadMemory(ushort addr)
{ {
var data = ReadBus(addr); var data = ReadBus(addr);
if (CPUMon.NextMemReadContended)
{
LastContendedReadByte = data;
CPUMon.NextMemReadContended = false;
}
return data; return data;
} }

View File

@ -52,7 +52,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed) if (!deviceAddressed)
{ {
// If this is an unused port the floating memory bus should be returned // If this is an unused port the floating memory bus should be returned
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result); ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
} }
return (byte)result; return (byte)result;

View File

@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// offsets // offsets
RenderTableOffset = 58; RenderTableOffset = 58;
ContentionOffset = 9; ContentionOffset = 9;
FloatingBusOffset = 1; FloatingBusOffset = 0;
// timing // timing
ClockSpeed = 3546900; ClockSpeed = 3546900;
FrameCycleLength = 70908; FrameCycleLength = 70908;
@ -43,6 +43,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
MachineType.ZXSpectrum128Plus2a); MachineType.ZXSpectrum128Plus2a);
SetupScreenSize(); SetupScreenSize();
GenerateP3PortTable();
} }
#endregion #endregion

View File

@ -358,6 +358,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public override byte ReadMemory(ushort addr) public override byte ReadMemory(ushort addr)
{ {
var data = ReadBus(addr); var data = ReadBus(addr);
if (CPUMon.NextMemReadContended)
LastContendedReadByte = data;
return data; return data;
} }

View File

@ -56,7 +56,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed) if (!deviceAddressed)
{ {
// If this is an unused port the floating memory bus should be returned // If this is an unused port the floating memory bus should be returned
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result); ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
} }
return (byte)result; return (byte)result;

View File

@ -55,7 +55,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// If this is an unused port the floating memory bus should be returned // If this is an unused port the floating memory bus should be returned
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result); ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
} }
return (byte)result; return (byte)result;