//
// 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 IRegister16 BC = Register16Factory.Create();
private IRegister16 DE = Register16Factory.Create();
private IRegister16 HL = Register16Factory.Create();
private IRegister16 IX = Register16Factory.Create();
private IRegister16 IY = Register16Factory.Create();
private ushort SP;
private ushort PC;
// Alternate registers
//
private IRegister16 AF_ = Register16Factory.Create();
private IRegister16 BC_ = Register16Factory.Create();
private IRegister16 DE_ = Register16Factory.Create();
private IRegister16 HL_ = Register16Factory.Create();
// 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.Value = 0xffff;
DE.Value = 0xffff;
HL.Value = 0xffff;
AF_.Value = 0xffff;
BC_.Value = 0xffff;
DE_.Value = 0xffff;
HL_.Value = 0xffff;
IX.Value = 0xffff;
IY.Value = 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()
{
// 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<