From a00e548533eed5b1aead479e70a117eb05458a5f Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 8 Jan 2012 22:37:21 +0000 Subject: Added rest of ED opcodes and GPL fixed headers. --- src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs | 104 +++++- .../Z80CpuBaseOpcodes.cs | 2 +- .../Z80CpuDecodeByte.cs | 2 +- .../Z80CpuDecodeCB.cs | 2 +- .../Z80CpuDecodeED.cs | 399 ++++++++++++++++++++- .../Z80CpuDecodeShiftedCB.cs | 2 +- .../Z80CpuEventArgs.cs | 87 +++++ src/Noddybox.Emulation.EightBit.Z80/Z80Flags.cs | 83 +++++ src/Noddybox.Emulation.EightBit/Binary.cs | 2 +- src/Noddybox.Emulation.EightBit/ICpu.cs | 2 +- src/Noddybox.Emulation.EightBit/IDevice.cs | 2 +- src/Noddybox.Emulation.EightBit/IMemory.cs | 2 +- src/Noddybox.Emulation.EightBit/Register16.cs | 2 +- src/Noddybox.Emulation/Clock.cs | 2 +- 14 files changed, 667 insertions(+), 26 deletions(-) create mode 100644 src/Noddybox.Emulation.EightBit.Z80/Z80CpuEventArgs.cs create mode 100644 src/Noddybox.Emulation.EightBit.Z80/Z80Flags.cs (limited to 'src') diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs index 78f0bfa..f937ea9 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80Cpu.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // @@ -26,20 +26,11 @@ namespace Noddybox.Emulation.EightBit.Z80 { #region Private types - [Flags] - private enum Z80Flags + private enum EventType { - None = 0x00, - Carry = 0x01, - Neg = 0x02, - PV = 0x04, - Hidden3 = 0x08, - HalfCarry = 0x10, - Hidden5 = 0x20, - Zero = 0x40, - Sign = 0x80, - Hidden = Hidden3 | Hidden5 - }; + HALT, + EDHook + } #endregion @@ -295,5 +286,90 @@ namespace Noddybox.Emulation.EightBit.Z80 } #endregion + + #region Events + + /// + /// The CPU has been halted. + /// + public event EventHandler HaltEvent; + + /// + /// A no-operation ED opcode has been executed. Useful for placing + /// hooks into the Z80 code. + /// + public event EventHandler EDNopEvent; + + /// + /// Called to raise + /// + /// The event arguments. + protected void OnHaltEvent(Z80CpuEventArgs e) + { + EventHandler handler = HaltEvent; + + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Called to raise + /// + /// The event arguments. + protected void OnEDNopEvent(Z80CpuEventArgs e) + { + EventHandler handler = EDNopEvent; + + if (handler != null) + { + handler(this, e); + } + } + + private void TriggerEvent(EventType type, byte opcode) + { + Z80CpuEventArgs e = new Z80CpuEventArgs + { + Opcode = opcode, + A = this.A, + F = this.F, + BC = this.BC, + DE = this.DE, + HL = this.HL, + SP = this.SP, + PC = this.PC, + AF_ = this.AF_, + BC_ = this.BC_, + DE_ = this.DE_, + HL_ = this.HL_ + }; + + switch(type) + { + case EventType.HALT: + OnHaltEvent(e); + break; + + case EventType.EDHook: + OnEDNopEvent(e); + break; + } + + A = e.A; + F = e.F; + BC = e.BC; + DE = e.DE; + HL = e.HL; + SP = e.SP; + PC = e.PC; + AF_ = e.AF_; + BC_ = e.BC_; + DE_ = e.DE_; + HL_ = e.HL_; + } + + #endregion } } diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs index 47f4d28..389ba41 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeByte.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeByte.cs index e03a3f3..f0256ba 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeByte.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeByte.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeCB.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeCB.cs index fc17936..5abf167 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeCB.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeCB.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeED.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeED.cs index d06ee3d..a6037f6 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeED.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeED.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // @@ -29,6 +29,7 @@ namespace Noddybox.Emulation.EightBit.Z80 { ushort addr; byte b; + Register16 tmp = new Register16(0); switch(opcode) { @@ -135,7 +136,401 @@ namespace Noddybox.Emulation.EightBit.Z80 device.Write(BC.reg, DE.high); break; - default: + case 0x52: // SBC HL,DE + clock.Add(15); + SBC(ref HL.reg, DE.reg); + break; + + case 0x53: // LD (nnnn),DE + clock.Add(20); + addr = FetchWord(); + memory.Write(addr++, DE.low); + memory.Write(addr, DE.high); + break; + + case 0x54: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x55: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x56: // IM 1 + clock.Add(8); + IM = 1; + break; + + case 0x57: // LD A,I + clock.Add(9); + A = (byte)I; + break; + + case 0x58: // IN E,(C) + clock.Add(12); + DE.low = device.Read(BC.reg); + F = Z80Flags.Carry | PSZtable[BC.low] | H35table[BC.low]; + break; + + case 0x59: // OUT (C),E + clock.Add(12); + device.Write(BC.reg, DE.low); + break; + + case 0x5a: // ADC HL, DE + clock.Add(15); + ADC16(ref HL.reg, DE.reg); + break; + + case 0x5b: // LD DE,(nnnn) + clock.Add(20); + addr = FetchWord(); + DE.low = memory.Read(addr++); + DE.high = memory.Read(addr); + break; + + case 0x5c: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x5d: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x5e: // IM 2 + clock.Add(8); + IM = 2; + break; + + case 0x5f: // LD A,R + clock.Add(9); + A = R; + break; + + case 0x60: // IN H,(C) + clock.Add(12); + HL.high = device.Read(BC.reg); + F = Z80Flags.Carry | PSZtable[DE.high] | H35table[DE.high]; + break; + + case 0x61: // OUT (C),H + clock.Add(12); + device.Write(BC.reg, HL.high); + break; + + case 0x62: // SBC HL,HL + clock.Add(15); + SBC(ref HL.reg, HL.reg); + break; + + case 0x63: // LD (nnnn),HL + clock.Add(20); + addr = FetchWord(); + memory.Write(addr++, HL.low); + memory.Write(addr, HL.high); + break; + + case 0x64: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x65: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x66: // IM 0 + clock.Add(8); + IM = 0; + break; + + case 0x67: // RRD + clock.Add(18); + b = memory.Read(HL.reg); + memory.Write(HL.reg, (byte)((b >> 4)|(A << 4))); + A = (byte)((A & 0xf0) | (b & 0x0f)); + F = Z80Flags.Carry | PSZtable[A] | H35table[A]; + break; + + case 0x68: // IN L,(C) + clock.Add(12); + HL.low = device.Read(BC.reg); + F = Z80Flags.Carry | PSZtable[BC.low] | H35table[BC.low]; + break; + + case 0x69: // OUT (C),L + clock.Add(12); + device.Write(BC.reg, HL.low); + break; + + case 0x6a: // ADC HL, HL + clock.Add(15); + ADC16(ref HL.reg, HL.reg); + break; + + case 0x6b: // LD HL,(nnnn) + clock.Add(20); + addr = FetchWord(); + HL.low = memory.Read(addr++); + HL.high = memory.Read(addr); + break; + + case 0x6c: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x6d: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x6e: // IM 0/1 + clock.Add(8); + IM = 0; + break; + + case 0x6f: // RLD + clock.Add(18); + b = memory.Read(HL.reg); + memory.Write(HL.reg, (byte)((b << 4)|(A & 0x0f))); + A = (byte)((A & 0xf0) | (b >> 4)); + F = Z80Flags.Carry | PSZtable[A] | H35table[A]; + break; + + case 0x70: // IN (C) + clock.Add(12); + b = device.Read(BC.reg); + F = Z80Flags.Carry | PSZtable[b] | H35table[b]; + break; + + case 0x71: // OUT (C) + clock.Add(12); + device.Write(BC.reg, 0); + break; + + case 0x72: // SBC HL,SP + clock.Add(15); + SBC(ref HL.reg, SP); + break; + + case 0x73: // LD (nnnn),SP + clock.Add(20); + addr = FetchWord(); + memory.Write(addr++, (byte)(SP & 0xff)); + memory.Write(addr, (byte)(SP >> 8)); + break; + + case 0x74: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x75: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x76: // IM 1 + clock.Add(8); + IM = 1; + break; + + case 0x77: // NOP + clock.Add(18); + TriggerEvent(EventType.EDHook, opcode); + break; + + case 0x78: // IN A,(C) + clock.Add(12); + A = device.Read(BC.reg); + F = Z80Flags.Carry | PSZtable[BC.low] | H35table[BC.low]; + break; + + case 0x79: // OUT (C),A + clock.Add(12); + device.Write(BC.reg, A); + break; + + case 0x7a: // ADC HL, SP + clock.Add(15); + ADC16(ref HL.reg, SP); + break; + + case 0x7b: // LD SP,(nnnn) + clock.Add(20); + addr = FetchWord(); + tmp.low = memory.Read(addr++); + tmp.high = memory.Read(addr); + SP = tmp.reg; + break; + + case 0x7c: // NEG + clock.Add(8); + b = A; + A = 0; + SUB8(b); + break; + + case 0x7d: // RETN + clock.Add(14); + IFF1 = IFF2; + PC = POP(); + break; + + case 0x7e: // IM 2 + clock.Add(8); + IM = 2; + break; + + case 0x7f: // NOP + clock.Add(8); + TriggerEvent(EventType.EDHook, opcode); + break; + + case 0xa0: // LDI + clock.Add(16); + LDI(); + break; + + case 0xa1: // CPI + clock.Add(16); + CPI(); + break; + + case 0xa2: // INI + clock.Add(16); + INI(); + break; + + case 0xa3: // OUTI + clock.Add(16); + OUTI(); + break; + + case 0xa8: // LDD + clock.Add(16); + LDD(); + break; + + case 0xa9: // CPD + clock.Add(16); + CPD(); + break; + + case 0xaa: // IND + clock.Add(16); + IND(); + break; + + case 0xab: // OUTD + clock.Add(16); + OUTD(); + break; + + case 0xb0: // LDIR + clock.Add(16); + LDI(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xb1: // CPIR + clock.Add(16); + CPI(); + if (BC.reg > 0 && (F & Z80Flags.Zero) == Z80Flags.None) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xb2: // INIR + clock.Add(16); + INI(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xb3: // OTIR + clock.Add(16); + OUTI(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xb8: // LDDR + clock.Add(16); + LDD(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xb9: // CPDR + clock.Add(16); + CPD(); + if (BC.reg > 0 && (F & Z80Flags.Zero) == Z80Flags.None) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xba: // INDR + clock.Add(16); + IND(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + case 0xbb: // OTDR + clock.Add(16); + OUTD(); + if (BC.reg > 0) + { + clock.Add(5); + PC -= 2; + } + break; + + default: // NOP + clock.Add(8); + TriggerEvent(EventType.EDHook, opcode); break; } } diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeShiftedCB.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeShiftedCB.cs index 80ce41d..4545fbc 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeShiftedCB.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuDecodeShiftedCB.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuEventArgs.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuEventArgs.cs new file mode 100644 index 0000000..fb0173a --- /dev/null +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuEventArgs.cs @@ -0,0 +1,87 @@ +// This file is part of the Noddybox.Emulation C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; + +namespace Noddybox.Emulation.EightBit.Z80 +{ + /// + /// Represents events from the Z80. + /// + public class Z80CpuEventArgs : EventArgs + { + /// + /// The opcode that was executed to trigger the event. + /// + public byte Opcode {get; set;} + + /// + /// The current state of the accumulator. + /// + public byte A {get; set;} + + /// + /// The current state of the flag register. + /// + public Z80Flags F {get; set;} + + /// + /// The current state of the BC register pair. + /// + public Register16 BC {get; set;} + + /// + /// The current state of the DE register pair. + /// + public Register16 DE {get; set;} + + /// + /// The current state of the HL register pair. + /// + public Register16 HL {get; set;} + + /// + /// The current state of the stack pointer. + /// + public ushort SP {get; set;} + + /// + /// The current state of the program counter. + /// + public ushort PC {get; set;} + + /// + /// The alternate AF' register. + /// + public Register16 AF_ {get; set;} + + /// + /// The alternate BC' register. + /// + public Register16 BC_ {get; set;} + + /// + /// The alternate DE' register. + /// + public Register16 DE_ {get; set;} + + /// + /// The alternate HL' register. + /// + public Register16 HL_ {get; set;} + } +} diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80Flags.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80Flags.cs new file mode 100644 index 0000000..edcd5f5 --- /dev/null +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80Flags.cs @@ -0,0 +1,83 @@ +// This file is part of the Noddybox.Emulation C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; + +namespace Noddybox.Emulation.EightBit.Z80 +{ + /// + /// Defines the bits in the Z80 flag register. + /// + [Flags] + public enum Z80Flags + { + /// + /// No flags set. + /// + None = 0x00, + + /// + /// The carry flag. + /// + Carry = 0x01, + + /// + /// The negative flag. + /// + Neg = 0x02, + + /// + /// The parity/overflow flag. + /// + PV = 0x04, + + /// + /// A hidden flag. Undocumented by Zilog, but affected by most operations. + /// + Hidden3 = 0x08, + + /// + /// The half-carry flag. + /// + HalfCarry = 0x10, + + /// + /// A hidden flag. Undocumented by Zilog, but affected by most operations. + /// + Hidden5 = 0x20, + + /// + /// The zero flag. + /// + Zero = 0x40, + + /// + /// The sign flag. + /// + Sign = 0x80, + + /// + /// A bitmask for all the hidden registers. + /// + Hidden = Hidden3 | Hidden5, + + /// + /// All bits set. + /// + All = 0xff + }; +} diff --git a/src/Noddybox.Emulation.EightBit/Binary.cs b/src/Noddybox.Emulation.EightBit/Binary.cs index eb03a8c..1c267e6 100644 --- a/src/Noddybox.Emulation.EightBit/Binary.cs +++ b/src/Noddybox.Emulation.EightBit/Binary.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) Ian Cowburn 2012 // diff --git a/src/Noddybox.Emulation.EightBit/ICpu.cs b/src/Noddybox.Emulation.EightBit/ICpu.cs index e06c624..9d1909c 100644 --- a/src/Noddybox.Emulation.EightBit/ICpu.cs +++ b/src/Noddybox.Emulation.EightBit/ICpu.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit/IDevice.cs b/src/Noddybox.Emulation.EightBit/IDevice.cs index 9ed2a92..3473898 100644 --- a/src/Noddybox.Emulation.EightBit/IDevice.cs +++ b/src/Noddybox.Emulation.EightBit/IDevice.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit/IMemory.cs b/src/Noddybox.Emulation.EightBit/IMemory.cs index 285a2aa..1d03ccd 100644 --- a/src/Noddybox.Emulation.EightBit/IMemory.cs +++ b/src/Noddybox.Emulation.EightBit/IMemory.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation.EightBit/Register16.cs b/src/Noddybox.Emulation.EightBit/Register16.cs index a64eaf4..10367cc 100644 --- a/src/Noddybox.Emulation.EightBit/Register16.cs +++ b/src/Noddybox.Emulation.EightBit/Register16.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // diff --git a/src/Noddybox.Emulation/Clock.cs b/src/Noddybox.Emulation/Clock.cs index b268a7e..72a2cc8 100644 --- a/src/Noddybox.Emulation/Clock.cs +++ b/src/Noddybox.Emulation/Clock.cs @@ -11,7 +11,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // -- cgit v1.2.3