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 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; } }
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
cpu.IRQ = true;
|
||||
}
|
||||
if (signal.CpuRDY)
|
||||
if (signal.CpuAEC)
|
||||
{
|
||||
cpu.ExecuteOne();
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue