Video chip timing in the old core now builds its timing tables dynamically instead of having them hardcoded- should greatly reduce human error. The algorithm should cover every single revision of VIC.

This commit is contained in:
saxxonpike 2013-08-24 15:21:51 +00:00
parent 1400c84fdd
commit 228fa3869f
12 changed files with 377 additions and 530 deletions

View File

@ -163,6 +163,7 @@
<Compile Include="Computers\Commodore64\MOS\Vic.Render.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.Sprite.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.State.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.TimingBuilder.cs" />
<Compile Include="Computers\Commodore64\MOS\Vic.VideoProvider.cs" />
<Compile Include="Computers\Commodore64\Sync.cs" />
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />

View File

@ -51,8 +51,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
sid = new MOS6581(44100, initRegion);
switch (initRegion)
{
case Region.NTSC: vic = new MOS6567(); break;
case Region.PAL: vic = new MOS6569(); break;
case Region.NTSC: vic = MOS6567.Create(); break;
case Region.PAL: vic = MOS6569.Create(); break;
}
userPort = new UserPort();
}

View File

@ -1,13 +1,12 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// vic ntsc
public class MOS6567 : Vic
static public class MOS6567
{
static protected int[][] pipeline = new int[5][];
public MOS6567()
: base(65, 263, pipeline, 14318181 / 14)
{
}
static int[][] pipeline = new int[5][];
static public Vic Create()
{
return new Vic(65, 263, pipeline, 14318181 / 14);
}
}
}

View File

@ -1,244 +1,17 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// vic pal
public class MOS6569 : Vic
public class MOS6569
{
static protected int[][] pipeline = new int[][]
{
new int[] // xposition
{
0x0194, 0x0198,
0x019C, 0x01A0,
0x01A4, 0x01A8,
0x01AC, 0x01B0,
0x01B4, 0x01B8,
static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, 0x1F8, -1, -1);
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x164);
static int[] ba = Vic.TimingBuilder_BA(fetch);
0x01BC, 0x01C0,
0x01C4, 0x01C8,
0x01CC, 0x01D0,
0x01D4, 0x01D8,
0x01DC, 0x01E0,
0x01E4, 0x01E8,
0x01EC, 0x01F0,
0x01F4, 0x0000,
0x0004, 0x0008,
0x000C, 0x0010,
0x0014, 0x0018,
0x001C, 0x0020,
0x0024, 0x0028,
0x002C, 0x0030,
0x0034, 0x0038,
0x003C, 0x0040,
0x0044, 0x0048,
0x004C, 0x0050,
0x0054, 0x0058,
0x005C, 0x0060,
0x0064, 0x0068,
0x006C, 0x0070,
0x0074, 0x0078,
0x007C, 0x0080,
0x0084, 0x0088,
0x008C, 0x0090,
0x0094, 0x0098,
0x009C, 0x00A0,
0x00A4, 0x00A8,
0x00AC, 0x00B0,
0x00B4, 0x00B8,
0x00BC, 0x00C0,
0x00C4, 0x00C8,
0x00CC, 0x00D0,
0x00D4, 0x00D8,
0x00DC, 0x00E0,
0x00E4, 0x00E8,
0x00EC, 0x00F0,
0x00F4, 0x00F8,
0x00FC, 0x0100,
0x0104, 0x0108,
0x010C, 0x0110,
0x0114, 0x0118,
0x011C, 0x0120,
0x0124, 0x0128,
0x012C, 0x0130,
0x0134, 0x0138,
0x013C, 0x0140,
0x0144, 0x0148,
0x014C, 0x0150,
0x0154, 0x0158,
0x015C, 0x0160,
0x0164, 0x0168,
0x016C, 0x0170,
0x0174, 0x0178,
0x017C, 0x0180,
0x0184, 0x0188,
0x018C, 0x0190
},
new int[] // fetch (100=ref 200=c 300=g 400=i 500=none)
{
0x0003, 0x0013,
0x0023, 0x0033,
0x0004, 0x0014,
0x0024, 0x0034,
0x0005, 0x0015,
0x0025, 0x0035,
0x0006, 0x0016,
0x0026, 0x0036,
0x0007, 0x0017,
0x0027, 0x0037,
0x0100, 0x0500,
0x0100, 0x0500,
0x0100, 0x0500,
0x0100, 0x0500,
0x0100, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0200,
0x0300, 0x0500,
0x0400, 0x0500,
0x0400, 0x0500,
0x0000, 0x0010,
0x0020, 0x0030,
0x0001, 0x0011,
0x0021, 0x0031,
0x0002, 0x0012,
0x0022, 0x0032
},
new int[] // BA
{
0x0843, 0x0843,
0x0543, 0x0543,
0x0548, 0x0548,
0x0546, 0x0546,
0x0586, 0x0586,
0x0576, 0x0576,
0x0876, 0x0876,
0x0876, 0x0876,
0x0878, 0x0878,
0x0878, 0x0878,
0x0000, 0x0000,
0x1000, 0x1000, // 12: badline ba start
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000, // 15: badline start
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x0880, 0x0880, // 55: sprites
0x0880, 0x0880,
0x0810, 0x0810,
0x0810, 0x0810,
0x0210, 0x0210,
0x0218, 0x0218,
0x0213, 0x0213,
0x0283, 0x0283,
0x0243, 0x0243
},
static int[][] pipeline = new int[][]
{
timing,
fetch,
ba,
new int[] // actions
{
0, 0,
@ -256,12 +29,12 @@
0, 0,
0, 0,
0, 0,
0, pipelineUpdateVc,
0, pipelineChkSprChunch,
0, Vic.pipelineUpdateVc,
0, Vic.pipelineChkSprChunch,
0, pipelineUpdateMcBase,
0, pipelineChkBrdL1,
0, pipelineChkBrdL0,
0, Vic.pipelineUpdateMcBase,
0, Vic.pipelineChkBrdL1,
0, Vic.pipelineChkBrdL0,
0, 0,
0, 0,
@ -305,11 +78,11 @@
0, 0,
0, 0,
0, 0,
pipelineChkSprDma, 0,
Vic.pipelineChkSprDma, 0,
pipelineChkSprDma, pipelineChkBrdR0 | pipelineChkSprExp,
0, pipelineChkBrdR1,
pipelineChkSprDisp, pipelineUpdateRc,
Vic.pipelineChkSprDma, Vic.pipelineChkBrdR0 | Vic.pipelineChkSprExp,
0, Vic.pipelineChkBrdR1,
Vic.pipelineChkSprDisp, Vic.pipelineUpdateRc,
0, 0,
0, 0,
@ -319,9 +92,9 @@
}
};
public MOS6569()
: base(63, 312, pipeline, 17734472 / 18)
{
}
static public Vic Create()
{
return new Vic(63, 312, pipeline, 17734472 / 18);
}
}
}

View File

@ -5,22 +5,22 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
protected const int baResetCounter = 6;
protected const int pipelineUpdateVc = 1;
protected const int pipelineChkSprChunch = 2;
protected const int pipelineUpdateMcBase = 4;
protected const int pipelineChkBrdL1 = 8;
protected const int pipelineChkBrdL0 = 16;
protected const int pipelineChkSprDma = 32;
protected const int pipelineChkBrdR0 = 64;
protected const int pipelineChkSprExp = 128;
protected const int pipelineChkBrdR1 = 256;
protected const int pipelineChkSprDisp = 512;
protected const int pipelineUpdateRc = 1024;
protected const int rasterIrqLine0Cycle = 1;
protected const int rasterIrqLineXCycle = 0;
public const int baResetCounter = 6;
public const int pipelineUpdateVc = 1;
public const int pipelineChkSprChunch = 2;
public const int pipelineUpdateMcBase = 4;
public const int pipelineChkBrdL1 = 8;
public const int pipelineChkBrdL0 = 16;
public const int pipelineChkSprDma = 32;
public const int pipelineChkBrdR0 = 64;
public const int pipelineChkSprExp = 128;
public const int pipelineChkBrdR1 = 256;
public const int pipelineChkSprDisp = 512;
public const int pipelineUpdateRc = 1024;
public const int rasterIrqLine0Cycle = 1;
public const int rasterIrqLineXCycle = 0;
protected int parseaddr;
protected int parsecycleBAsprite0;

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
public byte Peek(int addr)

View File

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
protected int ecmPixel;
protected int pixel;
@ -33,222 +33,138 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private void Render()
{
renderEnabled = bufRect.Contains(bufPoint);
for (int i = 0; i < 4; i++)
{
renderEnabled = bufRect.Contains(bufPoint);
for (int i = 0; i < 4; i++)
if (borderCheckLEnable && rasterX == borderL)
{
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
pixelOwner = 8;
for (int j = 0; j < 8; j++)
{
sprData = 0;
sprPixel = pixel;
Sprite spr = sprites[j];
if (spr.x == rasterX)
spr.shiftEnable = true;
if (spr.shiftEnable)
{
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
pixelOwner = 8;
for (int j = 0; j < 8; j++)
{
sprData = 0;
sprPixel = pixel;
Sprite spr = sprites[j];
if (spr.x == rasterX)
spr.shiftEnable = true;
if (spr.shiftEnable)
if (spr.multicolor)
{
if (spr.multicolor)
{
sprData = (spr.sr & 0xC00000);
if (spr.multicolorCrunch && spr.xCrunch)
spr.sr <<= 2;
spr.multicolorCrunch ^= spr.xCrunch;
}
else
{
sprData = (spr.sr & 0x800000);
if (spr.xCrunch)
spr.sr <<= 1;
}
spr.xCrunch ^= spr.xExpand;
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)
{
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] == 0x80))
{
spr.collideData = true;
}
}
if (spr.sr == 0)
spr.shiftEnable = false; //optimization
sprData = (spr.sr & 0xC00000);
if (spr.multicolorCrunch && spr.xCrunch)
spr.sr <<= 2;
spr.multicolorCrunch ^= spr.xCrunch;
}
}
// 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)
else
{
displayC = bufferC[displayIndex];
sr |= bufferG[displayIndex];
sprData = (spr.sr & 0x800000);
if (spr.xCrunch)
spr.sr <<= 1;
}
bitmapColumn = 0;
spr.xCrunch ^= spr.xExpand;
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)
{
if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x80))
pixel = sprPixel;
pixelOwner = j;
}
else
{
if (!borderOnVertical)
{
spr.collideSprite = true;
sprites[pixelOwner].collideSprite = true;
}
}
// sprite-data collision
if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] == 0x80))
{
spr.collideData = true;
}
}
if (spr.sr == 0)
spr.shiftEnable = false; //optimization
}
}
#if true
switch (videoMode)
// 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)
{
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;
displayC = bufferC[displayIndex];
sr |= bufferG[displayIndex];
}
bitmapColumn = 0;
}
#else
if (!extraColorMode && !bitmapMode & !multicolorMode)
{
// 000
switch (videoMode)
{
case VicVideoMode.Mode000:
pixelData = (sr & 0x80);
sr <<= 1;
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
}
else if (!extraColorMode && !bitmapMode & multicolorMode)
{
// 001
break;
case VicVideoMode.Mode001:
if ((displayC & 0x800) != 0)
{
// multicolor 001
@ -272,33 +188,27 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
sr <<= 1;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
}
}
else if (!extraColorMode && bitmapMode & !multicolorMode)
{
// 010
break;
case VicVideoMode.Mode010:
pixelData = (sr & 0x80);
sr <<= 1;
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
}
else if (!extraColorMode && bitmapMode & multicolorMode)
{
// 011
break;
case VicVideoMode.Mode011:
pixelData = (sr & 0xC0);
if ((bitmapColumn & 1) != 0)
sr <<= 2;
if (pixelData == 0x00)
if (pixelData == 0x00)
pixel = backgroundColor0;
else if (pixelData == 0x40)
else if (pixelData == 0x40)
pixel = (displayC >> 4) & 0xF;
else if (pixelData == 0x80)
else if (pixelData == 0x80)
pixel = displayC & 0xF;
else
else
pixel = (displayC >> 8) & 0xF;
}
else if (extraColorMode && !bitmapMode & !multicolorMode)
{
// 100
break;
case VicVideoMode.Mode100:
pixelData = (sr & 0x80);
sr <<= 1;
if (pixelData != 0)
@ -317,44 +227,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
else
pixel = backgroundColor3;
}
}
else if (extraColorMode && !bitmapMode & multicolorMode)
{
// 101
break;
default:
pixelData = 0;
pixel = 0;
}
else if (extraColorMode && bitmapMode & !multicolorMode)
{
// 110
pixelData = 0;
pixel = 0;
}
else
{
// 111
pixelData = 0;
pixel = 0;
}
#endif
// 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++;
break;
}
// 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

@ -5,7 +5,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
protected class Sprite
{

View File

@ -6,7 +6,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
protected int backgroundColor0;
protected int backgroundColor1;

View File

@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
sealed public partial class Vic
{
static public int[] TimingBuilder_BA(int[] fetch)
{
int baRestart = 7;
int bacounter = 0;
int start = 0;
int length = fetch.Length;
int[] result = new int[length];
int[] spriteBA = new int[8];
int charBA = 0;
while (true)
{
if (fetch[start] == 0)
break;
start++;
}
while (true)
{
if (fetch[start] == 0x200)
break;
start--;
}
if (start < 0)
start += length;
int offset = start;
while (true)
{
int ba = 0x0888;
if (fetch[offset] == 0x200)
charBA = baRestart;
else if ((fetch[offset] & 0xFF00) == 0x0000)
spriteBA[fetch[offset] & 0x007] = baRestart;
for (int i = 0; i < 8; i++)
{
if (spriteBA[i] > 0)
{
ba <<= 4;
ba |= i;
spriteBA[i]--;
}
}
ba &= 0x0FFF;
if (charBA > 0)
{
ba = 0x1000;
charBA--;
}
result[offset] = ba;
offset--;
if (offset < 0)
offset += length;
if (offset == start)
break;
}
for (int i = 0; i < length; i += 2)
{
result[i] = result[i + 1];
}
return result;
}
static public int[] TimingBuilder_Fetch(int[] timing, int sprite)
{
int length = timing.Length;
int[] result = new int[length];
int offset;
int index = -1;
int refreshCounter = 0;
bool spriteActive = false;
int spriteIndex = 0;
int spritePhase = 0;
int charCounter = 0;
for (int i = 0; i < length; i++)
{
result[i++] = 0x500;
result[i] = 0x100;
}
while (true)
{
index++;
if (index >= length)
index -= length;
offset = timing[index];
if (charCounter > 0)
{
result[index] = (charCounter & 1) == 0 ? 0x200 : 0x300;
charCounter--;
if (charCounter == 0)
break;
}
if (refreshCounter > 0)
{
result[index] = (refreshCounter & 1) == 0 ? 0x500 : 0x100;
refreshCounter--;
if (refreshCounter == 0)
charCounter = 80;
}
if (offset == sprite)
{
spriteActive = true;
}
if (spriteActive)
{
result[index] = (spriteIndex | (spritePhase << 4));
spritePhase++;
if (spritePhase == 4)
{
spritePhase = 0;
spriteIndex++;
if (spriteIndex == 8)
{
spriteActive = false;
refreshCounter = 9;
}
}
}
}
return result.ToArray();
}
static public int[] TimingBuilder_XRaster(int start, int width, int count, int delayOffset, int delayAmount)
{
List<int> result = new List<int>();
int rasterX = start;
bool delayed = false;
count >>= 2;
for (int i = 0; i < count; i++)
{
result.Add(rasterX);
if (!delayed)
{
rasterX += 4;
if (rasterX >= width)
rasterX -= width;
}
else
{
delayAmount--;
if (delayAmount <= 0)
delayed = false;
continue;
}
if (rasterX == delayOffset && delayAmount > 0)
delayed = true;
}
return result.ToArray();
}
}
}

View File

@ -2,7 +2,7 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic : IVideoProvider
sealed public partial class Vic : IVideoProvider
{
protected int[] buf;
protected int bufHeight;

View File

@ -3,7 +3,7 @@ using System.Drawing;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
public abstract partial class Vic
sealed public partial class Vic
{
public Func<int, byte> ReadColorRam;
public Func<int, byte> ReadMemory;