468 lines
9.5 KiB
C#
468 lines
9.5 KiB
C#
![]() |
using BizHawk.Common.NumberExtensions;
|
|||
|
using System;
|
|||
|
|
|||
|
namespace BizHawk.Emulation.Common.Components.LR35902
|
|||
|
{
|
|||
|
public partial class LR35902
|
|||
|
{
|
|||
|
public void Read_Func(ushort dest, ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
|
|||
|
}
|
|||
|
|
|||
|
// speical read for POP AF that always clears the lower 4 bits of F
|
|||
|
public void Read_Func_F(ushort dest, ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
Regs[dest] = (ushort)(ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8)) & 0xF0);
|
|||
|
}
|
|||
|
|
|||
|
public void Write_Func(ushort dest_l, ushort dest_h, ushort src)
|
|||
|
{
|
|||
|
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h]) << 8), (byte)Regs[src]);
|
|||
|
}
|
|||
|
|
|||
|
public void TR_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
Regs[dest] = Regs[src];
|
|||
|
}
|
|||
|
|
|||
|
public void ADD16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
|
|||
|
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
|
|||
|
|
|||
|
Reg16_d += Reg16_s;
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(16);
|
|||
|
|
|||
|
ushort ans_l = (ushort)(Reg16_d & 0xFF);
|
|||
|
ushort ans_h = (ushort)((Reg16_d & 0xFF00) >> 8);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest_l] | ((Regs[dest_h] & 0x0F) << 8);
|
|||
|
Reg16_s = Regs[src_l] | ((Regs[src_h] & 0x0F) << 8);
|
|||
|
|
|||
|
Reg16_d += Reg16_s;
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(12);
|
|||
|
FlagN = false;
|
|||
|
|
|||
|
Regs[dest_l] = ans_l;
|
|||
|
Regs[dest_h] = ans_h;
|
|||
|
}
|
|||
|
|
|||
|
public void ADD8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest];
|
|||
|
Reg16_d += Regs[src];
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest] & 0xF;
|
|||
|
Reg16_d += (Regs[src] & 0xF);
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
|
|||
|
FlagN = false;
|
|||
|
|
|||
|
Regs[dest] = ans;
|
|||
|
}
|
|||
|
|
|||
|
public void SUB8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest];
|
|||
|
Reg16_d -= Regs[src];
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest] & 0xF;
|
|||
|
Reg16_d -= (Regs[src] & 0xF);
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = true;
|
|||
|
|
|||
|
Regs[dest] = ans;
|
|||
|
}
|
|||
|
|
|||
|
public void BIT_Func(ushort bit, ushort src)
|
|||
|
{
|
|||
|
FlagZ = !Regs[src].Bit(bit);
|
|||
|
FlagH = true;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void SET_Func(ushort bit, ushort src)
|
|||
|
{
|
|||
|
Regs[src] |= (ushort)(1 << bit);
|
|||
|
}
|
|||
|
|
|||
|
public void RES_Func(ushort bit, ushort src)
|
|||
|
{
|
|||
|
Regs[src] &= (ushort)(0xFF - (1 << bit));
|
|||
|
}
|
|||
|
|
|||
|
public void ASGN_Func(ushort src, ushort val)
|
|||
|
{
|
|||
|
Regs[src] = val;
|
|||
|
}
|
|||
|
|
|||
|
public void SWAP_Func(ushort src)
|
|||
|
{
|
|||
|
ushort temp = (ushort)((Regs[src] << 4) & 0xF0);
|
|||
|
Regs[src] = (ushort)(temp | (Regs[src] >> 4));
|
|||
|
|
|||
|
FlagZ = Regs[src] == 0;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
FlagC = false;
|
|||
|
}
|
|||
|
|
|||
|
public void SLA_Func(ushort src)
|
|||
|
{
|
|||
|
FlagC = Regs[src].Bit(7);
|
|||
|
|
|||
|
Regs[src] = (ushort)((Regs[src] << 1) & 0xFF);
|
|||
|
|
|||
|
FlagZ = Regs[src] == 0;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void SRA_Func(ushort src)
|
|||
|
{
|
|||
|
FlagC = Regs[src].Bit(0);
|
|||
|
|
|||
|
ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation
|
|||
|
|
|||
|
Regs[src] = (ushort)((Regs[src] >> 1) | temp);
|
|||
|
|
|||
|
FlagZ = Regs[src] == 0;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void SRL_Func(ushort src)
|
|||
|
{
|
|||
|
FlagC = Regs[src].Bit(0) ? true : false;
|
|||
|
|
|||
|
Regs[src] = (ushort)(Regs[src] >> 1);
|
|||
|
|
|||
|
FlagZ = Regs[src] == 0;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void CPL_Func(ushort src)
|
|||
|
{
|
|||
|
Regs[src] = (ushort)((~Regs[src]) & 0xFF);
|
|||
|
|
|||
|
FlagH = true;
|
|||
|
FlagN = true;
|
|||
|
}
|
|||
|
|
|||
|
public void CCF_Func(ushort src)
|
|||
|
{
|
|||
|
FlagC = !FlagC;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void SCF_Func(ushort src)
|
|||
|
{
|
|||
|
FlagC = true;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void AND8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
Regs[dest] = (ushort)(Regs[dest] & Regs[src]);
|
|||
|
|
|||
|
FlagZ = Regs[dest] == 0;
|
|||
|
FlagC = false;
|
|||
|
FlagH = true;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void OR8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
Regs[dest] = (ushort)(Regs[dest] | Regs[src]);
|
|||
|
|
|||
|
FlagZ = Regs[dest] == 0;
|
|||
|
FlagC = false;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void XOR8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]);
|
|||
|
|
|||
|
FlagZ = Regs[dest] == 0;
|
|||
|
FlagC = false;
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void CP8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest];
|
|||
|
Reg16_d -= Regs[src];
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest] & 0xF;
|
|||
|
Reg16_d -= (Regs[src] & 0xF);
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
|
|||
|
FlagN = true;
|
|||
|
}
|
|||
|
|
|||
|
public void RRC_Func(ushort src)
|
|||
|
{
|
|||
|
bool imm = src == Aim;
|
|||
|
if (imm) { src = A; }
|
|||
|
|
|||
|
FlagC = Regs[src].Bit(0);
|
|||
|
|
|||
|
Regs[src] = (ushort)((FlagC ? 0x80 : 0) | (Regs[src] >> 1));
|
|||
|
|
|||
|
FlagZ = imm ? false : (Regs[src] == 0);
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void RR_Func(ushort src)
|
|||
|
{
|
|||
|
bool imm = src == Aim;
|
|||
|
if (imm) { src = A; }
|
|||
|
|
|||
|
ushort c = (ushort)(FlagC ? 0x80 : 0);
|
|||
|
|
|||
|
FlagC = Regs[src].Bit(0);
|
|||
|
|
|||
|
Regs[src] = (ushort)(c | (Regs[src] >> 1));
|
|||
|
|
|||
|
FlagZ = imm ? false : (Regs[src] == 0);
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void RLC_Func(ushort src)
|
|||
|
{
|
|||
|
bool imm = src == Aim;
|
|||
|
if (imm) { src = A; }
|
|||
|
|
|||
|
ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0);
|
|||
|
FlagC = Regs[src].Bit(7);
|
|||
|
|
|||
|
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
|
|||
|
|
|||
|
FlagZ = imm ? false : (Regs[src] == 0);
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void RL_Func(ushort src)
|
|||
|
{
|
|||
|
bool imm = src == Aim;
|
|||
|
if (imm) { src = A; }
|
|||
|
|
|||
|
ushort c = (ushort)(FlagC ? 1 : 0);
|
|||
|
FlagC = Regs[src].Bit(7);
|
|||
|
|
|||
|
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
|
|||
|
|
|||
|
FlagZ = imm ? false : (Regs[src] == 0);
|
|||
|
FlagH = false;
|
|||
|
FlagN = false;
|
|||
|
}
|
|||
|
|
|||
|
public void INC8_Func(ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[src];
|
|||
|
Reg16_d += 1;
|
|||
|
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[src] & 0xF;
|
|||
|
Reg16_d += 1;
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = false;
|
|||
|
|
|||
|
Regs[src] = ans;
|
|||
|
}
|
|||
|
|
|||
|
public void DEC8_Func(ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[src];
|
|||
|
Reg16_d -= 1;
|
|||
|
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[src] & 0xF;
|
|||
|
Reg16_d -= 1;
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = true;
|
|||
|
|
|||
|
Regs[src] = ans;
|
|||
|
}
|
|||
|
|
|||
|
public void INC16_Func(ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
|
|||
|
|
|||
|
Reg16_d += 1;
|
|||
|
|
|||
|
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
|
|||
|
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
|
|||
|
}
|
|||
|
|
|||
|
public void DEC16_Func(ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
|
|||
|
|
|||
|
Reg16_d -= 1;
|
|||
|
|
|||
|
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
|
|||
|
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
|
|||
|
}
|
|||
|
|
|||
|
public void ADC8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest];
|
|||
|
int c = FlagC ? 1 : 0;
|
|||
|
|
|||
|
Reg16_d += (Regs[src] + c);
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest] & 0xF;
|
|||
|
Reg16_d += ((Regs[src] & 0xF) + c);
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = false;
|
|||
|
|
|||
|
Regs[dest] = ans;
|
|||
|
}
|
|||
|
|
|||
|
public void SBC8_Func(ushort dest, ushort src)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest];
|
|||
|
int c = FlagC ? 1 : 0;
|
|||
|
|
|||
|
Reg16_d -= (Regs[src] + c);
|
|||
|
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
FlagZ = (Reg16_d & 0xFF) == 0;
|
|||
|
|
|||
|
ushort ans = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest] & 0xF;
|
|||
|
Reg16_d -= ((Regs[src] & 0xF) + c);
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = true;
|
|||
|
|
|||
|
Regs[dest] = ans;
|
|||
|
}
|
|||
|
|
|||
|
// DA code courtesy of AWJ: http://forums.nesdev.com/viewtopic.php?f=20&t=15944
|
|||
|
public void DA_Func(ushort src)
|
|||
|
{
|
|||
|
byte a = (byte)Regs[src];
|
|||
|
|
|||
|
if (!FlagN)
|
|||
|
{ // after an addition, adjust if (half-)carry occurred or if result is out of bounds
|
|||
|
if (FlagC || a > 0x99) { a += 0x60; FlagC = true; }
|
|||
|
if (FlagH || (a & 0x0f) > 0x09) { a += 0x6; }
|
|||
|
}
|
|||
|
else
|
|||
|
{ // after a subtraction, only adjust if (half-)carry occurred
|
|||
|
if (FlagC) { a -= 0x60; }
|
|||
|
if (FlagH) { a -= 0x6; }
|
|||
|
}
|
|||
|
|
|||
|
a &= 0xFF;
|
|||
|
|
|||
|
Regs[src] = a;
|
|||
|
|
|||
|
FlagZ = a == 0;
|
|||
|
FlagH = false;
|
|||
|
}
|
|||
|
|
|||
|
// used for signed operations
|
|||
|
public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
|
|||
|
{
|
|||
|
int Reg16_d = Regs[dest_l];
|
|||
|
int Reg16_s = Regs[src_l];
|
|||
|
|
|||
|
Reg16_d += Reg16_s;
|
|||
|
|
|||
|
ushort temp = 0;
|
|||
|
|
|||
|
// since this is signed addition, calculate the high byte carry appropriately
|
|||
|
if (Reg16_s.Bit(7))
|
|||
|
{
|
|||
|
if (((Reg16_d & 0xFF) >= Regs[dest_l]))
|
|||
|
{
|
|||
|
temp = 0xFF;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
temp = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0);
|
|||
|
}
|
|||
|
|
|||
|
ushort ans_l = (ushort)(Reg16_d & 0xFF);
|
|||
|
|
|||
|
// JR operations do not effect flags
|
|||
|
if (dest_l != PCl)
|
|||
|
{
|
|||
|
FlagC = Reg16_d.Bit(8);
|
|||
|
|
|||
|
// redo for half carry flag
|
|||
|
Reg16_d = Regs[dest_l] & 0xF;
|
|||
|
Reg16_d += Regs[src_l] & 0xF;
|
|||
|
|
|||
|
FlagH = Reg16_d.Bit(4);
|
|||
|
FlagN = false;
|
|||
|
FlagZ = false;
|
|||
|
}
|
|||
|
|
|||
|
Regs[dest_l] = ans_l;
|
|||
|
Regs[dest_h] += temp;
|
|||
|
Regs[dest_h] &= 0xFF;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|