Commodore64: Experimental Vic implementation nearly complete.

This commit is contained in:
saxxonpike 2013-08-21 12:12:30 +00:00
parent c827d42f2d
commit cfc2b141bf
1 changed files with 255 additions and 18 deletions

View File

@ -14,17 +14,30 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
bool badLineCondition; bool badLineCondition;
bool badLineEnable; bool badLineEnable;
int characterData; int characterData;
int[] characterMatrix;
int colorData; int colorData;
int[] colorMatrix;
int data; int data;
int graphicsData; int graphicsData;
int graphicsGeneratorCharacter;
int graphicsGeneratorColor;
int graphicsGeneratorData;
int graphicsGeneratorPixel;
int graphicsGeneratorPixelData;
bool idleState;
bool mainBorder; bool mainBorder;
int mainBorderEnd;
int mainBorderStart;
bool phi0; bool phi0;
int phi1Data; int phi1Data;
int pixel; int pixel;
int[] pixelDataBuffer;
int rasterX; int rasterX;
int refreshCounter; int refreshCounter;
int rowCounter; int rowCounter;
bool verticalBorder; bool verticalBorder;
int verticalBorderEnd;
int verticalBorderStart;
int videoCounter; int videoCounter;
int videoCounterBase; int videoCounterBase;
int videoMatrixLineIndex; int videoMatrixLineIndex;
@ -42,6 +55,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
if (screenYEnd < screenYStart) if (screenYEnd < screenYStart)
screenHeight += rasterCount; screenHeight += rasterCount;
// create video buffer
videoBuffer = new int[screenWidth * screenHeight];
// reset registers // reset registers
pixelBufferLength = 12; pixelBufferLength = 12;
Reset(); Reset();
@ -49,16 +65,39 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
public void Clock() public void Clock()
{ {
// these should be cached somewhere
mainBorderStart = columnSelect ? 0x18 : 0x1F;
mainBorderEnd = columnSelect ? 0x158 : 0x14F;
verticalBorderStart = rowSelect ? 0x33 : 0x37;
verticalBorderEnd = rowSelect ? 0xFB : 0xF7;
do do
{ {
// process horizontal triggers // process hblank trigger
if (rasterX == screenXStart) if (rasterX == screenXStart)
hBlank = false; hBlank = false;
else if (rasterX == screenXEnd) else if (rasterX == screenXEnd && !hBlank)
{ {
hBlank = true; hBlank = true;
rasterDelay = hBlankDelay; rasterDelay = hBlankDelay;
// process row counter
if (rowCounter == 7)
{
idleState = true;
videoCounterBase = videoCounter;
}
else if (!idleState)
rowCounter++;
// process vertical border flipflop
if (rasterY == mainBorderEnd)
verticalBorder = true;
if (rasterY == mainBorderStart && displayEnable)
verticalBorder = false;
} }
// process character BA trigger
if (rasterX == characterBAStart) if (rasterX == characterBAStart)
characterBA = false; characterBA = false;
else if (rasterX == characterBAEnd) else if (rasterX == characterBAEnd)
@ -66,13 +105,21 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
characterBA = true; characterBA = true;
graphicsFetch = false; graphicsFetch = false;
} }
// process character fetch trigger
if (rasterX == characterFetchStart) if (rasterX == characterFetchStart)
{ {
graphicsFetch = true; graphicsFetch = true;
refreshFetch = false; refreshFetch = false;
} }
// process new line/raster triggers
if (rasterX == rasterWidth) if (rasterX == rasterWidth)
{
rasterX = 0; rasterX = 0;
videoCounter = videoCounterBase;
videoMatrixLineIndex = 0;
}
else if (rasterX == rasterAdvance) else if (rasterX == rasterAdvance)
{ {
// process vertical triggers // process vertical triggers
@ -81,20 +128,26 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
vBlank = false; vBlank = false;
else if (rasterY == screenYEnd) else if (rasterY == screenYEnd)
vBlank = true; vBlank = true;
else if (rasterY == rasterCount)
{
rasterY = 0;
videoCounterBase = 0;
videoBufferIndex = 0;
}
} }
// determine BA and fetch state
ba = true;
// None is used for when we don't assert control. // None is used for when we don't assert control.
fetchState = phi0 ? FetchState.Idle : FetchState.None; fetchState = phi0 ? FetchState.Idle : FetchState.None;
// determine BA state
ba = true;
if (characterBA) if (characterBA)
{ {
// covers badlines and display area fetches // covers badlines and display area fetches
characterFetch = (badLineCondition && badLineEnable); characterFetch = (badLineCondition && badLineEnable);
ba = !characterFetch; ba = !characterFetch;
fetchState = phi0 ? FetchState.Graphics : (characterFetch ? FetchState.Character : FetchState.None); fetchState = phi0 ? FetchState.Graphics : FetchState.Character;
} }
else if (refreshFetch) else if (refreshFetch)
{ {
@ -104,6 +157,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
else else
{ {
// covers sprite pointer and data fetches // covers sprite pointer and data fetches
spriteIndex = 0;
foreach (Sprite sprite in sprites) foreach (Sprite sprite in sprites)
{ {
if (rasterX == sprite.BAStart) if (rasterX == sprite.BAStart)
@ -113,18 +167,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sprite.BA = true; sprite.BA = true;
sprite.Fetch = false; sprite.Fetch = false;
} }
if (!sprite.BA && sprite.Enabled) if (sprite.Fetch)
{ {
fetchState = FetchState.Sprite; fetchState = FetchState.Sprite;
ba = false; ba = false;
break; break;
} }
if (rasterX == sprite.FetchStart) else if (rasterX == sprite.FetchStart)
{ {
sprite.Fetch = true; sprite.Fetch = sprite.Enabled;
fetchState = FetchState.Pointer; fetchState = FetchState.Pointer;
ba = !sprite.Fetch;
break; break;
} }
spriteIndex++;
} }
} }
@ -147,17 +203,34 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
switch (fetchState) switch (fetchState)
{ {
case FetchState.Character: case FetchState.Character:
address = videoCounter | videoMemory; if (badLineCondition)
colorData = ReadColorRam(address); {
characterData = ReadRam(address); address = videoCounter | videoMemory;
data = characterData; colorMatrix[videoMatrixLineIndex] = colorData = ReadColorRam(address);
characterMatrix[videoMatrixLineIndex] = characterData = data = ReadRam(address);
}
else if (!idleState)
{
colorData = colorMatrix[videoMatrixLineIndex];
characterData = characterMatrix[videoMatrixLineIndex];
}
else
{
colorData = 0;
characterData = 0;
}
break; break;
case FetchState.Graphics: case FetchState.Graphics:
address = (extraColorMode ? 0x39FF : 0x3FFF); address = (extraColorMode ? 0x39FF : 0x3FFF);
if (bitmapMode) if (!idleState)
address &= (rowCounter | (videoCounter << 3) | (characterBitmap & 0x2000)); {
else if (bitmapMode)
address &= (rowCounter | (data << 3) | characterBitmap); address &= (rowCounter | (videoCounter << 3) | (characterBitmap & 0x2000));
else
address &= (rowCounter | (characterData << 3) | characterBitmap);
videoMatrixLineIndex++;
videoMatrixLineIndex &= 0x3F;
}
data = ReadRam(address); data = ReadRam(address);
graphicsData = data; graphicsData = data;
break; break;
@ -172,6 +245,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
case FetchState.Refresh: case FetchState.Refresh:
address = refreshCounter | 0x3F00; address = refreshCounter | 0x3F00;
data = ReadRam(address); data = ReadRam(address);
refreshCounter--;
refreshCounter &= 0xFF;
break; break;
case FetchState.Sprite: case FetchState.Sprite:
address = data | sprites[spriteIndex].Counter; address = data | sprites[spriteIndex].Counter;
@ -182,20 +257,169 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
// render 4 pixels // render 4 pixels
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
// pixelbuffer -> videobuffer
if (!hBlank && !vBlank) if (!hBlank && !vBlank)
{ {
videoBuffer[videoBufferIndex] = palette[pixelBuffer[pixelBufferIndex]];
videoBufferIndex++; videoBufferIndex++;
} }
// graphics generator
if ((rasterX & 0x7) == xScroll)
{
graphicsGeneratorCharacter = characterData;
graphicsGeneratorColor = colorData;
graphicsGeneratorData = graphicsData;
}
// shift graphics data
if (!multiColorMode || (!bitmapMode && ((colorData & 0x4) == 0)))
{
graphicsGeneratorPixelData = graphicsData & 0x01;
graphicsData >>= 1;
}
else if ((rasterX & 0x7) == xScroll)
{
graphicsGeneratorPixelData = graphicsData & 0x03;
graphicsData >>= 2;
}
// generate pixel
if (!verticalBorder)
{
if (extraColorMode)
{
if (bitmapMode)
{
// ECM=1, BMM=1, MCM=1
// ECM=1, BMM=1, MCM=0
graphicsGeneratorPixel = 0;
}
else
{
if (multiColorMode)
{
// ECM=1, BMM=0, MCM=1
graphicsGeneratorPixel = 0;
}
else
{
// ECM=1, BMM=0, MCM=0
if (graphicsGeneratorPixelData == 0)
graphicsGeneratorPixel = backgroundColor[characterData >> 6];
else
graphicsGeneratorPixel = colorData;
}
}
}
else
{
if (bitmapMode)
{
if (multiColorMode)
{
// ECM=0, BMM=1, MCM=1
if (graphicsGeneratorPixelData == 0x0)
graphicsGeneratorPixel = backgroundColor[0];
else if (graphicsGeneratorPixelData == 0x1)
graphicsGeneratorPixel = characterData >> 4;
else if (graphicsGeneratorPixelData == 0x2)
graphicsGeneratorPixel = (characterData & 0xF);
else
graphicsGeneratorPixel = colorData;
}
else
{
// ECM=0, BMM=1, MCM=0
if (graphicsGeneratorPixelData == 0x0)
graphicsGeneratorPixel = (characterData & 0xF);
else
graphicsGeneratorPixel = characterData >> 4;
}
}
else
{
if (multiColorMode)
{
// ECM=0, BMM=0, MCM=1
if ((colorData & 0x4) == 0)
{
if (graphicsGeneratorPixelData == 0x0)
graphicsGeneratorPixel = backgroundColor[0];
else
graphicsGeneratorPixel = (colorData & 0x7);
}
else
{
if (graphicsGeneratorPixelData == 0x0)
graphicsGeneratorPixel = backgroundColor[0];
else if (graphicsGeneratorPixelData == 0x1)
graphicsGeneratorPixel = backgroundColor[1];
else if (graphicsGeneratorPixelData == 0x2)
graphicsGeneratorPixel = backgroundColor[2];
else
graphicsGeneratorPixel = (colorData & 0x7);
}
}
else
{
// ECM=0, BMM=0, MCM=0
if (graphicsGeneratorPixelData == 0x0)
graphicsGeneratorPixel = backgroundColor[0];
else
graphicsGeneratorPixel = colorData;
}
}
}
}
else
{
// vertical border enabled, disable output
graphicsGeneratorPixel = backgroundColor[0];
graphicsGeneratorPixelData = 0x0;
}
// pixel generator -> pixelbuffer
pixelBuffer[pixelBufferIndex] = graphicsGeneratorPixel;
// border unit comparisons
if (rasterX == verticalBorderStart)
mainBorder = true;
else if (rasterX == verticalBorderEnd)
{
if (rasterY == mainBorderStart)
verticalBorder = true;
if (rasterY == mainBorderEnd && displayEnable)
verticalBorder = false;
if (!verticalBorder)
mainBorder = false;
}
// border unit -> pixelbuffer
if (mainBorder || verticalBorder)
pixelBuffer[borderPixelBufferIndex] = borderColor;
// advance pixelbuffer
pixelBufferIndex++;
if (pixelBufferIndex == pixelBufferLength)
pixelBufferIndex = 0;
borderPixelBufferIndex++;
if (borderPixelBufferIndex == pixelBufferLength)
borderPixelBufferIndex = 0;
// horizontal raster delay found in 6567R8
if (rasterDelay > 0) if (rasterDelay > 0)
rasterDelay--; rasterDelay--;
else else
rasterX++; rasterX++;
} }
if (!phi0)
phi1Data = data;
phi0 = !phi0; phi0 = !phi0;
} while (phi0); } while (phi0);
// at the end, clock other devices if applicable // at the end, clock other devices if applicable
ClockPhi0(); ClockPhi0();
} }
@ -218,8 +442,21 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
// empty out the pixel buffer // empty out the pixel buffer
pixelBuffer = new int[pixelBufferLength]; pixelBuffer = new int[pixelBufferLength];
pixelDataBuffer = new int[pixelBufferLength];
pixelBufferIndex = 0; pixelBufferIndex = 0;
borderPixelBufferIndex = 8; borderPixelBufferIndex = 8;
// internal screen row buffer
colorMatrix = new int[40];
characterMatrix = new int[40];
rowCounter = 0;
videoCounter = 0;
videoCounterBase = 0;
videoMatrixLineIndex = 0;
// border unit
mainBorder = true;
verticalBorder = true;
} }
} }
} }