Commodore64: More work on the experimental VIC. Some speedups in the current VIC from caching the video mode and removing unnecessary shifts from the inner loops of the background graphics generator.

This commit is contained in:
saxxonpike 2013-08-23 08:57:20 +00:00
parent 31b9e37f86
commit bde52b25bd
10 changed files with 342 additions and 129 deletions

View File

@ -24,6 +24,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
public int Address { get { return address; } } public int Address { get { return address; } }
public int CharacterData { get { return characterData; } } public int CharacterData { get { return characterData; } }
public int ColorData { get { return colorData; } } public int ColorData { get { return colorData; } }
public int CyclesPerFrame { get { return rasterCount * rasterWidth / 8; } }
public int CyclesPerSecond { get { return frequency; } }
public int Data { get { return data; } } public int Data { get { return data; } }
public int DataPhi1 { get { return phi1Data; } } public int DataPhi1 { get { return phi1Data; } }
public int GraphicsData { get { return graphicsData; } } public int GraphicsData { get { return graphicsData; } }

View File

@ -8,9 +8,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sealed public partial class Vic sealed public partial class Vic
{ {
const int AEC_DELAY = 7; const int AEC_DELAY = 7;
const int GRAPHICS_GENERATOR_DELAY = 12;
const int BORDER_GENERATOR_DELAY = 8; const int BORDER_GENERATOR_DELAY = 8;
const int BORDER_GENERATOR_DELAY_BIT = 1 << BORDER_GENERATOR_DELAY; const int BORDER_GENERATOR_DELAY_BIT = 1 << BORDER_GENERATOR_DELAY;
const bool BORDER_ENABLE = false;
int address; int address;
bool aec; bool aec;
@ -29,8 +29,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int graphicsGeneratorColor; int graphicsGeneratorColor;
int graphicsGeneratorData; int graphicsGeneratorData;
bool graphicsGeneratorMulticolor; bool graphicsGeneratorMulticolor;
int graphicsGeneratorOutputData;
int graphicsGeneratorPipeData;
int graphicsGeneratorPipePixel0;
int graphicsGeneratorPipePixel2;
int graphicsGeneratorPixel; int graphicsGeneratorPixel;
int graphicsGeneratorPixelData;
bool graphicsGeneratorShiftToggle; bool graphicsGeneratorShiftToggle;
bool idleState; bool idleState;
bool mainBorder; bool mainBorder;
@ -39,12 +42,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
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;
Sprite spriteBuffer; Sprite spriteBuffer;
int spriteGeneratorBackgroundData;
int spriteGeneratorPixel; int spriteGeneratorPixel;
int spriteGeneratorPixelData; int spriteGeneratorPixelData;
bool spriteGeneratorPixelEnabled; bool spriteGeneratorPixelEnabled;
@ -59,39 +60,59 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
public Vic(VicSettings settings) public Vic(VicSettings settings)
{ {
// initialize timing values // initialize timing values
InitTiming(settings.timing); timing = settings.timing;
// calculate visible screen dimensions // reset registers
screenWidth = screenXEnd - screenXStart; Reset();
screenHeight = screenYEnd - screenYStart;
if (screenXEnd < screenXStart) // calculate visible width
screenWidth += rasterWidth; screenWidth = 0;
if (screenYEnd < screenYStart) rasterX = screenXStart;
screenHeight += rasterCount; while (rasterX != screenXEnd)
{
screenWidth++;
rasterX++;
if (rasterX == rasterWidth)
rasterX = 0;
}
// calculate visible height
screenHeight = 0;
rasterY = screenYStart;
while (rasterY != screenYEnd)
{
screenHeight++;
rasterY++;
if (rasterY == rasterCount)
rasterY = 0;
}
// reset raster counters
rasterX = 0;
rasterY = 0;
// create video buffer // create video buffer
videoBuffer = new int[screenWidth * screenHeight]; videoBuffer = new int[screenWidth * screenHeight];
// reset registers
pixelBufferLength = GRAPHICS_GENERATOR_DELAY;
Reset();
} }
public void Clock() public void Clock()
{ {
// these should be cached somewhere // these should be cached somewhere
mainBorderStart = columnSelect ? 0x18 : 0x1F; mainBorderEnd = columnSelect ? 0x18 : 0x1F;
mainBorderEnd = columnSelect ? 0x158 : 0x14F; mainBorderStart = columnSelect ? 0x158 : 0x14F;
verticalBorderStart = rowSelect ? 0x33 : 0x37; verticalBorderEnd = rowSelect ? 0x33 : 0x37;
verticalBorderEnd = rowSelect ? 0xFB : 0xF7; verticalBorderStart = rowSelect ? 0xFB : 0xF7;
// process badline enable & condition // process badline enable & condition
if (rasterY >= 0x30 && rasterY < 0xF8) if (!badLineCondition && rasterY >= 0x30 && rasterY < 0xF8)
{ {
if (rasterY == 0x30 && displayEnable) if (rasterY == 0x30 && displayEnable)
badLineEnable = true; badLineEnable = true;
if (badLineEnable && ((rasterY & 0x7) == yScroll)) if (badLineEnable && ((rasterY & 0x7) == yScroll))
{
badLineCondition = true; badLineCondition = true;
idleState = false;
}
} }
// process sprites on phi1 // process sprites on phi1
@ -208,6 +229,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
rasterX = 0; rasterX = 0;
videoCounter = videoCounterBase; videoCounter = videoCounterBase;
videoMatrixLineIndex = 0; videoMatrixLineIndex = 0;
if (badLineCondition)
rowCounter = 0;
if (rasterY == rasterYCompare)
rasterInterrupt = true;
} }
else if (rasterX == rasterAdvance) else if (rasterX == rasterAdvance)
{ {
@ -224,25 +249,36 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
videoBufferIndex = 0; videoBufferIndex = 0;
badLineEnable = false; badLineEnable = false;
} }
badLineCondition = false;
} }
// determine BA and fetch state // determine BA and fetch state
ba = true; 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.None : FetchState.Idle;
if (characterBA) if (!characterBA && badLineCondition && badLineEnable)
{ {
// covers badlines and display area fetches ba = false;
characterFetch = (badLineCondition && badLineEnable);
ba = !characterFetch;
fetchState = phi0 ? FetchState.Graphics : FetchState.Character;
} }
else if (refreshFetch)
if (graphicsFetch)
{
if (badLineCondition && badLineEnable)
{
fetchState = phi0 ? FetchState.Character : FetchState.Graphics;
}
else
{
fetchState = phi0 ? FetchState.CharacterInternal : FetchState.Graphics;
}
}
if (refreshFetch)
{ {
// covers memory refresh fetches // covers memory refresh fetches
fetchState = phi0 ? FetchState.Refresh : FetchState.None; fetchState = phi0 ? FetchState.None : FetchState.Refresh;
} }
else else
{ {
@ -270,7 +306,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{ {
sprite.Fetch = true; sprite.Fetch = true;
fetchState = FetchState.Pointer; fetchState = FetchState.Pointer;
ba = !sprite.Fetch; ba = !sprite.DMA;
break; break;
} }
spriteIndex++; spriteIndex++;
@ -302,17 +338,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
colorMatrix[videoMatrixLineIndex] = colorData = ReadColorRam(address); colorMatrix[videoMatrixLineIndex] = colorData = ReadColorRam(address);
characterMatrix[videoMatrixLineIndex] = characterData = data = ReadRam(address); characterMatrix[videoMatrixLineIndex] = characterData = data = ReadRam(address);
} }
else if (!idleState)
{
colorData = colorMatrix[videoMatrixLineIndex];
characterData = characterMatrix[videoMatrixLineIndex];
}
else else
{ {
colorData = 0; colorData = 0;
characterData = 0; characterData = 0;
} }
break; break;
case FetchState.CharacterInternal:
colorData = colorMatrix[videoMatrixLineIndex];
characterData = characterMatrix[videoMatrixLineIndex];
break;
case FetchState.Graphics: case FetchState.Graphics:
address = (extraColorMode ? 0x39FF : 0x3FFF); address = (extraColorMode ? 0x39FF : 0x3FFF);
if (!idleState) if (!idleState)
@ -322,7 +357,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
else else
address &= (rowCounter | (characterData << 3) | characterBitmap); address &= (rowCounter | (characterData << 3) | characterBitmap);
videoMatrixLineIndex++; videoMatrixLineIndex++;
videoMatrixLineIndex &= 0x3F; videoCounter = ((videoCounter + 1) & 0x3FF);
} }
data = ReadRam(address); data = ReadRam(address);
graphicsData = data; graphicsData = data;
@ -354,7 +389,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
// render 4 pixels (there are 8 per cycle) // render 4 pixels (there are 8 per cycle)
for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++)
{ {
// initialize background pixel data generator // initialize background pixel data generator
if ((rasterX & 0x7) == xScroll) if ((rasterX & 0x7) == xScroll)
@ -366,40 +401,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
graphicsGeneratorShiftToggle = !graphicsGeneratorMulticolor; graphicsGeneratorShiftToggle = !graphicsGeneratorMulticolor;
} }
// extract graphics data
graphicsGeneratorOutputData = (graphicsGeneratorData & (graphicsGeneratorMulticolor ? 0xC0 : 0x80));
graphicsGeneratorPipeData <<= 2;
graphicsGeneratorPipeData |= graphicsGeneratorOutputData;
// shift graphics data // shift graphics data
if (graphicsGeneratorShiftToggle) if (graphicsGeneratorShiftToggle)
graphicsGeneratorPixelData >>= graphicsGeneratorMulticolor ? 2 : 1; graphicsGeneratorData <<= graphicsGeneratorMulticolor ? 2 : 1;
graphicsGeneratorShiftToggle = !graphicsGeneratorShiftToggle || !graphicsGeneratorMulticolor; graphicsGeneratorShiftToggle = !graphicsGeneratorShiftToggle || !graphicsGeneratorMulticolor;
// generate data and color for the pixelbuffer // generate data and color for the pixelbuffer
if (!verticalBorder) if (!verticalBorder || !BORDER_ENABLE)
{ {
// graphics generator // graphics generator
if (extraColorMode) if (extraColorMode && !bitmapMode && !multiColorMode)
{
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 // ECM=1, BMM=0, MCM=0
if (graphicsGeneratorPixelData == 0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = backgroundColor[characterData >> 6]; graphicsGeneratorPixel = backgroundColor[characterData >> 6];
else else
graphicsGeneratorPixel = colorData; graphicsGeneratorPixel = colorData;
} }
}
}
else else
{ {
if (bitmapMode) if (bitmapMode)
@ -407,11 +430,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
if (multiColorMode) if (multiColorMode)
{ {
// ECM=0, BMM=1, MCM=1 // ECM=0, BMM=1, MCM=1
if (graphicsGeneratorPixelData == 0x0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = backgroundColor[0]; graphicsGeneratorPixel = backgroundColor[0];
else if (graphicsGeneratorPixelData == 0x1) else if (graphicsGeneratorOutputData == 0x40)
graphicsGeneratorPixel = characterData >> 4; graphicsGeneratorPixel = characterData >> 4;
else if (graphicsGeneratorPixelData == 0x2) else if (graphicsGeneratorOutputData == 0x80)
graphicsGeneratorPixel = (characterData & 0xF); graphicsGeneratorPixel = (characterData & 0xF);
else else
graphicsGeneratorPixel = colorData; graphicsGeneratorPixel = colorData;
@ -419,7 +442,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
else else
{ {
// ECM=0, BMM=1, MCM=0 // ECM=0, BMM=1, MCM=0
if (graphicsGeneratorPixelData == 0x0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = (characterData & 0xF); graphicsGeneratorPixel = (characterData & 0xF);
else else
graphicsGeneratorPixel = characterData >> 4; graphicsGeneratorPixel = characterData >> 4;
@ -432,18 +455,18 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
// ECM=0, BMM=0, MCM=1 // ECM=0, BMM=0, MCM=1
if ((colorData & 0x4) == 0) if ((colorData & 0x4) == 0)
{ {
if (graphicsGeneratorPixelData == 0x0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = backgroundColor[0]; graphicsGeneratorPixel = backgroundColor[0];
else else
graphicsGeneratorPixel = (colorData & 0x7); graphicsGeneratorPixel = (colorData & 0x7);
} }
else else
{ {
if (graphicsGeneratorPixelData == 0x0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = backgroundColor[0]; graphicsGeneratorPixel = backgroundColor[0];
else if (graphicsGeneratorPixelData == 0x1) else if (graphicsGeneratorOutputData == 0x40)
graphicsGeneratorPixel = backgroundColor[1]; graphicsGeneratorPixel = backgroundColor[1];
else if (graphicsGeneratorPixelData == 0x2) else if (graphicsGeneratorOutputData == 0x80)
graphicsGeneratorPixel = backgroundColor[2]; graphicsGeneratorPixel = backgroundColor[2];
else else
graphicsGeneratorPixel = (colorData & 0x7); graphicsGeneratorPixel = (colorData & 0x7);
@ -452,7 +475,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
else else
{ {
// ECM=0, BMM=0, MCM=0 // ECM=0, BMM=0, MCM=0
if (graphicsGeneratorPixelData == 0x0) if (graphicsGeneratorOutputData == 0x00)
graphicsGeneratorPixel = backgroundColor[0]; graphicsGeneratorPixel = backgroundColor[0];
else else
graphicsGeneratorPixel = colorData; graphicsGeneratorPixel = colorData;
@ -464,11 +487,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{ {
// vertical border enabled, disable output // vertical border enabled, disable output
graphicsGeneratorPixel = backgroundColor[0]; graphicsGeneratorPixel = backgroundColor[0];
graphicsGeneratorPixelData = 0x0; }
// shift color data
if (phi0)
{
graphicsGeneratorPipePixel2 <<= 4;
graphicsGeneratorPipePixel2 |= graphicsGeneratorPixel;
graphicsGeneratorPixel = (graphicsGeneratorPipePixel2 & 0x00F00000) >> 20;
}
else
{
graphicsGeneratorPipePixel0 <<= 4;
graphicsGeneratorPipePixel0 |= graphicsGeneratorPixel;
graphicsGeneratorPixel = (graphicsGeneratorPipePixel0 & 0x00F00000) >> 20;
} }
// sprite generator // sprite generator
spriteGeneratorBackgroundData = pixelDataBuffer[pixelBufferIndex];
spriteIndex = 0; spriteIndex = 0;
spriteGeneratorPixelEnabled = false; spriteGeneratorPixelEnabled = false;
foreach (Sprite sprite in sprites) foreach (Sprite sprite in sprites)
@ -524,7 +559,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
// determine sprite-background collision // determine sprite-background collision
if ((spriteGeneratorBackgroundData & 0x2) != 0) if ((graphicsGeneratorData & 0x200000) != 0)
sprite.DataCollision = true; sprite.DataCollision = true;
} }
@ -534,14 +569,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
// combine the pixels // combine the pixels
if (spriteGeneratorPixelEnabled && (!spriteGeneratorPriority || ((spriteGeneratorBackgroundData & 0x2) == 0))) if (spriteGeneratorPixelEnabled && (!spriteGeneratorPriority || ((graphicsGeneratorPipeData & 0x80000) == 0)))
pixel = spriteGeneratorPixel; pixel = spriteGeneratorPixel;
else else
pixel = pixelBuffer[pixelBufferIndex]; pixel = graphicsGeneratorPixel;
// pixel generator data -> pixeldatabuffer
pixelDataBuffer[pixelBufferIndex] = graphicsGeneratorPixelData;
pixelBuffer[pixelBufferIndex] = graphicsGeneratorPixel;
// border unit comparisons // border unit comparisons
if (rasterX == verticalBorderStart) if (rasterX == verticalBorderStart)
@ -560,7 +591,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
borderDelay <<= 1; borderDelay <<= 1;
if (mainBorder || verticalBorder) if (mainBorder || verticalBorder)
borderDelay |= 1; borderDelay |= 1;
if ((borderDelay & BORDER_GENERATOR_DELAY_BIT) != 0) if (BORDER_ENABLE && (borderDelay & BORDER_GENERATOR_DELAY_BIT) != 0)
pixel = borderColor; pixel = borderColor;
// rendered pixel -> videobuffer // rendered pixel -> videobuffer
@ -570,11 +601,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
videoBufferIndex++; videoBufferIndex++;
} }
// advance pixelbuffer
pixelBufferIndex++;
if (pixelBufferIndex == pixelBufferLength)
pixelBufferIndex = 0;
// horizontal raster delay found in 6567R8 // horizontal raster delay found in 6567R8
if (rasterDelay > 0) if (rasterDelay > 0)
rasterDelay--; rasterDelay--;
@ -588,31 +614,40 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
phi0 = !phi0; phi0 = !phi0;
} while (phi0); } while (phi0);
// process irq
irq = !(
(rasterInterrupt && rasterInterruptEnable)
);
// at the end, clock other devices if applicable // at the end, clock other devices if applicable
if (ClockPhi0 != null)
ClockPhi0(); ClockPhi0();
} }
public void Reset() public void Reset()
{ {
// set up color arrays
backgroundColor = new int[4]; backgroundColor = new int[4];
spriteMultiColor = new int[2]; spriteMultiColor = new int[2];
// set up sprites
sprites = new Sprite[8]; sprites = new Sprite[8];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
sprites[i] = new Sprite(); sprites[i] = new Sprite();
for (int i = 0; i < 0x40; i++) for (int i = 0; i < 0x40; i++)
Poke(i, 0); Poke(i, 0);
// set up pin state
phi0 = false; phi0 = false;
irq = true;
ba = true;
aec = true;
// we set these so no video is displayed before // we set these so no video is displayed before
// the first frame starts // the first frame starts
vBlank = true; vBlank = true;
hBlank = true; hBlank = true;
// empty out the pixel buffer
pixelBuffer = new int[pixelBufferLength];
pixelDataBuffer = new int[pixelBufferLength];
pixelBufferIndex = 0;
// internal screen row buffer // internal screen row buffer
colorMatrix = new int[40]; colorMatrix = new int[40];
characterMatrix = new int[40]; characterMatrix = new int[40];
@ -624,6 +659,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
// border unit // border unit
mainBorder = true; mainBorder = true;
verticalBorder = true; verticalBorder = true;
// setup timing
InitTiming();
} }
} }
} }

View File

@ -25,6 +25,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
bool rasterInterrupt; bool rasterInterrupt;
bool rasterInterruptEnable; bool rasterInterruptEnable;
int rasterY; int rasterY;
int rasterYCompare;
bool reset; bool reset;
bool rowSelect; bool rowSelect;
bool spriteCollisionInterrupt; bool spriteCollisionInterrupt;
@ -192,6 +193,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
} }
public byte PeekByte(int addr)
{
return (byte)(Peek(addr) & 0xFF);
}
public void Poke(int addr, int val) public void Poke(int addr, int val)
{ {
switch (addr) switch (addr)
@ -228,9 +234,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
displayEnable = ((val & 0x10) != 0); displayEnable = ((val & 0x10) != 0);
bitmapMode = ((val & 0x20) != 0); bitmapMode = ((val & 0x20) != 0);
extraColorMode = ((val & 0x40) != 0); extraColorMode = ((val & 0x40) != 0);
rasterY = (rasterY & 0xFF) | ((val & 0x80) << 1); rasterYCompare = (rasterYCompare & 0xFF) | ((val & 0x80) << 1);
return; return;
case 0x12: rasterY = (rasterY & 0x100) | val; return; case 0x12: rasterYCompare = (rasterYCompare & 0x100) | val; return;
case 0x13: lightPenX = val; return; case 0x13: lightPenX = val; return;
case 0x14: lightPenY = val; return; case 0x14: lightPenY = val; return;
case 0x15: case 0x15:
@ -246,8 +252,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
case 0x16: case 0x16:
xScroll = (val & 0x07); xScroll = (val & 0x07);
columnSelect = ((val & 0x08) != 0); columnSelect = ((val & 0x08) != 0);
multiColorMode = ((val & 0x08) != 0); multiColorMode = ((val & 0x10) != 0);
reset = ((val & 0x08) != 0); reset = ((val & 0x20) != 0);
return; return;
case 0x17: case 0x17:
sprites[0].ExpandY = ((val & 0x01) != 0); sprites[0].ExpandY = ((val & 0x01) != 0);
@ -345,6 +351,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
} }
public void PokeByte(int addr, byte val)
{
Poke(addr, val);
}
public int Read(int addr) public int Read(int addr)
{ {
int result; int result;
@ -362,6 +373,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
} }
} }
public byte ReadByte(int addr)
{
return (byte)(Read(addr) & 0xFF);
}
public void Write(int addr, int val) public void Write(int addr, int val)
{ {
addr &= 0x3F; addr &= 0x3F;
@ -403,5 +419,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
return; return;
} }
} }
public void WriteByte(int addr, byte val)
{
Write(addr, val);
}
} }
} }

View File

@ -15,7 +15,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
Character, Character,
Refresh, Refresh,
Sprite, Sprite,
Pointer Pointer,
CharacterInternal
} }
FetchState fetchState; FetchState fetchState;
@ -24,6 +25,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int characterBAStart; int characterBAStart;
bool characterFetch; bool characterFetch;
int characterFetchStart; int characterFetchStart;
int frequency;
bool graphicsFetch; bool graphicsFetch;
bool hBlank; bool hBlank;
int hBlankDelay; int hBlankDelay;
@ -43,9 +45,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int spriteDMADisableEnd; int spriteDMADisableEnd;
int spriteDMADisableStart; int spriteDMADisableStart;
int spriteShiftDisableStart; int spriteShiftDisableStart;
VicTiming timing;
bool vBlank; bool vBlank;
void InitTiming(VicTiming timing) void InitTiming()
{ {
int spriteBAStart = timing.SpriteBAStart; int spriteBAStart = timing.SpriteBAStart;
@ -54,6 +57,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sprites[i].BAStart = spriteBAStart % timing.HSize; sprites[i].BAStart = spriteBAStart % timing.HSize;
sprites[i].BAEnd = (spriteBAStart + 40) % timing.HSize; sprites[i].BAEnd = (spriteBAStart + 40) % timing.HSize;
sprites[i].FetchStart = (spriteBAStart + 24) % timing.HSize; sprites[i].FetchStart = (spriteBAStart + 24) % timing.HSize;
spriteBAStart = (spriteBAStart + 32) % timing.HSize;
} }
characterBAStart = timing.CharacterBAStart % timing.HSize; characterBAStart = timing.CharacterBAStart % timing.HSize;
@ -66,6 +70,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
rasterWidth = timing.HSize; rasterWidth = timing.HSize;
rasterAdvance = timing.LineStart; rasterAdvance = timing.LineStart;
rasterCount = timing.VSize; rasterCount = timing.VSize;
frequency = timing.Frequency;
spriteDMACheckStart = characterBAEnd; spriteDMACheckStart = characterBAEnd;
spriteDMACheckEnd = (spriteDMACheckStart + 8) % timing.HSize; spriteDMACheckEnd = (spriteDMACheckStart + 8) % timing.HSize;
spriteCounterCheckStart = (spriteDMACheckEnd + 16) % timing.HSize; spriteCounterCheckStart = (spriteDMACheckEnd + 16) % timing.HSize;
@ -78,6 +83,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sealed public class VicTiming sealed public class VicTiming
{ {
public int CharacterBAStart; //VMBA public int CharacterBAStart; //VMBA
public int Frequency;
public int HBlankDelay; public int HBlankDelay;
public int HBlankEnd; //HBLANK public int HBlankEnd; //HBLANK
public int HBlankStart; //HBLANK public int HBlankStart; //HBLANK

View File

@ -7,9 +7,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{ {
sealed public partial class Vic : IVideoProvider sealed public partial class Vic : IVideoProvider
{ {
int[] pixelBuffer;
int pixelBufferIndex;
int pixelBufferLength;
int screenHeight; int screenHeight;
int screenWidth; int screenWidth;
int[] videoBuffer; int[] videoBuffer;

View File

@ -41,6 +41,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips
static private VicSettings Settings6569() static private VicSettings Settings6569()
{ {
VicSettings result = new VicSettings(); VicSettings result = new VicSettings();
VicTiming timing = new VicTiming();
timing.CharacterBAStart = 0x1EC;
timing.Frequency = 17734472 / 18;
timing.HBlankDelay = 0;
timing.HBlankEnd = 0x1E0;
timing.HBlankStart = 0x17C;
timing.HSize = 0x1F8;
timing.LineStart = 0x194;
timing.RefreshStart = 0x1E4;
timing.SpriteBAStart = 0x14C;
timing.VBlankEnd = 0x010;
timing.VBlankStart = 0x12C;
timing.VSize = 0x138;
result.timing = timing;
return result; return result;
} }

View File

@ -31,6 +31,11 @@
return ram[addr & 0x3FF]; return ram[addr & 0x3FF];
} }
public int ReadInt(int addr)
{
return ram[addr & 0x3FF];
}
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
Sync.SyncObject(ser, this); Sync.SyncObject(ser, this);

View File

@ -353,6 +353,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
rasterInterruptLine &= 0xFF; rasterInterruptLine &= 0xFF;
rasterInterruptLine |= (val & 0x80) << 1; rasterInterruptLine |= (val & 0x80) << 1;
UpdateBorder(); UpdateBorder();
UpdateVideoMode();
break; break;
case 0x12: case 0x12:
rasterInterruptLine &= 0x100; rasterInterruptLine &= 0x100;
@ -379,6 +380,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
columnSelect = ((val & 0x08) != 0); columnSelect = ((val & 0x08) != 0);
multicolorMode = ((val & 0x10) != 0); multicolorMode = ((val & 0x10) != 0);
UpdateBorder(); UpdateBorder();
UpdateVideoMode();
break; break;
case 0x17: case 0x17:
sprites[0].yExpand = ((val & 0x01) != 0); sprites[0].yExpand = ((val & 0x01) != 0);

View File

@ -16,6 +16,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
protected int pixelBufferDelay; protected int pixelBufferDelay;
protected int pixelBufferIndex; protected int pixelBufferIndex;
protected int pixelData; protected int pixelData;
protected int pixelOwner;
protected int sprData;
protected int sprPixel;
protected VicVideoMode videoMode;
protected enum VicVideoMode : int
{
Mode000,
Mode001,
Mode010,
Mode011,
Mode100,
ModeBad
}
private void Render() private void Render()
{ {
@ -63,11 +77,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex];
// render sprite // render sprite
int pixelOwner = 8; pixelOwner = 8;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
int sprData; sprData = 0;
int sprPixel = pixel; sprPixel = pixel;
Sprite spr = sprites[j]; Sprite spr = sprites[j];
@ -78,28 +92,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
if (spr.multicolor) if (spr.multicolor)
{ {
sprData = (spr.sr & 0xC00000) >> 22; sprData = (spr.sr & 0xC00000);
if (spr.multicolorCrunch && spr.xCrunch) if (spr.multicolorCrunch && spr.xCrunch)
spr.sr <<= 2; spr.sr <<= 2;
spr.multicolorCrunch ^= spr.xCrunch; spr.multicolorCrunch ^= spr.xCrunch;
} }
else else
{ {
sprData = (spr.sr & 0x800000) >> 22; sprData = (spr.sr & 0x800000);
if (spr.xCrunch) if (spr.xCrunch)
spr.sr <<= 1; spr.sr <<= 1;
} }
spr.xCrunch ^= spr.xExpand; spr.xCrunch ^= spr.xExpand;
if (sprData == 1)
sprPixel = spriteMulticolor0;
else if (sprData == 2)
sprPixel = spr.color;
else if (sprData == 3)
sprPixel = spriteMulticolor1;
if (sprData != 0) if (sprData != 0)
{ {
if (sprData == 0x400000)
sprPixel = spriteMulticolor0;
else if (sprData == 0x800000)
sprPixel = spr.color;
else if (sprData == 0xC00000)
sprPixel = spriteMulticolor1;
// sprite-sprite collision // sprite-sprite collision
if (pixelOwner >= 8) if (pixelOwner >= 8)
{ {
@ -117,7 +131,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
// sprite-data collision // sprite-data collision
if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] >= 0x2)) if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] == 0x80))
{ {
spr.collideData = true; spr.collideData = true;
} }
@ -145,10 +159,90 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
bitmapColumn = 0; bitmapColumn = 0;
} }
#if true
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;
}
#else
if (!extraColorMode && !bitmapMode & !multicolorMode) if (!extraColorMode && !bitmapMode & !multicolorMode)
{ {
// 000 // 000
pixelData = (sr & 0x80) >> 6; pixelData = (sr & 0x80);
sr <<= 1; sr <<= 1;
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0; pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
} }
@ -158,15 +252,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if ((displayC & 0x800) != 0) if ((displayC & 0x800) != 0)
{ {
// multicolor 001 // multicolor 001
pixelData = (sr & 0xC0) >> 6; pixelData = (sr & 0xC0);
if ((bitmapColumn & 1) != 0) if ((bitmapColumn & 1) != 0)
sr <<= 2; sr <<= 2;
if (pixelData == 0) if (pixelData == 0x00)
pixel = backgroundColor0; pixel = backgroundColor0;
else if (pixelData == 1) else if (pixelData == 0x40)
pixel = backgroundColor1; pixel = backgroundColor1;
else if (pixelData == 2) else if (pixelData == 0x80)
pixel = backgroundColor2; pixel = backgroundColor2;
else else
pixel = (displayC & 0x700) >> 8; pixel = (displayC & 0x700) >> 8;
@ -174,7 +268,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else else
{ {
// standard 001 // standard 001
pixelData = (sr & 0x80) >> 6; pixelData = (sr & 0x80);
sr <<= 1; sr <<= 1;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0; pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
} }
@ -182,22 +276,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else if (!extraColorMode && bitmapMode & !multicolorMode) else if (!extraColorMode && bitmapMode & !multicolorMode)
{ {
// 010 // 010
pixelData = (sr & 0x80) >> 6; pixelData = (sr & 0x80);
sr <<= 1; sr <<= 1;
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF); pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
} }
else if (!extraColorMode && bitmapMode & multicolorMode) else if (!extraColorMode && bitmapMode & multicolorMode)
{ {
// 011 // 011
pixelData = (sr & 0xC0) >> 6; pixelData = (sr & 0xC0);
if ((bitmapColumn & 1) != 0) if ((bitmapColumn & 1) != 0)
sr <<= 2; sr <<= 2;
if (pixelData == 0) if (pixelData == 0x00)
pixel = backgroundColor0; pixel = backgroundColor0;
else if (pixelData == 1) else if (pixelData == 0x40)
pixel = (displayC >> 4) & 0xF; pixel = (displayC >> 4) & 0xF;
else if (pixelData == 2) else if (pixelData == 0x80)
pixel = displayC & 0xF; pixel = displayC & 0xF;
else else
pixel = (displayC >> 8) & 0xF; pixel = (displayC >> 8) & 0xF;
@ -205,7 +299,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else if (extraColorMode && !bitmapMode & !multicolorMode) else if (extraColorMode && !bitmapMode & !multicolorMode)
{ {
// 100 // 100
pixelData = (sr & 0x80) >> 6; pixelData = (sr & 0x80);
sr <<= 1; sr <<= 1;
if (pixelData != 0) if (pixelData != 0)
{ {
@ -213,12 +307,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
} }
else else
{ {
ecmPixel = (displayC >> 6) & 0x3; ecmPixel = (displayC) & 0xC0;
if (ecmPixel == 0) if (ecmPixel == 0x00)
pixel = backgroundColor0; pixel = backgroundColor0;
else if (ecmPixel == 1) else if (ecmPixel == 0x40)
pixel = backgroundColor1; pixel = backgroundColor1;
else if (ecmPixel == 2) else if (ecmPixel == 0x80)
pixel = backgroundColor2; pixel = backgroundColor2;
else else
pixel = backgroundColor3; pixel = backgroundColor3;
@ -243,6 +337,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pixel = 0; pixel = 0;
} }
#endif
// put the rendered pixel into the background buffer // put the rendered pixel into the background buffer
pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData; pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData;
pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel; pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel;

View File

@ -197,5 +197,35 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
(enableIntLightPen & intLightPen)); (enableIntLightPen & intLightPen));
} }
} }
private void UpdateVideoMode()
{
if (!extraColorMode && !bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode000;
return;
}
else if (!extraColorMode && !bitmapMode && multicolorMode)
{
videoMode = VicVideoMode.Mode001;
return;
}
else if (!extraColorMode && bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode010;
return;
}
else if (!extraColorMode && bitmapMode && multicolorMode)
{
videoMode = VicVideoMode.Mode011;
return;
}
else if (extraColorMode && !bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode100;
return;
}
videoMode = VicVideoMode.ModeBad;
}
} }
} }