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:
parent
14a2952faf
commit
03087a88eb
|
@ -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" />
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue