c64- VIC per-cycle behavior

This commit is contained in:
saxxonpike 2012-11-05 20:47:20 +00:00
parent ac1f9a90a1
commit f1b4861d87
4 changed files with 132 additions and 29 deletions

View File

@ -105,7 +105,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
public bool CpuRDY { get { return _VicBAOutput; } }
public bool LPOutput { get { return _VicLPInput; } set { _VicLPInput = 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 VicLP { get { return _VicLPInput; } }
}

View File

@ -96,7 +96,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
cpu.IRQ = true;
}
if (signal.CpuRDY)
if (signal.CpuAEC)
{
cpu.ExecuteOne();
}

View File

@ -64,6 +64,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
// registers
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 bool readTrigger = true;
public bool writeTrigger = true;
@ -86,6 +90,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
sid = newSid;
cia0 = newCia0;
cia1 = newCia1;
cia0.ports[0] = cia0PortA;
cia0.ports[1] = cia0PortB;
cia1.ports[0] = cia1PortA;
cia1.ports[1] = cia1PortB;
cpuPort = new DirectionalDataPort(0x37, 0x2F);
layout = new MemoryLayout();
@ -101,30 +109,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
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)
{
MemoryDesignation result;
@ -425,9 +409,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
addr = (ushort)(addr & 0x1FFF);
if (addr >= 0x1000 && addr < 0x2000)
{
return charRom[addr & 0x0FFF];
}
else
return ram[addr | vicOffset];
{
int baseAddr = (3 - (cia1PortA.Data & 0x03)) << 14;
return ram[addr | baseAddr];
}
}
public void WipeMemory()

View File

@ -432,6 +432,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
}
}
public enum VicIITask
{
Idle,
VideoMatrix,
CharGen,
SpritePointer,
SpriteData,
DramRefresh
}
public class VicII
{
// buffer
@ -463,12 +473,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int characterFetchOffset;
// raster
public bool badLine;
public int borderBottom;
public int borderLeft;
public bool borderOnHorizontal;
public bool borderOnVertical;
public int borderRight;
public int borderTop;
public byte[] characterMemory;
public int cycle;
public bool displayEnabled;
public int rasterInterruptLine;
@ -477,7 +489,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int rasterOffsetX;
public int rasterTotalLines;
public int rasterWidth;
public int refreshAddress;
public int renderOffset;
public byte[,] spriteData;
public ushort[] spritePointers;
public VicIITask task;
public int totalCycles;
public int visibleBottom;
public int visibleHeight;
public int visibleLeft;
@ -510,7 +527,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
visibleWidth = 368;
visibleHeight = 217;
renderOffset = 0;
characterFetchOffset = rasterWidth - 3;
break;
case VicIIMode.PAL:
break;
@ -522,31 +538,124 @@ namespace BizHawk.Emulation.Computers.Commodore64
rasterOffsetX = rasterLineLeft;
borderOnHorizontal = true;
borderOnVertical = true;
totalCycles = rasterWidth / 8;
// initialize buffer
buffer = new int[rasterWidth * rasterTotalLines];
bufferSize = buffer.Length;
// initialize sprites
spritePointers = new ushort[8];
spriteData = new byte[8, 64];
// initialize registers
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()
{
refreshAddress = 0x3FFF;
regs = new VicIIRegs();
signal.VicBA = true;
signal.VicAEC = true;
signal.VicIRQ = false;
UpdateBorder();
}
public void PerformCycle()
{
// display enable check on line $30
if (regs.RASTER == 0x30)
{
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
for (int i = 0; i < 8; i++)
{
@ -568,6 +677,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
regs.VCBASE = 0;
renderOffset = 0;
displayEnabled = false;
refreshAddress = 0x3FFF;
}
// check to see if we are within viewing area Y
@ -645,6 +755,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
return result;
}
public bool SpriteOnLine(int index)
{
return false;
}
public void UpdateBorder()
{
borderTop = regs.RSEL ? 0x033 : 0x037;