From 7f8084d4104015b749affd189ec15f64fe6a6217 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Wed, 6 Jun 2018 14:39:41 +0100 Subject: [PATCH] ZXHawk: IORQ check now happens pre T-Cycle --- .../SinclairSpectrum/Machine/CPUMonitor.cs | 316 ++++++------------ .../Computers/SinclairSpectrum/Machine/ULA.cs | 2 +- .../Machine/ZXSpectrum48K/ZX48.Port.cs | 2 +- 3 files changed, 111 insertions(+), 209 deletions(-) diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs index 1623679213..8ac36b391a 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs @@ -67,14 +67,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { _machine.ULADevice.RenderScreen((int)_machine.CurrentFrameCycle); - if (portContending) + // is the next CPU cycle causing a BUSRQ or IORQ? + if (BUSRQ > 0) { - RunPortContention(); - } - else - { - // is the next CPU cycle causing a BUSRQ? - if (BUSRQ > 0) + // check for IORQ + if (!CheckIO()) { // is the memory address of the BUSRQ potentially contended? if (_machine.IsContended(AscertainBUSRQAddress())) @@ -89,129 +86,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum } _cpu.ExecuteOne(); - - /* - else if (ContCounter > 0) - { - // still contention cycles to process - IsContending = true; - } - else - { - // is the next CPU cycle causing a BUSRQ? - if (BUSRQ > 0) - { - // is the memory address of the BUSRQ potentially contended? - if (_machine.IsContended(AscertainBUSRQAddress())) - { - var cont = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); - if (cont > 0) - { - ContCounter = cont + 1; - IsContending = true; - } - } - } - } - /* - else - { - // no contention cycles to process (so far) on this cycle - IsContending = false; - ContCounter = 0; - - if (portContending) - { - // a port operation is still in progress - portContCounter++; - if (portContCounter > 3) - { - // we are now out of the IN/OUT operation - portContCounter = 0; - portContending = false; - } - else - { - // still IN/OUT cycles to process - if (IsPortContended(portContCounter)) - { - var cont = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); - if (cont > 0) - { - ContCounter = cont + 1; - IsContending = true; - // dont let this fall through - // just manually do the first contention cycle - ContCounter--; - _cpu.TotalExecutedCycles++; - return; - } - } - } - } - - // is the next CPU cycle causing a BUSRQ? - if (BUSRQ > 0) - { - // is the memory address of the BUSRQ potentially contended? - if (_machine.IsContended(AscertainBUSRQAddress())) - { - var cont = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); - if (cont > 0) - { - ContCounter = cont + 1; - IsContending = true; - } - } - } - /* - // is the next CPU cycle an OUT operation? - else if (cur_instr[instr_pntr] == Z80A.OUT) - { - portContending = true; - lastPortAddr = (ushort)(_cpu.Regs[cur_instr[instr_pntr + 1]] | _cpu.Regs[cur_instr[instr_pntr + 2]] << 8); - portContCounter = 0; - if (IsPortContended(portContCounter)) - { - var cont = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); - if (cont > 0) - { - ContCounter = cont; - IsContending = true; - } - } - } - // is the next cpu cycle an IN operation? - else if (cur_instr[instr_pntr] == Z80A.IN) - { - portContending = true; - lastPortAddr = (ushort)(_cpu.Regs[cur_instr[instr_pntr + 2]] | _cpu.Regs[cur_instr[instr_pntr + 3]] << 8); - portContCounter = 0; - if (IsPortContended(portContCounter)) - { - var cont = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); - if (cont > 0) - { - ContCounter = cont; - IsContending = true; - } - } - } - */ - /* }*/ - - /* - // run a CPU cycle if no contention is applicable - if (!IsContending) - { - _cpu.ExecuteOne(); - } - else - { - _cpu.TotalExecutedCycles++; - ContCounter--; - } - */ } /// @@ -263,34 +137,36 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum case 21: addr = (ushort)(_cpu.Regs[_cpu.R] | _cpu.Regs[_cpu.I] << 8); break; + // BC + case Z80A.BIO1: + case Z80A.BIO2: + case Z80A.BIO3: + case Z80A.BIO4: + addr = (ushort)(_cpu.Regs[_cpu.C] | _cpu.Regs[_cpu.B] << 8); + break; + // WZ + case Z80A.WIO1: + case Z80A.WIO2: + case Z80A.WIO3: + case Z80A.WIO4: + addr = (ushort)(_cpu.Regs[_cpu.Z] | _cpu.Regs[_cpu.W] << 8); + break; } return addr; } - + /// - /// Perfors the actual port contention (if necessary) + /// Returns TRUE if the supplied T-cycle within an IO operation has the possibility of being contended + /// This can be different based on the emulated ZX Spectrum model /// - private void RunPortContention() + /// + /// + private bool IsIOCycleContended(int T) { - //return; - bool lowBitSet = false; + bool lowBitSet = (lastPortAddr & 0x0001) != 0; bool highByte407f = false; - int offset = 0; // _machine.ULADevice.contentionOffset; // -5;// 57;// - 10; - var c = _machine.CurrentFrameCycle; - var t = _machine.ULADevice.FrameLength; - int f = (int)c + offset; - if (f >= t) - f = f - t; - else if (f < 0) - f = t + f; - - if ((lastPortAddr & 0x0001) != 0) - lowBitSet = true; - - portContCounter--; - switch (machineType) { case MachineType.ZXSpectrum16: @@ -309,20 +185,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum // high byte 40-7f // low bit set // C:1, C:1, C:1, C:1 - switch (portContCounter) + switch (T) { - case 3: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 2: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 1: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 0: - _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); - portContCounter = 0; - portContending = false; - break; - default: - portContCounter = 0; - portContending = false; - break; + case 1: + case 2: + case 3: + case 4: + return true; } } else @@ -330,19 +199,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum // high byte 40-7f // low bit reset // C:1, C:3 - switch (portContCounter) + switch (T) { - case 3: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 2: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 1: break; - case 0: - portContCounter = 0; - portContending = false; - break; - default: - portContCounter = 0; - portContending = false; - break; + case 1: + case 2: + return true; } } } @@ -353,40 +214,17 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { // high byte not 40-7f // low bit set - // N:4 - switch (portContCounter) - { - case 3: break; - case 2: break; - case 1: break; - case 0: - portContCounter = 0; - portContending = false; - break; - default: - portContCounter = 0; - portContending = false; - break; - } + // N:4 } else { // high byte not 40-7f // low bit reset // N:1, C:3 - switch (portContCounter) + switch (T) { - case 3: break; - case 2: _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue(f); break; - case 1: break; - case 0: - portContCounter = 0; - portContending = false; - break; - default: - portContCounter = 0; - portContending = false; - break; + case 2: + return true; } } } @@ -396,17 +234,81 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum case MachineType.ZXSpectrum128Plus3: break; } + + return false; } /// - /// Starts the port contention process + /// Running every cycle, this determines whether the upcoming BUSRQ is for an IO operation + /// Also processes any contention /// - /// - public void ContendPort(ushort port) + /// + private bool CheckIO() { - portContending = true; - portContCounter = 4; - lastPortAddr = port; + bool isIO = false; + + switch (BUSRQ) + { + // BC: T1 + case Z80A.BIO1: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(1)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // BC: T2 + case Z80A.BIO2: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(2)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // BC: T3 + case Z80A.BIO3: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(3)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // BC: T4 + case Z80A.BIO4: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(4)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + + // WZ: T1 + case Z80A.WIO1: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(1)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // WZ: T2 + case Z80A.WIO2: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(2)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // WZ: T3 + case Z80A.WIO3: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(3)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + // WZ: T4 + case Z80A.WIO4: + lastPortAddr = AscertainBUSRQAddress(); + isIO = true; + if (IsIOCycleContended(4)) + _cpu.TotalExecutedCycles += _machine.ULADevice.GetPortContentionValue((int)_machine.CurrentFrameCycle); + break; + } + + return isIO; } /// diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs index 6a3e7ca04d..345b468cb7 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs @@ -797,7 +797,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum /// public int GetPortContentionValue(int tstate) { - int off = 1; + int off = 5; tstate += off; if (tstate >= FrameCycleLength) tstate -= FrameCycleLength; diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs index d4170ffd9e..f6b01cc3be 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs @@ -154,7 +154,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum 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. */ - CPUMon.ContendPort(addr); + //CPUMon.ContendPort(addr); return; }