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

View File

@ -25,6 +25,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
bool rasterInterrupt;
bool rasterInterruptEnable;
int rasterY;
int rasterYCompare;
bool reset;
bool rowSelect;
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)
{
switch (addr)
@ -228,9 +234,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
displayEnable = ((val & 0x10) != 0);
bitmapMode = ((val & 0x20) != 0);
extraColorMode = ((val & 0x40) != 0);
rasterY = (rasterY & 0xFF) | ((val & 0x80) << 1);
rasterYCompare = (rasterYCompare & 0xFF) | ((val & 0x80) << 1);
return;
case 0x12: rasterY = (rasterY & 0x100) | val; return;
case 0x12: rasterYCompare = (rasterYCompare & 0x100) | val; return;
case 0x13: lightPenX = val; return;
case 0x14: lightPenY = val; return;
case 0x15:
@ -246,8 +252,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
case 0x16:
xScroll = (val & 0x07);
columnSelect = ((val & 0x08) != 0);
multiColorMode = ((val & 0x08) != 0);
reset = ((val & 0x08) != 0);
multiColorMode = ((val & 0x10) != 0);
reset = ((val & 0x20) != 0);
return;
case 0x17:
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)
{
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)
{
addr &= 0x3F;
@ -403,5 +419,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
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,
Refresh,
Sprite,
Pointer
Pointer,
CharacterInternal
}
FetchState fetchState;
@ -24,6 +25,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int characterBAStart;
bool characterFetch;
int characterFetchStart;
int frequency;
bool graphicsFetch;
bool hBlank;
int hBlankDelay;
@ -43,9 +45,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int spriteDMADisableEnd;
int spriteDMADisableStart;
int spriteShiftDisableStart;
VicTiming timing;
bool vBlank;
void InitTiming(VicTiming timing)
void InitTiming()
{
int spriteBAStart = timing.SpriteBAStart;
@ -54,6 +57,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sprites[i].BAStart = spriteBAStart % timing.HSize;
sprites[i].BAEnd = (spriteBAStart + 40) % timing.HSize;
sprites[i].FetchStart = (spriteBAStart + 24) % timing.HSize;
spriteBAStart = (spriteBAStart + 32) % timing.HSize;
}
characterBAStart = timing.CharacterBAStart % timing.HSize;
@ -66,6 +70,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
rasterWidth = timing.HSize;
rasterAdvance = timing.LineStart;
rasterCount = timing.VSize;
frequency = timing.Frequency;
spriteDMACheckStart = characterBAEnd;
spriteDMACheckEnd = (spriteDMACheckStart + 8) % timing.HSize;
spriteCounterCheckStart = (spriteDMACheckEnd + 16) % timing.HSize;
@ -78,6 +83,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
sealed public class VicTiming
{
public int CharacterBAStart; //VMBA
public int Frequency;
public int HBlankDelay;
public int HBlankEnd; //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
{
int[] pixelBuffer;
int pixelBufferIndex;
int pixelBufferLength;
int screenHeight;
int screenWidth;
int[] videoBuffer;

View File

@ -41,6 +41,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips
static private VicSettings Settings6569()
{
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;
}

View File

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

View File

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

View File

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

View File

@ -197,5 +197,35 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
(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;
}
}
}