Commodore64: Experimental Vic implementation nearly complete.
This commit is contained in:
parent
c827d42f2d
commit
cfc2b141bf
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue