Started new port contention methods and increased the auto-tape monitor timeout (to eliminate false-positive stops)
This commit is contained in:
parent
8708e987f7
commit
ae8b030e57
|
@ -144,74 +144,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
/// Primary purpose is to detect tape traps and manage auto play (if/when this is ever implemented)
|
/// Primary purpose is to detect tape traps and manage auto play (if/when this is ever implemented)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void EndFrame()
|
public void EndFrame()
|
||||||
{/*
|
|
||||||
if (TapeIsPlaying)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// check whether we need to auto-stop the tape
|
|
||||||
if (IsMachineAtErrorAddress())
|
|
||||||
{
|
|
||||||
_machine.Spectrum.OSD_TapeStoppedAuto();
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the tape is not playing - check to see if we need to autostart the tape
|
|
||||||
if (IsMachineInLoadMode())
|
|
||||||
{
|
|
||||||
_machine.Spectrum.OSD_TapePlayingAuto();
|
|
||||||
Play();
|
|
||||||
//sw.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (TapeIsPlaying && sw.IsRunning)
|
|
||||||
{
|
|
||||||
if (!IsMachineInLoadMode() && sw.ElapsedMilliseconds == 2000)
|
|
||||||
{
|
|
||||||
sw.Stop();
|
|
||||||
sw.Reset();
|
|
||||||
_machine.Spectrum.OSD_TapeStoppedAuto();
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
MonitorFrame();
|
MonitorFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether the machine is in a state that is waiting to load tape content
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool IsMachineInLoadMode()
|
|
||||||
{
|
|
||||||
if (!_machine.Spectrum.Settings.AutoLoadTape)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_cpu.RegPC == 1523)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether the machine has reached the error rom address (and the tape needs to be stopped)
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private bool IsMachineAtErrorAddress()
|
|
||||||
{
|
|
||||||
//if (!_machine.Spectrum.Settings.AutoLoadTape)
|
|
||||||
//return false;
|
|
||||||
|
|
||||||
if (_cpu.RegPC == 64464) // 40620) // ERROR_ROM_ADDRESS)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Tape Controls
|
#region Tape Controls
|
||||||
|
@ -656,7 +592,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
_machine.Spectrum.OSD_TapePlayingAuto();
|
_machine.Spectrum.OSD_TapePlayingAuto();
|
||||||
}
|
}
|
||||||
|
|
||||||
_monitorTimeOut = 50;
|
_monitorTimeOut = 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -676,6 +612,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
{
|
{
|
||||||
_monitorTimeOut--;
|
_monitorTimeOut--;
|
||||||
|
|
||||||
|
if (_monitorTimeOut < 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (_monitorTimeOut < 0)
|
if (_monitorTimeOut < 0)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
|
@ -688,8 +629,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
|
|
||||||
#region State Serialization
|
#region State Serialization
|
||||||
|
|
||||||
private int _tempBlockCount;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bizhawk state serialization
|
/// Bizhawk state serialization
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -40,5 +40,81 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
CPU.TotalExecutedCycles += tStates;
|
CPU.TotalExecutedCycles += tStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simulates IO port contention based on the supplied address
|
||||||
|
/// This method is for 48k machines and should be overridden for other models
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="addr"></param>
|
||||||
|
public virtual void ContendPortAddress(ushort addr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
It takes four T states for the Z80 to read a value from an I/O port, or write a value to a port. As is the case with memory access,
|
||||||
|
this can be lengthened by the ULA. There are two effects which occur here:
|
||||||
|
|
||||||
|
If the port address being accessed has its low bit reset, the ULA is required to supply the result, which leads to a delay if it is
|
||||||
|
currently busy handling the screen.
|
||||||
|
The address of the port being accessed is placed on the data bus. If this is in the range 0x4000 to 0x7fff, the ULA treats this as an
|
||||||
|
attempted access to contended memory and therefore introduces a delay. If the port being accessed is between 0xc000 and 0xffff,
|
||||||
|
this effect does not apply, even on a 128K machine if a contended memory bank is paged into the range 0xc000 to 0xffff.
|
||||||
|
|
||||||
|
These two effects combine to lead to the following contention patterns:
|
||||||
|
|
||||||
|
High byte | |
|
||||||
|
in 40 - 7F? | Low bit | Contention pattern
|
||||||
|
------------+---------+-------------------
|
||||||
|
No | Reset | N:1, C:3
|
||||||
|
No | Set | N:4
|
||||||
|
Yes | Reset | C:1, C:3
|
||||||
|
Yes | Set | C:1, C:1, C:1, C:1
|
||||||
|
|
||||||
|
The 'Contention pattern' column should be interpreted from left to right. An "N:n" entry means that no delay is applied at this cycle, and the Z80 continues uninterrupted for 'n' T states. A "C:n" entry means that the ULA halts the Z80; the delay is exactly the same as would occur for a contended memory access at this cycle (eg 6 T states at cycle 14335, 5 at 14336, etc on the 48K machine). After this delay, the Z80 then continues for 'n' cycles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// is the low bit reset (i.e. is this addressing the ULA)?
|
||||||
|
bool lowBit = (addr & 0x0001) != 0;
|
||||||
|
|
||||||
|
if ((addr & 0xc000) == 0x4000 || (addr & 0xc000) == 0xC000)
|
||||||
|
{
|
||||||
|
// high byte is in 40 - 7F
|
||||||
|
if (lowBit)
|
||||||
|
{
|
||||||
|
// lowbit is set
|
||||||
|
// C:1, C:1, C:1, C:1
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
||||||
|
CPU.TotalExecutedCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// low bit is reset
|
||||||
|
// C:1, C:3
|
||||||
|
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
||||||
|
CPU.TotalExecutedCycles++;
|
||||||
|
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
||||||
|
CPU.TotalExecutedCycles += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// high byte is NOT in 40 - 7F
|
||||||
|
if (lowBit)
|
||||||
|
{
|
||||||
|
// lowbit is set
|
||||||
|
// C:1, C:1, C:1, C:1
|
||||||
|
CPU.TotalExecutedCycles += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// lowbit is reset
|
||||||
|
// N:1, C:3
|
||||||
|
CPU.TotalExecutedCycles++;
|
||||||
|
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
||||||
|
CPU.TotalExecutedCycles += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
{
|
{
|
||||||
InputRead = true;
|
InputRead = true;
|
||||||
|
|
||||||
// It takes four T states for the Z80 to read a value from an I/O port, or write a value to a port
|
// process IO contention
|
||||||
// (not including added ULA contention)
|
ContendPortAddress(port);
|
||||||
// The Bizhawk Z80A implementation appears to not consume any T-States for this operation
|
|
||||||
PortContention(4);
|
|
||||||
|
|
||||||
int result = 0xFF;
|
int result = 0xFF;
|
||||||
|
|
||||||
|
@ -28,8 +26,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
// Technically the ULA should respond to every even I/O address
|
// Technically the ULA should respond to every even I/O address
|
||||||
bool lowBitReset = (port & 0x0001) == 0;
|
bool lowBitReset = (port & 0x0001) == 0;
|
||||||
|
|
||||||
ULADevice.Contend(port);
|
|
||||||
|
|
||||||
// Kempston Joystick
|
// Kempston Joystick
|
||||||
if ((port & 0xe0) == 0 || (port & 0x20) == 0)
|
if ((port & 0xe0) == 0 || (port & 0x20) == 0)
|
||||||
{
|
{
|
||||||
|
@ -92,10 +88,20 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
result &= KeyboardDevice.KeyLine[0];
|
result &= KeyboardDevice.KeyLine[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TapeDevice.MonitorRead();
|
||||||
|
|
||||||
|
var earBit = TapeDevice.GetEarBit(CPU.TotalExecutedCycles);
|
||||||
|
|
||||||
|
if (!earBit)
|
||||||
|
{
|
||||||
|
result &= 0xbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
result = result & 0x1f; //mask out lower 4 bits
|
result = result & 0x1f; //mask out lower 4 bits
|
||||||
result = result | 0xa0; //set bit 5 & 7 to 1
|
result = result | 0xa0; //set bit 5 & 7 to 1
|
||||||
|
|
||||||
TapeDevice.MonitorRead();
|
|
||||||
|
|
||||||
if (TapeDevice.TapeIsPlaying)//.CurrentMode == TapeOperationMode.Load)
|
if (TapeDevice.TapeIsPlaying)//.CurrentMode == TapeOperationMode.Load)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +139,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -177,24 +183,16 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public override void WritePort(ushort port, byte value)
|
public override void WritePort(ushort port, byte value)
|
||||||
{
|
{
|
||||||
// It takes four T states for the Z80 to read a value from an I/O port, or write a value to a port
|
// process IO contention
|
||||||
// (not including added ULA contention)
|
ContendPortAddress(port);
|
||||||
// The Bizhawk Z80A implementation appears to not consume any T-States for this operation
|
|
||||||
PortContention(4);
|
|
||||||
|
|
||||||
|
|
||||||
// Check whether the low bit is reset
|
// Check whether the low bit is reset
|
||||||
// Technically the ULA should respond to every even I/O address
|
// Technically the ULA should respond to every even I/O address
|
||||||
bool lowBitReset = (port & 0x01) == 0;
|
if ((port & 0x0001) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
ULADevice.Contend(port);
|
|
||||||
|
|
||||||
// Only even addresses address the ULA
|
|
||||||
if (lowBitReset)
|
|
||||||
{
|
|
||||||
// store the last OUT byte
|
// store the last OUT byte
|
||||||
LastULAOutByte = value;
|
LastULAOutByte = value;
|
||||||
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Bit 7 6 5 4 3 2 1 0
|
Bit 7 6 5 4 3 2 1 0
|
||||||
|
@ -216,6 +214,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
//TapeDevice.ProcessMicBit((value & MIC_BIT) != 0);
|
//TapeDevice.ProcessMicBit((value & MIC_BIT) != 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,6 +268,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||||
t.DataPeriods = new List<int>();
|
t.DataPeriods = new List<int>();
|
||||||
|
|
||||||
int pauseLen = GetWordValue(data, _position);
|
int pauseLen = GetWordValue(data, _position);
|
||||||
|
|
||||||
int blockLen = GetWordValue(data, _position + 2);
|
int blockLen = GetWordValue(data, _position + 2);
|
||||||
|
|
||||||
_position += 4;
|
_position += 4;
|
||||||
|
|
Loading…
Reference in New Issue