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)
{