From 2e3102879b2d3059f4ce0efc1a0ecd4bc3142a99 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 28 Dec 2011 00:11:12 +0000 Subject: Added some more base classes and started on the Z80 implementation. --- .../Noddybox.Emulation.EightBit.Z80.csproj | 75 +++++++++ .../Properties/AssemblyInfo.cs | 37 +++++ Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs | 167 +++++++++++++++++++++ Noddybox.Emulation.EightBit/ICpu.cs | 54 +++++++ Noddybox.Emulation.EightBit/IDevice.cs | 4 +- Noddybox.Emulation.EightBit/IMemory.cs | 4 +- Noddybox.Emulation.EightBit/IRegister16.cs | 34 +++++ .../Noddybox.Emulation.EightBit.csproj | 11 ++ Noddybox.Emulation.EightBit/Register16BigEndian.cs | 53 +++++++ Noddybox.Emulation.EightBit/Register16Factory.cs | 31 ++++ .../Register16LittleEndian.cs | 53 +++++++ Noddybox.Emulation.sln | 6 + Noddybox.Emulation.suo | Bin 0 -> 37376 bytes Noddybox.Emulation/Clock.cs | 9 ++ 14 files changed, 534 insertions(+), 4 deletions(-) create mode 100644 Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj create mode 100644 Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs create mode 100644 Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs create mode 100644 Noddybox.Emulation.EightBit/ICpu.cs create mode 100644 Noddybox.Emulation.EightBit/IRegister16.cs create mode 100644 Noddybox.Emulation.EightBit/Register16BigEndian.cs create mode 100644 Noddybox.Emulation.EightBit/Register16Factory.cs create mode 100644 Noddybox.Emulation.EightBit/Register16LittleEndian.cs create mode 100644 Noddybox.Emulation.suo diff --git a/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj b/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj new file mode 100644 index 0000000..60cb7ff --- /dev/null +++ b/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj @@ -0,0 +1,75 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {7F257886-40D3-4E2A-BA9C-C5FEE93C08E9} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Noddybox.Emulation.EightBit.Z80 + Noddybox.Emulation.EightBit.Z80 + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + {ADC7A871-4DED-4A92-A447-2D784AB60FAF} + Noddybox.Emulation.EightBit + + + {A2478066-4DFD-4042-BF98-963922DC97F8} + Noddybox.Emulation + + + + + + + \ No newline at end of file diff --git a/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs b/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..52b6054 --- /dev/null +++ b/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Noddybox.Emulation.EightBit.Z80")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Noddybox.Emulation.EightBit.Z80")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3b53cbb7-adc4-4405-ba85-4b345a46ed11")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs b/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs new file mode 100644 index 0000000..d967bb9 --- /dev/null +++ b/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs @@ -0,0 +1,167 @@ +using System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace Noddybox.Emulation.EightBit.Z80 +{ + /// + /// Provides an implementation of a Zilog Z80 processor. + /// + public partial class Z80Cpu : ICpu + { + #region Private types + + [Flags] + private enum Z80Flags + { + None = 0x00, + Carry = 0x01, + Neg = 0x02, + PV = 0x04, + Hidden3 = 0x08, + HalfCarry = 0x10, + Hidden5 = 0x20, + Zero = 0x40, + Sign = 0x80 + }; + + #endregion + + #region Private data + + // Lookup tables + // + private Z80Flags[] PSZtable = new Z80Flags[512]; + private Z80Flags[] SZtable = new Z80Flags[512]; + private Z80Flags[] Ptable = new Z80Flags[512]; + private Z80Flags[] Stable = new Z80Flags[512]; + private Z80Flags[] Ztable = new Z80Flags[512]; + + // Machine accessors + // + private IMemory memory; + private IDevice device; + private Clock clock; + + // Main registers + // + private byte A; + private byte F; + private byte R; + private byte IFF1; + private byte IFF2; + private IRegister16 BC = Register16Factory.Create(); + private IRegister16 DE = Register16Factory.Create(); + private IRegister16 HL = Register16Factory.Create(); + private IRegister16 IX = Register16Factory.Create(); + private IRegister16 IY = Register16Factory.Create(); + private IRegister16 SP = Register16Factory.Create(); + private IRegister16 PC = Register16Factory.Create(); + + // Alternate registers + // + private IRegister16 AF_ = Register16Factory.Create(); + private IRegister16 BC_ = Register16Factory.Create(); + private IRegister16 DE_ = Register16Factory.Create(); + private IRegister16 HL_ = Register16Factory.Create(); + + #endregion + + #region ICpu Members + + public void Initialise(IMemory memory, IDevice device, Clock clock) + { + this.memory = memory; + this.device = device; + this.clock = clock; + + Reset(); + } + + public void Reset() + { + // TODO: Initial register settings. + } + + public void Step() + { + // TODO: Single step. + } + + public void Run() + { + // TODO: Run for a frame + } + + public void MaskableInterrupt(byte value) + { + // TODO: INT + } + + public void NonMaskableInterrupt(byte value) + { + // TODO: NMI + } + + #endregion + + #region Constructors + + public Z80Cpu() + { + // Setup lookup tables + // + for(int f = 0; f < 256; f++) + { + Z80Flags p = Z80Flags.None; + Z80Flags z = Z80Flags.None; + Z80Flags s = Z80Flags.None; + int parity = 0; + + for(int b=0; b < 8; b++) + { + if ((f & (1< + /// Defines an 8-bit CPU. + /// + public interface ICpu + { + /// + /// Initialise the CPU to give it access to memory and devices. + /// + /// The memory to access. + /// The devices to access. + /// The clock to use. + void Initialise(IMemory memory, IDevice device, Clock clock); + + /// + /// Resets the CPU to its initial state. + /// + void Reset(); + + /// + /// Runs the next instruction. + /// + void Step(); + + /// + /// Runs the CPU until the next frame flyback. + /// + void Run(); + + /// + /// Generates a maskable interrupt to the CPU. + /// + /// Optional value from an interrupting device. May be ignored depending on the CPU type. + void MaskableInterrupt(byte value); + + /// + /// Generates a non-maskable interrupt to the CPU. + /// + /// Optional value from an interrupting device. May be ignored depending on the CPU type. + void NonMaskableInterrupt(byte value); + } +} diff --git a/Noddybox.Emulation.EightBit/IDevice.cs b/Noddybox.Emulation.EightBit/IDevice.cs index 108adf9..00ef38d 100644 --- a/Noddybox.Emulation.EightBit/IDevice.cs +++ b/Noddybox.Emulation.EightBit/IDevice.cs @@ -22,13 +22,13 @@ namespace Noddybox.Emulation.EightBit /// /// The address of the device. /// The byte returned from the device. - byte Read(UInt16 device); + byte Read(ushort device); /// /// Write to a device. /// /// The address of the device. /// The value to write to the device. - void Write(UInt16 device, byte value); + void Write(ushort device, byte value); } } diff --git a/Noddybox.Emulation.EightBit/IMemory.cs b/Noddybox.Emulation.EightBit/IMemory.cs index 5131eb0..2c842a5 100644 --- a/Noddybox.Emulation.EightBit/IMemory.cs +++ b/Noddybox.Emulation.EightBit/IMemory.cs @@ -21,13 +21,13 @@ namespace Noddybox.Emulation.EightBit /// /// The address to read. /// The value at that address. - byte Read(UInt16 address); + byte Read(ushort address); /// /// Writes a byte at a given address. /// /// The address to write to. /// The value to write. - void Write(UInt16 address, byte value); + void Write(ushort address, byte value); } } diff --git a/Noddybox.Emulation.EightBit/IRegister16.cs b/Noddybox.Emulation.EightBit/IRegister16.cs new file mode 100644 index 0000000..e3bfc69 --- /dev/null +++ b/Noddybox.Emulation.EightBit/IRegister16.cs @@ -0,0 +1,34 @@ +using System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace Noddybox.Emulation.EightBit +{ + /// + /// Provides a common 8-bit register pattern, which is two 8-bit registers rolled into one. + /// + public interface IRegister16 + { + /// + /// Get/set the low byte of the 16-bit register. + /// + byte Low {get; set;} + + /// + /// Get/set the high byte of the 16-bit register. + /// + byte High {get; set;} + + /// + /// Get/set the value of the 16-bit register. + /// + ushort Value {get; set;} + } +} diff --git a/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj b/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj index 316b00b..c7d5924 100644 --- a/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj +++ b/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj @@ -49,9 +49,20 @@ + + + + + + + + + {A2478066-4DFD-4042-BF98-963922DC97F8} + Noddybox.Emulation + diff --git a/Noddybox.Emulation.EightBit/Register16BigEndian.cs b/Noddybox.Emulation.EightBit/Register16BigEndian.cs new file mode 100644 index 0000000..8378543 --- /dev/null +++ b/Noddybox.Emulation.EightBit/Register16BigEndian.cs @@ -0,0 +1,53 @@ +using System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using System.Runtime.InteropServices; + +namespace Noddybox.Emulation.EightBit +{ + [StructLayout(LayoutKind.Explicit)] + public struct Register16BigEndian : IRegister16 + { + #region Register fields + + [FieldOffset(0)] + ushort reg; + + [FieldOffset(1)] + byte low; + + [FieldOffset(0)] + byte high; + + #endregion + + #region IRegister16 Members + + public byte Low + { + get {return low;} + set {low = value;} + } + + public byte High + { + get {return high;} + set {high = value;} + } + + public ushort Value + { + get {return reg;} + set {reg = value;} + } + + #endregion + } +} diff --git a/Noddybox.Emulation.EightBit/Register16Factory.cs b/Noddybox.Emulation.EightBit/Register16Factory.cs new file mode 100644 index 0000000..fd31fe4 --- /dev/null +++ b/Noddybox.Emulation.EightBit/Register16Factory.cs @@ -0,0 +1,31 @@ +using System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace Noddybox.Emulation.EightBit +{ + /// + /// Defines a common 16-bit register, which is two bytes which are separately addressable. + /// + public static class Register16Factory + { + public static IRegister16 Create() + { + if (BitConverter.IsLittleEndian) + { + return new Register16LittleEndian(); + } + else + { + return new Register16BigEndian(); + } + } + } +} diff --git a/Noddybox.Emulation.EightBit/Register16LittleEndian.cs b/Noddybox.Emulation.EightBit/Register16LittleEndian.cs new file mode 100644 index 0000000..a2cf8a8 --- /dev/null +++ b/Noddybox.Emulation.EightBit/Register16LittleEndian.cs @@ -0,0 +1,53 @@ +using System; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Ink; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; +using System.Runtime.InteropServices; + +namespace Noddybox.Emulation.EightBit +{ + [StructLayout(LayoutKind.Explicit)] + public struct Register16LittleEndian : IRegister16 + { + #region Register fields + + [FieldOffset(0)] + ushort reg; + + [FieldOffset(0)] + byte low; + + [FieldOffset(1)] + byte high; + + #endregion + + #region IRegister16 Members + + public byte Low + { + get {return low;} + set {low = value;} + } + + public byte High + { + get {return high;} + set {high = value;} + } + + public ushort Value + { + get {return reg;} + set {reg = value;} + } + + #endregion + } +} diff --git a/Noddybox.Emulation.sln b/Noddybox.Emulation.sln index 78f38c7..7578ca2 100644 --- a/Noddybox.Emulation.sln +++ b/Noddybox.Emulation.sln @@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation", "Noddy EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit", "Noddybox.Emulation.EightBit\Noddybox.Emulation.EightBit.csproj", "{ADC7A871-4DED-4A92-A447-2D784AB60FAF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit.Z80", "Noddybox.Emulation.EightBit.Z80\Noddybox.Emulation.EightBit.Z80.csproj", "{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -19,6 +21,10 @@ Global {ADC7A871-4DED-4A92-A447-2D784AB60FAF}.Debug|Any CPU.Build.0 = Debug|Any CPU {ADC7A871-4DED-4A92-A447-2D784AB60FAF}.Release|Any CPU.ActiveCfg = Release|Any CPU {ADC7A871-4DED-4A92-A447-2D784AB60FAF}.Release|Any CPU.Build.0 = Release|Any CPU + {7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Noddybox.Emulation.suo b/Noddybox.Emulation.suo new file mode 100644 index 0000000..8cd6ad5 Binary files /dev/null and b/Noddybox.Emulation.suo differ diff --git a/Noddybox.Emulation/Clock.cs b/Noddybox.Emulation/Clock.cs index 79beafb..55a0e7b 100644 --- a/Noddybox.Emulation/Clock.cs +++ b/Noddybox.Emulation/Clock.cs @@ -64,6 +64,15 @@ namespace Noddybox.Emulation } } + /// + /// Adds a number of ticks to the clock. + /// + /// The ticks to add. + public void Add(uint ticks) + { + frameCount += ticks; + } + #endregion #region Constructors -- cgit v1.2.3