Commodore64: Split the Vic code into a number of files. More time spent coding, less time spent looking for things.

This commit is contained in:
saxxonpike 2013-08-17 20:51:09 +00:00
parent 14a2952faf
commit 03087a88eb
6 changed files with 1096 additions and 1050 deletions

View File

@ -152,6 +152,10 @@
<Compile Include="Computers\Commodore64\MOS\Timer.cs" />
<Compile Include="Computers\Commodore64\MOS\UserPort.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.Parse.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.Registers.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.Render.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.Sprite.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.VideoProvider.cs" />
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />

View File

@ -0,0 +1,235 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
{
private int parseaddr;
private int parsecycleBAsprite0;
private int parsecycleBAsprite1;
private int parsecycleBAsprite2;
private int parsecycleFetchSpriteIndex;
private int parsefetch;
private int parseba;
private int parseact;
private void ParseCycle()
{
{
parseaddr = 0x3FFF;
parsefetch = pipeline[1][cycleIndex];
parseba = pipeline[2][cycleIndex];
parseact = pipeline[3][cycleIndex];
// apply X location
rasterX = pipeline[0][cycleIndex];
// perform fetch
switch (parsefetch & 0xFF00)
{
case 0x0100:
// fetch R
refreshCounter = (refreshCounter - 1) & 0xFF;
parseaddr = (0x3F00 | refreshCounter);
ReadMemory(parseaddr);
break;
case 0x0200:
// fetch C
if (!idle)
{
if (badline)
{
parseaddr = ((pointerVM << 10) | vc);
dataC = ReadMemory(parseaddr);
dataC |= ((int)ReadColorRam(parseaddr) & 0xF) << 8;
bufferC[vmli] = dataC;
}
else
{
dataC = bufferC[vmli];
}
}
else
{
dataC = 0;
bufferC[vmli] = dataC;
}
break;
case 0x0300:
// fetch G
if (idle)
parseaddr = 0x3FFF;
else
{
if (bitmapMode)
parseaddr = (rc | (vc << 3) | ((pointerCB & 0x4) << 11));
else
parseaddr = (rc | ((dataC & 0xFF) << 3) | (pointerCB << 11));
}
if (extraColorMode)
parseaddr &= 0x39FF;
dataG = ReadMemory(parseaddr);
if (!idle)
{
bufferG[vmli] = dataG;
vmli = (vmli + 1) & 0x3F;
vc = (vc + 1) & 0x3FF;
}
break;
case 0x0400:
// fetch I
parseaddr = (extraColorMode ? 0x39FF : 0x3FFF);
dataG = ReadMemory(parseaddr);
dataC = 0;
break;
case 0x0500:
// no fetch
break;
default:
parsecycleFetchSpriteIndex = (parsefetch & 0x7);
switch (parsefetch & 0xF0)
{
case 0x00:
// fetch P
parseaddr = (0x3F8 | (pointerVM << 10) | parsecycleFetchSpriteIndex);
sprites[parsecycleFetchSpriteIndex].pointer = ReadMemory(parseaddr);
sprites[parsecycleFetchSpriteIndex].shiftEnable = false;
break;
case 0x10:
case 0x20:
case 0x30:
// fetch S
if (sprites[parsecycleFetchSpriteIndex].dma)
{
Sprite spr = sprites[parsecycleFetchSpriteIndex];
parseaddr = (spr.mc | (spr.pointer << 6));
spr.sr <<= 8;
spr.sr |= ReadMemory(parseaddr);
spr.mc++;
}
break;
}
break;
}
// perform BA flag manipulation
switch (parseba)
{
case 0x0000:
pinBA = true;
break;
case 0x1000:
pinBA = !badline;
break;
default:
parsecycleBAsprite0 = (parseba & 0x000F);
parsecycleBAsprite1 = (parseba & 0x00F0) >> 4;
parsecycleBAsprite2 = (parseba & 0x0F00) >> 8;
if ((parsecycleBAsprite0 < 8 && sprites[parsecycleBAsprite0].dma) ||
(parsecycleBAsprite1 < 8 && sprites[parsecycleBAsprite1].dma) ||
(parsecycleBAsprite2 < 8 && sprites[parsecycleBAsprite2].dma))
pinBA = false;
else
pinBA = true;
break;
}
// perform actions
borderCheckLEnable = true;
borderCheckREnable = true;
if ((parseact & pipelineChkSprChunch) != 0)
{
//for (int i = 0; i < 8; i++)
foreach (Sprite spr in sprites)
{
//Sprite spr = sprites[i];
if (spr.yCrunch)
spr.mcbase += 2;
spr.shiftEnable = false;
spr.xCrunch = !spr.xExpand;
spr.multicolorCrunch = !spr.multicolor;
}
}
if ((parseact & pipelineChkSprDisp) != 0)
{
//for (int i = 0; i < 8; i++)
foreach (Sprite spr in sprites)
{
//Sprite spr = sprites[i];
spr.mc = spr.mcbase;
if (spr.dma && spr.y == (rasterLine & 0xFF))
{
spr.display = true;
}
}
}
if ((parseact & pipelineChkSprDma) != 0)
{
//for (int i = 0; i < 8; i++)
foreach (Sprite spr in sprites)
{
//Sprite spr = sprites[i];
if (spr.enable && spr.y == (rasterLine & 0xFF) && !spr.dma)
{
spr.dma = true;
spr.mcbase = 0;
spr.yCrunch = !spr.yExpand;
}
}
}
if ((parseact & pipelineChkSprExp) != 0)
{
if (sprites[0].yExpand) sprites[0].yCrunch ^= true;
if (sprites[1].yExpand) sprites[1].yCrunch ^= true;
if (sprites[2].yExpand) sprites[2].yCrunch ^= true;
if (sprites[3].yExpand) sprites[3].yCrunch ^= true;
if (sprites[4].yExpand) sprites[4].yCrunch ^= true;
if (sprites[5].yExpand) sprites[5].yCrunch ^= true;
if (sprites[6].yExpand) sprites[6].yCrunch ^= true;
if (sprites[7].yExpand) sprites[7].yCrunch ^= true;
}
if ((parseact & pipelineUpdateMcBase) != 0)
{
//for (int i = 0; i < 8; i++)
foreach (Sprite spr in sprites)
{
//Sprite spr = sprites[i];
if (spr.yCrunch)
{
spr.mcbase++;
if (spr.mcbase == 63)
{
spr.dma = false;
spr.display = false;
}
}
}
}
if ((parseact & pipelineUpdateRc) != 0)
{
if (rc == 7)
{
idle = true;
vcbase = vc;
}
if (!idle)
rc = (rc + 1) & 0x7;
}
if ((parseact & pipelineUpdateVc) != 0)
{
vc = vcbase;
vmli = 0;
if (badline)
rc = 0;
}
cycleIndex++;
}
}
}
}

View File

@ -0,0 +1,528 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
{
private int backgroundColor0;
private int backgroundColor1;
private int backgroundColor2;
private int backgroundColor3;
private bool bitmapMode;
private int borderColor;
private bool columnSelect;
private bool displayEnable;
private bool enableIntLightPen;
private bool enableIntRaster;
private bool enableIntSpriteCollision;
private bool enableIntSpriteDataCollision;
private bool extraColorMode;
private bool intLightPen;
private bool intRaster;
private bool intSpriteCollision;
private bool intSpriteDataCollision;
private int lightPenX;
private int lightPenY;
private bool multicolorMode;
private int pointerCB;
private int pointerVM;
private int rasterInterruptLine;
private int rasterLine;
private int rasterX;
private bool rowSelect;
private int spriteMulticolor0;
private int spriteMulticolor1;
private Sprite[] sprites;
private int xScroll;
private int yScroll;
public byte Peek(int addr)
{
return ReadRegister((addr & 0x3F));
}
public void Poke(int addr, byte val)
{
WriteRegister((addr & 0x3F), val);
}
public byte Read(int addr)
{
byte result;
addr &= 0x3F;
switch (addr)
{
case 0x1E:
case 0x1F:
// reading clears these
result = ReadRegister(addr);
WriteRegister(addr, 0);
break;
default:
result = ReadRegister((addr & 0x3F));
break;
}
return result;
}
private byte ReadRegister(int addr)
{
byte result = 0xFF; //unused bit value
switch (addr)
{
case 0x00:
case 0x02:
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x0E:
result = (byte)(sprites[addr >> 1].x & 0xFF);
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0x09:
case 0x0B:
case 0x0D:
case 0x0F:
result = (byte)(sprites[addr >> 1].y & 0xFF);
break;
case 0x10:
result = (byte)(
((sprites[0].x >> 8) & 0x01) |
((sprites[1].x >> 7) & 0x02) |
((sprites[2].x >> 6) & 0x04) |
((sprites[3].x >> 5) & 0x08) |
((sprites[4].x >> 4) & 0x10) |
((sprites[5].x >> 3) & 0x20) |
((sprites[6].x >> 2) & 0x40) |
((sprites[7].x >> 1) & 0x80)
);
break;
case 0x11:
result = (byte)(
(yScroll & 0x7) |
(rowSelect ? 0x08 : 0x00) |
(displayEnable ? 0x10 : 0x00) |
(bitmapMode ? 0x20 : 0x00) |
(extraColorMode ? 0x40 : 0x00) |
((rasterLine & 0x100) >> 1)
);
break;
case 0x12:
result = (byte)(rasterLine & 0xFF);
break;
case 0x13:
result = (byte)(lightPenX & 0xFF);
break;
case 0x14:
result = (byte)(lightPenY & 0xFF);
break;
case 0x15:
result = (byte)(
(sprites[0].enable ? 0x01 : 0x00) |
(sprites[1].enable ? 0x02 : 0x00) |
(sprites[2].enable ? 0x04 : 0x00) |
(sprites[3].enable ? 0x08 : 0x00) |
(sprites[4].enable ? 0x10 : 0x00) |
(sprites[5].enable ? 0x20 : 0x00) |
(sprites[6].enable ? 0x40 : 0x00) |
(sprites[7].enable ? 0x80 : 0x00)
);
break;
case 0x16:
result &= 0xC0;
result |= (byte)(
(xScroll & 0x7) |
(columnSelect ? 0x08 : 0x00) |
(multicolorMode ? 0x10 : 0x00)
);
break;
case 0x17:
result = (byte)(
(sprites[0].yExpand ? 0x01 : 0x00) |
(sprites[1].yExpand ? 0x02 : 0x00) |
(sprites[2].yExpand ? 0x04 : 0x00) |
(sprites[3].yExpand ? 0x08 : 0x00) |
(sprites[4].yExpand ? 0x10 : 0x00) |
(sprites[5].yExpand ? 0x20 : 0x00) |
(sprites[6].yExpand ? 0x40 : 0x00) |
(sprites[7].yExpand ? 0x80 : 0x00)
);
break;
case 0x18:
result &= 0x01;
result |= (byte)(
((pointerVM & 0xF) << 4) |
((pointerCB & 0x7) << 1)
);
break;
case 0x19:
result &= 0x70;
result |= (byte)(
(intRaster ? 0x01 : 0x00) |
(intSpriteDataCollision ? 0x02 : 0x00) |
(intSpriteCollision ? 0x04 : 0x00) |
(intLightPen ? 0x08 : 0x00) |
(pinIRQ ? 0x00 : 0x80)
);
break;
case 0x1A:
result &= 0xF0;
result |= (byte)(
(enableIntRaster ? 0x01 : 0x00) |
(enableIntSpriteDataCollision ? 0x02 : 0x00) |
(enableIntSpriteCollision ? 0x04 : 0x00) |
(enableIntLightPen ? 0x08 : 0x00)
);
break;
case 0x1B:
result = (byte)(
(sprites[0].priority ? 0x01 : 0x00) |
(sprites[1].priority ? 0x02 : 0x00) |
(sprites[2].priority ? 0x04 : 0x00) |
(sprites[3].priority ? 0x08 : 0x00) |
(sprites[4].priority ? 0x10 : 0x00) |
(sprites[5].priority ? 0x20 : 0x00) |
(sprites[6].priority ? 0x40 : 0x00) |
(sprites[7].priority ? 0x80 : 0x00)
);
break;
case 0x1C:
result = (byte)(
(sprites[0].multicolor ? 0x01 : 0x00) |
(sprites[1].multicolor ? 0x02 : 0x00) |
(sprites[2].multicolor ? 0x04 : 0x00) |
(sprites[3].multicolor ? 0x08 : 0x00) |
(sprites[4].multicolor ? 0x10 : 0x00) |
(sprites[5].multicolor ? 0x20 : 0x00) |
(sprites[6].multicolor ? 0x40 : 0x00) |
(sprites[7].multicolor ? 0x80 : 0x00)
);
break;
case 0x1D:
result = (byte)(
(sprites[0].xExpand ? 0x01 : 0x00) |
(sprites[1].xExpand ? 0x02 : 0x00) |
(sprites[2].xExpand ? 0x04 : 0x00) |
(sprites[3].xExpand ? 0x08 : 0x00) |
(sprites[4].xExpand ? 0x10 : 0x00) |
(sprites[5].xExpand ? 0x20 : 0x00) |
(sprites[6].xExpand ? 0x40 : 0x00) |
(sprites[7].xExpand ? 0x80 : 0x00)
);
break;
case 0x1E:
result = (byte)(
(sprites[0].collideSprite ? 0x01 : 0x00) |
(sprites[1].collideSprite ? 0x02 : 0x00) |
(sprites[2].collideSprite ? 0x04 : 0x00) |
(sprites[3].collideSprite ? 0x08 : 0x00) |
(sprites[4].collideSprite ? 0x10 : 0x00) |
(sprites[5].collideSprite ? 0x20 : 0x00) |
(sprites[6].collideSprite ? 0x40 : 0x00) |
(sprites[7].collideSprite ? 0x80 : 0x00)
);
break;
case 0x1F:
result = (byte)(
(sprites[0].collideData ? 0x01 : 0x00) |
(sprites[1].collideData ? 0x02 : 0x00) |
(sprites[2].collideData ? 0x04 : 0x00) |
(sprites[3].collideData ? 0x08 : 0x00) |
(sprites[4].collideData ? 0x10 : 0x00) |
(sprites[5].collideData ? 0x20 : 0x00) |
(sprites[6].collideData ? 0x40 : 0x00) |
(sprites[7].collideData ? 0x80 : 0x00)
);
break;
case 0x20:
result &= 0xF0;
result |= (byte)(borderColor & 0x0F);
break;
case 0x21:
result &= 0xF0;
result |= (byte)(backgroundColor0 & 0x0F);
break;
case 0x22:
result &= 0xF0;
result |= (byte)(backgroundColor1 & 0x0F);
break;
case 0x23:
result &= 0xF0;
result |= (byte)(backgroundColor2 & 0x0F);
break;
case 0x24:
result &= 0xF0;
result |= (byte)(backgroundColor3 & 0x0F);
break;
case 0x25:
result &= 0xF0;
result |= (byte)(spriteMulticolor0 & 0x0F);
break;
case 0x26:
result &= 0xF0;
result |= (byte)(spriteMulticolor1 & 0x0F);
break;
case 0x27:
case 0x28:
case 0x29:
case 0x2A:
case 0x2B:
case 0x2C:
case 0x2D:
case 0x2E:
result &= 0xF0;
result |= (byte)(sprites[addr - 0x27].color & 0xF);
break;
default:
// not connected
break;
}
return result;
}
public void Write(int addr, byte val)
{
addr &= 0x3F;
switch (addr)
{
case 0x19:
// interrupts are cleared by writing a 1
if ((val & 0x01) != 0)
intRaster = false;
if ((val & 0x02) != 0)
intSpriteDataCollision = false;
if ((val & 0x04) != 0)
intSpriteCollision = false;
if ((val & 0x08) != 0)
intLightPen = false;
UpdatePins();
break;
case 0x1A:
WriteRegister(addr, val);
break;
case 0x1E:
case 0x1F:
// can't write to these
break;
case 0x2F:
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
// not connected
break;
default:
WriteRegister(addr, val);
break;
}
}
private void WriteRegister(int addr, byte val)
{
switch (addr)
{
case 0x00:
case 0x02:
case 0x04:
case 0x06:
case 0x08:
case 0x0A:
case 0x0C:
case 0x0E:
sprites[addr >> 1].x &= 0x100;
sprites[addr >> 1].x |= val;
break;
case 0x01:
case 0x03:
case 0x05:
case 0x07:
case 0x09:
case 0x0B:
case 0x0D:
case 0x0F:
sprites[addr >> 1].y = val;
break;
case 0x10:
sprites[0].x = (sprites[0].x & 0xFF) | ((val & 0x01) << 8);
sprites[1].x = (sprites[1].x & 0xFF) | ((val & 0x02) << 7);
sprites[2].x = (sprites[2].x & 0xFF) | ((val & 0x04) << 6);
sprites[3].x = (sprites[3].x & 0xFF) | ((val & 0x08) << 5);
sprites[4].x = (sprites[4].x & 0xFF) | ((val & 0x10) << 4);
sprites[5].x = (sprites[5].x & 0xFF) | ((val & 0x20) << 3);
sprites[6].x = (sprites[6].x & 0xFF) | ((val & 0x40) << 2);
sprites[7].x = (sprites[7].x & 0xFF) | ((val & 0x80) << 1);
break;
case 0x11:
yScroll = (val & 0x07);
rowSelect = ((val & 0x08) != 0);
displayEnable = ((val & 0x10) != 0);
bitmapMode = ((val & 0x20) != 0);
extraColorMode = ((val & 0x40) != 0);
rasterInterruptLine &= 0xFF;
rasterInterruptLine |= (val & 0x80) << 1;
UpdateBorder();
break;
case 0x12:
rasterInterruptLine &= 0x100;
rasterInterruptLine |= val;
break;
case 0x13:
lightPenX = val;
break;
case 0x14:
lightPenY = val;
break;
case 0x15:
sprites[0].enable = ((val & 0x01) != 0);
sprites[1].enable = ((val & 0x02) != 0);
sprites[2].enable = ((val & 0x04) != 0);
sprites[3].enable = ((val & 0x08) != 0);
sprites[4].enable = ((val & 0x10) != 0);
sprites[5].enable = ((val & 0x20) != 0);
sprites[6].enable = ((val & 0x40) != 0);
sprites[7].enable = ((val & 0x80) != 0);
break;
case 0x16:
xScroll = (val & 0x07);
columnSelect = ((val & 0x08) != 0);
multicolorMode = ((val & 0x10) != 0);
UpdateBorder();
break;
case 0x17:
sprites[0].yExpand = ((val & 0x01) != 0);
sprites[1].yExpand = ((val & 0x02) != 0);
sprites[2].yExpand = ((val & 0x04) != 0);
sprites[3].yExpand = ((val & 0x08) != 0);
sprites[4].yExpand = ((val & 0x10) != 0);
sprites[5].yExpand = ((val & 0x20) != 0);
sprites[6].yExpand = ((val & 0x40) != 0);
sprites[7].yExpand = ((val & 0x80) != 0);
break;
case 0x18:
pointerVM = ((val >> 4) & 0xF);
pointerCB = ((val >> 1) & 0x7);
break;
case 0x19:
intRaster = ((val & 0x01) != 0);
intSpriteDataCollision = ((val & 0x02) != 0);
intSpriteCollision = ((val & 0x04) != 0);
intLightPen = ((val & 0x08) != 0);
UpdatePins();
break;
case 0x1A:
enableIntRaster = ((val & 0x01) != 0);
enableIntSpriteDataCollision = ((val & 0x02) != 0);
enableIntSpriteCollision = ((val & 0x04) != 0);
enableIntLightPen = ((val & 0x08) != 0);
UpdatePins();
break;
case 0x1B:
sprites[0].priority = ((val & 0x01) != 0);
sprites[1].priority = ((val & 0x02) != 0);
sprites[2].priority = ((val & 0x04) != 0);
sprites[3].priority = ((val & 0x08) != 0);
sprites[4].priority = ((val & 0x10) != 0);
sprites[5].priority = ((val & 0x20) != 0);
sprites[6].priority = ((val & 0x40) != 0);
sprites[7].priority = ((val & 0x80) != 0);
break;
case 0x1C:
sprites[0].multicolor = ((val & 0x01) != 0);
sprites[1].multicolor = ((val & 0x02) != 0);
sprites[2].multicolor = ((val & 0x04) != 0);
sprites[3].multicolor = ((val & 0x08) != 0);
sprites[4].multicolor = ((val & 0x10) != 0);
sprites[5].multicolor = ((val & 0x20) != 0);
sprites[6].multicolor = ((val & 0x40) != 0);
sprites[7].multicolor = ((val & 0x80) != 0);
break;
case 0x1D:
sprites[0].xExpand = ((val & 0x01) != 0);
sprites[1].xExpand = ((val & 0x02) != 0);
sprites[2].xExpand = ((val & 0x04) != 0);
sprites[3].xExpand = ((val & 0x08) != 0);
sprites[4].xExpand = ((val & 0x10) != 0);
sprites[5].xExpand = ((val & 0x20) != 0);
sprites[6].xExpand = ((val & 0x40) != 0);
sprites[7].xExpand = ((val & 0x80) != 0);
break;
case 0x1E:
sprites[0].collideSprite = ((val & 0x01) != 0);
sprites[1].collideSprite = ((val & 0x02) != 0);
sprites[2].collideSprite = ((val & 0x04) != 0);
sprites[3].collideSprite = ((val & 0x08) != 0);
sprites[4].collideSprite = ((val & 0x10) != 0);
sprites[5].collideSprite = ((val & 0x20) != 0);
sprites[6].collideSprite = ((val & 0x40) != 0);
sprites[7].collideSprite = ((val & 0x80) != 0);
break;
case 0x1F:
sprites[0].collideData = ((val & 0x01) != 0);
sprites[1].collideData = ((val & 0x02) != 0);
sprites[2].collideData = ((val & 0x04) != 0);
sprites[3].collideData = ((val & 0x08) != 0);
sprites[4].collideData = ((val & 0x10) != 0);
sprites[5].collideData = ((val & 0x20) != 0);
sprites[6].collideData = ((val & 0x40) != 0);
sprites[7].collideData = ((val & 0x80) != 0);
break;
case 0x20:
borderColor = (val & 0xF);
break;
case 0x21:
backgroundColor0 = (val & 0xF);
break;
case 0x22:
backgroundColor1 = (val & 0xF);
break;
case 0x23:
backgroundColor2 = (val & 0xF);
break;
case 0x24:
backgroundColor3 = (val & 0xF);
break;
case 0x25:
spriteMulticolor0 = (val & 0xF);
break;
case 0x26:
spriteMulticolor1 = (val & 0xF);
break;
case 0x27:
case 0x28:
case 0x29:
case 0x2A:
case 0x2B:
case 0x2C:
case 0x2D:
case 0x2E:
sprites[addr - 0x27].color = (val & 0xF);
break;
default:
break;
}
}
}
}

View File

@ -0,0 +1,247 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
{
private void Render()
{
{
renderEnabled = bufRect.Contains(bufPoint);
for (int i = 0; i < 4; i++)
{
if (borderCheckLEnable && rasterX == borderL)
{
if (rasterLine == borderB)
borderOnVertical = true;
if (rasterLine == borderT && displayEnable)
borderOnVertical = false;
if (!borderOnVertical)
borderOnMain = false;
}
if (borderCheckREnable && rasterX == borderR)
{
borderOnMain = true;
}
// recall pixel from buffer
pixel = pixelBuffer[pixelBufferIndex];
// plot pixel if within viewing area
if (renderEnabled)
{
buf[bufOffset] = palette[pixel];
bufOffset++;
if (bufOffset == bufLength)
bufOffset = 0;
}
bufPoint.X++;
if (bufPoint.X == bufWidth)
{
bufPoint.X = 0;
bufPoint.Y++;
if (bufPoint.Y == bufHeight)
bufPoint.Y = 0;
}
// put the pixel from the background buffer into the main buffer
pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex];
// render sprite
int pixelOwner = 8;
for (int j = 0; j < 8; j++)
{
int sprData;
int sprPixel = pixel;
Sprite spr = sprites[j];
if (spr.x == rasterX)
spr.shiftEnable = true;
if (spr.shiftEnable)
{
if (spr.multicolor)
{
sprData = (spr.sr & 0xC00000) >> 22;
if (spr.multicolorCrunch && spr.xCrunch)
spr.sr <<= 2;
spr.multicolorCrunch ^= spr.xCrunch;
}
else
{
sprData = (spr.sr & 0x800000) >> 22;
if (spr.xCrunch)
spr.sr <<= 1;
}
spr.xCrunch ^= spr.xExpand;
switch (sprData)
{
case 1: sprPixel = spriteMulticolor0; break;
case 2: sprPixel = spr.color; break;
case 3: sprPixel = spriteMulticolor1; break;
}
if (sprData != 0)
{
// sprite-sprite collision
if (pixelOwner >= 8)
{
if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x2))
pixel = sprPixel;
pixelOwner = j;
}
else
{
if (!borderOnVertical)
{
spr.collideSprite = true;
sprites[pixelOwner].collideSprite = true;
}
}
// sprite-data collision
if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] >= 0x2))
{
spr.collideData = true;
}
}
if (spr.sr == 0)
spr.shiftEnable = false; //optimization
}
}
// border doesn't work with the background buffer
if (borderOnMain || borderOnVertical)
pixel = borderColor;
// store pixel in buffer
pixelBuffer[pixelBufferIndex] = pixel;
// fill shift register
if (xOffset == xScroll)
{
if (displayIndex < 40 && !idle)
{
displayC = bufferC[displayIndex];
sr |= bufferG[displayIndex];
}
bitmapColumn = 0;
}
if (!extraColorMode && !bitmapMode & !multicolorMode)
{
// 000
pixelData = (sr & 0x80) >> 6;
sr <<= 1;
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
}
else if (!extraColorMode && !bitmapMode & multicolorMode)
{
// 001
if ((displayC & 0x800) != 0)
{
// multicolor 001
pixelData = (sr & 0xC0) >> 6;
if ((bitmapColumn & 1) != 0)
sr <<= 2;
switch (pixelData)
{
case 0x00: pixel = backgroundColor0; break;
case 0x01: pixel = backgroundColor1; break;
case 0x02: pixel = backgroundColor2; break;
default: pixel = (displayC & 0x700) >> 8; break;
}
}
else
{
// standard 001
pixelData = (sr & 0x80) >> 6;
sr <<= 1;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
}
}
else if (!extraColorMode && bitmapMode & !multicolorMode)
{
// 010
pixelData = (sr & 0x80) >> 6;
sr <<= 1;
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
}
else if (!extraColorMode && bitmapMode & multicolorMode)
{
// 011
pixelData = (sr & 0xC0) >> 6;
if ((bitmapColumn & 1) != 0)
sr <<= 2;
switch (pixelData)
{
case 0x00: pixel = backgroundColor0; break;
case 0x01: pixel = (displayC >> 4) & 0xF; break;
case 0x02: pixel = displayC & 0xF; break;
default: pixel = (displayC >> 8) & 0xF; break;
}
}
else if (extraColorMode && !bitmapMode & !multicolorMode)
{
// 100
pixelData = (sr & 0x80) >> 6;
sr <<= 1;
if (pixelData != 0)
{
pixel = displayC >> 8;
}
else
{
switch ((displayC >> 6) & 0x3)
{
case 0x00: pixel = backgroundColor0; break;
case 0x01: pixel = backgroundColor1; break;
case 0x02: pixel = backgroundColor2; break;
default: pixel = backgroundColor3; break;
}
}
}
else if (extraColorMode && !bitmapMode & multicolorMode)
{
// 101
pixelData = 0;
pixel = 0;
}
else if (extraColorMode && bitmapMode & !multicolorMode)
{
// 110
pixelData = 0;
pixel = 0;
}
else
{
// 111
pixelData = 0;
pixel = 0;
}
// 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++;
bitmapColumn++;
}
}
}
}
}

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
{
private class Sprite
{
public bool collideData;
public bool collideSprite;
public int color;
public bool display;
public bool dma;
public bool enable;
public int mc;
public int mcbase;
public bool multicolor;
public bool multicolorCrunch;
public int pointer;
public bool priority;
public bool shiftEnable;
public int sr;
public int x;
public bool xCrunch;
public bool xExpand;
public int y;
public bool yCrunch;
public bool yExpand;
public void HardReset()
{
collideData = false;
collideSprite = false;
color = 0;
display = false;
dma = false;
enable = false;
mc = 0;
mcbase = 0;
multicolor = false;
multicolorCrunch = false;
pointer = 0;
priority = false;
shiftEnable = false;
sr = 0;
x = 0;
xCrunch = false;
xExpand = false;
y = 0;
yCrunch = false;
yExpand = false;
}
public void SyncState(Serializer ser)
{
ser.Sync("collideData", ref collideData);
ser.Sync("collideSprite", ref collideSprite);
ser.Sync("color", ref color);
ser.Sync("display", ref display);
ser.Sync("dma", ref dma);
ser.Sync("enable", ref enable);
ser.Sync("mc", ref mc);
ser.Sync("mcbase", ref mcbase);
ser.Sync("multicolor", ref multicolor);
ser.Sync("multicolorCrunch", ref multicolorCrunch);
ser.Sync("pointer", ref pointer);
ser.Sync("priority", ref priority);
ser.Sync("shiftEnable", ref shiftEnable);
ser.Sync("sr", ref sr);
ser.Sync("x", ref x);
ser.Sync("xCrunch", ref xCrunch);
ser.Sync("xExpand", ref xExpand);
ser.Sync("y", ref y);
ser.Sync("yCrunch", ref yCrunch);
ser.Sync("yExpand", ref yExpand);
}
}
}
}

File diff suppressed because it is too large Load Diff