Commodore64: Border unit implemented fully, timing is much better now and works for both PAL and NTSC.

This commit is contained in:
saxxonpike 2013-08-24 20:13:16 +00:00
parent dde1169325
commit 1c18da52b3
15 changed files with 149 additions and 65 deletions

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
PAL
}
public partial class C64 : IEmulator
sealed public partial class C64 : IEmulator
{
private Motherboard board;
private bool loadPrg;

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
/// <summary>
/// Contains the onboard chipset and glue.
/// </summary>
public partial class Motherboard
sealed public partial class Motherboard
{
// chips
public Chip23XX basicRom;

View File

@ -7,7 +7,7 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class Motherboard
sealed public partial class Motherboard
{
bool CassPort_ReadDataOutput()
{

View File

@ -2,7 +2,7 @@
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class C64 : IEmulator
sealed public partial class C64 : IEmulator
{
public void ClearSaveRam()
{

View File

@ -5,7 +5,7 @@ using System.IO;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class C64 : IEmulator
sealed public partial class C64 : IEmulator
{
// internal variables
private bool _islag = true;

View File

@ -1,12 +1,22 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
using System.Drawing;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// vic ntsc
static public class MOS6567
{
static int[] timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, 0x208, 0x18C, 8);
static int cycles = 65;
static int lines = 263;
static int vblankstart = 0x00D;
static int vblankend = 0x018;
static int hblankstart = 0x18C;
static int hblankend = 0x1F0;
static int scanwidth = cycles * 8;
static int[] timing = Vic.TimingBuilder_XRaster(0x19C, 0x200, scanwidth, 0x18C, 8);
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x174);
static int[] ba = Vic.TimingBuilder_BA(fetch);
static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C);
static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C, hblankstart, hblankend);
static int[][] pipeline = new int[][]
{
@ -18,7 +28,13 @@
static public Vic Create()
{
return new Vic(65, 263, pipeline, 14318181 / 14);
return new Vic(
cycles, lines,
pipeline,
14318181 / 14,
hblankstart, hblankend,
vblankstart, vblankend
);
}
}
}

View File

@ -1,12 +1,22 @@
namespace BizHawk.Emulation.Computers.Commodore64.MOS
using System.Drawing;
namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
// vic pal
static public class MOS6569
{
static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, 0x1F8, -1, -1);
static int cycles = 63;
static int lines = 312;
static int vblankstart = 0x12C;
static int vblankend = 0x00F;
static int hblankstart = 0x17C;
static int hblankend = 0x1E0;
static int scanwidth = cycles * 8;
static int[] timing = Vic.TimingBuilder_XRaster(0x194, 0x1F8, scanwidth, -1, -1);
static int[] fetch = Vic.TimingBuilder_Fetch(timing, 0x164);
static int[] ba = Vic.TimingBuilder_BA(fetch);
static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C);
static int[] act = Vic.TimingBuilder_Act(timing, 0x004, 0x14C, hblankstart, hblankend);
static int[][] pipeline = new int[][]
{
@ -18,7 +28,13 @@
static public Vic Create()
{
return new Vic(63, 312, pipeline, 17734472 / 18);
return new Vic(
cycles, lines,
pipeline,
17734472 / 18,
hblankstart, hblankend,
vblankstart, vblankend
);
}
}
}

View File

@ -613,11 +613,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public Sid(int[][] newWaveformTable, int newSampleRate, Region newRegion)
{
uint cyclesPerSec = 0;
uint cyclesNum;
uint cyclesDen;
uint sampleRate = 44100;
switch (newRegion)
{
case Region.NTSC: cyclesPerSec = 14318181 / 14; break;
case Region.PAL: cyclesPerSec = 17734472 / 18; break;
case Region.NTSC: cyclesNum = 14318181; cyclesDen = 14; break;
case Region.PAL: cyclesNum = 17734472; cyclesDen = 18; break;
default: return;
}
waveformTable = newWaveformTable;
@ -636,7 +640,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
for (int i = 0; i < 3; i++)
filterEnable[i] = false;
resampler = new Sound.Utilities.SpeexResampler(0, cyclesPerSec, 44100, cyclesPerSec, 44100, null, null);
resampler = new Sound.Utilities.SpeexResampler(0, cyclesNum, sampleRate * cyclesDen, cyclesNum, sampleRate * cyclesDen, null, null);
}
public void Dispose()

View File

@ -19,6 +19,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public const int pipelineChkBrdR1 = 256;
public const int pipelineChkSprDisp = 512;
public const int pipelineUpdateRc = 1024;
public const int pipelineHBlankL = 0x10000000;
public const int pipelineHBlankR = 0x20000000;
public const int pipelineHoldX = 0x40000000;
public const int rasterIrqLine0Cycle = 1;
public const int rasterIrqLineXCycle = 0;
@ -43,6 +45,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// apply X location
rasterX = pipeline[0][cycleIndex];
rasterXHold = ((parseact & pipelineHoldX) != 0);
// perform fetch
parsefetchType = parsefetch & 0xFF00;
@ -158,7 +161,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// perform actions
borderCheckLEnable = ((parseact & (pipelineChkBrdL0 | pipelineChkBrdL1)) != 0);
borderCheckREnable = ((parseact & (pipelineChkBrdR0 | pipelineChkBrdR1)) != 0);
rasterXHold = ((parseact & pipelineHoldX) != 0);
hblankCheckEnableL = ((parseact & pipelineHBlankL) != 0);
hblankCheckEnableR = ((parseact & pipelineHBlankR) != 0);
if (parseact != 0)
{

View File

@ -7,6 +7,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{
sealed public partial class Vic
{
int borderSR;
int ecmPixel;
int pixel;
int[] pixelBackgroundBuffer;
@ -33,47 +34,52 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private void Render()
{
renderEnabled = bufRect.Contains(bufPoint);
if (hblankCheckEnableL)
{
if (rasterX == hblankEnd)
hblank = false;
}
else if (hblankCheckEnableR)
{
if (rasterX == hblankStart)
hblank = true;
}
renderEnabled = !hblank && !vblank; //bufRect.Contains(bufPoint);
for (int i = 0; i < 4; i++)
{
if (borderCheckLEnable)
if (borderCheckLEnable && (rasterX == borderL))
{
if (rasterX == borderL)
{
if (rasterLine == borderB)
borderOnVertical = true;
if (rasterLine == borderT && displayEnable)
borderOnVertical = false;
if (!borderOnVertical)
borderOnMain = false;
}
}
if (borderCheckREnable)
{
if (rasterX == borderR)
borderOnMain = true;
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];
// border doesn't work with the background buffer
borderSR <<= 1;
if (borderOnMain || borderOnVertical)
borderSR |= 1;
if ((borderSR & 0x100) != 0)
pixel = borderColor;
// 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];
@ -143,10 +149,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
}
// border doesn't work with the background buffer
if (borderOnMain || borderOnVertical)
pixel = borderColor;
// store pixel in buffer
pixelBuffer[pixelBufferIndex] = pixel;

View File

@ -42,11 +42,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
bool enableIntSpriteCollision;
bool enableIntSpriteDataCollision;
bool extraColorMode;
bool hblank;
bool idle;
bool intLightPen;
bool intRaster;
bool intSpriteCollision;
bool intSpriteDataCollision;
int hblankEnd;
int hblankStart;
bool hblankCheckEnableL;
bool hblankCheckEnableR;
int lastRasterLine;
int lightPenX;
int lightPenY;
@ -69,6 +74,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int spriteMulticolor1;
Sprite[] sprites;
int sr;
bool vblank;
int vblankEnd;
int vblankStart;
int vc;
int vcbase;
int vmli;
@ -105,6 +113,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
enableIntSpriteCollision = false;
enableIntSpriteDataCollision = false;
extraColorMode = false;
hblank = true;
idle = true;
intLightPen = false;
intRaster = false;
@ -127,6 +136,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
spriteMulticolor0 = 0;
spriteMulticolor1 = 0;
sr = 0;
vblank = true;
vc = 0;
vcbase = 0;
vmli = 0;

View File

@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pipelineChkSprDisp, pipelineUpdateRc
};
static public int[] TimingBuilder_Act(int[] timing, int cycle14, int cycle55)
static public int[] TimingBuilder_Act(int[] timing, int cycle14, int cycle55, int hblankStart, int hblankEnd)
{
List<int> result = new List<int>();
@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
result.Add(0);
}
bool hBlankL = false;
bool hBlankR = false;
for (int i = 0; i < length; i++)
{
// pipeline raster X delay
@ -54,6 +56,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
result[i] |= pipelineChkBrdR0;
if (timing[i] == 0x15C)
result[i] |= pipelineChkBrdR1;
if (timing[i] == (hblankStart & 0xFFD))
result[i] |= pipelineHBlankR;
if (timing[i] == (hblankEnd & 0xFFD))
result[i] |= pipelineHBlankL;
}
return result.ToArray();
@ -196,6 +202,34 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
return result.ToArray();
}
static public int TimingBuilder_ScreenHeight(int vblankStart, int vblankEnd, int lines)
{
int offset = vblankEnd;
int result = 0;
while (true)
{
if (offset >= lines)
offset -= lines;
if (offset == vblankStart)
return result;
offset++;
result++;
}
}
static public int TimingBuilder_ScreenWidth(int[] timing, int hblankStart, int hblankEnd)
{
int length = timing.Length;
int result = 0;
int offset = 0;
while (timing[offset] != hblankEnd) { offset = (offset + 1) % length; }
while (timing[offset] != hblankStart) { offset = (offset + 1) % length; result++; }
//while (timing[offset] == hblankStart) { offset = (offset + 1) % length; result++; }
return (result * 4);
}
static public int[] TimingBuilder_XRaster(int start, int width, int count, int delayOffset, int delayAmount)
{
List<int> result = new List<int>();

View File

@ -8,8 +8,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int bufHeight;
int bufLength;
int bufOffset;
Point bufPoint;
Rectangle bufRect;
int bufWidth;
// palette
@ -40,12 +38,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public int BufferHeight
{
get { return bufRect.Height; }
get { return bufHeight; }
}
public int BufferWidth
{
get { return bufRect.Width; }
get { return bufWidth; }
}
public int[] GetVideoBuffer()
@ -55,7 +53,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public int VirtualWidth
{
get { return bufRect.Width; }
get { return bufWidth; }
}
}
}

View File

@ -18,12 +18,16 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
int totalCycles;
int totalLines;
public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec)
public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd)
{
{
debugScreen = false;
this.hblankStart = hblankStart;
this.hblankEnd = hblankEnd;
this.vblankStart = vblankStart;
this.vblankEnd = vblankEnd;
totalCycles = newCycles;
totalLines = newLines;
pipeline = newPipeline;
@ -31,19 +35,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
pixelBufferDelay = 12;
pixelBackgroundBufferDelay = 4;
if (debugScreen)
{
bufRect = new Rectangle(0, 0, totalCycles * 8, totalLines);
}
else
{
bufRect = new Rectangle(136 - 24, 51 - 24, 320 + 48, 200 + 48);
}
bufWidth = TimingBuilder_ScreenWidth(pipeline[0], hblankStart, hblankEnd);
bufHeight = TimingBuilder_ScreenHeight(vblankStart, vblankEnd, newLines);
buf = new int[bufRect.Width * bufRect.Height];
buf = new int[bufWidth * bufHeight];
bufLength = buf.Length;
bufWidth = (totalCycles * 8);
bufHeight = (totalLines);
sprites = new Sprite[8];
for (int i = 0; i < 8; i++)
@ -145,6 +141,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if (rasterLine == borderT && displayEnable)
borderOnVertical = false;
if (rasterLine == vblankStart)
vblank = true;
if (rasterLine == vblankEnd)
vblank = false;
cycleIndex = 0;
cycle = 0;
rasterLine++;

View File

@ -24,7 +24,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
IntBuffer refIntBuffer;
Int32 refPointX;
Int32 refPointY;
Rectangle refRect;
SByte refSByte;
UInt16 refUInt16;
UInt32 refUInt32;