commodore64: work begins on alternate VIC emulation

This commit is contained in:
saxxonpike 2012-11-17 06:03:44 +00:00
parent 0a8355ce1a
commit c1556de4a4
4 changed files with 1736 additions and 0 deletions

View File

@ -103,6 +103,9 @@
<Compile Include="Computers\Commodore64\Via.cs" />
<Compile Include="Computers\Commodore64\VicII.cs" />
<Compile Include="Computers\Commodore64\VicIIBackgroundGenerator.cs" />
<Compile Include="Computers\Commodore64\VicIINew.cs" />
<Compile Include="Computers\Commodore64\VicIINewPipeline.cs" />
<Compile Include="Computers\Commodore64\VicIIRegs.cs" />
<Compile Include="Computers\Commodore64\VicIISpriteGenerator.cs" />
<Compile Include="Computers\Commodore64\VicIIVideoProvider.cs" />
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public struct VicIIDataGenerator
{
}
public struct VicIISpriteGenerator
{
}
public partial class VicIINew
{
public Memory mem;
public Region region;
public ChipSignals signal;
public VicIINew(ChipSignals newSignal, Region newRegion)
{
region = newRegion;
signal = newSignal;
HardReset();
InitPipeline(newRegion);
}
public void HardReset()
{
InitRegs();
cycle = 0;
}
public bool Interrupt
{
get
{
return IRQ;
}
}
public void PerformCycle()
{
ExecutePipeline();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,578 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class VicIINew
{
private class VicIINewSprite
{
// internal regs
public int MC;
public int MCBASE;
public bool MDMA;
public int MPTR;
public int MSR;
public int MSRC;
// external regs
public int MxC; // sprite color
public bool MxD; // sprite-data collision
public bool MxDP; // sprite priority
public bool MxE; // sprite enabled
public bool MxM; // sprite-sprite collision
public bool MxMC; // sprite multicolor
public int MxX; // sprite X coordinate
public bool MxXE; // sprite X expansion
public int MxY; // sprite Y coordinate
public bool MxYE; // sprite Y expansion
}
// internal regs
private int RC;
private int VC;
private int VMLI;
// external regs
private bool BMM; // bitmap mode
private int[] BxC = new int[4]; // background colors
private int CB; // character bitmap offset
private bool CSEL; // column select
private bool DEN; // display enabled
private int EC; // border color
private bool ECM; // extra color mode
private bool ELP; // enable lightpen interrupt
private bool EMBC; // enable sprite-data interrupt
private bool EMMC; // enable sprite-sprite interrupt
private bool ERST; // enable raster line interrupt
private bool ILP; // light pen interrupt active
private bool IMBC; // sprite-data interrupt active
private bool IMMC; // sprite-sprite interrupt active
private bool IRQ; // interrupt was triggered
private bool IRST; // raster line interrupt active
private int LPX; // lightpen X coordinate
private int LPY; // lightpen Y coordinate
private bool MCM; // multicolor mode
private int[] MMx = new int[2]; // sprite extra color
private int RASTER; // current raster line
private bool RES; // reset bit (does nothing in this version of the VIC)
private bool RSEL; // row select
private int VM; // video memory offset
private int XSCROLL; // X scroll position
private int YSCROLL; // Y scroll position
private VicIINewSprite[] sprites;
private bool badline;
private byte bitmapData;
private int borderBottom;
private int borderLeft;
private bool borderOnMain;
private bool borderOnVertical;
private int borderRight;
private int borderTop;
private byte characterData;
private byte characterDataBus;
private byte[] characterMemory;
private byte colorData;
private byte colorDataBus;
private byte[] colorMemory;
private bool displayEnabled;
private int graphicsMode;
private int rasterInterruptLine;
private int rasterLeft;
private int rasterLines;
private int rasterWidth;
private int rasterX;
private int refreshAddress;
private void InitRegs()
{
// reset regs
for (int i = 0; i < 0x40; i++)
this[i] = 0x00;
// power on state
this[0x16] = 0xC0;
this[0x18] = 0x01;
this[0x19] = 0x71;
this[0x1A] = 0xF0;
// init sprites
sprites = new VicIINewSprite[8];
for (int i = 0; i < 8; i++)
sprites[i] = new VicIINewSprite();
}
private 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 = sprites[addr >> 1].MxX;
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0x09:
case 0x0B:
case 0x0D:
case 0x0F:
result = sprites[addr >> 1].MxY;
break;
case 0x10:
result = ((sprites[0].MxX & 0x100) != 0) ? 0x01 : 0x00;
result |= ((sprites[1].MxX & 0x100) != 0) ? 0x02 : 0x00;
result |= ((sprites[2].MxX & 0x100) != 0) ? 0x04 : 0x00;
result |= ((sprites[3].MxX & 0x100) != 0) ? 0x08 : 0x00;
result |= ((sprites[4].MxX & 0x100) != 0) ? 0x10 : 0x00;
result |= ((sprites[5].MxX & 0x100) != 0) ? 0x20 : 0x00;
result |= ((sprites[6].MxX & 0x100) != 0) ? 0x40 : 0x00;
result |= ((sprites[7].MxX & 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 = (sprites[0].MxE ? 0x01 : 0x00);
result |= (sprites[1].MxE ? 0x02 : 0x00);
result |= (sprites[2].MxE ? 0x04 : 0x00);
result |= (sprites[3].MxE ? 0x08 : 0x00);
result |= (sprites[4].MxE ? 0x10 : 0x00);
result |= (sprites[5].MxE ? 0x20 : 0x00);
result |= (sprites[6].MxE ? 0x40 : 0x00);
result |= (sprites[7].MxE ? 0x80 : 0x00);
break;
case 0x16:
result &= 0xC0;
result |= XSCROLL & 0x07;
result |= (CSEL ? 0x08 : 0x00);
result |= (MCM ? 0x10 : 0x00);
result |= (RES ? 0x20 : 0x00);
break;
case 0x17:
result = (sprites[0].MxYE ? 0x01 : 0x00);
result |= (sprites[1].MxYE ? 0x02 : 0x00);
result |= (sprites[2].MxYE ? 0x04 : 0x00);
result |= (sprites[3].MxYE ? 0x08 : 0x00);
result |= (sprites[4].MxYE ? 0x10 : 0x00);
result |= (sprites[5].MxYE ? 0x20 : 0x00);
result |= (sprites[6].MxYE ? 0x40 : 0x00);
result |= (sprites[7].MxYE ? 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 = (sprites[0].MxDP ? 0x01 : 0x00);
result |= (sprites[1].MxDP ? 0x02 : 0x00);
result |= (sprites[2].MxDP ? 0x04 : 0x00);
result |= (sprites[3].MxDP ? 0x08 : 0x00);
result |= (sprites[4].MxDP ? 0x10 : 0x00);
result |= (sprites[5].MxDP ? 0x20 : 0x00);
result |= (sprites[6].MxDP ? 0x40 : 0x00);
result |= (sprites[7].MxDP ? 0x80 : 0x00);
break;
case 0x1C:
result = (sprites[0].MxMC ? 0x01 : 0x00);
result |= (sprites[1].MxMC ? 0x02 : 0x00);
result |= (sprites[2].MxMC ? 0x04 : 0x00);
result |= (sprites[3].MxMC ? 0x08 : 0x00);
result |= (sprites[4].MxMC ? 0x10 : 0x00);
result |= (sprites[5].MxMC ? 0x20 : 0x00);
result |= (sprites[6].MxMC ? 0x40 : 0x00);
result |= (sprites[7].MxMC ? 0x80 : 0x00);
break;
case 0x1D:
result = (sprites[0].MxXE ? 0x01 : 0x00);
result |= (sprites[1].MxXE ? 0x02 : 0x00);
result |= (sprites[2].MxXE ? 0x04 : 0x00);
result |= (sprites[3].MxXE ? 0x08 : 0x00);
result |= (sprites[4].MxXE ? 0x10 : 0x00);
result |= (sprites[5].MxXE ? 0x20 : 0x00);
result |= (sprites[6].MxXE ? 0x40 : 0x00);
result |= (sprites[7].MxXE ? 0x80 : 0x00);
break;
case 0x1E:
result = (sprites[0].MxM ? 0x01 : 0x00);
result |= (sprites[1].MxM ? 0x02 : 0x00);
result |= (sprites[2].MxM ? 0x04 : 0x00);
result |= (sprites[3].MxM ? 0x08 : 0x00);
result |= (sprites[4].MxM ? 0x10 : 0x00);
result |= (sprites[5].MxM ? 0x20 : 0x00);
result |= (sprites[6].MxM ? 0x40 : 0x00);
result |= (sprites[7].MxM ? 0x80 : 0x00);
break;
case 0x1F:
result = (sprites[0].MxD ? 0x01 : 0x00);
result |= (sprites[1].MxD ? 0x02 : 0x00);
result |= (sprites[2].MxD ? 0x04 : 0x00);
result |= (sprites[3].MxD ? 0x08 : 0x00);
result |= (sprites[4].MxD ? 0x10 : 0x00);
result |= (sprites[5].MxD ? 0x20 : 0x00);
result |= (sprites[6].MxD ? 0x40 : 0x00);
result |= (sprites[7].MxD ? 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 |= sprites[addr - 0x27].MxC & 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;
sprites[index].MxX &= 0x100;
sprites[index].MxX |= (val & 0xFF);
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0x09:
case 0x0B:
case 0x0D:
case 0x0F:
index = addr >> 1;
sprites[index].MxY &= 0x100;
sprites[index].MxY |= (val & 0xFF);
break;
case 0x10:
sprites[0].MxX = (sprites[0].MxX & 0xFF) | ((val & 0x01) << 8);
sprites[1].MxX = (sprites[1].MxX & 0xFF) | ((val & 0x02) << 7);
sprites[2].MxX = (sprites[2].MxX & 0xFF) | ((val & 0x04) << 6);
sprites[3].MxX = (sprites[3].MxX & 0xFF) | ((val & 0x08) << 5);
sprites[4].MxX = (sprites[4].MxX & 0xFF) | ((val & 0x10) << 4);
sprites[5].MxX = (sprites[5].MxX & 0xFF) | ((val & 0x20) << 3);
sprites[6].MxX = (sprites[6].MxX & 0xFF) | ((val & 0x40) << 2);
sprites[7].MxX = (sprites[7].MxX & 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:
sprites[0].MxE = ((val & 0x01) != 0x00);
sprites[1].MxE = ((val & 0x02) != 0x00);
sprites[2].MxE = ((val & 0x04) != 0x00);
sprites[3].MxE = ((val & 0x08) != 0x00);
sprites[4].MxE = ((val & 0x10) != 0x00);
sprites[5].MxE = ((val & 0x20) != 0x00);
sprites[6].MxE = ((val & 0x40) != 0x00);
sprites[7].MxE = ((val & 0x80) != 0x00);
break;
case 0x16:
XSCROLL = (val & 0x07);
CSEL = ((val & 0x08) != 0x00);
MCM = ((val & 0x10) != 0x00);
RES = ((val & 0x20) != 0x00);
break;
case 0x17:
sprites[0].MxYE = ((val & 0x01) != 0x00);
sprites[1].MxYE = ((val & 0x02) != 0x00);
sprites[2].MxYE = ((val & 0x04) != 0x00);
sprites[3].MxYE = ((val & 0x08) != 0x00);
sprites[4].MxYE = ((val & 0x10) != 0x00);
sprites[5].MxYE = ((val & 0x20) != 0x00);
sprites[6].MxYE = ((val & 0x40) != 0x00);
sprites[7].MxYE = ((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);
break;
case 0x1A:
ERST = ((val & 0x01) != 0x00);
EMBC = ((val & 0x02) != 0x00);
EMMC = ((val & 0x04) != 0x00);
ELP = ((val & 0x08) != 0x00);
break;
case 0x1B:
sprites[0].MxDP = ((val & 0x01) != 0x00);
sprites[1].MxDP = ((val & 0x02) != 0x00);
sprites[2].MxDP = ((val & 0x04) != 0x00);
sprites[3].MxDP = ((val & 0x08) != 0x00);
sprites[4].MxDP = ((val & 0x10) != 0x00);
sprites[5].MxDP = ((val & 0x20) != 0x00);
sprites[6].MxDP = ((val & 0x40) != 0x00);
sprites[7].MxDP = ((val & 0x80) != 0x00);
break;
case 0x1C:
sprites[0].MxMC = ((val & 0x01) != 0x00);
sprites[1].MxMC = ((val & 0x02) != 0x00);
sprites[2].MxMC = ((val & 0x04) != 0x00);
sprites[3].MxMC = ((val & 0x08) != 0x00);
sprites[4].MxMC = ((val & 0x10) != 0x00);
sprites[5].MxMC = ((val & 0x20) != 0x00);
sprites[6].MxMC = ((val & 0x40) != 0x00);
sprites[7].MxMC = ((val & 0x80) != 0x00);
break;
case 0x1D:
sprites[0].MxXE = ((val & 0x01) != 0x00);
sprites[1].MxXE = ((val & 0x02) != 0x00);
sprites[2].MxXE = ((val & 0x04) != 0x00);
sprites[3].MxXE = ((val & 0x08) != 0x00);
sprites[4].MxXE = ((val & 0x10) != 0x00);
sprites[5].MxXE = ((val & 0x20) != 0x00);
sprites[6].MxXE = ((val & 0x40) != 0x00);
sprites[7].MxXE = ((val & 0x80) != 0x00);
break;
case 0x1E:
sprites[0].MxM = ((val & 0x01) != 0x00);
sprites[1].MxM = ((val & 0x02) != 0x00);
sprites[2].MxM = ((val & 0x04) != 0x00);
sprites[3].MxM = ((val & 0x08) != 0x00);
sprites[4].MxM = ((val & 0x10) != 0x00);
sprites[5].MxM = ((val & 0x20) != 0x00);
sprites[6].MxM = ((val & 0x40) != 0x00);
sprites[7].MxM = ((val & 0x80) != 0x00);
break;
case 0x1F:
sprites[0].MxD = ((val & 0x01) != 0x00);
sprites[1].MxD = ((val & 0x02) != 0x00);
sprites[2].MxD = ((val & 0x04) != 0x00);
sprites[3].MxD = ((val & 0x08) != 0x00);
sprites[4].MxD = ((val & 0x10) != 0x00);
sprites[5].MxD = ((val & 0x20) != 0x00);
sprites[6].MxD = ((val & 0x40) != 0x00);
sprites[7].MxD = ((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:
sprites[addr - 0x27].MxC = val & 0x0F;
break;
}
}
}
public byte Peek(int addr)
{
return this[addr & 0x3F];
}
public void Poke(int addr, byte val)
{
this[addr & 0x3F] = val;
}
public byte Read(ushort addr, byte val)
{
byte result = 0;
addr &= 0x3F;
switch (addr)
{
case 0x1E:
// clear after read
result = this[addr];
this[addr] = 0x00;
IMMC = false;
break;
case 0x1F:
// clear after read
result = this[addr];
this[addr] = 0x00;
IMBC = false;
break;
default:
result = this[addr];
break;
}
return result;
}
private void UpdateBorder()
{
borderTop = RSEL ? 0x033 : 0x037;
borderBottom = RSEL ? 0x0FB : 0x0F7;
borderLeft = CSEL ? 0x018 : 0x01F;
borderRight = CSEL ? 0x158 : 0x14F;
}
private void UpdateInterrupts()
{
IRQ = ((IRST & ERST) || (IMMC & EMMC) || (IMBC & EMBC) || (ILP & ELP));
}
private void UpdatePlotter()
{
graphicsMode = (ECM ? 0x04 : 0x00) | (BMM ? 0x02 : 0x00) | (MCM ? 0x01 : 0x00);
}
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)(this[addr] & 0x80);
this[addr] = val;
UpdateBorder();
UpdatePlotter();
break;
case 0x12:
// raster interrupt lower 8 bits
rasterInterruptLine &= 0x100;
rasterInterruptLine |= (val & 0xFF);
break;
case 0x16:
this[addr] = val;
UpdateBorder();
UpdatePlotter();
break;
case 0x19:
// only allow clearing of these flags
if ((val & 0x01) != 0x00)
IRST = false;
if ((val & 0x02) != 0x00)
IMBC = false;
if ((val & 0x04) != 0x00)
IMMC = false;
if ((val & 0x08) != 0x00)
ILP = false;
UpdateInterrupts();
break;
case 0x1E:
case 0x1F:
// can't write to these regs
break;
default:
this[addr] = val;
break;
}
}
}
}