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)
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <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
|
||||
|
||||
#region Tape Controls
|
||||
|
@ -656,7 +592,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
_machine.Spectrum.OSD_TapePlayingAuto();
|
||||
}
|
||||
|
||||
_monitorTimeOut = 50;
|
||||
_monitorTimeOut = 500;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -676,6 +612,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
{
|
||||
_monitorTimeOut--;
|
||||
|
||||
if (_monitorTimeOut < 2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (_monitorTimeOut < 0)
|
||||
{
|
||||
Stop();
|
||||
|
@ -688,8 +629,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
|
||||
#region State Serialization
|
||||
|
||||
private int _tempBlockCount;
|
||||
|
||||
/// <summary>
|
||||
/// Bizhawk state serialization
|
||||
/// </summary>
|
||||
|
|
|
@ -39,6 +39,82 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
{
|
||||
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;
|
||||
|
||||
// It takes four T states for the Z80 to read a value from an I/O port, or write a value to a port
|
||||
// (not including added ULA contention)
|
||||
// The Bizhawk Z80A implementation appears to not consume any T-States for this operation
|
||||
PortContention(4);
|
||||
// process IO contention
|
||||
ContendPortAddress(port);
|
||||
|
||||
int result = 0xFF;
|
||||
|
||||
|
@ -28,8 +26,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// Technically the ULA should respond to every even I/O address
|
||||
bool lowBitReset = (port & 0x0001) == 0;
|
||||
|
||||
ULADevice.Contend(port);
|
||||
|
||||
// Kempston Joystick
|
||||
if ((port & 0xe0) == 0 || (port & 0x20) == 0)
|
||||
{
|
||||
|
@ -90,12 +86,22 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if ((port & 0x100) == 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 | 0xa0; //set bit 5 & 7 to 1
|
||||
|
||||
TapeDevice.MonitorRead();
|
||||
|
||||
|
||||
if (TapeDevice.TapeIsPlaying)//.CurrentMode == TapeOperationMode.Load)
|
||||
{
|
||||
|
@ -133,7 +139,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -177,45 +183,37 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// <param name="value"></param>
|
||||
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
|
||||
// (not including added ULA contention)
|
||||
// The Bizhawk Z80A implementation appears to not consume any T-States for this operation
|
||||
PortContention(4);
|
||||
|
||||
// process IO contention
|
||||
ContendPortAddress(port);
|
||||
|
||||
// Check whether the low bit is reset
|
||||
// Technically the ULA should respond to every even I/O address
|
||||
bool lowBitReset = (port & 0x01) == 0;
|
||||
if ((port & 0x0001) != 0)
|
||||
return;
|
||||
|
||||
ULADevice.Contend(port);
|
||||
// store the last OUT byte
|
||||
LastULAOutByte = value;
|
||||
|
||||
// Only even addresses address the ULA
|
||||
if (lowBitReset)
|
||||
{
|
||||
// store the last OUT byte
|
||||
LastULAOutByte = value;
|
||||
CPU.TotalExecutedCycles += ULADevice.contentionTable[CurrentFrameCycle];
|
||||
/*
|
||||
Bit 7 6 5 4 3 2 1 0
|
||||
+-------------------------------+
|
||||
| | | | E | M | Border |
|
||||
+-------------------------------+
|
||||
*/
|
||||
|
||||
/*
|
||||
Bit 7 6 5 4 3 2 1 0
|
||||
+-------------------------------+
|
||||
| | | | E | M | Border |
|
||||
+-------------------------------+
|
||||
*/
|
||||
// Border - LSB 3 bits hold the border colour
|
||||
if (ULADevice.borderColour != (value & BORDER_BIT))
|
||||
ULADevice.UpdateScreenBuffer(CurrentFrameCycle);
|
||||
|
||||
// Border - LSB 3 bits hold the border colour
|
||||
if (ULADevice.borderColour != (value & BORDER_BIT))
|
||||
ULADevice.UpdateScreenBuffer(CurrentFrameCycle);
|
||||
ULADevice.borderColour = value & BORDER_BIT;
|
||||
|
||||
ULADevice.borderColour = value & BORDER_BIT;
|
||||
// Buzzer
|
||||
BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
|
||||
|
||||
// Buzzer
|
||||
BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
|
||||
|
||||
// Tape
|
||||
//TapeDevice.ProcessMicBit((value & MIC_BIT) != 0);
|
||||
// Tape
|
||||
//TapeDevice.ProcessMicBit((value & MIC_BIT) != 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,6 +268,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
t.DataPeriods = new List<int>();
|
||||
|
||||
int pauseLen = GetWordValue(data, _position);
|
||||
|
||||
int blockLen = GetWordValue(data, _position + 2);
|
||||
|
||||
_position += 4;
|
||||
|
|
Loading…
Reference in New Issue