diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 36b6f5462a..6ac5775daf 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -263,6 +263,7 @@ + @@ -1437,6 +1438,7 @@ + diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs index 25a03161fc..d2cff11e0e 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/CPUMonitor.cs @@ -39,12 +39,112 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum /// public void Cycle() { + if (portContending) { - RunPortContention(); + RunPortContention(); + } + /* + else + { + // check for wait state on cycle that has just happened + // next cycle should be a read/write operation + if (cur_instr[instr_pntr] == Z80A.WAIT) + { + ushort addr = 0; + bool abort = false; + + // identify the type of operation and get the targetted address + switch (cur_instr[instr_pntr + 1]) + { + // op fetch + case Z80A.OP_F: + addr = RegPC; + break; + // read/writes + case Z80A.RD: + case Z80A.RD_INC: + case Z80A.WR: + case Z80A.WR_INC: + addr = (ushort)(_cpu.Regs[cur_instr[instr_pntr + 3]] | _cpu.Regs[cur_instr[instr_pntr + 4]] << 8); + break; + default: + abort = true; + break; + } + + if (!abort) + { + // is the address in a potentially contended bank? + if (_machine.IsContended(addr)) + { + // will the ULA be contending this address on the next cycle? + var delay = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle + 1); + _cpu.TotalExecutedCycles += delay; + } + } + } + + } + */ + return; + // check for wait state on next cycle + // the cycle after that should be a read/write operation or op fetch + if (instr_pntr >= cur_instr.Length - 1) + { + // will overflow + return; + } + + if (cur_instr[instr_pntr + 1] == Z80A.WAIT) + { + // return; + ushort addr = 0; + + // identify the type of operation and get the targetted address + var op = cur_instr[instr_pntr + 2]; + switch (op) + { + // op fetch + case Z80A.OP_F: + addr = (ushort)(RegPC); + if (_machine.IsContended(addr)) + { + var delay = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); + if (delay > 0) + { + _cpu.TotalExecutedCycles += delay; + _machine.ULADevice.RenderScreen((int)_machine.CurrentFrameCycle); + } + } + break; + // read/writes + case Z80A.RD: + case Z80A.RD_INC: + case Z80A.WR: + case Z80A.WR_INC: + case Z80A.I_RD: + case Z80A.I_WR: + addr = (ushort)(_cpu.Regs[cur_instr[instr_pntr + 4]] | _cpu.Regs[cur_instr[instr_pntr + 5]] << 8); + if (_machine.IsContended(addr)) + { + var delay = _machine.ULADevice.GetContentionValue((int)_machine.CurrentFrameCycle); + if (delay > 0) + { + _cpu.TotalExecutedCycles += delay; + _machine.ULADevice.RenderScreen((int)_machine.CurrentFrameCycle); + } + } + break; + case Z80A.FTCH_DB: + break; + default: + break; + } } } + #region Port Contention public int portContCounter = 0; @@ -78,6 +178,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { case MachineType.ZXSpectrum16: case MachineType.ZXSpectrum48: + case MachineType.ZXSpectrum128: + case MachineType.ZXSpectrum128Plus2: if ((lastPortAddr & 0xc000) == 0x4000) highByte407f = true; @@ -160,10 +262,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum } break; - case MachineType.ZXSpectrum128: - case MachineType.ZXSpectrum128Plus2: - break; - case MachineType.ZXSpectrum128Plus2a: case MachineType.ZXSpectrum128Plus3: break; diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs index 1a8ff0a328..d6bea89b67 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.cs @@ -169,7 +169,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum // check for interrupt ULADevice.CheckForInterrupt(CurrentFrameCycle); - // run a single CPU instruction + // run a single CPU instruction + CPU.ExecuteOne(); CPUMon.Cycle(); diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs index 68639979e9..bff1ec4334 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs @@ -176,7 +176,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum /// public override void ContendPort(ushort addr) { - throw new NotImplementedException(); + CPUMon.ContendPort(addr); + return; } } } diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Screen.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Screen.cs new file mode 100644 index 0000000000..cbd98f1128 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Screen.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum +{ + class Screen128 : ULA + { + #region Construction + + public Screen128(SpectrumBase machine) + : base(machine) + { + // timing + ClockSpeed = 3546900; + FrameCycleLength = 70908; + InterruptStartTime = 33; + InterruptLength = 36; + ScanlineTime = 228; + + BorderLeftTime = 24; + BorderRightTime = 24; + + FirstPaperLine = 63; + FirstPaperTState = 64; + + Border4T = true; + Border4TStage = 2; + + // screen layout + ScreenWidth = 256; + ScreenHeight = 192; + BorderTopHeight = 48; + BorderBottomHeight = 56; + BorderLeftWidth = 48; + BorderRightWidth = 48; + ScanLineWidth = BorderLeftWidth + ScreenWidth + BorderRightWidth; + + RenderingTable = new RenderTable(this, + MachineType.ZXSpectrum128); + + SetupScreenSize(); + } + + #endregion + } +} diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.cs index fc2369a3a1..ed556a3025 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.cs @@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum PagingDisabled = false; //ULADevice = new ULA128(this); - ULADevice = new Screen48(this); // still todo + ULADevice = new Screen128(this); // still todo BuzzerDevice = new Beeper(this); BuzzerDevice.Init(44100, ULADevice.FrameLength); diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs index 3eb942d51f..2423078a83 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs @@ -289,7 +289,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum /// public override void ContendPort(ushort addr) { - throw new NotImplementedException(); + CPUMon.ContendPort(addr); + return; } } } diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Screen.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Screen.cs new file mode 100644 index 0000000000..e9026ce5d7 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Screen.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum +{ + class Screen128Plus2a : ULA + { + #region Construction + + public Screen128Plus2a(SpectrumBase machine) + : base(machine) + { + // timing + ClockSpeed = 3546900; + FrameCycleLength = 70908; + InterruptStartTime = 33; + InterruptLength = 32; + ScanlineTime = 228; + + BorderLeftTime = 24; + BorderRightTime = 24; + + FirstPaperLine = 63; + FirstPaperTState = 64; + + Border4T = true; + Border4TStage = 2; + + // screen layout + ScreenWidth = 256; + ScreenHeight = 192; + BorderTopHeight = 48; + BorderBottomHeight = 56; + BorderLeftWidth = 48; + BorderRightWidth = 48; + ScanLineWidth = BorderLeftWidth + ScreenWidth + BorderRightWidth; + + RenderingTable = new RenderTable(this, + MachineType.ZXSpectrum128Plus2a); + + SetupScreenSize(); + } + + #endregion + } +} diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.cs index 487cc386b4..363f1a52ac 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.cs @@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum PagingDisabled = false; //ULADevice = new ULAPlus2a(this); - ULADevice = new Screen48(this); // still todo + ULADevice = new Screen128Plus2a(this); // still todo BuzzerDevice = new Beeper(this); BuzzerDevice.Init(44100, ULADevice.FrameLength); diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs index c3b53fff79..d1c30ee3a8 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs @@ -224,7 +224,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum /// public override void ContendPort(ushort addr) { - throw new NotImplementedException(); + CPUMon.ContendPort(addr); + return; } } } diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.cs index decfb7466e..4e6d889d55 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.cs @@ -20,9 +20,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { Spectrum = spectrum; CPU = cpu; - CPUMon.machineType = MachineType.ZXSpectrum128Plus3; + CPUMon = new CPUMonitor(this); + CPUMon.machineType = MachineType.ZXSpectrum128Plus3; ROMPaged = 0; SHADOWPaged = false; @@ -30,7 +31,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum PagingDisabled = false; // ULADevice = new ULAPlus3(this); - ULADevice = new Screen48(this); // still todo + ULADevice = new Screen128Plus2a(this); // still todo BuzzerDevice = new Beeper(this); BuzzerDevice.Init(44100, ULADevice.FrameLength); diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs index 624df29d2c..7dd6f3cd21 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs @@ -124,7 +124,14 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { if (IsContended(addr)) { - var delay = ULADevice.GetContentionValue((int)CurrentFrameCycle); + var off = 1; + var offset = CurrentFrameCycle + off; + if (offset < 0) + offset += ULADevice.FrameCycleLength; + if (offset >= ULADevice.FrameCycleLength) + offset -= ULADevice.FrameCycleLength; + + var delay = ULADevice.GetContentionValue((int)offset); if (delay > 0) {