//
// 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<