Commodore64: Rewrote the character graphics generator as a shift register like real equipment. Roughly 10% performance increase and looks great. Sprites need work yet.

This commit is contained in:
saxxonpike 2013-08-25 00:31:52 +00:00
parent cfd3f05f1e
commit c0bad5eccb
8 changed files with 166 additions and 173 deletions

View File

@ -301,7 +301,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// underflow?
if (u)
{
//timerDelay[index] = 2;
timerDelay[index] = 1;
t = timerLatch[index];
if (timerRunMode[index] == RunMode.Oneshot)
timerOn[index] = false;

View File

@ -6,12 +6,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
static public class MOS6567
{
static int cycles = 65;
static int lines = 263;
static int vblankstart = 0x00D;
static int vblankend = 0x018;
static int hblankstart = 0x18C;
static int hblankend = 0x1F0;
static int scanwidth = cycles * 8;
static int lines = 263;
static int vblankstart = 0x00D % lines;
static int vblankend = 0x018 % lines;
static int hblankoffset = 20;
static int hblankstart = (0x18C + hblankoffset) % scanwidth;
static int hblankend = (0x1F0 + hblankoffset) % scanwidth;
static int[] timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, scanwidth, 0x18C, 8);
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x174);

View File

@ -6,12 +6,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
static public class MOS6569
{
static int cycles = 63;
static int lines = 312;
static int vblankstart = 0x12C;
static int vblankend = 0x00F;
static int hblankstart = 0x17C;
static int hblankend = 0x1E0;
static int scanwidth = cycles * 8;
static int lines = 312;
static int vblankstart = 0x12C % lines;
static int vblankend = 0x00F % lines;
static int hblankoffset = 20;
static int hblankstart = (0x17C + hblankoffset) % scanwidth;
static int hblankend = (0x1E0 + hblankoffset) % scanwidth;
static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, scanwidth, -1, -1);
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x164);

View File

@ -94,6 +94,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (extraColorMode)
parseaddr &= 0x39FF;
dataG = ReadMemory(parseaddr);
sr |= dataG << (7 - xScroll);
if (!idle)
{
bufferG[vmli] = dataG;

View File

@ -10,16 +10,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int borderSR;
int ecmPixel;
int pixel;
int[] pixelBackgroundBuffer;
int pixelBackgroundBufferDelay;
int pixelBackgroundBufferIndex;
int[] pixelBuffer;
int pixelBufferDelay;
int pixelBufferIndex;
int pixelData;
int pixelOwner;
int sprData;
int sprPixel;
int srOutput = 0;
int srOutputMC = 0;
int hblankSR = 0;
VicVideoMode videoMode;
enum VicVideoMode : int
@ -44,10 +41,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (rasterX == hblankStart)
hblank = true;
}
renderEnabled = !hblank && !vblank; //bufRect.Contains(bufPoint);
renderEnabled = (!hblank && !vblank);
for (int i = 0; i < 4; i++)
{
// fill shift register
if (bitmapColumn >= 8)
{
displayC >>= 12;
displayC &= 0xFFF;
if (!idle)
{
displayC |= (dataC << 12);
}
bitmapColumn &= 7;
}
if (borderCheckLEnable && (rasterX == borderL))
{
if (rasterLine == borderB)
@ -58,32 +67,80 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
borderOnMain = false;
}
if (borderCheckREnable && (rasterX == borderR))
borderOnMain = true;
// recall pixel from buffer
pixel = pixelBuffer[pixelBufferIndex];
// border doesn't work with the background buffer
borderSR <<= 1;
if (borderOnMain || borderOnVertical)
borderSR |= 1;
if ((borderSR & 0x100) != 0)
pixel = borderColor;
// plot pixel if within viewing area
if (renderEnabled)
srOutput = sr & srMask2;
if ((bitmapColumn & 1) == 0)
srOutputMC = sr & srMask3;
switch (videoMode)
{
case VicVideoMode.Mode000:
pixelData = srOutput;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
break;
case VicVideoMode.Mode001:
if ((displayC & 0x800) != 0)
{
// multicolor 001
pixelData = srOutputMC;
buf[bufOffset] = palette[pixel];
bufOffset++;
if (bufOffset == bufLength)
bufOffset = 0;
if (pixelData == srMask0)
pixel = backgroundColor0;
else if (pixelData == srMask1)
pixel = backgroundColor1;
else if (pixelData == srMask2)
pixel = backgroundColor2;
else
pixel = (displayC & 0x700) >> 8;
}
else
{
// standard 001
pixelData = srOutput;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
}
break;
case VicVideoMode.Mode010:
pixelData = srOutput;
pixel = (pixelData != 0) ? (displayC >> 4) : (displayC);
break;
case VicVideoMode.Mode011:
pixelData = srOutputMC;
if (pixelData == srMask0)
pixel = backgroundColor0;
else if (pixelData == srMask1)
pixel = (displayC >> 4);
else if (pixelData == srMask2)
pixel = displayC;
else
pixel = (displayC >> 8);
break;
case VicVideoMode.Mode100:
pixelData = srOutput;
if (pixelData != 0)
{
pixel = displayC >> 8;
}
else
{
ecmPixel = (displayC) & 0xC0;
if (ecmPixel == 0x00)
pixel = backgroundColor0;
else if (ecmPixel == 0x40)
pixel = backgroundColor1;
else if (ecmPixel == 0x80)
pixel = backgroundColor2;
else
pixel = backgroundColor3;
}
break;
default:
pixelData = 0;
pixel = 0;
break;
}
// put the pixel from the background buffer into the main buffer
pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex];
pixel &= 0xF;
sr <<= 1;
// render sprite
pixelOwner = 8;
for (int j = 0; j < 8; j++)
@ -125,7 +182,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// sprite-sprite collision
if (pixelOwner >= 8)
{
if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x80))
if (!spr.priority || ((sr & srMask) == 0))
pixel = sprPixel;
pixelOwner = j;
}
@ -139,7 +196,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
// sprite-data collision
if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] == 0x80))
if (!borderOnVertical && ((sr & srMask) != 0))
{
spr.collideData = true;
}
@ -149,113 +206,31 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
}
// store pixel in buffer
pixelBuffer[pixelBufferIndex] = pixel;
if (borderCheckREnable && (rasterX == borderR))
borderOnMain = true;
// fill shift register
if (xOffset == xScroll)
// border doesn't work with the background buffer
if (borderOnMain || borderOnVertical)
pixel = borderColor;
// plot pixel if within viewing area
if (renderEnabled)
{
if (displayIndex < 40 && !idle)
{
displayC = bufferC[displayIndex];
sr |= bufferG[displayIndex];
}
bitmapColumn = 0;
buf[bufOffset] = palette[pixBuffer[pixBufferIndex]];
bufOffset++;
if (bufOffset == bufLength)
bufOffset = 0;
}
pixBuffer[pixBufferIndex] = pixel;
pixBufferIndex++;
switch (videoMode)
{
case VicVideoMode.Mode000:
pixelData = (sr & 0x80);
sr <<= 1;
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
break;
case VicVideoMode.Mode001:
if ((displayC & 0x800) != 0)
{
// multicolor 001
pixelData = (sr & 0xC0);
if ((bitmapColumn & 1) != 0)
sr <<= 2;
if (pixelData == 0x00)
pixel = backgroundColor0;
else if (pixelData == 0x40)
pixel = backgroundColor1;
else if (pixelData == 0x80)
pixel = backgroundColor2;
else
pixel = (displayC & 0x700) >> 8;
}
else
{
// standard 001
pixelData = (sr & 0x80);
sr <<= 1;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
}
break;
case VicVideoMode.Mode010:
pixelData = (sr & 0x80);
sr <<= 1;
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
break;
case VicVideoMode.Mode011:
pixelData = (sr & 0xC0);
if ((bitmapColumn & 1) != 0)
sr <<= 2;
if (pixelData == 0x00)
pixel = backgroundColor0;
else if (pixelData == 0x40)
pixel = (displayC >> 4) & 0xF;
else if (pixelData == 0x80)
pixel = displayC & 0xF;
else
pixel = (displayC >> 8) & 0xF;
break;
case VicVideoMode.Mode100:
pixelData = (sr & 0x80);
sr <<= 1;
if (pixelData != 0)
{
pixel = displayC >> 8;
}
else
{
ecmPixel = (displayC) & 0xC0;
if (ecmPixel == 0x00)
pixel = backgroundColor0;
else if (ecmPixel == 0x40)
pixel = backgroundColor1;
else if (ecmPixel == 0x80)
pixel = backgroundColor2;
else
pixel = backgroundColor3;
}
break;
default:
pixelData = 0;
pixel = 0;
break;
}
// put the rendered pixel into the background buffer
pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData;
pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel;
pixelBackgroundBufferIndex++;
if (pixelBackgroundBufferIndex == pixelBackgroundBufferDelay)
pixelBackgroundBufferIndex = 0;
// advance pixel buffer
pixelBufferIndex++;
if (pixelBufferIndex == pixelBufferDelay)
pixelBufferIndex = 0;
rasterX++;
xOffset++;
if (!rasterXHold)
rasterX++;
bitmapColumn++;
}
if (pixBufferIndex >= pixBufferSize)
pixBufferIndex = 0;
}
}
}

View File

@ -34,8 +34,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int dataC;
int dataG;
bool debugScreen;
int delayedC;
bool displayEnable;
int displayIndex;
int displayC;
bool enableIntLightPen;
bool enableIntRaster;
@ -59,7 +59,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
bool pinAEC = true;
bool pinBA = true;
bool pinIRQ = true;
int[] pixelDataBuffer;
//int[] pixelDataBuffer;
int pointerCB;
int pointerVM;
int rasterInterruptLine;
@ -74,13 +74,19 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int spriteMulticolor1;
Sprite[] sprites;
int sr;
int srMask;
int srMask0;
int srMask1;
int srMask2;
int srMask3;
int srMaskMC;
bool vblank;
int vblankEnd;
int vblankStart;
int vc;
int vcbase;
int vmli;
int xOffset;
//int xOffset;
int xScroll;
int yScroll;
@ -107,7 +113,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
borderOnVertical = true;
columnSelect = false;
displayEnable = false;
displayIndex = 0;
enableIntLightPen = false;
enableIntRaster = false;
enableIntSpriteCollision = false;
@ -123,8 +128,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
lightPenX = 0;
lightPenY = 0;
multicolorMode = false;
pixelBufferIndex = 0;
pixelBackgroundBufferIndex = 0;
//pixelBufferIndex = 0;
//pixelBackgroundBufferIndex = 0;
pointerCB = 0;
pointerVM = 0;
rasterInterruptLine = 0;
@ -136,11 +141,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
spriteMulticolor0 = 0;
spriteMulticolor1 = 0;
sr = 0;
srMask0 = 0x000000;
srMask1 = 0x200000;
srMask2 = srMask1 << 1;
srMask3 = srMask1 | srMask2;
srMask = srMask2;
srMaskMC = srMask3;
vblank = true;
vc = 0;
vcbase = 0;
vmli = 0;
xOffset = 0;
//xOffset = 0;
xScroll = 0;
yScroll = 0;
@ -156,13 +167,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
// clear pixel buffer
for (int i = 0; i < pixelBufferDelay; i++)
{
pixelBuffer[i] = 0;
pixelDataBuffer[i] = 0;
}
for (int i = 0; i < pixelBackgroundBufferDelay; i++)
pixelBackgroundBuffer[i] = 0;
//for (int i = 0; i < pixelBufferDelay; i++)
//{
// pixelBuffer[i] = 0;
// pixelDataBuffer[i] = 0;
//}
//for (int i = 0; i < pixelBackgroundBufferDelay; i++)
// pixelBackgroundBuffer[i] = 0;
pixBuffer = new int[pixBufferSize];
UpdateBorder();
}

View File

@ -9,6 +9,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int bufLength;
int bufOffset;
int bufWidth;
int pixBufferSize = 12;
int[] pixBuffer;
int pixBufferIndex;
// palette
int[] palette =

View File

@ -20,7 +20,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd)
{
{
{
debugScreen = false;
this.hblankStart = hblankStart;
@ -32,8 +32,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
totalLines = newLines;
pipeline = newPipeline;
cyclesPerSec = newCyclesPerSec;
pixelBufferDelay = 12;
pixelBackgroundBufferDelay = 4;
//pixelBufferDelay = 4;
//pixelBackgroundBufferDelay = 12;
bufWidth = TimingBuilder_ScreenWidth(pipeline[0], hblankStart, hblankEnd);
bufHeight = TimingBuilder_ScreenHeight(vblankStart, vblankEnd, newLines);
@ -47,9 +47,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
bufferC = new int[40];
bufferG = new int[40];
pixelBuffer = new int[pixelBufferDelay];
pixelDataBuffer = new int[pixelBufferDelay];
pixelBackgroundBuffer = new int[pixelBackgroundBufferDelay];
//pixelBuffer = new int[pixelBufferDelay];
//pixelDataBuffer = new int[pixelBufferDelay];
//pixelBackgroundBuffer = new int[pixelBackgroundBufferDelay];
}
}
@ -71,7 +71,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public void ExecutePhase1()
{
//xScroll = 1;
bitmapColumn = 8 - xScroll;
{
// raster IRQ compare
if ((cycle == rasterIrqLineXCycle && rasterLine > 0) || (cycle == rasterIrqLine0Cycle && rasterLine == 0))
@ -88,9 +89,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// badline compare
if (badlineEnable && rasterLine >= 0x030 && rasterLine < 0x0F7 && ((rasterLine & 0x7) == yScroll))
{
badline = true;
}
else
{
badline = false;
}
// go into display state on a badline
if (badline)
@ -106,15 +111,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (!sprites[6].yExpand) sprites[6].yCrunch = true;
if (!sprites[7].yExpand) sprites[7].yCrunch = true;
// set up display index for rendering
if (cycle == 15)
displayIndex = 0;
else if (cycle > 15 && cycle <= 55)
displayIndex++;
ParseCycle();
xOffset = 0;
//xOffset = 0;
Render();
// if the BA counter is nonzero, allow CPU bus access
@ -197,7 +196,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
irqShift <<= 1;
irqShift |= (irqTemp ? 0x1 : 0x0);
pinIRQ = (irqShift & 0x2) != 0;
pinIRQ = (irqShift & 0x1) != 0;
}
private void UpdateVideoMode()