From 2b8d49726e448e22b5055da5ba4395d043030984 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 1 Jan 2012 14:21:26 +0000 Subject: Moved sources to help in compilation for other platforms and isolated phone projects. --- .../Noddybox.Emulation.EightBit.Z80.csproj | 76 --- .../Properties/AssemblyInfo.cs | 37 -- Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs | 226 ------- .../Z80CpuBaseOpcodes.cs | 695 --------------------- Noddybox.Emulation.EightBit/Binary.cs | 63 -- Noddybox.Emulation.EightBit/ICpu.cs | 57 -- Noddybox.Emulation.EightBit/IDevice.cs | 37 -- Noddybox.Emulation.EightBit/IMemory.cs | 36 -- .../Noddybox.Emulation.EightBit.csproj | 75 --- .../Properties/AssemblyInfo.cs | 37 -- Noddybox.Emulation.EightBit/Register16.cs | 88 --- Noddybox.Emulation.Phone.sln | 32 + Noddybox.Emulation.Phone.suo | Bin 0 -> 42496 bytes Noddybox.Emulation.sln | 32 - Noddybox.Emulation.suo | Bin 42496 -> 0 bytes Noddybox.Emulation/Clock.cs | 112 ---- Noddybox.Emulation/Noddybox.Emulation.csproj | 65 -- Noddybox.Emulation/Noddybox.Emulation.suo | Bin 15872 -> 0 bytes Noddybox.Emulation/Properties/AssemblyInfo.cs | 37 -- .../Noddybox.Emulation.EightBit.Z80.csproj | 80 +++ .../Properties/AssemblyInfo.cs | 37 ++ .../Noddybox.Emulation.EightBit.csproj | 85 +++ .../Properties/AssemblyInfo.cs | 37 ++ .../Noddybox.Emulation/Noddybox.Emulation.csproj | 67 ++ .../Noddybox.Emulation/Noddybox.Emulation.suo | Bin 0 -> 15872 bytes .../Noddybox.Emulation/Properties/AssemblyInfo.cs | 37 ++ src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs | 226 +++++++ .../Z80CpuBaseOpcodes.cs | 695 +++++++++++++++++++++ src/Noddybox.Emulation.EightBit/Binary.cs | 63 ++ src/Noddybox.Emulation.EightBit/ICpu.cs | 57 ++ src/Noddybox.Emulation.EightBit/IDevice.cs | 37 ++ src/Noddybox.Emulation.EightBit/IMemory.cs | 36 ++ src/Noddybox.Emulation.EightBit/Register16.cs | 88 +++ src/Noddybox.Emulation/Clock.cs | 112 ++++ 34 files changed, 1689 insertions(+), 1673 deletions(-) delete mode 100644 Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj delete mode 100644 Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs delete mode 100644 Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs delete mode 100644 Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs delete mode 100644 Noddybox.Emulation.EightBit/Binary.cs delete mode 100644 Noddybox.Emulation.EightBit/ICpu.cs delete mode 100644 Noddybox.Emulation.EightBit/IDevice.cs delete mode 100644 Noddybox.Emulation.EightBit/IMemory.cs delete mode 100644 Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj delete mode 100644 Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs delete mode 100644 Noddybox.Emulation.EightBit/Register16.cs create mode 100644 Noddybox.Emulation.Phone.sln create mode 100644 Noddybox.Emulation.Phone.suo delete mode 100644 Noddybox.Emulation.sln delete mode 100644 Noddybox.Emulation.suo delete mode 100644 Noddybox.Emulation/Clock.cs delete mode 100644 Noddybox.Emulation/Noddybox.Emulation.csproj delete mode 100644 Noddybox.Emulation/Noddybox.Emulation.suo delete mode 100644 Noddybox.Emulation/Properties/AssemblyInfo.cs create mode 100644 WindowsPhone/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj create mode 100644 WindowsPhone/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs create mode 100644 WindowsPhone/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj create mode 100644 WindowsPhone/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs create mode 100644 WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.csproj create mode 100644 WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.suo create mode 100644 WindowsPhone/Noddybox.Emulation/Properties/AssemblyInfo.cs create mode 100644 src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs create mode 100644 src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs create mode 100644 src/Noddybox.Emulation.EightBit/Binary.cs create mode 100644 src/Noddybox.Emulation.EightBit/ICpu.cs create mode 100644 src/Noddybox.Emulation.EightBit/IDevice.cs create mode 100644 src/Noddybox.Emulation.EightBit/IMemory.cs create mode 100644 src/Noddybox.Emulation.EightBit/Register16.cs create mode 100644 src/Noddybox.Emulation/Clock.cs diff --git a/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj b/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj deleted file mode 100644 index 03c8010..0000000 --- a/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj +++ /dev/null @@ -1,76 +0,0 @@ - - - - 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 deleted file mode 100644 index 52b6054..0000000 --- a/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -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 deleted file mode 100644 index 5c40854..0000000 --- a/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs +++ /dev/null @@ -1,226 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -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]; - private Z80Flags[] H35table = new Z80Flags[256]; - - // Machine accessors - // - private IMemory memory; - private IDevice device; - private Clock clock; - - // Main registers - // - private byte A; - private Z80Flags F; - private Register16 BC = new Register16(0); - private Register16 DE = new Register16(0); - private Register16 HL = new Register16(0); - private Register16 IX = new Register16(0); - private Register16 IY = new Register16(0); - private ushort SP; - private ushort PC; - - // Alternate registers - // - private Register16 AF_ = new Register16(0); - private Register16 BC_ = new Register16(0); - private Register16 DE_ = new Register16(0); - private Register16 HL_ = new Register16(0); - - // Auxilliary registers and flags - // - private byte I; - private byte R; - private bool IFF1; - private bool IFF2; - private int IM; - private bool HALT; - - #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() - { - PC = 0; - A = 0xff; - F = (Z80Flags)0xff; - - BC.reg = 0xffff; - DE.reg = 0xffff; - HL.reg = 0xffff; - AF_.reg = 0xffff; - BC_.reg = 0xffff; - DE_.reg = 0xffff; - HL_.reg = 0xffff; - - IX.reg = 0xffff; - IY.reg = 0xffff; - - SP = 0xffff; - - IFF1 = false; - IFF2 = false; - IM = 0; - I = 0; - R = 0; - HALT = false; - } - - public void Step() - { - // TODO: Single step. - } - - public void Run() - { - while(!clock.FrameDone) - { - Step(); - } - } - - public void MaskableInterrupt(byte value) - { - clock.Add(2); - - // TODO: INT - } - - public void NonMaskableInterrupt(byte value) - { - clock.Add(2); - - // TODO: NMI - } - - #endregion - - #region Constructors - - public Z80Cpu() - { - // Verify runtime - // - Register16.Verify(); - - // Setup lookup tables - // - for(int f = 0; f < 256; f++) - { - Z80Flags p = Z80Flags.None; - Z80Flags z = Z80Flags.None; - Z80Flags s = Z80Flags.None; - Z80Flags h3 = Z80Flags.None; - Z80Flags h5 = Z80Flags.None; - - int parity = 0; - - for(int b=0; b < 8; b++) - { - if ((f & (1< - /// Set a flag in the status register. - /// - /// The flag. - private void SetFlag(Z80Flags flag) - { - F |= flag; - } - - /// - /// Clear a flag in the status register. - /// - /// The flag. - private void ClearFlag(Z80Flags flag) - { - F &= ~flag; - } - - #endregion - - #region Stack commands - - /// - /// Push a value on the stack. - /// - /// The value. - private void PUSH(ushort val) - { - memory.Write(--SP, (byte)(val & 0xff)); - memory.Write(--SP, (byte)(Binary.ShiftRight(val, 8) & 0xff)); - } - - /// - /// Pop a value from the stack. - /// - /// - private ushort POP() - { - SP = (ushort)((SP + 2) & 0xffff); - return (ushort)(memory.Read((ushort)(SP-2)) | - (memory.Read((ushort)(SP - 1)) >> 8)); - } - - #endregion - - #region ALU arithmetic and comparison - - /// - /// Add an 8-bit value to the accumulator without carry. - /// - /// The vakue. - private void Add8(byte b) - { - int w = A + b; - - F = SZtable[w] | H35table[w & 0xff]; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } - - A = (byte)(w & 0xff); - } - - /// - /// Add an 8-bit value to the accumulator with carry. - /// - /// The vakue. - private void Adc8(byte b) - { - int w = A + b + (int)(F & Z80Flags.Carry); - - F = SZtable[w] | H35table[w & 0xff]; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } - - A = (byte)(w & 0xff); - } - - /// - /// Subtract an 8-bit value from the accumulator without carry. - /// - /// The vakue. - private void Sub8(byte b) - { - int w = A - b; - - if (w < 0) - { - w += 0x200; - } - - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } - - A = (byte)(w & 0xff); - } - - /// - /// Compare an 8-bit value with the accumulator. - /// - /// The vakue. - private void Cmp8(byte b) - { - int w = A - b; - - if (w < 0) - { - w += 0x200; - } - - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } - } - - /// - /// Subtract an 8-bit value from the accumulator with carry. - /// - /// The vakue. - private void Sbc8(byte b) - { - int w = A - b - (int)(F & Z80Flags.Carry); - - if (w < 0) - { - w += 0x200; - } - - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } - - A = (byte)(w & 0xff); - } - - /// - /// Add a 16-bit value to a register without carry. - /// - /// The vakue. - private void Add16(ref ushort reg, ushort b) - { - int w = reg + b; - - F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; - - if (w > 0xffff) - { - F |= Z80Flags.Carry; - } - - if ((reg ^ w ^ b) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } - - reg = (ushort)(w & 0xffff); - - F |= H35table[reg >> 8]; - } - - /// - /// Add a 16-bit value to a register with carry. - /// - /// The vakue. - private void Adc16(ref ushort reg, ushort b) - { - int w = reg + b + (int)(F & Z80Flags.Carry); - - F = Z80Flags.None; - - if ((w & 0xffff) == 0) - { - F |= Z80Flags.Zero; - } - - if ((w & 0x8000) == 0x8000) - { - F |= Z80Flags.Sign; - } - - if (w > 0xffff) - { - F |= Z80Flags.Carry; - } - - if (((b ^ reg ^ 0x8000) & ((reg ^ w) & 0x8000)) == 0x8000) - { - F |= Z80Flags.PV; - } - - if ((reg ^ w ^ b) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } - - reg = (ushort)(w & 0xffff); - - F |= H35table[reg >> 8]; - } - - - /// - /// Subtract a 16-bit value from a register with carry. - /// - /// The vakue. - private void Sbc16(ref ushort reg, ushort b) - { - int w = reg - b - (int)(F & Z80Flags.Carry); - - F = Z80Flags.Neg; - - if (w < 0) - { - w += 0x10000; - F |= Z80Flags.Carry; - } - - if ((w & 0xffff) == 0) - { - F |= Z80Flags.Zero; - } - - if ((w & 0x8000) == 0x8000) - { - F |= Z80Flags.Sign; - } - - if (((b ^ reg) & ((reg ^ w) & 0x8000)) == 0x8000) - { - F |= Z80Flags.PV; - } - - if ((reg ^ w ^ b) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } - - reg = (ushort)(w & 0xffff); - - F |= H35table[reg >> 8]; - } - - /// - /// Increment an 8-bit register. - /// - /// The register to increment. - void Inc8(ref byte reg) - { - reg++; - - F = Z80Flags.Carry; - - if (reg == 0x80) - { - F |= Z80Flags.PV; - } - - if ((reg & 0x0f) == 0x00) - { - F |= Z80Flags.HalfCarry; - } - } - - /// - /// Decrement an 8-bit register. - /// - /// The register to decrement. - void Dec8(ref byte reg) - { - reg--; - - F = Z80Flags.Carry | Z80Flags.Neg; - - if (reg == 0x7f) - { - F |= Z80Flags.PV; - } - - if ((reg & 0x0f) == 0x0f) - { - F |= Z80Flags.HalfCarry; - } - } - - #endregion - - #region ALU rotate and shift operations - - /// - /// Do RRCA. - /// - private void RRCA() - { - F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; - F |= (Z80Flags)(A & 1); - A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(A, 7)); - F |= H35table[A]; - } - - /// - /// Do RRA. - /// - private void RRA() - { - byte carry = (byte)(F & Z80Flags.Carry); - F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; - F |= (Z80Flags)(A & 1); - A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(carry, 7)); - F |= H35table[A]; - } - - /// - /// Do RRC. - /// - /// The register to operate on. - private void RRC(ref byte reg) - { - F = (Z80Flags)(reg & (int)Z80Flags.Carry); - reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(reg, 7)); - F |= PSZtable[reg] | H35table[reg]; - } - - /// - /// Do RR. - /// - /// The register to operate on. - private void RR(ref byte reg) - { - byte carry = (byte)(F & Z80Flags.Carry); - F = (Z80Flags)(reg & (int)Z80Flags.Carry); - reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(carry, 7)); - F |= PSZtable[reg] | H35table[reg]; - } - - /// - /// Do RLCA. - /// - private void RLCA() - { - F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) - | (Z80Flags)Binary.ShiftRight(A, 7); - - A = (byte)(Binary.ShiftLeft(A, 1) | Binary.ShiftRight(A, 7)); - - F |= H35table[A]; - } - - /// - /// Do RLA. - /// - private void RLA() - { - byte carry = (byte)(F & Z80Flags.Carry); - F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) - | (Z80Flags)Binary.ShiftRight(A, 7); - A = (byte)(Binary.ShiftRight(A, 1) | carry); - F |= H35table[A]; - } - - /// - /// Do RLC. - /// - /// The register to operate on. - private void RLC(ref byte reg) - { - byte carry = Binary.ShiftRight(reg, 7); - reg = (byte)(Binary.ShiftLeft(reg, 1) | carry); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - /// - /// Do RL. - /// - /// The register to operate on. - private void RL(ref byte reg) - { - byte carry = Binary.ShiftRight(reg, 7); - reg = (byte)(Binary.ShiftLeft(reg, 1) | (int)(F & Z80Flags.Carry)); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - /// - /// Do SRL. - /// - /// The register to operate on. - private void SRL(ref byte reg) - { - byte carry = (byte)(reg & 1); - reg = Binary.ShiftLeft(reg, 1); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - /// - /// Do SRA. - /// - /// The register to operate on. - private void SRA(ref byte reg) - { - byte carry = (byte)(reg & 1); - reg = (byte)(Binary.ShiftLeft(reg, 1) | (reg & 0x80)); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - /// - /// Do SLL. - /// - /// The register to operate on. - private void SLL(ref byte reg) - { - byte carry = Binary.ShiftRight(reg, 7); - reg = (byte)(Binary.ShiftRight(reg, 1) | 0x01); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - /// - /// Do SLA. - /// - /// The register to operate on. - private void SLA(ref byte reg) - { - byte carry = Binary.ShiftRight(reg, 7); - reg = Binary.ShiftRight(reg, 1); - F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; - } - - #endregion - - #region ALU boolean operations - - /// - /// AND a value with the accumulator. - /// - /// The value. - void AND(byte val) - { - A &= val; - F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; - } - - /// - /// OR a value with the accumulator. - /// - /// The value. - void OR(byte val) - { - A |= val; - F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; - } - - /// - /// XOR a value with the accumulator. - /// - /// The value. - void XOR(byte val) - { - A ^= val; - F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; - } - - /// - /// Perform the BIT operation. - /// - /// The register to operate on. - /// The bit to test. - void BIT(ref byte reg, int bit) - { - F &= Z80Flags.Carry; - F |= Z80Flags.HalfCarry; - - if ((reg & (1 << bit)) != 0) - { - if (bit == 7 && (reg & (int)Z80Flags.Sign) != 0) - { - F |= Z80Flags.Sign; - } - - if (bit == 5 && (reg & (int)Z80Flags.Hidden5) != 0) - { - F |= Z80Flags.Hidden5; - } - - if (bit == 3 && (reg & (int)Z80Flags.Hidden3) != 0) - { - F |= Z80Flags.Hidden3; - } - } - else - { - F |= Z80Flags.Zero | Z80Flags.PV; - } - } - - /// - /// Perform the bit set operation. - /// - /// The register to operate on. - /// The bit to test. - void BIT_SET(ref byte reg, int bit) - { - reg |= (byte)(1 << bit); - } - - /// - /// Perform the bit clear operation. - /// - /// The register to operate on. - /// The bit to test. - void BIT_RES(ref byte reg, int bit) - { - reg &= (byte)~(1 << bit); - } - - #endregion - - #region Jump operations - - /// - /// The call operation. - /// - private void CALL() - { - PUSH((ushort)(PC + 2)); - PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); - } - - /// - /// The jump operation. - /// - private void JP() - { - PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); - } - - /// - /// The jump relative operation. - /// - private void JR() - { - PC = (ushort)(PC + (sbyte)memory.Read(PC) + 1); - } - - /// - /// Jump relative if the passed condition flag ANDed with the flag - /// register equals the passed check value. - /// - /// The condition flag. - /// The check value. - private void JR_COND(Z80Flags cond, Z80Flags val) - { - if ((F & cond) == val) - { - clock.Add(12); - JR(); - } - else - { - clock.Add(7); - PC++; - } - } - - /// - /// Jump if the passed condition flag ANDed with the flag - /// register equals the passed check value. - /// - /// The condition flag. - /// The check value. - private void JP_COND(Z80Flags cond, Z80Flags val) - { - clock.Add(10); - - if ((F & cond) == val) - { - JP(); - } - else - { - PC+=2; - } - } - - /// - /// Call if the passed condition flag ANDed with the flag - /// register equals the passed check value. - /// - /// The condition flag. - /// The check value. - private void CALL_COND(Z80Flags cond, Z80Flags val) - { - if ((F & cond) == val) - { - clock.Add(17); - CALL(); - } - else - { - clock.Add(10); - PC+=2; - } - } - - /// - /// Return if the passed condition flag ANDed with the flag - /// register equals the passed check value. - /// - /// The condition flag. - /// The check value. - private void RET_COND(Z80Flags cond, Z80Flags val) - { - if ((F & cond) == val) - { - clock.Add(11); - PC = POP(); - } - else - { - clock.Add(5); - } - } - - /// - /// Reset the PC to an address - /// register equals the passed check value. - /// - /// The address. - private void RST(ushort addr) - { - clock.Add(11); - PUSH(PC); - PC = addr; - } - - #endregion - } -} diff --git a/Noddybox.Emulation.EightBit/Binary.cs b/Noddybox.Emulation.EightBit/Binary.cs deleted file mode 100644 index 0b1928b..0000000 --- a/Noddybox.Emulation.EightBit/Binary.cs +++ /dev/null @@ -1,63 +0,0 @@ -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 helpers for shifting smaller values around without casts all over the shop. - /// - public static class Binary - { - /// - /// Shift 8-bits to the left. - /// - /// The byte. - /// How many bits to shift. - /// The shifted value. - public static byte ShiftLeft(byte b, int shift) - { - return (byte)((b << shift) & 0xff); - } - - /// - /// Shift 8-bits to the right. - /// - /// The byte. - /// How many bits to shift. - /// The shifted value. - public static byte ShiftRight(byte b, int shift) - { - return (byte)((b >> shift) & 0xff); - } - - /// - /// Shift 16-bits to the left. - /// - /// The word. - /// How many bits to shift. - /// The shifted value. - public static ushort ShiftLeft(ushort w, int shift) - { - return (ushort)((w << shift) & 0xffff); - } - - /// - /// Shift 16-bits to the right. - /// - /// The word. - /// How many bits to shift. - /// The shifted value. - public static ushort ShiftRight(ushort w, int shift) - { - return (ushort)((w >> shift) & 0xffff); - } - } -} diff --git a/Noddybox.Emulation.EightBit/ICpu.cs b/Noddybox.Emulation.EightBit/ICpu.cs deleted file mode 100644 index dc2f811..0000000 --- a/Noddybox.Emulation.EightBit/ICpu.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -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 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 deleted file mode 100644 index b8d234a..0000000 --- a/Noddybox.Emulation.EightBit/IDevice.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -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 an interface for devices for 8-bit processers which used special commands to access - /// devices rather than using memory-mapped IO, for example the Z80. - /// - public interface IDevice - { - /// - /// Read from a device. - /// - /// The address of the device. - /// The byte returned from the device. - byte Read(ushort device); - - /// - /// Write to a device. - /// - /// The address of the device. - /// The value to write to the device. - void Write(ushort device, byte value); - } -} diff --git a/Noddybox.Emulation.EightBit/IMemory.cs b/Noddybox.Emulation.EightBit/IMemory.cs deleted file mode 100644 index 2aa63d9..0000000 --- a/Noddybox.Emulation.EightBit/IMemory.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -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 an interface for memory. - /// - public interface IMemory - { - /// - /// Reads a byte at a given address. - /// - /// The address to read. - /// The value at that address. - byte Read(ushort address); - - /// - /// Writes a byte at a given address. - /// - /// The address to write to. - /// The value to write. - void Write(ushort address, byte value); - } -} diff --git a/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj b/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj deleted file mode 100644 index 2136f3c..0000000 --- a/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - Debug - AnyCPU - 10.0.20506 - 2.0 - {ADC7A871-4DED-4A92-A447-2D784AB60FAF} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Noddybox.Emulation.EightBit - Noddybox.Emulation.EightBit - 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 - - - - - - - - - - - - - - - - - - - - {A2478066-4DFD-4042-BF98-963922DC97F8} - Noddybox.Emulation - - - - - - - \ No newline at end of file diff --git a/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs b/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs deleted file mode 100644 index a0de499..0000000 --- a/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -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")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Noddybox.Emulation.EightBit")] -[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("c8c4f2cb-4b04-48a5-9add-a89b3995e00f")] - -// 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/Register16.cs b/Noddybox.Emulation.EightBit/Register16.cs deleted file mode 100644 index 06c9c01..0000000 --- a/Noddybox.Emulation.EightBit/Register16.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -using System; -using System.Runtime.InteropServices; - -namespace Noddybox.Emulation.EightBit -{ - /// - /// Provides a common 8-bit register pattern, which is two 8-bit registers rolled into one. - /// While this could be done at runtime using this - /// method was chosen for speed reasons; interfaces cannot define fields, which is sensible - /// enoough, but accessing fields directly would allow ref variables to be used with this type's - /// fields. - /// - [StructLayout(LayoutKind.Explicit)] - public struct Register16 - { -#if TARGET_IS_BIGENDIAN - - /// - /// The 16-bit register. - /// - [FieldOffset(0)] - public ushort reg; - - /// - /// The high 8-bits of the register. - /// - [FieldOffset(0)] - public byte high; - - /// - /// The low 8-bits of the register. - /// - [FieldOffset(1)] - public byte low; - -#else - - /// - /// The 16-bit register. - /// - [FieldOffset(0)] - public ushort reg; - - /// - /// The low 8-bits of the register. - /// - [FieldOffset(0)] - public byte low; - - /// - /// The high 8-bits of the register. - /// - [FieldOffset(1)] - public byte high; - -#endif - - /// - /// Public constructor. This is provided to stop the compiler complaining when you use the struct as it - /// doesn't realise that setting will also set and . - /// - /// The 16-bit value to assign. - public Register16(ushort val) - { - high = 0; - low = 0; - reg = val; - } - - /// - /// Used to verify the compile-time setting at runtime. - /// - public static void Verify() - { - Register16 r = new Register16(0); - - r.reg = 0x1234; - - if (r.low != 0x24 || r.high != 0x12) - { - throw new Exception("Compile time endian setting incorrect"); - } - } - } -} diff --git a/Noddybox.Emulation.Phone.sln b/Noddybox.Emulation.Phone.sln new file mode 100644 index 0000000..dce912f --- /dev/null +++ b/Noddybox.Emulation.Phone.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 Express for Windows Phone +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation", "WindowsPhone\Noddybox.Emulation\Noddybox.Emulation.csproj", "{A2478066-4DFD-4042-BF98-963922DC97F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit", "WindowsPhone\Noddybox.Emulation.EightBit\Noddybox.Emulation.EightBit.csproj", "{ADC7A871-4DED-4A92-A447-2D784AB60FAF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit.Z80", "WindowsPhone\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 + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A2478066-4DFD-4042-BF98-963922DC97F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2478066-4DFD-4042-BF98-963922DC97F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2478066-4DFD-4042-BF98-963922DC97F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2478066-4DFD-4042-BF98-963922DC97F8}.Release|Any CPU.Build.0 = Release|Any CPU + {ADC7A871-4DED-4A92-A447-2D784AB60FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {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 + EndGlobalSection +EndGlobal diff --git a/Noddybox.Emulation.Phone.suo b/Noddybox.Emulation.Phone.suo new file mode 100644 index 0000000..0e0dc15 Binary files /dev/null and b/Noddybox.Emulation.Phone.suo differ diff --git a/Noddybox.Emulation.sln b/Noddybox.Emulation.sln deleted file mode 100644 index 7578ca2..0000000 --- a/Noddybox.Emulation.sln +++ /dev/null @@ -1,32 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 Express for Windows Phone -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation", "Noddybox.Emulation\Noddybox.Emulation.csproj", "{A2478066-4DFD-4042-BF98-963922DC97F8}" -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 - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A2478066-4DFD-4042-BF98-963922DC97F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2478066-4DFD-4042-BF98-963922DC97F8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2478066-4DFD-4042-BF98-963922DC97F8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2478066-4DFD-4042-BF98-963922DC97F8}.Release|Any CPU.Build.0 = Release|Any CPU - {ADC7A871-4DED-4A92-A447-2D784AB60FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {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 - EndGlobalSection -EndGlobal diff --git a/Noddybox.Emulation.suo b/Noddybox.Emulation.suo deleted file mode 100644 index e96b21c..0000000 Binary files a/Noddybox.Emulation.suo and /dev/null differ diff --git a/Noddybox.Emulation/Clock.cs b/Noddybox.Emulation/Clock.cs deleted file mode 100644 index 0b733cb..0000000 --- a/Noddybox.Emulation/Clock.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2012 Ian Cowburn -// -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 -{ - /// - /// Provides a basic clock implementation that is geared towards the VBL. - /// - public class Clock - { - #region Private fields - - private uint perSecond; - private uint perFrame; - private uint perLine; - private uint frameCount; - - #endregion - - #region Public properties - - /// - /// Returns true if the frame has finished. - /// - public bool FrameDone - { - get - { - return frameCount > perFrame; - } - } - - /// - /// Returns the current raster line. - /// - public uint RasterLine - { - get - { - return frameCount / perLine; - } - } - - #endregion - - #region Public members - - /// - /// Starts a new frame. - /// - public void StartFrame() - { - if (FrameDone) - { - frameCount -= perFrame; - } - } - - /// - /// Adds a number of ticks to the clock. - /// - /// The ticks to add. - public void Add(uint ticks) - { - frameCount += ticks; - } - - #endregion - - #region Constructors - - /// - /// Defines a clock. - /// - /// The number of ticks per second. - /// The number of frames per second. - public Clock(uint ticksPerSecond, uint framesPerSecond) - { - this.perSecond = ticksPerSecond; - this.perFrame = ticksPerSecond / framesPerSecond; - this.perLine = 1; - this.frameCount = 0; - } - - /// - /// Defines a clock. - /// - /// The number of ticks per second. - /// The number of frames per second. - /// The number of clock ticks per raster line. - public Clock(uint ticksPerSecond, uint framesPerSecond, uint ticksPerLine) - { - this.perSecond = ticksPerSecond; - this.perFrame = ticksPerSecond / framesPerSecond; - this.perLine = ticksPerLine; - this.frameCount = 0; - } - - #endregion - } -} diff --git a/Noddybox.Emulation/Noddybox.Emulation.csproj b/Noddybox.Emulation/Noddybox.Emulation.csproj deleted file mode 100644 index 040aa44..0000000 --- a/Noddybox.Emulation/Noddybox.Emulation.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - Debug - AnyCPU - 10.0.20506 - 2.0 - {A2478066-4DFD-4042-BF98-963922DC97F8} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Noddybox.Emulation - Noddybox.Emulation - 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 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Noddybox.Emulation/Noddybox.Emulation.suo b/Noddybox.Emulation/Noddybox.Emulation.suo deleted file mode 100644 index 0f14302..0000000 Binary files a/Noddybox.Emulation/Noddybox.Emulation.suo and /dev/null differ diff --git a/Noddybox.Emulation/Properties/AssemblyInfo.cs b/Noddybox.Emulation/Properties/AssemblyInfo.cs deleted file mode 100644 index d5a5343..0000000 --- a/Noddybox.Emulation/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -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")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Noddybox.Emulation")] -[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("9fc20d24-5257-4661-8f14-6ce15dff1ac8")] - -// 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/WindowsPhone/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj b/WindowsPhone/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj new file mode 100644 index 0000000..1e0579f --- /dev/null +++ b/WindowsPhone/Noddybox.Emulation.EightBit.Z80/Noddybox.Emulation.EightBit.Z80.csproj @@ -0,0 +1,80 @@ + + + + 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 + + + + + + + + + + + + Z80Cpu.cs + + + Z80CpuBaseOpcodes.cs + + + + + + {ADC7A871-4DED-4A92-A447-2D784AB60FAF} + Noddybox.Emulation.EightBit + + + {A2478066-4DFD-4042-BF98-963922DC97F8} + Noddybox.Emulation + + + + + + + \ No newline at end of file diff --git a/WindowsPhone/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs b/WindowsPhone/Noddybox.Emulation.EightBit.Z80/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..52b6054 --- /dev/null +++ b/WindowsPhone/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/WindowsPhone/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj b/WindowsPhone/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj new file mode 100644 index 0000000..8d37cd9 --- /dev/null +++ b/WindowsPhone/Noddybox.Emulation.EightBit/Noddybox.Emulation.EightBit.csproj @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {ADC7A871-4DED-4A92-A447-2D784AB60FAF} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Noddybox.Emulation.EightBit + Noddybox.Emulation.EightBit + 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 + + + + + + + + + + + + Binary.cs + + + ICpu.cs + + + IDevice.cs + + + IMemory.cs + + + Register16.cs + + + + + + {A2478066-4DFD-4042-BF98-963922DC97F8} + Noddybox.Emulation + + + + + + + \ No newline at end of file diff --git a/WindowsPhone/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs b/WindowsPhone/Noddybox.Emulation.EightBit/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a0de499 --- /dev/null +++ b/WindowsPhone/Noddybox.Emulation.EightBit/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")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Noddybox.Emulation.EightBit")] +[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("c8c4f2cb-4b04-48a5-9add-a89b3995e00f")] + +// 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/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.csproj b/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.csproj new file mode 100644 index 0000000..c245f3b --- /dev/null +++ b/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {A2478066-4DFD-4042-BF98-963922DC97F8} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Noddybox.Emulation + Noddybox.Emulation + 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 + + + + + + + + + + + + Clock.cs + + + + + + + + \ No newline at end of file diff --git a/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.suo b/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.suo new file mode 100644 index 0000000..0f14302 Binary files /dev/null and b/WindowsPhone/Noddybox.Emulation/Noddybox.Emulation.suo differ diff --git a/WindowsPhone/Noddybox.Emulation/Properties/AssemblyInfo.cs b/WindowsPhone/Noddybox.Emulation/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d5a5343 --- /dev/null +++ b/WindowsPhone/Noddybox.Emulation/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")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Noddybox.Emulation")] +[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("9fc20d24-5257-4661-8f14-6ce15dff1ac8")] + +// 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/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs new file mode 100644 index 0000000..5c40854 --- /dev/null +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs @@ -0,0 +1,226 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +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]; + private Z80Flags[] H35table = new Z80Flags[256]; + + // Machine accessors + // + private IMemory memory; + private IDevice device; + private Clock clock; + + // Main registers + // + private byte A; + private Z80Flags F; + private Register16 BC = new Register16(0); + private Register16 DE = new Register16(0); + private Register16 HL = new Register16(0); + private Register16 IX = new Register16(0); + private Register16 IY = new Register16(0); + private ushort SP; + private ushort PC; + + // Alternate registers + // + private Register16 AF_ = new Register16(0); + private Register16 BC_ = new Register16(0); + private Register16 DE_ = new Register16(0); + private Register16 HL_ = new Register16(0); + + // Auxilliary registers and flags + // + private byte I; + private byte R; + private bool IFF1; + private bool IFF2; + private int IM; + private bool HALT; + + #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() + { + PC = 0; + A = 0xff; + F = (Z80Flags)0xff; + + BC.reg = 0xffff; + DE.reg = 0xffff; + HL.reg = 0xffff; + AF_.reg = 0xffff; + BC_.reg = 0xffff; + DE_.reg = 0xffff; + HL_.reg = 0xffff; + + IX.reg = 0xffff; + IY.reg = 0xffff; + + SP = 0xffff; + + IFF1 = false; + IFF2 = false; + IM = 0; + I = 0; + R = 0; + HALT = false; + } + + public void Step() + { + // TODO: Single step. + } + + public void Run() + { + while(!clock.FrameDone) + { + Step(); + } + } + + public void MaskableInterrupt(byte value) + { + clock.Add(2); + + // TODO: INT + } + + public void NonMaskableInterrupt(byte value) + { + clock.Add(2); + + // TODO: NMI + } + + #endregion + + #region Constructors + + public Z80Cpu() + { + // Verify runtime + // + Register16.Verify(); + + // Setup lookup tables + // + for(int f = 0; f < 256; f++) + { + Z80Flags p = Z80Flags.None; + Z80Flags z = Z80Flags.None; + Z80Flags s = Z80Flags.None; + Z80Flags h3 = Z80Flags.None; + Z80Flags h5 = Z80Flags.None; + + int parity = 0; + + for(int b=0; b < 8; b++) + { + if ((f & (1< + /// Set a flag in the status register. + /// + /// The flag. + private void SetFlag(Z80Flags flag) + { + F |= flag; + } + + /// + /// Clear a flag in the status register. + /// + /// The flag. + private void ClearFlag(Z80Flags flag) + { + F &= ~flag; + } + + #endregion + + #region Stack commands + + /// + /// Push a value on the stack. + /// + /// The value. + private void PUSH(ushort val) + { + memory.Write(--SP, (byte)(val & 0xff)); + memory.Write(--SP, (byte)(Binary.ShiftRight(val, 8) & 0xff)); + } + + /// + /// Pop a value from the stack. + /// + /// + private ushort POP() + { + SP = (ushort)((SP + 2) & 0xffff); + return (ushort)(memory.Read((ushort)(SP-2)) | + (memory.Read((ushort)(SP - 1)) >> 8)); + } + + #endregion + + #region ALU arithmetic and comparison + + /// + /// Add an 8-bit value to the accumulator without carry. + /// + /// The vakue. + private void Add8(byte b) + { + int w = A + b; + + F = SZtable[w] | H35table[w & 0xff]; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Add an 8-bit value to the accumulator with carry. + /// + /// The vakue. + private void Adc8(byte b) + { + int w = A + b + (int)(F & Z80Flags.Carry); + + F = SZtable[w] | H35table[w & 0xff]; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Subtract an 8-bit value from the accumulator without carry. + /// + /// The vakue. + private void Sub8(byte b) + { + int w = A - b; + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Compare an 8-bit value with the accumulator. + /// + /// The vakue. + private void Cmp8(byte b) + { + int w = A - b; + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + } + + /// + /// Subtract an 8-bit value from the accumulator with carry. + /// + /// The vakue. + private void Sbc8(byte b) + { + int w = A - b - (int)(F & Z80Flags.Carry); + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Add a 16-bit value to a register without carry. + /// + /// The vakue. + private void Add16(ref ushort reg, ushort b) + { + int w = reg + b; + + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + + if (w > 0xffff) + { + F |= Z80Flags.Carry; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + /// + /// Add a 16-bit value to a register with carry. + /// + /// The vakue. + private void Adc16(ref ushort reg, ushort b) + { + int w = reg + b + (int)(F & Z80Flags.Carry); + + F = Z80Flags.None; + + if ((w & 0xffff) == 0) + { + F |= Z80Flags.Zero; + } + + if ((w & 0x8000) == 0x8000) + { + F |= Z80Flags.Sign; + } + + if (w > 0xffff) + { + F |= Z80Flags.Carry; + } + + if (((b ^ reg ^ 0x8000) & ((reg ^ w) & 0x8000)) == 0x8000) + { + F |= Z80Flags.PV; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + + /// + /// Subtract a 16-bit value from a register with carry. + /// + /// The vakue. + private void Sbc16(ref ushort reg, ushort b) + { + int w = reg - b - (int)(F & Z80Flags.Carry); + + F = Z80Flags.Neg; + + if (w < 0) + { + w += 0x10000; + F |= Z80Flags.Carry; + } + + if ((w & 0xffff) == 0) + { + F |= Z80Flags.Zero; + } + + if ((w & 0x8000) == 0x8000) + { + F |= Z80Flags.Sign; + } + + if (((b ^ reg) & ((reg ^ w) & 0x8000)) == 0x8000) + { + F |= Z80Flags.PV; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + /// + /// Increment an 8-bit register. + /// + /// The register to increment. + void Inc8(ref byte reg) + { + reg++; + + F = Z80Flags.Carry; + + if (reg == 0x80) + { + F |= Z80Flags.PV; + } + + if ((reg & 0x0f) == 0x00) + { + F |= Z80Flags.HalfCarry; + } + } + + /// + /// Decrement an 8-bit register. + /// + /// The register to decrement. + void Dec8(ref byte reg) + { + reg--; + + F = Z80Flags.Carry | Z80Flags.Neg; + + if (reg == 0x7f) + { + F |= Z80Flags.PV; + } + + if ((reg & 0x0f) == 0x0f) + { + F |= Z80Flags.HalfCarry; + } + } + + #endregion + + #region ALU rotate and shift operations + + /// + /// Do RRCA. + /// + private void RRCA() + { + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + F |= (Z80Flags)(A & 1); + A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(A, 7)); + F |= H35table[A]; + } + + /// + /// Do RRA. + /// + private void RRA() + { + byte carry = (byte)(F & Z80Flags.Carry); + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + F |= (Z80Flags)(A & 1); + A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(carry, 7)); + F |= H35table[A]; + } + + /// + /// Do RRC. + /// + /// The register to operate on. + private void RRC(ref byte reg) + { + F = (Z80Flags)(reg & (int)Z80Flags.Carry); + reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(reg, 7)); + F |= PSZtable[reg] | H35table[reg]; + } + + /// + /// Do RR. + /// + /// The register to operate on. + private void RR(ref byte reg) + { + byte carry = (byte)(F & Z80Flags.Carry); + F = (Z80Flags)(reg & (int)Z80Flags.Carry); + reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(carry, 7)); + F |= PSZtable[reg] | H35table[reg]; + } + + /// + /// Do RLCA. + /// + private void RLCA() + { + F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + | (Z80Flags)Binary.ShiftRight(A, 7); + + A = (byte)(Binary.ShiftLeft(A, 1) | Binary.ShiftRight(A, 7)); + + F |= H35table[A]; + } + + /// + /// Do RLA. + /// + private void RLA() + { + byte carry = (byte)(F & Z80Flags.Carry); + F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + | (Z80Flags)Binary.ShiftRight(A, 7); + A = (byte)(Binary.ShiftRight(A, 1) | carry); + F |= H35table[A]; + } + + /// + /// Do RLC. + /// + /// The register to operate on. + private void RLC(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftLeft(reg, 1) | carry); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do RL. + /// + /// The register to operate on. + private void RL(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftLeft(reg, 1) | (int)(F & Z80Flags.Carry)); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SRL. + /// + /// The register to operate on. + private void SRL(ref byte reg) + { + byte carry = (byte)(reg & 1); + reg = Binary.ShiftLeft(reg, 1); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SRA. + /// + /// The register to operate on. + private void SRA(ref byte reg) + { + byte carry = (byte)(reg & 1); + reg = (byte)(Binary.ShiftLeft(reg, 1) | (reg & 0x80)); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SLL. + /// + /// The register to operate on. + private void SLL(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftRight(reg, 1) | 0x01); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SLA. + /// + /// The register to operate on. + private void SLA(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = Binary.ShiftRight(reg, 1); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + #endregion + + #region ALU boolean operations + + /// + /// AND a value with the accumulator. + /// + /// The value. + void AND(byte val) + { + A &= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// OR a value with the accumulator. + /// + /// The value. + void OR(byte val) + { + A |= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// XOR a value with the accumulator. + /// + /// The value. + void XOR(byte val) + { + A ^= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// Perform the BIT operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT(ref byte reg, int bit) + { + F &= Z80Flags.Carry; + F |= Z80Flags.HalfCarry; + + if ((reg & (1 << bit)) != 0) + { + if (bit == 7 && (reg & (int)Z80Flags.Sign) != 0) + { + F |= Z80Flags.Sign; + } + + if (bit == 5 && (reg & (int)Z80Flags.Hidden5) != 0) + { + F |= Z80Flags.Hidden5; + } + + if (bit == 3 && (reg & (int)Z80Flags.Hidden3) != 0) + { + F |= Z80Flags.Hidden3; + } + } + else + { + F |= Z80Flags.Zero | Z80Flags.PV; + } + } + + /// + /// Perform the bit set operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT_SET(ref byte reg, int bit) + { + reg |= (byte)(1 << bit); + } + + /// + /// Perform the bit clear operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT_RES(ref byte reg, int bit) + { + reg &= (byte)~(1 << bit); + } + + #endregion + + #region Jump operations + + /// + /// The call operation. + /// + private void CALL() + { + PUSH((ushort)(PC + 2)); + PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + } + + /// + /// The jump operation. + /// + private void JP() + { + PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + } + + /// + /// The jump relative operation. + /// + private void JR() + { + PC = (ushort)(PC + (sbyte)memory.Read(PC) + 1); + } + + /// + /// Jump relative if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void JR_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(12); + JR(); + } + else + { + clock.Add(7); + PC++; + } + } + + /// + /// Jump if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void JP_COND(Z80Flags cond, Z80Flags val) + { + clock.Add(10); + + if ((F & cond) == val) + { + JP(); + } + else + { + PC+=2; + } + } + + /// + /// Call if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void CALL_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(17); + CALL(); + } + else + { + clock.Add(10); + PC+=2; + } + } + + /// + /// Return if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void RET_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(11); + PC = POP(); + } + else + { + clock.Add(5); + } + } + + /// + /// Reset the PC to an address + /// register equals the passed check value. + /// + /// The address. + private void RST(ushort addr) + { + clock.Add(11); + PUSH(PC); + PC = addr; + } + + #endregion + } +} diff --git a/src/Noddybox.Emulation.EightBit/Binary.cs b/src/Noddybox.Emulation.EightBit/Binary.cs new file mode 100644 index 0000000..0b1928b --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/Binary.cs @@ -0,0 +1,63 @@ +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 helpers for shifting smaller values around without casts all over the shop. + /// + public static class Binary + { + /// + /// Shift 8-bits to the left. + /// + /// The byte. + /// How many bits to shift. + /// The shifted value. + public static byte ShiftLeft(byte b, int shift) + { + return (byte)((b << shift) & 0xff); + } + + /// + /// Shift 8-bits to the right. + /// + /// The byte. + /// How many bits to shift. + /// The shifted value. + public static byte ShiftRight(byte b, int shift) + { + return (byte)((b >> shift) & 0xff); + } + + /// + /// Shift 16-bits to the left. + /// + /// The word. + /// How many bits to shift. + /// The shifted value. + public static ushort ShiftLeft(ushort w, int shift) + { + return (ushort)((w << shift) & 0xffff); + } + + /// + /// Shift 16-bits to the right. + /// + /// The word. + /// How many bits to shift. + /// The shifted value. + public static ushort ShiftRight(ushort w, int shift) + { + return (ushort)((w >> shift) & 0xffff); + } + } +} diff --git a/src/Noddybox.Emulation.EightBit/ICpu.cs b/src/Noddybox.Emulation.EightBit/ICpu.cs new file mode 100644 index 0000000..dc2f811 --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/ICpu.cs @@ -0,0 +1,57 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +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 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/src/Noddybox.Emulation.EightBit/IDevice.cs b/src/Noddybox.Emulation.EightBit/IDevice.cs new file mode 100644 index 0000000..b8d234a --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/IDevice.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +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 an interface for devices for 8-bit processers which used special commands to access + /// devices rather than using memory-mapped IO, for example the Z80. + /// + public interface IDevice + { + /// + /// Read from a device. + /// + /// The address of the device. + /// The byte returned from the device. + byte Read(ushort device); + + /// + /// Write to a device. + /// + /// The address of the device. + /// The value to write to the device. + void Write(ushort device, byte value); + } +} diff --git a/src/Noddybox.Emulation.EightBit/IMemory.cs b/src/Noddybox.Emulation.EightBit/IMemory.cs new file mode 100644 index 0000000..2aa63d9 --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/IMemory.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +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 an interface for memory. + /// + public interface IMemory + { + /// + /// Reads a byte at a given address. + /// + /// The address to read. + /// The value at that address. + byte Read(ushort address); + + /// + /// Writes a byte at a given address. + /// + /// The address to write to. + /// The value to write. + void Write(ushort address, byte value); + } +} diff --git a/src/Noddybox.Emulation.EightBit/Register16.cs b/src/Noddybox.Emulation.EightBit/Register16.cs new file mode 100644 index 0000000..06c9c01 --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/Register16.cs @@ -0,0 +1,88 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +using System; +using System.Runtime.InteropServices; + +namespace Noddybox.Emulation.EightBit +{ + /// + /// Provides a common 8-bit register pattern, which is two 8-bit registers rolled into one. + /// While this could be done at runtime using this + /// method was chosen for speed reasons; interfaces cannot define fields, which is sensible + /// enoough, but accessing fields directly would allow ref variables to be used with this type's + /// fields. + /// + [StructLayout(LayoutKind.Explicit)] + public struct Register16 + { +#if TARGET_IS_BIGENDIAN + + /// + /// The 16-bit register. + /// + [FieldOffset(0)] + public ushort reg; + + /// + /// The high 8-bits of the register. + /// + [FieldOffset(0)] + public byte high; + + /// + /// The low 8-bits of the register. + /// + [FieldOffset(1)] + public byte low; + +#else + + /// + /// The 16-bit register. + /// + [FieldOffset(0)] + public ushort reg; + + /// + /// The low 8-bits of the register. + /// + [FieldOffset(0)] + public byte low; + + /// + /// The high 8-bits of the register. + /// + [FieldOffset(1)] + public byte high; + +#endif + + /// + /// Public constructor. This is provided to stop the compiler complaining when you use the struct as it + /// doesn't realise that setting will also set and . + /// + /// The 16-bit value to assign. + public Register16(ushort val) + { + high = 0; + low = 0; + reg = val; + } + + /// + /// Used to verify the compile-time setting at runtime. + /// + public static void Verify() + { + Register16 r = new Register16(0); + + r.reg = 0x1234; + + if (r.low != 0x24 || r.high != 0x12) + { + throw new Exception("Compile time endian setting incorrect"); + } + } + } +} diff --git a/src/Noddybox.Emulation/Clock.cs b/src/Noddybox.Emulation/Clock.cs new file mode 100644 index 0000000..0b733cb --- /dev/null +++ b/src/Noddybox.Emulation/Clock.cs @@ -0,0 +1,112 @@ +// +// Copyright (c) 2012 Ian Cowburn +// +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 +{ + /// + /// Provides a basic clock implementation that is geared towards the VBL. + /// + public class Clock + { + #region Private fields + + private uint perSecond; + private uint perFrame; + private uint perLine; + private uint frameCount; + + #endregion + + #region Public properties + + /// + /// Returns true if the frame has finished. + /// + public bool FrameDone + { + get + { + return frameCount > perFrame; + } + } + + /// + /// Returns the current raster line. + /// + public uint RasterLine + { + get + { + return frameCount / perLine; + } + } + + #endregion + + #region Public members + + /// + /// Starts a new frame. + /// + public void StartFrame() + { + if (FrameDone) + { + frameCount -= perFrame; + } + } + + /// + /// Adds a number of ticks to the clock. + /// + /// The ticks to add. + public void Add(uint ticks) + { + frameCount += ticks; + } + + #endregion + + #region Constructors + + /// + /// Defines a clock. + /// + /// The number of ticks per second. + /// The number of frames per second. + public Clock(uint ticksPerSecond, uint framesPerSecond) + { + this.perSecond = ticksPerSecond; + this.perFrame = ticksPerSecond / framesPerSecond; + this.perLine = 1; + this.frameCount = 0; + } + + /// + /// Defines a clock. + /// + /// The number of ticks per second. + /// The number of frames per second. + /// The number of clock ticks per raster line. + public Clock(uint ticksPerSecond, uint framesPerSecond, uint ticksPerLine) + { + this.perSecond = ticksPerSecond; + this.perFrame = ticksPerSecond / framesPerSecond; + this.perLine = ticksPerLine; + this.frameCount = 0; + } + + #endregion + } +} -- cgit v1.2.3