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.Render.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.Sprite.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.Sprite.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.State.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\MOS\Vic.VideoProvider.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Sync.cs" />
|
<Compile Include="Computers\Commodore64\Sync.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />
|
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />
|
||||||
|
|
|
@ -51,8 +51,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
sid = new MOS6581(44100, initRegion);
|
sid = new MOS6581(44100, initRegion);
|
||||||
switch (initRegion)
|
switch (initRegion)
|
||||||
{
|
{
|
||||||
case Region.NTSC: vic = new MOS6567(); break;
|
case Region.NTSC: vic = MOS6567.Create(); break;
|
||||||
case Region.PAL: vic = new MOS6569(); break;
|
case Region.PAL: vic = MOS6569.Create(); break;
|
||||||
}
|
}
|
||||||
userPort = new UserPort();
|
userPort = new UserPort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
// vic ntsc
|
// vic ntsc
|
||||||
public class MOS6567 : Vic
|
static public class MOS6567
|
||||||
{
|
{
|
||||||
static protected int[][] pipeline = new int[5][];
|
static int[][] pipeline = new int[5][];
|
||||||
|
static public Vic Create()
|
||||||
public MOS6567()
|
{
|
||||||
: base(65, 263, pipeline, 14318181 / 14)
|
return new Vic(65, 263, pipeline, 14318181 / 14);
|
||||||
{
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,244 +1,17 @@
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
// vic pal
|
// vic pal
|
||||||
public class MOS6569 : Vic
|
public class MOS6569
|
||||||
{
|
{
|
||||||
static protected int[][] pipeline = new int[][]
|
static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, 0x1F8, -1, -1);
|
||||||
{
|
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x164);
|
||||||
new int[] // xposition
|
static int[] ba = Vic.TimingBuilder_BA(fetch);
|
||||||
{
|
|
||||||
0x0194, 0x0198,
|
|
||||||
0x019C, 0x01A0,
|
|
||||||
0x01A4, 0x01A8,
|
|
||||||
0x01AC, 0x01B0,
|
|
||||||
0x01B4, 0x01B8,
|
|
||||||
|
|
||||||
0x01BC, 0x01C0,
|
static int[][] pipeline = new int[][]
|
||||||
0x01C4, 0x01C8,
|
{
|
||||||
0x01CC, 0x01D0,
|
timing,
|
||||||
0x01D4, 0x01D8,
|
fetch,
|
||||||
0x01DC, 0x01E0,
|
ba,
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
new int[] // actions
|
new int[] // actions
|
||||||
{
|
{
|
||||||
0, 0,
|
0, 0,
|
||||||
|
@ -256,12 +29,12 @@
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, pipelineUpdateVc,
|
0, Vic.pipelineUpdateVc,
|
||||||
0, pipelineChkSprChunch,
|
0, Vic.pipelineChkSprChunch,
|
||||||
|
|
||||||
0, pipelineUpdateMcBase,
|
0, Vic.pipelineUpdateMcBase,
|
||||||
0, pipelineChkBrdL1,
|
0, Vic.pipelineChkBrdL1,
|
||||||
0, pipelineChkBrdL0,
|
0, Vic.pipelineChkBrdL0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
|
|
||||||
|
@ -305,11 +78,11 @@
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
pipelineChkSprDma, 0,
|
Vic.pipelineChkSprDma, 0,
|
||||||
|
|
||||||
pipelineChkSprDma, pipelineChkBrdR0 | pipelineChkSprExp,
|
Vic.pipelineChkSprDma, Vic.pipelineChkBrdR0 | Vic.pipelineChkSprExp,
|
||||||
0, pipelineChkBrdR1,
|
0, Vic.pipelineChkBrdR1,
|
||||||
pipelineChkSprDisp, pipelineUpdateRc,
|
Vic.pipelineChkSprDisp, Vic.pipelineUpdateRc,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
|
|
||||||
|
@ -319,9 +92,9 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public MOS6569()
|
static public Vic Create()
|
||||||
: base(63, 312, pipeline, 17734472 / 18)
|
{
|
||||||
{
|
return new Vic(63, 312, pipeline, 17734472 / 18);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,22 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
protected const int baResetCounter = 6;
|
public const int baResetCounter = 6;
|
||||||
protected const int pipelineUpdateVc = 1;
|
public const int pipelineUpdateVc = 1;
|
||||||
protected const int pipelineChkSprChunch = 2;
|
public const int pipelineChkSprChunch = 2;
|
||||||
protected const int pipelineUpdateMcBase = 4;
|
public const int pipelineUpdateMcBase = 4;
|
||||||
protected const int pipelineChkBrdL1 = 8;
|
public const int pipelineChkBrdL1 = 8;
|
||||||
protected const int pipelineChkBrdL0 = 16;
|
public const int pipelineChkBrdL0 = 16;
|
||||||
protected const int pipelineChkSprDma = 32;
|
public const int pipelineChkSprDma = 32;
|
||||||
protected const int pipelineChkBrdR0 = 64;
|
public const int pipelineChkBrdR0 = 64;
|
||||||
protected const int pipelineChkSprExp = 128;
|
public const int pipelineChkSprExp = 128;
|
||||||
protected const int pipelineChkBrdR1 = 256;
|
public const int pipelineChkBrdR1 = 256;
|
||||||
protected const int pipelineChkSprDisp = 512;
|
public const int pipelineChkSprDisp = 512;
|
||||||
protected const int pipelineUpdateRc = 1024;
|
public const int pipelineUpdateRc = 1024;
|
||||||
protected const int rasterIrqLine0Cycle = 1;
|
public const int rasterIrqLine0Cycle = 1;
|
||||||
protected const int rasterIrqLineXCycle = 0;
|
public const int rasterIrqLineXCycle = 0;
|
||||||
|
|
||||||
protected int parseaddr;
|
protected int parseaddr;
|
||||||
protected int parsecycleBAsprite0;
|
protected int parsecycleBAsprite0;
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
|
|
||||||
public byte Peek(int addr)
|
public byte Peek(int addr)
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
protected int ecmPixel;
|
protected int ecmPixel;
|
||||||
protected int pixel;
|
protected int pixel;
|
||||||
|
@ -33,222 +33,138 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
private void Render()
|
private void Render()
|
||||||
{
|
{
|
||||||
|
renderEnabled = bufRect.Contains(bufPoint);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
renderEnabled = bufRect.Contains(bufPoint);
|
if (borderCheckLEnable && rasterX == borderL)
|
||||||
|
|
||||||
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
|
||||||
|
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)
|
if (spr.multicolor)
|
||||||
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)
|
sprData = (spr.sr & 0xC00000);
|
||||||
{
|
if (spr.multicolorCrunch && spr.xCrunch)
|
||||||
sprData = (spr.sr & 0xC00000);
|
spr.sr <<= 2;
|
||||||
if (spr.multicolorCrunch && spr.xCrunch)
|
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
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
// 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];
|
sprData = (spr.sr & 0x800000);
|
||||||
sr |= bufferG[displayIndex];
|
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
|
// border doesn't work with the background buffer
|
||||||
switch (videoMode)
|
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:
|
displayC = bufferC[displayIndex];
|
||||||
pixelData = (sr & 0x80);
|
sr |= bufferG[displayIndex];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
bitmapColumn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
switch (videoMode)
|
||||||
|
{
|
||||||
if (!extraColorMode && !bitmapMode & !multicolorMode)
|
case VicVideoMode.Mode000:
|
||||||
{
|
|
||||||
// 000
|
|
||||||
pixelData = (sr & 0x80);
|
pixelData = (sr & 0x80);
|
||||||
sr <<= 1;
|
sr <<= 1;
|
||||||
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
|
pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0;
|
||||||
}
|
break;
|
||||||
else if (!extraColorMode && !bitmapMode & multicolorMode)
|
case VicVideoMode.Mode001:
|
||||||
{
|
|
||||||
// 001
|
|
||||||
if ((displayC & 0x800) != 0)
|
if ((displayC & 0x800) != 0)
|
||||||
{
|
{
|
||||||
// multicolor 001
|
// multicolor 001
|
||||||
|
@ -272,33 +188,27 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
sr <<= 1;
|
sr <<= 1;
|
||||||
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
|
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (!extraColorMode && bitmapMode & !multicolorMode)
|
case VicVideoMode.Mode010:
|
||||||
{
|
|
||||||
// 010
|
|
||||||
pixelData = (sr & 0x80);
|
pixelData = (sr & 0x80);
|
||||||
sr <<= 1;
|
sr <<= 1;
|
||||||
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
|
pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF);
|
||||||
}
|
break;
|
||||||
else if (!extraColorMode && bitmapMode & multicolorMode)
|
case VicVideoMode.Mode011:
|
||||||
{
|
|
||||||
// 011
|
|
||||||
pixelData = (sr & 0xC0);
|
pixelData = (sr & 0xC0);
|
||||||
if ((bitmapColumn & 1) != 0)
|
if ((bitmapColumn & 1) != 0)
|
||||||
sr <<= 2;
|
sr <<= 2;
|
||||||
|
|
||||||
if (pixelData == 0x00)
|
if (pixelData == 0x00)
|
||||||
pixel = backgroundColor0;
|
pixel = backgroundColor0;
|
||||||
else if (pixelData == 0x40)
|
else if (pixelData == 0x40)
|
||||||
pixel = (displayC >> 4) & 0xF;
|
pixel = (displayC >> 4) & 0xF;
|
||||||
else if (pixelData == 0x80)
|
else if (pixelData == 0x80)
|
||||||
pixel = displayC & 0xF;
|
pixel = displayC & 0xF;
|
||||||
else
|
else
|
||||||
pixel = (displayC >> 8) & 0xF;
|
pixel = (displayC >> 8) & 0xF;
|
||||||
}
|
break;
|
||||||
else if (extraColorMode && !bitmapMode & !multicolorMode)
|
case VicVideoMode.Mode100:
|
||||||
{
|
|
||||||
// 100
|
|
||||||
pixelData = (sr & 0x80);
|
pixelData = (sr & 0x80);
|
||||||
sr <<= 1;
|
sr <<= 1;
|
||||||
if (pixelData != 0)
|
if (pixelData != 0)
|
||||||
|
@ -317,44 +227,28 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
else
|
else
|
||||||
pixel = backgroundColor3;
|
pixel = backgroundColor3;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (extraColorMode && !bitmapMode & multicolorMode)
|
default:
|
||||||
{
|
|
||||||
// 101
|
|
||||||
pixelData = 0;
|
pixelData = 0;
|
||||||
pixel = 0;
|
pixel = 0;
|
||||||
}
|
break;
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
protected class Sprite
|
protected class Sprite
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
protected int backgroundColor0;
|
protected int backgroundColor0;
|
||||||
protected int backgroundColor1;
|
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
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public abstract partial class Vic : IVideoProvider
|
sealed public partial class Vic : IVideoProvider
|
||||||
{
|
{
|
||||||
protected int[] buf;
|
protected int[] buf;
|
||||||
protected int bufHeight;
|
protected int bufHeight;
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Drawing;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
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> ReadColorRam;
|
||||||
public Func<int, byte> ReadMemory;
|
public Func<int, byte> ReadMemory;
|
||||||
|
|
Loading…
Reference in New Issue