VIC- character generator implemented

This commit is contained in:
saxxonpike 2012-11-06 05:49:42 +00:00
parent e7f3abdfc3
commit 4af6b10971
4 changed files with 184 additions and 40 deletions

View File

@ -12,6 +12,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
// source // source
public Cartridge cart; public Cartridge cart;
public bool cartInserted; public bool cartInserted;
public string extension;
public byte[] inputFile; public byte[] inputFile;
// chipset // chipset
@ -50,15 +51,28 @@ namespace BizHawk.Emulation.Computers.Commodore64
mem = new Memory(romPath, vic, sid, cia0, cia1); mem = new Memory(romPath, vic, sid, cia0, cia1);
vic.mem = mem; vic.mem = mem;
// initialize media
Cartridge cart = new Cartridge(inputFile);
if (cart.valid)
{
mem.ApplyCartridge(cart);
}
// initialize cpu (hard reset vector) // initialize cpu (hard reset vector)
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8)); cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
// initialize media
switch (extension.ToUpper())
{
case @".PRG":
if (inputFile.Length > 2)
{
mem.ApplyMemory(inputFile);
// idle vector
cpu.PC = (ushort)2064;
}
break;
case @".CRT":
Cartridge cart = new Cartridge(inputFile);
if (cart.valid)
{
mem.ApplyCartridge(cart);
}
break;
}
} }
public byte PeekMemory(ushort addr) public byte PeekMemory(ushort addr)

View File

@ -12,6 +12,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public C64(GameInfo game, byte[] rom, string romextension) public C64(GameInfo game, byte[] rom, string romextension)
{ {
inputFile = rom; inputFile = rom;
extension = romextension;
SetupMemoryDomains(); SetupMemoryDomains();
CoreOutputComm = new CoreOutputComm(); CoreOutputComm = new CoreOutputComm();
CoreInputComm = new CoreInputComm(); CoreInputComm = new CoreInputComm();

View File

@ -74,9 +74,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
public Memory(string sourceFolder, VicII newVic, Sid newSid, Cia newCia0, Cia newCia1) public Memory(string sourceFolder, VicII newVic, Sid newSid, Cia newCia0, Cia newCia1)
{ {
ram = new byte[0x10000];
WipeMemory();
string basicFile = "basic"; string basicFile = "basic";
string charFile = "chargen"; string charFile = "chargen";
string kernalFile = "kernal"; string kernalFile = "kernal";
@ -84,7 +81,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
basicRom = File.ReadAllBytes(Path.Combine(sourceFolder, basicFile)); basicRom = File.ReadAllBytes(Path.Combine(sourceFolder, basicFile));
charRom = File.ReadAllBytes(Path.Combine(sourceFolder, charFile)); charRom = File.ReadAllBytes(Path.Combine(sourceFolder, charFile));
kernalRom = File.ReadAllBytes(Path.Combine(sourceFolder, kernalFile)); kernalRom = File.ReadAllBytes(Path.Combine(sourceFolder, kernalFile));
colorRam = new byte[0x1000];
vic = newVic; vic = newVic;
sid = newSid; sid = newSid;
@ -94,10 +90,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
cia0.ports[1] = cia0PortB; cia0.ports[1] = cia0PortB;
cia1.ports[0] = cia1PortA; cia1.ports[0] = cia1PortA;
cia1.ports[1] = cia1PortB; cia1.ports[1] = cia1PortB;
cpuPort = new DirectionalDataPort(0x37, 0x2F);
layout = new MemoryLayout(); HardReset();
UpdateLayout();
} }
public void ApplyCartridge(Cartridge newCart) public void ApplyCartridge(Cartridge newCart)
@ -109,6 +103,21 @@ namespace BizHawk.Emulation.Computers.Commodore64
UpdateLayout(); UpdateLayout();
} }
public void ApplyMemory(byte[] newMemory)
{
int address = newMemory[1];
address <<= 8;
address |= newMemory[0];
int count = newMemory.Length;
for (int i = 2; i < count; i++)
{
Write((ushort)(address & 0xFFFF), newMemory[i]);
address++;
}
}
public MemoryDesignation GetDesignation(ushort addr) public MemoryDesignation GetDesignation(ushort addr)
{ {
MemoryDesignation result; MemoryDesignation result;
@ -178,6 +187,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
return result; return result;
} }
public void HardReset()
{
ram = new byte[0x10000];
colorRam = new byte[0x1000];
WipeMemory();
cpuPort = new DirectionalDataPort(0x37, 0x2F);
layout = new MemoryLayout();
UpdateLayout();
}
public byte Peek(ushort addr) public byte Peek(ushort addr)
{ {
byte result; byte result;
@ -428,6 +447,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
for (int j = 0x40; j < 0x80; j++) for (int j = 0x40; j < 0x80; j++)
ram[i + j] = 0xFF; ram[i + j] = 0xFF;
} }
for (int i = 0; i < 0x1000; i++)
{
colorRam[i] = 0x0E;
}
} }
public void Write(ushort addr, byte val) public void Write(ushort addr, byte val)

View File

@ -471,16 +471,23 @@ namespace BizHawk.Emulation.Computers.Commodore64
// raster // raster
public bool badLine; public bool badLine;
public byte bitmapData;
public byte bitmapDataMask;
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 int characterIndex;
public byte[] characterMemory; public byte[] characterMemory;
public int characterRow;
public byte[] colorMemory; public byte[] colorMemory;
public int cycle; public int cycle;
public int cycleLeft;
public bool displayEnabled; public bool displayEnabled;
public bool hBlank;
public bool idle;
public int rasterInterruptLine; public int rasterInterruptLine;
public int rasterLineLeft; public int rasterLineLeft;
public int rasterOffset; public int rasterOffset;
@ -490,9 +497,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int refreshAddress; public int refreshAddress;
public int renderOffset; public int renderOffset;
public byte[,] spriteData; public byte[,] spriteData;
public int spriteFetchCycle;
public ushort[] spritePointers; public ushort[] spritePointers;
public VicIITask task; public VicIITask task;
public int totalCycles; public int totalCycles;
public bool vBlank;
public int visibleBottom; public int visibleBottom;
public int visibleHeight; public int visibleHeight;
public int visibleLeft; public int visibleLeft;
@ -506,6 +515,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
public VicIIRegs regs; public VicIIRegs regs;
public ChipSignals signal; public ChipSignals signal;
private delegate int PlotterDelegate(int offset);
private PlotterDelegate Plotter;
public VicII(ChipSignals newSignal, VicIIMode videoMode) public VicII(ChipSignals newSignal, VicIIMode videoMode)
{ {
signal = newSignal; signal = newSignal;
@ -513,17 +525,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
switch (videoMode) switch (videoMode)
{ {
case VicIIMode.NTSC: case VicIIMode.NTSC:
rasterWidth = 512; totalCycles = 65;
rasterTotalLines = 263; rasterTotalLines = 263;
rasterLineLeft = 0x19C; rasterLineLeft = 0x19C;
visibleLeft = 0x1E9; cycleLeft = 0;
visibleRight = 0x159; spriteFetchCycle = 58;
visibleTop = 0x41; visibleLeft = 0x19C; //0x1E9;
visibleBottom = 0x13; visibleRight = 0x19C;
visibleTop = 0x000; //0x041;
visibleBottom = 0x000; //0x013;
visibleRenderX = false; visibleRenderX = false;
visibleRenderY = false; visibleRenderY = false;
visibleWidth = 368; visibleWidth = 0x208; //418;
visibleHeight = 217; visibleHeight = 263; //235;
renderOffset = 0; renderOffset = 0;
break; break;
case VicIIMode.PAL: case VicIIMode.PAL:
@ -533,34 +547,44 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
// initialize raster // initialize raster
rasterWidth = totalCycles * 8;
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[visibleWidth * visibleHeight];
bufferSize = buffer.Length; bufferSize = buffer.Length;
// initialize sprites // initialize sprites
spritePointers = new ushort[8]; spritePointers = new ushort[8];
spriteData = new byte[8, 64]; spriteData = new byte[8, 64];
// initialize screen buffer
characterMemory = new byte[41];
colorMemory = new byte[41];
// initialize registers // initialize registers
HardReset(); HardReset();
} }
private void GetBitmapData()
{
ushort offset = (ushort)((regs.CB << 11) + (characterMemory[characterIndex] * 8) + characterRow);
bitmapData = mem.VicRead(offset);
}
private void GetScreenData(int index) private void GetScreenData(int index)
{ {
ushort offset = (ushort)(regs.VM + regs.VC); ushort offset = (ushort)((regs.VM << 10) + regs.VC);
characterMemory[index] = mem.VicRead(offset); characterMemory[index] = mem.VicRead(offset);
colorMemory[index] = mem.colorRam[regs.VC]; colorMemory[index] = mem.colorRam[regs.VC];
} }
private void GetSpriteData(int index) private void GetSpriteData(int index)
{ {
ushort offset = (ushort)(regs.VM + 0x3F8 + index); ushort offset = (ushort)((regs.VM << 10) + 0x3F8 + index);
spritePointers[index] = (ushort)(regs.VM + (mem.VicRead(offset) * 64)); spritePointers[index] = (ushort)((regs.VM << 10) + (mem.VicRead(offset) * 64));
for (ushort i = 0; i < 64; i++) for (ushort i = 0; i < 64; i++)
spriteData[index, i] = mem.VicRead((ushort)(spritePointers[index] + i)); spriteData[index, i] = mem.VicRead((ushort)(spritePointers[index] + i));
} }
@ -576,6 +600,15 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void PerformCycle() public void PerformCycle()
{ {
characterIndex = regs.VMLI;
characterRow = regs.RC;
// reset VC and VCBASE if on scan 0
if (regs.RASTER == 0x00)
{
regs.VCBASE = 0;
regs.VC = 0;
}
// display enable check on line $30 // display enable check on line $30
if (regs.RASTER == 0x30) if (regs.RASTER == 0x30)
@ -619,8 +652,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
regs.VC = regs.VCBASE; regs.VC = regs.VCBASE;
regs.VMLI = 0; regs.VMLI = 0;
if (badLine) characterIndex = 0;
regs.RC = 0;
} }
} }
else if (cycle >= 15 && cycle < 55) else if (cycle >= 15 && cycle < 55)
@ -635,6 +667,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
signal.VicAEC = true; signal.VicAEC = true;
} }
GetBitmapData();
regs.VC++; regs.VC++;
regs.VMLI++; regs.VMLI++;
} }
@ -643,18 +676,20 @@ namespace BizHawk.Emulation.Computers.Commodore64
// increment VIC row counter // increment VIC row counter
if (regs.RC == 7) if (regs.RC == 7)
{ {
regs.VCBASE = regs.VC; if (!borderOnHorizontal)
regs.VCBASE = regs.VC;
} }
regs.RC = (regs.RC + 1) & 0x07; regs.RC = (regs.RC + 1) & 0x07;
if (badLine) if (badLine)
{ {
regs.RC = 0; regs.RC = 0;
} }
} }
else if (cycle >= totalCycles - 6) else if (cycle >= spriteFetchCycle)
{ {
// fetch sprite data 0-2 // fetch sprite data 0-2
int index = (cycle - (totalCycles - 6)) >> 1; int index = (cycle - spriteFetchCycle) >> 1;
if (regs.MxE[index]) if (regs.MxE[index])
{ {
signal.VicAEC = false; signal.VicAEC = false;
@ -674,9 +709,27 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
// pixel clock is 8x the VIC clock // determine the plot mode
if (!regs.ECM && !regs.BMM && !regs.MCM)
Plotter = Plot000;
else if (!regs.ECM && !regs.BMM && regs.MCM)
Plotter = Plot001;
else if (!regs.ECM && regs.BMM && !regs.MCM)
Plotter = Plot010;
else if (!regs.ECM && regs.BMM && regs.MCM)
Plotter = Plot011;
else if (regs.ECM && !regs.BMM && !regs.MCM)
Plotter = Plot100;
else if (regs.ECM && !regs.BMM && regs.MCM)
Plotter = Plot101;
else if (regs.ECM && regs.BMM && !regs.MCM)
Plotter = Plot110;
else
Plotter = Plot111;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
// pixel clock is 8x the VIC clock
int pixel; int pixel;
// process raster position // process raster position
@ -684,25 +737,23 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
// reset to the left side // reset to the left side
rasterOffsetX -= rasterWidth; rasterOffsetX -= rasterWidth;
regs.RASTER = rasterOffset >> 9; regs.RASTER++;
cycle = 0;
// if vblank, reset the raster position // if vblank, reset the raster position
if (regs.RASTER == rasterTotalLines) if (regs.RASTER == rasterTotalLines)
{ {
rasterOffset = 0; rasterOffset = 0;
regs.RASTER = 0; regs.RASTER = 0;
regs.VCBASE = 0;
renderOffset = 0; renderOffset = 0;
displayEnabled = false; displayEnabled = false;
refreshAddress = 0x3FFF; refreshAddress = 0x3FFF;
} }
// check to see if we are within viewing area Y // check to see if we are within viewing area Y
if (regs.RASTER == visibleTop)
visibleRenderY = true;
if (regs.RASTER == visibleBottom) if (regs.RASTER == visibleBottom)
visibleRenderY = false; visibleRenderY = false;
if (regs.RASTER == visibleTop)
visibleRenderY = true;
// check to see if we are on a horizontal border // check to see if we are on a horizontal border
if (displayEnabled && (regs.RASTER == borderTop || regs.RASTER == borderBottom)) if (displayEnabled && (regs.RASTER == borderTop || regs.RASTER == borderBottom))
@ -714,10 +765,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
// check to see if we are within viewing area X // check to see if we are within viewing area X
if (rasterOffsetX == visibleLeft)
visibleRenderX = true;
if (rasterOffsetX == visibleRight) if (rasterOffsetX == visibleRight)
visibleRenderX = false; visibleRenderX = false;
if (rasterOffsetX == visibleLeft)
visibleRenderX = true;
// check to see if we are on a vertical border // check to see if we are on a vertical border
if (rasterOffsetX == borderLeft) if (rasterOffsetX == borderLeft)
@ -727,9 +778,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
// draw the border if it is on, otherwise draw the screen // draw the border if it is on, otherwise draw the screen
if (borderOnHorizontal || borderOnVertical) if (borderOnHorizontal || borderOnVertical)
{
pixel = regs.EC; pixel = regs.EC;
}
else else
pixel = regs.BxC[0]; {
pixel = Plotter(i);
}
// plot the pixel if within visible range // plot the pixel if within visible range
if (visibleRenderX && visibleRenderY) if (visibleRenderX && visibleRenderY)
@ -749,7 +804,58 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
signal.VicIRQ = regs.IRQ; signal.VicIRQ = regs.IRQ;
cycle++; cycle++;
if (cycle == totalCycles)
cycle = 0;
hBlank = !visibleRenderX;
vBlank = !visibleRenderY;
}
private int Plot000(int offset)
{
byte charData = bitmapData;
charData <<= offset;
if ((charData & 0x80) != 0x00)
return colorMemory[characterIndex];
else
return regs.BxC[0];
}
private int Plot001(int offset)
{
return regs.BxC[0];
}
private int Plot010(int offset)
{
return regs.BxC[0];
}
private int Plot011(int offset)
{
return regs.BxC[0];
}
private int Plot100(int offset)
{
return regs.BxC[0];
}
private int Plot101(int offset)
{
return regs.BxC[0];
}
private int Plot110(int offset)
{
return regs.BxC[0];
}
private int Plot111(int offset)
{
return regs.BxC[0];
} }
public byte Read(ushort addr) public byte Read(ushort addr)