diff --git a/Core/Cpu/RegisterPair.cs b/Core/Cpu/RegisterPair.cs
new file mode 100644
index 0000000..30bf18f
--- /dev/null
+++ b/Core/Cpu/RegisterPair.cs
@@ -0,0 +1,17 @@
+using System.Runtime.InteropServices;
+
+namespace Core.Cpu
+{
+ [StructLayout(LayoutKind.Explicit)]
+ public struct RegisterPair
+ {
+ [FieldOffset(0)]
+ public ushort Word;
+
+ [FieldOffset(0)]
+ public byte Low;
+
+ [FieldOffset(1)]
+ public byte High;
+ }
+}
\ No newline at end of file
diff --git a/Core/Cpu/Z80.cs b/Core/Cpu/Z80.cs
new file mode 100644
index 0000000..0e1b210
--- /dev/null
+++ b/Core/Cpu/Z80.cs
@@ -0,0 +1,74 @@
+using System;
+using Core.Interfaces;
+
+namespace Core.Cpu
+{
+ public partial class Z80
+ {
+ // Main Register Set
+ public RegisterPair AF;
+ public RegisterPair BC;
+ public RegisterPair DE;
+ public RegisterPair HL;
+
+ // Alternate Register Set
+ public RegisterPair AF_Prime;
+ public RegisterPair BC_Prime;
+ public RegisterPair DE_Prime;
+ public RegisterPair HL_Prime;
+
+ // Index Registers
+ public RegisterPair IX;
+ public RegisterPair IY;
+
+ // Special Purpose Registers
+ public ushort PC; // Program Counter
+ public ushort SP; // Stack Pointer
+ public byte I; // Interrupt Vector
+ public byte R; // Memory Refresh
+
+ // The Memory Bus
+ private readonly IMemory _memory;
+
+ public Z80(IMemory memory)
+ {
+ _memory = memory;
+ Reset();
+ }
+
+ public void Reset()
+ {
+ PC = 0x0000;
+ // The Z80 initializes SP to 0xFFFF on boot
+ SP = 0xFFFF;
+
+ AF.Word = 0;
+ BC.Word = 0;
+ DE.Word = 0;
+ HL.Word = 0;
+ }
+
+ public int Step()
+ {
+ // Fetch the next opcode and increment the Program Counter
+ byte opcode = _memory.Read(PC++);
+
+ // Decode and execute
+ return ExecuteOpcode(opcode);
+ }
+
+ private int ExecuteOpcode(byte opcode)
+ {
+ switch (opcode)
+ {
+ case 0x00: // NOP (No Operation)
+ return 4; // Takes 4 T-states
+
+ // We will expand this massive list soon!
+
+ default:
+ throw new NotImplementedException($"Opcode 0x{opcode:X2} at PC 0x{(PC - 1):X4} is not implemented.");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Core/Interfaces/IMemory.cs b/Core/Interfaces/IMemory.cs
new file mode 100644
index 0000000..49cdbb0
--- /dev/null
+++ b/Core/Interfaces/IMemory.cs
@@ -0,0 +1,8 @@
+namespace Core.Interfaces
+{
+ public interface IMemory
+ {
+ byte Read(ushort address);
+ void Write(ushort address, byte value);
+ }
+}
diff --git a/Core/Memory/MemoryBus.cs b/Core/Memory/MemoryBus.cs
new file mode 100644
index 0000000..c135787
--- /dev/null
+++ b/Core/Memory/MemoryBus.cs
@@ -0,0 +1,47 @@
+using System;
+using Core.Interfaces;
+
+namespace Core.Memory
+{
+ public class MemoryBus : IMemory
+ {
+ // The flat 64KB memory space
+ private readonly byte[] _memory = new byte[0x10000];
+
+ public byte Read(ushort address)
+ {
+ return _memory[address];
+ }
+
+ public void Write(ushort address, byte value)
+ {
+ /* ZX Spectrum 48K Memory Map:
+ * 0x0000 - 0x3FFF: ROM (16KB) -> Cannot write here!
+ * 0x4000 - 0x57FF: Display File (Screen Pixels)
+ * 0x5800 - 0x5AFF: Color Attributes
+ * 0x5B00 - 0xFFFF: General Purpose RAM
+ */
+
+ if (address < 0x4000)
+ {
+ // Attempted to write to the ROM area.
+ // We simply ignore the write command, just like real hardware.
+ return;
+ }
+
+ _memory[address] = value;
+ }
+
+ // Helper method to load the original Sinclair ROM file
+ public void LoadRom(byte[] romData)
+ {
+ if (romData.Length > 0x4000)
+ {
+ throw new ArgumentException("ROM file exceeds the 16KB capacity of Bank 0.");
+ }
+
+ // Copy the ROM data into the very beginning of the memory array
+ Array.Copy(romData, 0, _memory, 0, romData.Length);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj
index 663fdb8..454196b 100644
--- a/Desktop/Desktop.csproj
+++ b/Desktop/Desktop.csproj
@@ -8,4 +8,8 @@
enable
+
+
+
+
\ No newline at end of file
diff --git a/Desktop/Form1.Designer.cs b/Desktop/Form1.Designer.cs
index 7cf6955..52f7cd9 100644
--- a/Desktop/Form1.Designer.cs
+++ b/Desktop/Form1.Designer.cs
@@ -28,10 +28,17 @@
///
private void InitializeComponent()
{
- this.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
+ SuspendLayout();
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(800, 450);
+ Name = "Form1";
+ Text = "Form1";
+ Load += Form1_Load;
+ ResumeLayout(false);
}
#endregion
diff --git a/Desktop/Form1.cs b/Desktop/Form1.cs
index 3612dfe..d5006e3 100644
--- a/Desktop/Form1.cs
+++ b/Desktop/Form1.cs
@@ -6,5 +6,10 @@ namespace Desktop
{
InitializeComponent();
}
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+
+ }
}
}
diff --git a/Desktop/Form1.resx b/Desktop/Form1.resx
index 1af7de1..8b2ff64 100644
--- a/Desktop/Form1.resx
+++ b/Desktop/Form1.resx
@@ -1,17 +1,17 @@
-
diff --git a/ZxSpectrumEmulation.sln b/ZxSpectrumEmulation.sln
index a6a7b08..8c9846e 100644
--- a/ZxSpectrumEmulation.sln
+++ b/ZxSpectrumEmulation.sln
@@ -3,7 +3,25 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{0706292A-3AD4-4A04-A3CE-B692AC69D7A4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Desktop", "Desktop\Desktop.csproj", "{57408F14-0EEC-4E9E-BC97-3764DEB5738D}"
+EndProject
Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0706292A-3AD4-4A04-A3CE-B692AC69D7A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0706292A-3AD4-4A04-A3CE-B692AC69D7A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0706292A-3AD4-4A04-A3CE-B692AC69D7A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0706292A-3AD4-4A04-A3CE-B692AC69D7A4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {57408F14-0EEC-4E9E-BC97-3764DEB5738D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57408F14-0EEC-4E9E-BC97-3764DEB5738D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57408F14-0EEC-4E9E-BC97-3764DEB5738D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57408F14-0EEC-4E9E-BC97-3764DEB5738D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection