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

View File

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

View File

@ -357,11 +357,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ser.Sync("PagingConfiguration", ref PagingConfiguration);
ser.Sync("ROMhigh", ref ROMhigh);
ser.Sync("ROMlow", ref ROMlow);
ser.Sync("LastContendedReadByte", ref LastContendedReadByte);
KeyboardDevice.SyncState(ser);
BuzzerDevice.SyncState(ser);
TapeBuzzer.SyncState(ser);
ULADevice.SyncState(ser);
CPUMon.SyncState(ser);
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>
/// Returns floating bus value (if available)
/// </summary>
/// <param name="tstate"></param>
/// <returns></returns>
public void ReadFloatingBus(int tstate, ref int result)
public void ReadFloatingBus(int tstate, ref int result, ushort port)
{
tstate += FloatingBusOffset;
if (tstate >= RenderingTable.Renderer.Length)
@ -688,13 +707,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
case MachineType.ZXSpectrum48:
case MachineType.ZXSpectrum128:
case MachineType.ZXSpectrum128Plus2:
/*
if (item.FloatingBusAddress > 0)
{
result = _machine.FetchScreenMemory(item.FloatingBusAddress);
//result = 0x00;
}
*/
switch (item.RAction)
{
case RenderTable.RenderAction.BorderAndFetchByte1:
@ -708,15 +721,46 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
result = _machine.FetchScreenMemory(item.AttributeAddress);
break;
default:
//result = _machine.FetchScreenMemory(fetchA2);
break;
}
break;
case MachineType.ZXSpectrum128Plus2a:
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;
}
}

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
// 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
WritePort(port, (byte)result);
// return the floating bus value
@ -71,7 +71,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed)
{
// 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;

View File

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

View File

@ -52,7 +52,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed)
{
// 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;

View File

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

View File

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

View File

@ -56,7 +56,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!deviceAddressed)
{
// 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;

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
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result);
ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port);
}
return (byte)result;