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:
parent
1400c84fdd
commit
228fa3869f
|
@ -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" />
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue