c64- VIC per-cycle behavior
This commit is contained in:
parent
ac1f9a90a1
commit
f1b4861d87
|
@ -105,7 +105,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public bool CpuRDY { get { return _VicBAOutput; } }
|
public bool CpuRDY { get { return _VicBAOutput; } }
|
||||||
public bool LPOutput { get { return _VicLPInput; } set { _VicLPInput = value; } }
|
public bool LPOutput { get { return _VicLPInput; } set { _VicLPInput = value; } }
|
||||||
public bool VicAEC { get { return _VicAECOutput; } set { _VicAECOutput = value; } }
|
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 VicIRQ { get { return _VicIRQOutput; } set { _VicIRQOutput = value; } }
|
||||||
public bool VicLP { get { return _VicLPInput; } }
|
public bool VicLP { get { return _VicLPInput; } }
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
cpu.IRQ = true;
|
cpu.IRQ = true;
|
||||||
}
|
}
|
||||||
if (signal.CpuRDY)
|
if (signal.CpuAEC)
|
||||||
{
|
{
|
||||||
cpu.ExecuteOne();
|
cpu.ExecuteOne();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
|
|
||||||
// registers
|
// registers
|
||||||
public byte busData;
|
public byte busData;
|
||||||
|
public DirectionalDataPort cia0PortA = new DirectionalDataPort(0xFF, 0x00);
|
||||||
|
public DirectionalDataPort cia0PortB = new DirectionalDataPort(0xFF, 0x00);
|
||||||
|
public DirectionalDataPort cia1PortA = new DirectionalDataPort(0x7F, 0x00);
|
||||||
|
public DirectionalDataPort cia1PortB = new DirectionalDataPort(0xFF, 0x00);
|
||||||
public DirectionalDataPort cpuPort;
|
public DirectionalDataPort cpuPort;
|
||||||
public bool readTrigger = true;
|
public bool readTrigger = true;
|
||||||
public bool writeTrigger = true;
|
public bool writeTrigger = true;
|
||||||
|
@ -86,6 +90,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
sid = newSid;
|
sid = newSid;
|
||||||
cia0 = newCia0;
|
cia0 = newCia0;
|
||||||
cia1 = newCia1;
|
cia1 = newCia1;
|
||||||
|
cia0.ports[0] = cia0PortA;
|
||||||
|
cia0.ports[1] = cia0PortB;
|
||||||
|
cia1.ports[0] = cia1PortA;
|
||||||
|
cia1.ports[1] = cia1PortB;
|
||||||
cpuPort = new DirectionalDataPort(0x37, 0x2F);
|
cpuPort = new DirectionalDataPort(0x37, 0x2F);
|
||||||
|
|
||||||
layout = new MemoryLayout();
|
layout = new MemoryLayout();
|
||||||
|
@ -101,30 +109,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte CIA2ReadPortA()
|
|
||||||
{
|
|
||||||
return cia2A;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte CIA2ReadPortB()
|
|
||||||
{
|
|
||||||
return cia2B;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CIA2WritePortA(byte val, byte direction)
|
|
||||||
{
|
|
||||||
cia2A &= (byte)~direction;
|
|
||||||
cia2A |= (byte)(val & direction);
|
|
||||||
|
|
||||||
vicOffset = (ushort)((cia2A & 0x03) << 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CIA2WritePortB(byte val, byte direction)
|
|
||||||
{
|
|
||||||
cia2B &= (byte)~direction;
|
|
||||||
cia2B |= (byte)(val & direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemoryDesignation GetDesignation(ushort addr)
|
public MemoryDesignation GetDesignation(ushort addr)
|
||||||
{
|
{
|
||||||
MemoryDesignation result;
|
MemoryDesignation result;
|
||||||
|
@ -425,9 +409,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
addr = (ushort)(addr & 0x1FFF);
|
addr = (ushort)(addr & 0x1FFF);
|
||||||
if (addr >= 0x1000 && addr < 0x2000)
|
if (addr >= 0x1000 && addr < 0x2000)
|
||||||
|
{
|
||||||
return charRom[addr & 0x0FFF];
|
return charRom[addr & 0x0FFF];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ram[addr | vicOffset];
|
{
|
||||||
|
int baseAddr = (3 - (cia1PortA.Data & 0x03)) << 14;
|
||||||
|
return ram[addr | baseAddr];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WipeMemory()
|
public void WipeMemory()
|
||||||
|
|
|
@ -432,6 +432,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum VicIITask
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
VideoMatrix,
|
||||||
|
CharGen,
|
||||||
|
SpritePointer,
|
||||||
|
SpriteData,
|
||||||
|
DramRefresh
|
||||||
|
}
|
||||||
|
|
||||||
public class VicII
|
public class VicII
|
||||||
{
|
{
|
||||||
// buffer
|
// buffer
|
||||||
|
@ -463,12 +473,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public int characterFetchOffset;
|
public int characterFetchOffset;
|
||||||
|
|
||||||
// raster
|
// raster
|
||||||
|
public bool badLine;
|
||||||
public int borderBottom;
|
public int borderBottom;
|
||||||
public int borderLeft;
|
public int borderLeft;
|
||||||
public bool borderOnHorizontal;
|
public bool borderOnHorizontal;
|
||||||
public bool borderOnVertical;
|
public bool borderOnVertical;
|
||||||
public int borderRight;
|
public int borderRight;
|
||||||
public int borderTop;
|
public int borderTop;
|
||||||
|
public byte[] characterMemory;
|
||||||
public int cycle;
|
public int cycle;
|
||||||
public bool displayEnabled;
|
public bool displayEnabled;
|
||||||
public int rasterInterruptLine;
|
public int rasterInterruptLine;
|
||||||
|
@ -477,7 +489,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public int rasterOffsetX;
|
public int rasterOffsetX;
|
||||||
public int rasterTotalLines;
|
public int rasterTotalLines;
|
||||||
public int rasterWidth;
|
public int rasterWidth;
|
||||||
|
public int refreshAddress;
|
||||||
public int renderOffset;
|
public int renderOffset;
|
||||||
|
public byte[,] spriteData;
|
||||||
|
public ushort[] spritePointers;
|
||||||
|
public VicIITask task;
|
||||||
|
public int totalCycles;
|
||||||
public int visibleBottom;
|
public int visibleBottom;
|
||||||
public int visibleHeight;
|
public int visibleHeight;
|
||||||
public int visibleLeft;
|
public int visibleLeft;
|
||||||
|
@ -510,7 +527,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
visibleWidth = 368;
|
visibleWidth = 368;
|
||||||
visibleHeight = 217;
|
visibleHeight = 217;
|
||||||
renderOffset = 0;
|
renderOffset = 0;
|
||||||
characterFetchOffset = rasterWidth - 3;
|
|
||||||
break;
|
break;
|
||||||
case VicIIMode.PAL:
|
case VicIIMode.PAL:
|
||||||
break;
|
break;
|
||||||
|
@ -522,31 +538,124 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
rasterOffsetX = rasterLineLeft;
|
rasterOffsetX = rasterLineLeft;
|
||||||
borderOnHorizontal = true;
|
borderOnHorizontal = true;
|
||||||
borderOnVertical = true;
|
borderOnVertical = true;
|
||||||
|
totalCycles = rasterWidth / 8;
|
||||||
|
|
||||||
// initialize buffer
|
// initialize buffer
|
||||||
buffer = new int[rasterWidth * rasterTotalLines];
|
buffer = new int[rasterWidth * rasterTotalLines];
|
||||||
bufferSize = buffer.Length;
|
bufferSize = buffer.Length;
|
||||||
|
|
||||||
|
// initialize sprites
|
||||||
|
spritePointers = new ushort[8];
|
||||||
|
spriteData = new byte[8, 64];
|
||||||
|
|
||||||
// initialize registers
|
// initialize registers
|
||||||
HardReset();
|
HardReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GetSpriteData(int index)
|
||||||
|
{
|
||||||
|
ushort offset = (ushort)(regs.VM + 0x3F8 + index);
|
||||||
|
spritePointers[index] = (ushort)(regs.VM + (mem.VicRead(offset) * 64));
|
||||||
|
for (ushort i = 0; i < 64; i++)
|
||||||
|
spriteData[index, i] = mem.VicRead((ushort)(spritePointers[index] + i));
|
||||||
|
}
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
{
|
{
|
||||||
|
refreshAddress = 0x3FFF;
|
||||||
regs = new VicIIRegs();
|
regs = new VicIIRegs();
|
||||||
signal.VicBA = true;
|
signal.VicAEC = true;
|
||||||
signal.VicIRQ = false;
|
signal.VicIRQ = false;
|
||||||
UpdateBorder();
|
UpdateBorder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PerformCycle()
|
public void PerformCycle()
|
||||||
{
|
{
|
||||||
|
|
||||||
// display enable check on line $30
|
// display enable check on line $30
|
||||||
if (regs.RASTER == 0x30)
|
if (regs.RASTER == 0x30)
|
||||||
{
|
{
|
||||||
displayEnabled = (displayEnabled | regs.DEN);
|
displayEnabled = (displayEnabled | regs.DEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// badline calculation (for when the VIC must pause the CPU to get character data)
|
||||||
|
badLine = (regs.YSCROLL == (regs.RASTER & 0x07) && displayEnabled);
|
||||||
|
|
||||||
|
// decide what to do this cycle
|
||||||
|
if (cycle >= 0 && cycle < 10)
|
||||||
|
{
|
||||||
|
// fetch sprite data 3-7
|
||||||
|
int index = (cycle >> 1) + 3;
|
||||||
|
if (regs.MxE[index])
|
||||||
|
{
|
||||||
|
signal.VicAEC = false;
|
||||||
|
if ((cycle & 0x01) == 0x00)
|
||||||
|
{
|
||||||
|
GetSpriteData(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
signal.VicAEC = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cycle >= 10 && cycle < 15)
|
||||||
|
{
|
||||||
|
// dram refresh
|
||||||
|
mem.VicRead((ushort)refreshAddress);
|
||||||
|
refreshAddress = (refreshAddress - 1) & 0xFF;
|
||||||
|
refreshAddress |= 0x3F00;
|
||||||
|
|
||||||
|
// VIC internal register reset on cycle 13
|
||||||
|
if (cycle == 13)
|
||||||
|
{
|
||||||
|
regs.VC = regs.VCBASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cycle >= 15 && cycle < 55)
|
||||||
|
{
|
||||||
|
if (badLine)
|
||||||
|
{
|
||||||
|
// fetch video data
|
||||||
|
signal.VicAEC = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
signal.VicAEC = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cycle == 57)
|
||||||
|
{
|
||||||
|
// increment VIC row counter
|
||||||
|
if (regs.RC == 7)
|
||||||
|
{
|
||||||
|
regs.VCBASE = regs.VC;
|
||||||
|
}
|
||||||
|
regs.RC = (regs.RC + 1) & 0x07;
|
||||||
|
if (badLine)
|
||||||
|
{
|
||||||
|
regs.RC = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cycle >= totalCycles - 6)
|
||||||
|
{
|
||||||
|
// fetch sprite data 0-2
|
||||||
|
int index = (cycle - (totalCycles - 6)) >> 1;
|
||||||
|
if (regs.MxE[index])
|
||||||
|
{
|
||||||
|
signal.VicAEC = false;
|
||||||
|
if ((cycle & 0x01) == 0x00)
|
||||||
|
{
|
||||||
|
GetSpriteData(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
signal.VicAEC = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// pixel clock is 8x the VIC clock
|
// pixel clock is 8x the VIC clock
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
@ -568,6 +677,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
regs.VCBASE = 0;
|
regs.VCBASE = 0;
|
||||||
renderOffset = 0;
|
renderOffset = 0;
|
||||||
displayEnabled = false;
|
displayEnabled = false;
|
||||||
|
refreshAddress = 0x3FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if we are within viewing area Y
|
// check to see if we are within viewing area Y
|
||||||
|
@ -645,6 +755,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool SpriteOnLine(int index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateBorder()
|
public void UpdateBorder()
|
||||||
{
|
{
|
||||||
borderTop = regs.RSEL ? 0x033 : 0x037;
|
borderTop = regs.RSEL ? 0x033 : 0x037;
|
||||||
|
|
Loading…
Reference in New Issue