c64- VIC register class
This commit is contained in:
parent
9d83249eba
commit
821553cda8
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public Memory mem;
|
||||
public Sid sid;
|
||||
public VicII vic;
|
||||
public VicSignals vicSignal;
|
||||
public ChipSignals signal;
|
||||
|
||||
private void HardReset()
|
||||
{
|
||||
|
@ -35,8 +35,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
cia2 = new Cia(Cia.DummyReadPort, Cia.DummyReadPort, Cia.DummyWritePort, Cia.DummyWritePort);
|
||||
|
||||
// initialize vic
|
||||
vicSignal = new VicSignals();
|
||||
vic = new VicII(vicSignal, VicIIMode.NTSC);
|
||||
signal = new ChipSignals();
|
||||
vic = new VicII(signal, VicIIMode.NTSC);
|
||||
|
||||
// initialize sid
|
||||
sid = new Sid();
|
||||
|
@ -88,4 +88,21 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
mem.Write(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class ChipSignals
|
||||
{
|
||||
private bool[] _CiaIRQOutput = new bool[2];
|
||||
private bool _VicAECOutput;
|
||||
private bool _VicBAOutput;
|
||||
private bool _VicIRQOutput;
|
||||
private bool _VicLPInput;
|
||||
|
||||
public bool CpuAEC { get { return _VicAECOutput; } }
|
||||
public bool CpuIRQ { get { return _VicIRQOutput | _CiaIRQOutput[0] | _CiaIRQOutput[1]; } }
|
||||
public bool CpuRDY { get { return _VicBAOutput; } }
|
||||
public bool VicAEC { get { return _VicAECOutput; } set { _VicAECOutput = value; } }
|
||||
public bool VicBA { get { return _VicBAOutput; } set { _VicBAOutput = value; } }
|
||||
public bool VicIRQ { get { return _VicIRQOutput; } set { _VicIRQOutput = value; } }
|
||||
public bool VicLP { get { return _VicLPInput; } }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,11 +92,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
for (int i = 0; i < cyclesPerSecond; i++)
|
||||
{
|
||||
if (vicSignal.Interrupt || cia1.interrupt || cia2.interrupt)
|
||||
if (signal.CpuIRQ)
|
||||
{
|
||||
cpu.IRQ = true;
|
||||
}
|
||||
if (vicSignal.AllowCpu)
|
||||
if (signal.CpuRDY)
|
||||
{
|
||||
cpu.ExecuteOne();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,429 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
PAL
|
||||
}
|
||||
|
||||
public class VicIIRegs
|
||||
{
|
||||
public bool BMM;
|
||||
public int[] BxC = new int[4];
|
||||
public int CB;
|
||||
public bool CSEL;
|
||||
public bool DEN;
|
||||
public int EC;
|
||||
public bool ECM;
|
||||
public bool ELP;
|
||||
public bool EMBC;
|
||||
public bool EMMC;
|
||||
public bool ERST;
|
||||
public bool ILP;
|
||||
public bool IMBC;
|
||||
public bool IMMC;
|
||||
public bool IRQ;
|
||||
public bool IRST;
|
||||
public int LPX;
|
||||
public int LPY;
|
||||
public bool MCM;
|
||||
public int[] MMx = new int[2];
|
||||
public int[] MxC = new int[8];
|
||||
public bool[] MxD = new bool[8];
|
||||
public bool[] MxDP = new bool[8];
|
||||
public bool[] MxE = new bool[8];
|
||||
public bool[] MxM = new bool[8];
|
||||
public bool[] MxMC = new bool[8];
|
||||
public int[] MxX = new int[8];
|
||||
public bool[] MxXE = new bool[8];
|
||||
public int[] MxY = new int[8];
|
||||
public bool[] MxYE = new bool[8];
|
||||
public int RASTER;
|
||||
public int RASTERX;
|
||||
public int RC;
|
||||
public bool RES;
|
||||
public bool RSEL;
|
||||
public int VC;
|
||||
public int VCBASE;
|
||||
public int VM;
|
||||
public int VMLI;
|
||||
public int XSCROLL;
|
||||
public int YSCROLL;
|
||||
|
||||
public VicIIRegs()
|
||||
{
|
||||
// power on state
|
||||
|
||||
this[0x16] = 0xC0;
|
||||
this[0x18] = 0x01;
|
||||
this[0x19] = 0x71;
|
||||
this[0x1A] = 0xF0;
|
||||
}
|
||||
|
||||
public byte this[int addr]
|
||||
{
|
||||
get
|
||||
{
|
||||
int result = 0xFF; // value for any open bits
|
||||
addr &= 0x3F;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
result = MxX[addr >> 1];
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
case 0x09:
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
result = MxY[addr >> 1];
|
||||
break;
|
||||
case 0x10:
|
||||
result = ((MxX[0] & 0x100) != 0) ? 0x01 : 0x00;
|
||||
result |= ((MxX[1] & 0x100) != 0) ? 0x02 : 0x00;
|
||||
result |= ((MxX[2] & 0x100) != 0) ? 0x04 : 0x00;
|
||||
result |= ((MxX[3] & 0x100) != 0) ? 0x08 : 0x00;
|
||||
result |= ((MxX[4] & 0x100) != 0) ? 0x10 : 0x00;
|
||||
result |= ((MxX[5] & 0x100) != 0) ? 0x20 : 0x00;
|
||||
result |= ((MxX[6] & 0x100) != 0) ? 0x40 : 0x00;
|
||||
result |= ((MxX[7] & 0x100) != 0) ? 0x80 : 0x00;
|
||||
break;
|
||||
case 0x11:
|
||||
result = YSCROLL & 0x07;
|
||||
result |= (RSEL ? 0x08 : 0x00);
|
||||
result |= (DEN ? 0x10 : 0x00);
|
||||
result |= (BMM ? 0x20 : 0x00);
|
||||
result |= (ECM ? 0x40 : 0x00);
|
||||
result |= ((RASTER & 0x100) >> 1);
|
||||
break;
|
||||
case 0x12:
|
||||
result = RASTER & 0xFF;
|
||||
break;
|
||||
case 0x13:
|
||||
result = LPX;
|
||||
break;
|
||||
case 0x14:
|
||||
result = LPY;
|
||||
break;
|
||||
case 0x15:
|
||||
result = (MxE[0] ? 0x01 : 0x00);
|
||||
result |= (MxE[1] ? 0x02 : 0x00);
|
||||
result |= (MxE[2] ? 0x04 : 0x00);
|
||||
result |= (MxE[3] ? 0x08 : 0x00);
|
||||
result |= (MxE[4] ? 0x10 : 0x00);
|
||||
result |= (MxE[5] ? 0x20 : 0x00);
|
||||
result |= (MxE[6] ? 0x40 : 0x00);
|
||||
result |= (MxE[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x16:
|
||||
result &= 0xBF;
|
||||
result |= XSCROLL & 0x07;
|
||||
result |= (CSEL ? 0x08 : 0x00);
|
||||
result |= (MCM ? 0x10 : 0x00);
|
||||
result |= (RES ? 0x20 : 0x00);
|
||||
break;
|
||||
case 0x17:
|
||||
result = (MxYE[0] ? 0x01 : 0x00);
|
||||
result |= (MxYE[1] ? 0x02 : 0x00);
|
||||
result |= (MxYE[2] ? 0x04 : 0x00);
|
||||
result |= (MxYE[3] ? 0x08 : 0x00);
|
||||
result |= (MxYE[4] ? 0x10 : 0x00);
|
||||
result |= (MxYE[5] ? 0x20 : 0x00);
|
||||
result |= (MxYE[6] ? 0x40 : 0x00);
|
||||
result |= (MxYE[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x18:
|
||||
result &= 0x01;
|
||||
result |= (CB & 0x07) << 1;
|
||||
result |= (VM & 0x0F) << 4;
|
||||
break;
|
||||
case 0x19:
|
||||
result &= 0x70;
|
||||
result |= (IRST ? 0x01 : 0x00);
|
||||
result |= (IMBC ? 0x02 : 0x00);
|
||||
result |= (IMMC ? 0x04 : 0x00);
|
||||
result |= (ILP ? 0x08 : 0x00);
|
||||
result |= (IRQ ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x1A:
|
||||
result &= 0xF0;
|
||||
result |= (ERST ? 0x01 : 0x00);
|
||||
result |= (EMBC ? 0x02 : 0x00);
|
||||
result |= (EMMC ? 0x04 : 0x00);
|
||||
result |= (ELP ? 0x08 : 0x00);
|
||||
break;
|
||||
case 0x1B:
|
||||
result = (MxDP[0] ? 0x01 : 0x00);
|
||||
result |= (MxDP[1] ? 0x02 : 0x00);
|
||||
result |= (MxDP[2] ? 0x04 : 0x00);
|
||||
result |= (MxDP[3] ? 0x08 : 0x00);
|
||||
result |= (MxDP[4] ? 0x10 : 0x00);
|
||||
result |= (MxDP[5] ? 0x20 : 0x00);
|
||||
result |= (MxDP[6] ? 0x40 : 0x00);
|
||||
result |= (MxDP[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x1C:
|
||||
result = (MxMC[0] ? 0x01 : 0x00);
|
||||
result |= (MxMC[1] ? 0x02 : 0x00);
|
||||
result |= (MxMC[2] ? 0x04 : 0x00);
|
||||
result |= (MxMC[3] ? 0x08 : 0x00);
|
||||
result |= (MxMC[4] ? 0x10 : 0x00);
|
||||
result |= (MxMC[5] ? 0x20 : 0x00);
|
||||
result |= (MxMC[6] ? 0x40 : 0x00);
|
||||
result |= (MxMC[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x1D:
|
||||
result = (MxXE[0] ? 0x01 : 0x00);
|
||||
result |= (MxXE[1] ? 0x02 : 0x00);
|
||||
result |= (MxXE[2] ? 0x04 : 0x00);
|
||||
result |= (MxXE[3] ? 0x08 : 0x00);
|
||||
result |= (MxXE[4] ? 0x10 : 0x00);
|
||||
result |= (MxXE[5] ? 0x20 : 0x00);
|
||||
result |= (MxXE[6] ? 0x40 : 0x00);
|
||||
result |= (MxXE[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x1E:
|
||||
result = (MxM[0] ? 0x01 : 0x00);
|
||||
result |= (MxM[1] ? 0x02 : 0x00);
|
||||
result |= (MxM[2] ? 0x04 : 0x00);
|
||||
result |= (MxM[3] ? 0x08 : 0x00);
|
||||
result |= (MxM[4] ? 0x10 : 0x00);
|
||||
result |= (MxM[5] ? 0x20 : 0x00);
|
||||
result |= (MxM[6] ? 0x40 : 0x00);
|
||||
result |= (MxM[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x1F:
|
||||
result = (MxD[0] ? 0x01 : 0x00);
|
||||
result |= (MxD[1] ? 0x02 : 0x00);
|
||||
result |= (MxD[2] ? 0x04 : 0x00);
|
||||
result |= (MxD[3] ? 0x08 : 0x00);
|
||||
result |= (MxD[4] ? 0x10 : 0x00);
|
||||
result |= (MxD[5] ? 0x20 : 0x00);
|
||||
result |= (MxD[6] ? 0x40 : 0x00);
|
||||
result |= (MxD[7] ? 0x80 : 0x00);
|
||||
break;
|
||||
case 0x20:
|
||||
result &= 0xF0;
|
||||
result |= EC & 0x0F;
|
||||
break;
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
case 0x23:
|
||||
case 0x24:
|
||||
result &= 0xF0;
|
||||
result |= BxC[addr - 0x21] & 0x0F;
|
||||
break;
|
||||
case 0x25:
|
||||
case 0x26:
|
||||
result &= 0xF0;
|
||||
result |= MMx[addr - 0x25] & 0x0F;
|
||||
break;
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
case 0x2E:
|
||||
result &= 0xF0;
|
||||
result |= MxC[addr - 0x27] & 0x0F;
|
||||
break;
|
||||
default:
|
||||
result = 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
return (byte)(result);
|
||||
}
|
||||
set
|
||||
{
|
||||
int index;
|
||||
int val = value;
|
||||
addr &= 0x3F;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
index = addr >> 1;
|
||||
MxX[index] &= 0x100;
|
||||
MxX[index] |= (val & 0xFF);
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
case 0x09:
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
index = addr >> 1;
|
||||
MxY[index] &= 0x100;
|
||||
MxY[index] |= (val & 0xFF);
|
||||
break;
|
||||
case 0x10:
|
||||
MxX[0] = (MxX[0] & 0xFF) | ((val & 0x01) << 8);
|
||||
MxX[1] = (MxX[1] & 0xFF) | ((val & 0x02) << 7);
|
||||
MxX[2] = (MxX[2] & 0xFF) | ((val & 0x04) << 6);
|
||||
MxX[3] = (MxX[3] & 0xFF) | ((val & 0x08) << 5);
|
||||
MxX[4] = (MxX[4] & 0xFF) | ((val & 0x10) << 4);
|
||||
MxX[5] = (MxX[5] & 0xFF) | ((val & 0x20) << 3);
|
||||
MxX[6] = (MxX[6] & 0xFF) | ((val & 0x40) << 2);
|
||||
MxX[7] = (MxX[7] & 0xFF) | ((val & 0x80) << 1);
|
||||
break;
|
||||
case 0x11:
|
||||
YSCROLL = (val & 0x07);
|
||||
RSEL = ((val & 0x08) != 0x00);
|
||||
DEN = ((val & 0x10) != 0x00);
|
||||
BMM = ((val & 0x20) != 0x00);
|
||||
ECM = ((val & 0x40) != 0x00);
|
||||
RASTER &= 0xFF;
|
||||
RASTER |= ((val & 0x80) << 1);
|
||||
break;
|
||||
case 0x12:
|
||||
RASTER &= 0x100;
|
||||
RASTER |= (val & 0xFF);
|
||||
break;
|
||||
case 0x13:
|
||||
LPX = (val & 0xFF);
|
||||
break;
|
||||
case 0x14:
|
||||
LPY = (val & 0xFF);
|
||||
break;
|
||||
case 0x15:
|
||||
MxE[0] = ((val & 0x01) != 0x00);
|
||||
MxE[1] = ((val & 0x02) != 0x00);
|
||||
MxE[2] = ((val & 0x04) != 0x00);
|
||||
MxE[3] = ((val & 0x08) != 0x00);
|
||||
MxE[4] = ((val & 0x10) != 0x00);
|
||||
MxE[5] = ((val & 0x20) != 0x00);
|
||||
MxE[6] = ((val & 0x40) != 0x00);
|
||||
MxE[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x16:
|
||||
XSCROLL = (val & 0x07);
|
||||
CSEL = ((val & 0x08) != 0x00);
|
||||
MCM = ((val & 0x10) != 0x00);
|
||||
RES = ((val & 0x20) != 0x00);
|
||||
break;
|
||||
case 0x17:
|
||||
MxYE[0] = ((val & 0x01) != 0x00);
|
||||
MxYE[1] = ((val & 0x02) != 0x00);
|
||||
MxYE[2] = ((val & 0x04) != 0x00);
|
||||
MxYE[3] = ((val & 0x08) != 0x00);
|
||||
MxYE[4] = ((val & 0x10) != 0x00);
|
||||
MxYE[5] = ((val & 0x20) != 0x00);
|
||||
MxYE[6] = ((val & 0x40) != 0x00);
|
||||
MxYE[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x18:
|
||||
CB = (val & 0x0E) >> 1;
|
||||
VM = (val & 0xF0) >> 4;
|
||||
break;
|
||||
case 0x19:
|
||||
IRST = ((val & 0x01) != 0x00);
|
||||
IMBC = ((val & 0x02) != 0x00);
|
||||
IMMC = ((val & 0x04) != 0x00);
|
||||
ILP = ((val & 0x08) != 0x00);
|
||||
IRQ = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1A:
|
||||
ERST = ((val & 0x01) != 0x00);
|
||||
EMBC = ((val & 0x02) != 0x00);
|
||||
EMMC = ((val & 0x04) != 0x00);
|
||||
ELP = ((val & 0x08) != 0x00);
|
||||
break;
|
||||
case 0x1B:
|
||||
MxDP[0] = ((val & 0x01) != 0x00);
|
||||
MxDP[1] = ((val & 0x02) != 0x00);
|
||||
MxDP[2] = ((val & 0x04) != 0x00);
|
||||
MxDP[3] = ((val & 0x08) != 0x00);
|
||||
MxDP[4] = ((val & 0x10) != 0x00);
|
||||
MxDP[5] = ((val & 0x20) != 0x00);
|
||||
MxDP[6] = ((val & 0x40) != 0x00);
|
||||
MxDP[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1C:
|
||||
MxMC[0] = ((val & 0x01) != 0x00);
|
||||
MxMC[1] = ((val & 0x02) != 0x00);
|
||||
MxMC[2] = ((val & 0x04) != 0x00);
|
||||
MxMC[3] = ((val & 0x08) != 0x00);
|
||||
MxMC[4] = ((val & 0x10) != 0x00);
|
||||
MxMC[5] = ((val & 0x20) != 0x00);
|
||||
MxMC[6] = ((val & 0x40) != 0x00);
|
||||
MxMC[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1D:
|
||||
MxXE[0] = ((val & 0x01) != 0x00);
|
||||
MxXE[1] = ((val & 0x02) != 0x00);
|
||||
MxXE[2] = ((val & 0x04) != 0x00);
|
||||
MxXE[3] = ((val & 0x08) != 0x00);
|
||||
MxXE[4] = ((val & 0x10) != 0x00);
|
||||
MxXE[5] = ((val & 0x20) != 0x00);
|
||||
MxXE[6] = ((val & 0x40) != 0x00);
|
||||
MxXE[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1E:
|
||||
MxM[0] = ((val & 0x01) != 0x00);
|
||||
MxM[1] = ((val & 0x02) != 0x00);
|
||||
MxM[2] = ((val & 0x04) != 0x00);
|
||||
MxM[3] = ((val & 0x08) != 0x00);
|
||||
MxM[4] = ((val & 0x10) != 0x00);
|
||||
MxM[5] = ((val & 0x20) != 0x00);
|
||||
MxM[6] = ((val & 0x40) != 0x00);
|
||||
MxM[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1F:
|
||||
MxD[0] = ((val & 0x01) != 0x00);
|
||||
MxD[1] = ((val & 0x02) != 0x00);
|
||||
MxD[2] = ((val & 0x04) != 0x00);
|
||||
MxD[3] = ((val & 0x08) != 0x00);
|
||||
MxD[4] = ((val & 0x10) != 0x00);
|
||||
MxD[5] = ((val & 0x20) != 0x00);
|
||||
MxD[6] = ((val & 0x40) != 0x00);
|
||||
MxD[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x20:
|
||||
EC = (val & 0x0F);
|
||||
break;
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
case 0x23:
|
||||
case 0x24:
|
||||
BxC[addr - 0x21] = val & 0x0F;
|
||||
break;
|
||||
case 0x25:
|
||||
case 0x26:
|
||||
MMx[addr - 0x25] = val & 0x0F;
|
||||
break;
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
case 0x2E:
|
||||
MxC[addr - 0x27] = val & 0x0F;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class VicII
|
||||
{
|
||||
// buffer
|
||||
|
@ -38,30 +461,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
Colors.ARGB(0x95, 0x95, 0x95)
|
||||
};
|
||||
|
||||
// interrupts
|
||||
public bool interrupt = true;
|
||||
public bool lightPenInterrupt = true;
|
||||
public bool lightPenInterruptEnabled;
|
||||
public bool rasterInterrupt = true;
|
||||
public bool rasterInterruptEnabled;
|
||||
public bool spriteBackgroundInterrupt = true;
|
||||
public bool spriteBackgroundInterruptEnabled;
|
||||
public bool spriteSpriteInterrupt = true;
|
||||
public bool spriteSpriteInterruptEnabled;
|
||||
|
||||
// memory
|
||||
public bool characterFetch;
|
||||
public int characterFetchOffset;
|
||||
public int characterMemoryOffset;
|
||||
public byte[] charBuffer;
|
||||
public int charBufferOffset;
|
||||
public bool fetching;
|
||||
public int fetchOffsetX;
|
||||
public int screenMemoryOffset;
|
||||
|
||||
// lightpen
|
||||
public int lightPenX; // LPX
|
||||
public int lightPenY; // LPY
|
||||
|
||||
// raster
|
||||
public int[] backgroundColor; // B0C
|
||||
|
@ -74,10 +475,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public bool borderOnVertical;
|
||||
public int borderRight;
|
||||
public int borderTop;
|
||||
public bool extendHeight; // RSEL
|
||||
public bool extendWidth; // CSEL
|
||||
public int horizontalScroll; // XSCROLL
|
||||
public bool multiColorMode; // MCM
|
||||
public int rasterInterruptLine;
|
||||
public int rasterLineLeft;
|
||||
public int rasterOffset;
|
||||
|
@ -98,26 +495,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int visibleTop;
|
||||
public int visibleWidth;
|
||||
|
||||
// sprites
|
||||
public bool[] spriteBackgroundCollision; // M0D
|
||||
public bool[] spriteCollision; // M0M
|
||||
public int[] spriteColor; // M0C
|
||||
public bool[] spriteEnabled; // M0E
|
||||
public int[] spriteExtraColor; // MM0
|
||||
public bool[] spriteMultiColor; // M0MC
|
||||
public bool[] spritePriority; // M0DP
|
||||
public bool[] spriteStretchHorizontal; // M0XE
|
||||
public bool[] spriteStretchVertical; // M0YE
|
||||
public int[] spriteX; // M0X, M0X8
|
||||
public int[] spriteY; // M0Y
|
||||
|
||||
public VicSignals cpuSignal;
|
||||
public ChipSignals signal;
|
||||
public Memory mem;
|
||||
public byte[] regs;
|
||||
public VicIIRegs regs;
|
||||
|
||||
public VicII(VicSignals signals, VicIIMode videoMode)
|
||||
public VicII(ChipSignals newSignal, VicIIMode videoMode)
|
||||
{
|
||||
cpuSignal = signals;
|
||||
signal = newSignal;
|
||||
|
||||
switch (videoMode)
|
||||
{
|
||||
|
@ -134,10 +518,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
visibleWidth = 418;
|
||||
visibleHeight = 217;
|
||||
renderOffset = 0;
|
||||
borderLeft = 0x018;
|
||||
borderRight = 0x158;
|
||||
borderTop = 0x033;
|
||||
borderBottom = 0x0FA;
|
||||
characterFetchOffset = rasterWidth - 3;
|
||||
break;
|
||||
case VicIIMode.PAL:
|
||||
|
@ -148,23 +528,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
// initialize raster
|
||||
backgroundColor = new int[4];
|
||||
charBuffer = new byte[40];
|
||||
rasterOffsetX = rasterLineLeft;
|
||||
rasterOffsetY = 0;
|
||||
|
||||
// initialize sprites
|
||||
spriteBackgroundCollision = new bool[8];
|
||||
spriteCollision = new bool[8];
|
||||
spriteColor = new int[8];
|
||||
spriteEnabled = new bool[8];
|
||||
spriteExtraColor = new int[2];
|
||||
spriteMultiColor = new bool[8];
|
||||
spritePriority = new bool[8];
|
||||
spriteStretchHorizontal = new bool[8];
|
||||
spriteStretchVertical = new bool[8];
|
||||
spriteX = new int[8];
|
||||
spriteY = new int[8];
|
||||
|
||||
// initialize buffer
|
||||
buffer = new int[rasterWidth * rasterTotalLines];
|
||||
bufferSize = buffer.Length;
|
||||
|
@ -175,331 +541,75 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public void HardReset()
|
||||
{
|
||||
// power on state
|
||||
regs = new byte[0x40];
|
||||
Write(0x0016, 0xC0);
|
||||
Write(0x0018, 0x01);
|
||||
Write(0x0019, 0x71);
|
||||
Write(0x001A, 0xF0);
|
||||
for (ushort i = 0x0020; i <= 0x002E; i++)
|
||||
Write(i, 0xF0);
|
||||
|
||||
// unused registers always return FF
|
||||
for (int i = 0x2F; i <= 0x3F; i++)
|
||||
regs[i] = 0xFF;
|
||||
|
||||
UpdateRegs();
|
||||
}
|
||||
|
||||
public void LockBus()
|
||||
{
|
||||
cpuSignal.Lock();
|
||||
regs = new VicIIRegs();
|
||||
UpdateBorder();
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (rasterOffsetX == visibleLeft)
|
||||
visibleRenderX = true;
|
||||
if (rasterOffsetX == visibleRight)
|
||||
visibleRenderX = false;
|
||||
if (rasterOffsetX == borderLeft)
|
||||
borderOnHorizontal = false;
|
||||
if (rasterOffsetX == borderRight)
|
||||
borderOnHorizontal = true;
|
||||
|
||||
if ((rasterOffsetX == fetchOffsetX) && ((rasterOffsetY & 0x07) == verticalScroll))
|
||||
{
|
||||
cpuSignal.Lock();
|
||||
fetching = true;
|
||||
characterFetchOffset = (rasterOffsetY >> 3) * 40;
|
||||
charBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (fetching)
|
||||
{
|
||||
if (charBufferOffset >= 0)
|
||||
{
|
||||
charBuffer[charBufferOffset] = mem.VicRead((ushort)(screenMemoryOffset + characterFetchOffset));
|
||||
characterFetchOffset++;
|
||||
}
|
||||
charBufferOffset++;
|
||||
if (charBufferOffset == 40)
|
||||
{
|
||||
fetching = false;
|
||||
cpuSignal.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (borderOnVertical || borderOnHorizontal)
|
||||
{
|
||||
WritePixel(borderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePixel(backgroundColor[0]);
|
||||
}
|
||||
|
||||
rasterOffsetX++;
|
||||
if (rasterOffsetX == rasterWidth)
|
||||
rasterOffsetX = 0;
|
||||
|
||||
if (rasterOffsetX == rasterLineLeft)
|
||||
{
|
||||
rasterOffsetY++;
|
||||
|
||||
if (rasterOffsetY == visibleTop)
|
||||
visibleRenderY = true;
|
||||
if (rasterOffsetY == visibleBottom)
|
||||
visibleRenderY = false;
|
||||
if (rasterOffsetY == borderTop)
|
||||
borderOnVertical = false;
|
||||
if (rasterOffsetY == borderBottom)
|
||||
borderOnVertical = true;
|
||||
if (rasterOffsetY == rasterTotalLines)
|
||||
{
|
||||
rasterOffsetY = 0;
|
||||
renderOffset = 0;
|
||||
}
|
||||
|
||||
if (rasterInterruptEnabled && (rasterOffsetY == rasterInterruptLine))
|
||||
{
|
||||
rasterInterrupt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interrupt =
|
||||
(rasterInterrupt & rasterInterruptEnabled) |
|
||||
(spriteSpriteInterrupt & spriteSpriteInterruptEnabled) |
|
||||
(spriteBackgroundInterrupt & spriteBackgroundInterruptEnabled) |
|
||||
(lightPenInterrupt & lightPenInterruptEnabled);
|
||||
|
||||
cpuSignal.Interrupt = interrupt;
|
||||
UpdateRegs();
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
{
|
||||
return regs[addr & 0x3F];
|
||||
}
|
||||
|
||||
public void UnlockBus()
|
||||
{
|
||||
cpuSignal.Unlock();
|
||||
}
|
||||
|
||||
public void UpdateRegs()
|
||||
{
|
||||
// these registers update on their own
|
||||
|
||||
regs[0x11] = (byte)
|
||||
((verticalScroll & 0x07) |
|
||||
(extendHeight ? 0x08 : 0x00) |
|
||||
(screenEnabled ? 0x10 : 0x00) |
|
||||
(bitmapMode ? 0x20 : 0x00) |
|
||||
(backgroundMode ? 0x40 : 0x00) |
|
||||
((rasterOffsetY & 0x100) >> 1));
|
||||
regs[0x12] = (byte)(rasterOffsetY & 0xFF);
|
||||
regs[0x13] = (byte)(lightPenX >> 1);
|
||||
regs[0x14] = (byte)(lightPenY);
|
||||
regs[0x19] = (byte)
|
||||
((rasterInterrupt ? 0x01 : 0x00) |
|
||||
(spriteBackgroundInterrupt ? 0x02 : 0x00) |
|
||||
(spriteSpriteInterrupt ? 0x04 : 0x00) |
|
||||
(lightPenInterrupt ? 0x08 : 0x00) |
|
||||
(interrupt ? 0x80 : 0x00));
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
int index = 0;
|
||||
bool allowWrite = true;
|
||||
byte result = 0;
|
||||
addr &= 0x3F;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
index = addr >> 1;
|
||||
spriteX[index] &= 0xFF;
|
||||
spriteX[index] |= val;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
case 0x09:
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
index = addr >> 1;
|
||||
spriteY[index] &= 0xFF;
|
||||
spriteY[index] |= val;
|
||||
break;
|
||||
case 0x10:
|
||||
spriteX[0] = (spriteX[0] & 0xFF) | ((val & 0x01) << 8);
|
||||
spriteX[1] = (spriteX[1] & 0xFF) | ((val & 0x02) << 7);
|
||||
spriteX[2] = (spriteX[2] & 0xFF) | ((val & 0x04) << 6);
|
||||
spriteX[3] = (spriteX[3] & 0xFF) | ((val & 0x08) << 5);
|
||||
spriteX[4] = (spriteX[4] & 0xFF) | ((val & 0x10) << 4);
|
||||
spriteX[5] = (spriteX[5] & 0xFF) | ((val & 0x20) << 3);
|
||||
spriteX[6] = (spriteX[6] & 0xFF) | ((val & 0x40) << 2);
|
||||
spriteX[7] = (spriteX[7] & 0xFF) | ((val & 0x80) << 1);
|
||||
break;
|
||||
case 0x11:
|
||||
verticalScroll = val & 0x07;
|
||||
extendHeight = ((val & 0x08) != 0x00);
|
||||
screenEnabled = ((val & 0x10) != 0x00);
|
||||
bitmapMode = ((val & 0x20) != 0x00);
|
||||
backgroundMode = ((val & 0x40) != 0x00);
|
||||
rasterInterruptLine = (rasterInterruptLine & 0xFF) | ((val & 0x80) << 1);
|
||||
val = (byte)((val & 0x7F) | ((rasterOffsetY & 0x100) >> 1));
|
||||
break;
|
||||
case 0x12:
|
||||
rasterInterruptLine = (rasterInterruptLine & 0x100) | val;
|
||||
allowWrite = false;
|
||||
break;
|
||||
case 0x15:
|
||||
spriteEnabled[0] = ((val & 0x01) != 0x00);
|
||||
spriteEnabled[1] = ((val & 0x02) != 0x00);
|
||||
spriteEnabled[2] = ((val & 0x04) != 0x00);
|
||||
spriteEnabled[3] = ((val & 0x08) != 0x00);
|
||||
spriteEnabled[4] = ((val & 0x10) != 0x00);
|
||||
spriteEnabled[5] = ((val & 0x20) != 0x00);
|
||||
spriteEnabled[6] = ((val & 0x40) != 0x00);
|
||||
spriteEnabled[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x16:
|
||||
horizontalScroll = val & 0x07;
|
||||
extendWidth = ((val & 0x08) != 0x00);
|
||||
multiColorMode = ((val & 0x10) != 0x00);
|
||||
resetBit = ((val & 0x20) != 0x00);
|
||||
val |= 0xC0;
|
||||
break;
|
||||
case 0x17:
|
||||
spriteStretchVertical[0] = ((val & 0x01) != 0x00);
|
||||
spriteStretchVertical[1] = ((val & 0x02) != 0x00);
|
||||
spriteStretchVertical[2] = ((val & 0x04) != 0x00);
|
||||
spriteStretchVertical[3] = ((val & 0x08) != 0x00);
|
||||
spriteStretchVertical[4] = ((val & 0x10) != 0x00);
|
||||
spriteStretchVertical[5] = ((val & 0x20) != 0x00);
|
||||
spriteStretchVertical[6] = ((val & 0x40) != 0x00);
|
||||
spriteStretchVertical[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x18:
|
||||
characterMemoryOffset = (int)(val & 0x0E) << 10;
|
||||
screenMemoryOffset = (int)(val & 0xF0) << 6;
|
||||
break;
|
||||
case 0x19:
|
||||
rasterInterrupt = ((val & 0x01) != 0);
|
||||
spriteSpriteInterrupt = ((val & 0x02) != 0);
|
||||
spriteBackgroundInterrupt = ((val & 0x04) != 0);
|
||||
lightPenInterrupt = ((val & 0x08) != 0);
|
||||
allowWrite = false;
|
||||
break;
|
||||
case 0x1A:
|
||||
rasterInterruptEnabled = ((val & 0x01) != 0);
|
||||
spriteSpriteInterruptEnabled = ((val & 0x02) != 0);
|
||||
spriteBackgroundInterruptEnabled = ((val & 0x04) != 0);
|
||||
lightPenInterruptEnabled = ((val & 0x08) != 0);
|
||||
break;
|
||||
case 0x1B:
|
||||
spritePriority[0] = ((val & 0x01) != 0x00);
|
||||
spritePriority[1] = ((val & 0x02) != 0x00);
|
||||
spritePriority[2] = ((val & 0x04) != 0x00);
|
||||
spritePriority[3] = ((val & 0x08) != 0x00);
|
||||
spritePriority[4] = ((val & 0x10) != 0x00);
|
||||
spritePriority[5] = ((val & 0x20) != 0x00);
|
||||
spritePriority[6] = ((val & 0x40) != 0x00);
|
||||
spritePriority[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1C:
|
||||
spriteMultiColor[0] = ((val & 0x01) != 0x00);
|
||||
spriteMultiColor[1] = ((val & 0x02) != 0x00);
|
||||
spriteMultiColor[2] = ((val & 0x04) != 0x00);
|
||||
spriteMultiColor[3] = ((val & 0x08) != 0x00);
|
||||
spriteMultiColor[4] = ((val & 0x10) != 0x00);
|
||||
spriteMultiColor[5] = ((val & 0x20) != 0x00);
|
||||
spriteMultiColor[6] = ((val & 0x40) != 0x00);
|
||||
spriteMultiColor[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1D:
|
||||
spriteStretchHorizontal[0] = ((val & 0x01) != 0x00);
|
||||
spriteStretchHorizontal[1] = ((val & 0x02) != 0x00);
|
||||
spriteStretchHorizontal[2] = ((val & 0x04) != 0x00);
|
||||
spriteStretchHorizontal[3] = ((val & 0x08) != 0x00);
|
||||
spriteStretchHorizontal[4] = ((val & 0x10) != 0x00);
|
||||
spriteStretchHorizontal[5] = ((val & 0x20) != 0x00);
|
||||
spriteStretchHorizontal[6] = ((val & 0x40) != 0x00);
|
||||
spriteStretchHorizontal[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1E:
|
||||
spriteCollision[0] = ((val & 0x01) != 0x00);
|
||||
spriteCollision[1] = ((val & 0x02) != 0x00);
|
||||
spriteCollision[2] = ((val & 0x04) != 0x00);
|
||||
spriteCollision[3] = ((val & 0x08) != 0x00);
|
||||
spriteCollision[4] = ((val & 0x10) != 0x00);
|
||||
spriteCollision[5] = ((val & 0x20) != 0x00);
|
||||
spriteCollision[6] = ((val & 0x40) != 0x00);
|
||||
spriteCollision[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x1F:
|
||||
spriteBackgroundCollision[0] = ((val & 0x01) != 0x00);
|
||||
spriteBackgroundCollision[1] = ((val & 0x02) != 0x00);
|
||||
spriteBackgroundCollision[2] = ((val & 0x04) != 0x00);
|
||||
spriteBackgroundCollision[3] = ((val & 0x08) != 0x00);
|
||||
spriteBackgroundCollision[4] = ((val & 0x10) != 0x00);
|
||||
spriteBackgroundCollision[5] = ((val & 0x20) != 0x00);
|
||||
spriteBackgroundCollision[6] = ((val & 0x40) != 0x00);
|
||||
spriteBackgroundCollision[7] = ((val & 0x80) != 0x00);
|
||||
break;
|
||||
case 0x20:
|
||||
borderColor = val;
|
||||
break;
|
||||
case 0x21:
|
||||
backgroundColor[0] = val;
|
||||
break;
|
||||
case 0x22:
|
||||
backgroundColor[1] = val;
|
||||
break;
|
||||
case 0x23:
|
||||
backgroundColor[2] = val;
|
||||
break;
|
||||
case 0x24:
|
||||
backgroundColor[3] = val;
|
||||
break;
|
||||
case 0x25:
|
||||
spriteExtraColor[0] = val;
|
||||
break;
|
||||
case 0x26:
|
||||
spriteExtraColor[1] = val;
|
||||
break;
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
case 0x2E:
|
||||
index = addr - 0x27;
|
||||
spriteColor[index] = val;
|
||||
// collision regs clear after read
|
||||
result = regs[addr];
|
||||
regs[addr] = 0x00;
|
||||
break;
|
||||
default:
|
||||
allowWrite = false;
|
||||
result = regs[addr];
|
||||
break;
|
||||
}
|
||||
|
||||
if (allowWrite)
|
||||
regs[addr] = val;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void UpdateBorder()
|
||||
{
|
||||
borderTop = regs.RSEL ? 0x033 : 0x037;
|
||||
borderBottom = regs.RSEL ? 0x0FA : 0x0F6;
|
||||
borderLeft = regs.CSEL ? 0x018 : 0x01F;
|
||||
borderRight = regs.CSEL ? 0x14E : 0x157;
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
addr &= 0x3F;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x11:
|
||||
rasterInterruptLine &= 0xFF;
|
||||
rasterInterruptLine |= (val & 0x80) << 1;
|
||||
// raster upper bit can't be changed, save and restore the value
|
||||
val &= 0x7F;
|
||||
val |= (byte)(regs[addr] & 0x80);
|
||||
regs[addr] = val;
|
||||
UpdateBorder();
|
||||
break;
|
||||
case 0x12:
|
||||
// raster interrupt lower 8 bits
|
||||
rasterInterruptLine &= 0x100;
|
||||
rasterInterruptLine |= (val & 0xFF);
|
||||
break;
|
||||
case 0x16:
|
||||
regs[addr] = val;
|
||||
UpdateBorder();
|
||||
break;
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
// can't write to these regs
|
||||
break;
|
||||
default:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void WritePixel(int value)
|
||||
|
@ -511,47 +621,4 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class VicSignals
|
||||
{
|
||||
public bool AllowCpu;
|
||||
public bool Interrupt;
|
||||
public int LockCounter;
|
||||
|
||||
public VicSignals()
|
||||
{
|
||||
AllowCpu = true;
|
||||
Interrupt = false;
|
||||
LockCounter = 0;
|
||||
}
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
if (AllowCpu)
|
||||
{
|
||||
LockCounter = 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void PerformCycle()
|
||||
{
|
||||
if (AllowCpu)
|
||||
{
|
||||
if (LockCounter > 0)
|
||||
{
|
||||
LockCounter--;
|
||||
if (LockCounter == 0)
|
||||
{
|
||||
AllowCpu = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
AllowCpu = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue