VIC: More accurate pixel pipeline

This commit is contained in:
SaxxonPike 2019-07-09 05:26:26 -05:00
parent 3efea15038
commit 9f733d3e7a
4 changed files with 131 additions and 142 deletions

View File

@ -42,6 +42,10 @@
private int _parseBa;
private int _parseAct;
private bool _parseIsSprCrunch;
private int _parsePixelData;
private int _parsePixelDataIndex;
private int _parseSrData0;
private int _parseSrData1;
private void ParseCycle()
{
@ -80,8 +84,6 @@
_dataC = 0;
_bufferC[_vmli] = _dataC;
}
_srColorSync |= 0x01 << (7 - _xScroll);
break;
case FetchTypeGraphics:
// fetch G
@ -96,14 +98,114 @@
if (_extraColorModeBuffer)
_parseAddr &= AddressMaskEc;
_dataG = ReadMemory(_parseAddr);
_sr |= _dataG << (7 - _xScroll);
_srSync |= 0xAA << (7 - _xScroll);
if (!_idle)
{
_bufferG[_vmli] = _dataG;
_vmli = (_vmli + 1) & 0x3F;
_vc = (_vc + 1) & 0x3FF;
}
// graphics data shift register
_srData1 &= ~(0xFF << (7 - _xScroll));
_srActive |= 0xFF << (7 - _xScroll);
if (_multicolorMode && (_bitmapMode || (_dataC & 0x800) != 0))
{
_parseSrData0 = (_dataG & 0x55) | ((_dataG & 0x55) << 1);
_parseSrData1 = (_dataG & 0xAA) | ((_dataG & 0xAA) >> 1);
}
else
{
_parseSrData0 = _bitmapMode ? 0 : _dataG;
_parseSrData1 = _dataG;
}
_srData1 |= _parseSrData1 << (7 - _xScroll);
// graphics color shift register
_srColor0 &= ~(0xFF << (7 - _xScroll));
_srColor1 &= ~(0xFF << (7 - _xScroll));
_srColor2 &= ~(0xFF << (7 - _xScroll));
_srColor3 &= ~(0xFF << (7 - _xScroll));
for (_parsePixelDataIndex = 7; _parsePixelDataIndex >= 0; _parsePixelDataIndex--)
{
_parsePixelData = ((_parseSrData0 & 0x80) >> 7) | ((_parseSrData1 & 0x80) >> 6);
switch (_videoMode)
{
case VideoMode000:
case VideoMode001:
switch (_parsePixelData)
{
case 0:
_pixel = _backgroundColor0;
break;
case 1:
_pixel = _idle ? 0 : _backgroundColor1;
break;
case 2:
_pixel = _idle ? 0 :_backgroundColor2;
break;
default:
_pixel = _idle ? 0 : (_multicolorMode ? _dataC & 0x700 : _dataC) >> 8;
break;
}
break;
case VideoMode010:
case VideoMode011:
switch (_parsePixelData)
{
case 0:
_pixel = _backgroundColor0;
break;
case 1:
_pixel = _idle ? 0 : _dataC >> 4;
break;
case 2:
_pixel = _idle ? 0 : _dataC;
break;
default:
_pixel = _idle ? 0 : _dataC >> 8;
break;
}
break;
case VideoMode100:
if (_parsePixelData != 0)
{
_pixel = _idle ? 0 : _dataC >> 8;
}
else
{
_pixel = (_dataC & 0xC0) >> 6;
switch (_pixel)
{
case 0:
_pixel = _backgroundColor0;
break;
case 1:
_pixel = _idle ? 0 : _backgroundColor1;
break;
case 2:
_pixel = _idle ? 0 : _backgroundColor2;
break;
default:
_pixel = _idle ? 0 : _backgroundColor3;
break;
}
}
break;
default:
_parsePixelData = 0;
_pixel = 0;
break;
}
_parseSrData0 <<= 1;
_parseSrData1 <<= 1;
_srColor0 |= (_pixel & 1) << (7 - _xScroll + _parsePixelDataIndex);
_srColor1 |= ((_pixel >> 1) & 1) << (7 - _xScroll + _parsePixelDataIndex);
_srColor2 |= ((_pixel >> 2) & 1) << (7 - _xScroll + _parsePixelDataIndex);
_srColor3 |= ((_pixel >> 3) & 1) << (7 - _xScroll + _parsePixelDataIndex);
}
break;
case FetchTypeNone:
// fetch none
@ -221,7 +323,6 @@
if ((_parseAct & PipelineUpdateVc) != 0) // VC/RC rule 2
{
_vc = _vcbase;
_srColorIndexLatch = 0;
_vmli = 0;
if (_badline)
{

View File

@ -4,18 +4,19 @@
{
private int _borderPixel;
private int _bufferPixel;
private int _ecmPixel;
private int _pixel;
private int _pixelCounter;
private int _pixelData;
private int _pixelOwner;
private Sprite _spr;
private int _sprData;
private int _sprIndex;
private int _sprPixel;
private int _srSync;
private int _srColorSync;
private int _srColorIndexLatch;
private int _srColor0;
private int _srColor1;
private int _srColor2;
private int _srColor3;
private int _srData1;
private int _srActive;
private int _videoMode;
private int _borderOnShiftReg;
@ -26,10 +27,7 @@
private const int VideoMode100 = 4;
private const int VideoModeInvalid = -1;
private const int SrMask1 = 0x20000;
private const int SrMask2 = SrMask1 << 1;
private const int SrMask3 = SrMask1 | SrMask2;
private const int SrColorMask = 0x8000;
private const int SrMask1 = 0x40000;
private const int SrSpriteMask = SrSpriteMask2;
private const int SrSpriteMask1 = 0x400000;
private const int SrSpriteMask2 = SrSpriteMask1 << 1;
@ -47,13 +45,6 @@
_pixelCounter = 4;
while (--_pixelCounter >= 0)
{
if ((_srColorSync & SrColorMask) != 0)
{
_displayC = _bufferC[_srColorIndexLatch];
_srColorIndexLatch = (_srColorIndexLatch + 1) & 0x3F;
}
#region PRE-RENDER BORDER
// check left border
@ -73,105 +64,14 @@
#endregion
#region CHARACTER GRAPHICS
switch (_videoMode)
{
case VideoMode000:
_pixelData = _sr & SrMask2;
_pixel = _pixelData != 0 ? _displayC >> 8 : _backgroundColor0;
break;
case VideoMode001:
if ((_displayC & 0x800) != 0)
{
// multicolor 001
if ((_srSync & SrMask2) != 0)
_pixelData = _sr & SrMask3;
// render graphics
_pixel = (_srActive & SrMask1) != 0
? ((_srColor0 & SrMask1) >> 18) |
((_srColor1 & SrMask1) >> 17) |
((_srColor2 & SrMask1) >> 16) |
((_srColor3 & SrMask1) >> 15)
: _backgroundColor0;
switch (_pixelData)
{
case 0:
_pixel = _backgroundColor0;
break;
case SrMask1:
_pixel = _idle ? 0 : _backgroundColor1;
break;
case SrMask2:
_pixel = _idle ? 0 :_backgroundColor2;
break;
default:
_pixel = _idle ? 0 : (_displayC & 0x700) >> 8;
break;
}
}
else
{
// standard 001
_pixelData = _sr & SrMask2;
_pixel = _pixelData != 0 ? (_idle ? 0 : _displayC >> 8) : _backgroundColor0;
}
break;
case VideoMode010:
_pixelData = _sr & SrMask2;
_pixel = _idle ? 0 : _pixelData != 0 ? _displayC >> 4 : _displayC;
break;
case VideoMode011:
if ((_srSync & SrMask2) != 0)
_pixelData = _sr & SrMask3;
switch (_pixelData)
{
case 0:
_pixel = _backgroundColor0;
break;
case SrMask1:
_pixel = _idle ? 0 : _displayC >> 4;
break;
case SrMask2:
_pixel = _idle ? 0 : _displayC;
break;
default:
_pixel = _idle ? 0 : _displayC >> 8;
break;
}
break;
case VideoMode100:
_pixelData = _sr & SrMask2;
if (_pixelData != 0)
{
_pixel = _idle ? 0 : _displayC >> 8;
}
else
{
_ecmPixel = (_displayC & 0xC0) >> 6;
switch (_ecmPixel)
{
case 0:
_pixel = _backgroundColor0;
break;
case 1:
_pixel = _idle ? 0 : _backgroundColor1;
break;
case 2:
_pixel = _idle ? 0 : _backgroundColor2;
break;
default:
_pixel = _idle ? 0 : _backgroundColor3;
break;
}
}
break;
default:
_pixelData = 0;
_pixel = 0;
break;
}
_pixel &= 0xF;
_sr <<= 1;
_srSync <<= 1;
_srColorSync <<= 1;
#endregion
#region SPRITES
// render sprites
_pixelOwner = -1;
for (_sprIndex = 0; _sprIndex < 8; _sprIndex++)
@ -252,7 +152,7 @@
}
// sprite-data collision
if (!_borderOnVertical && (_pixelData >= SrMask2))
if (!_borderOnVertical && (_srData1 & SrMask1) != 0)
{
_spr.CollideData = true;
_intSpriteDataCollision = true;
@ -261,7 +161,7 @@
// sprite priority logic
if (_spr.Priority)
{
_pixel = _pixelData >= SrMask2 ? _pixel : _sprPixel;
_pixel = (_srData1 & SrMask1) != 0 ? _pixel : _sprPixel;
}
else
{
@ -271,8 +171,6 @@
}
}
#endregion
#region POST-RENDER BORDER
// border doesn't work with the background buffer
@ -298,6 +196,13 @@
if (!_rasterXHold)
_rasterX++;
_srColor0 <<= 1;
_srColor1 <<= 1;
_srColor2 <<= 1;
_srColor3 <<= 1;
_srData1 <<= 1;
_srActive <<= 1;
}
if (_pixBufferBorderIndex >= PixBorderBufferSize)

View File

@ -22,14 +22,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private int _borderR;
private int _borderT;
private int[] _bufferC;
private int[] _bufferG;
private int _cycle;
private int _cycleIndex;
private bool _columnSelect;
private int _dataC;
private int _dataG;
private bool _displayEnable;
private int _displayC;
private bool _enableIntLightPen;
private bool _enableIntRaster;
private bool _enableIntSpriteCollision;
@ -72,7 +70,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private readonly Sprite _sprite6;
private readonly Sprite _sprite7;
private readonly Sprite[] _sprites;
private int _sr;
private bool _vblank;
private int _vblankEnd;
private int _vblankStart;
@ -130,7 +127,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_spriteSpriteCollisionClearPending = false;
_spriteMulticolor0 = 0;
_spriteMulticolor1 = 0;
_sr = 0;
_vc = 0;
_vcbase = 0;
_vmli = 0;
@ -149,7 +145,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
for (var i = 0; i < 40; i++)
{
_bufferC[i] = 0;
_bufferG[i] = 0;
}
_pixBuffer = new int[PixBufferSize];
@ -161,11 +156,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void SyncState(Serializer ser)
{
ser.Sync(nameof(_cyclesExecuted), ref _cyclesExecuted);
ser.Sync(nameof(_parseIsSprCrunch), ref _parseIsSprCrunch);
ser.Sync(nameof(_srSync), ref _srSync);
ser.Sync(nameof(_srColorSync), ref _srColorSync);
ser.Sync(nameof(_srColorIndexLatch), ref _srColorIndexLatch);
ser.Sync(nameof(_videoMode), ref _videoMode);
ser.Sync(nameof(_borderOnShiftReg), ref _borderOnShiftReg);
ser.Sync(nameof(_backgroundColor0), ref _backgroundColor0);
@ -186,14 +177,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
ser.Sync(nameof(_borderR), ref _borderR);
ser.Sync(nameof(_borderT), ref _borderT);
ser.Sync(nameof(_bufferC), ref _bufferC, useNull: false);
ser.Sync(nameof(_bufferG), ref _bufferG, useNull: false);
ser.Sync(nameof(_cycle), ref _cycle);
ser.Sync(nameof(_cycleIndex), ref _cycleIndex);
ser.Sync(nameof(_columnSelect), ref _columnSelect);
ser.Sync(nameof(_dataC), ref _dataC);
ser.Sync(nameof(_dataG), ref _dataG);
ser.Sync(nameof(_displayEnable), ref _displayEnable);
ser.Sync(nameof(_displayC), ref _displayC);
ser.Sync(nameof(_enableIntLightPen), ref _enableIntLightPen);
ser.Sync(nameof(_enableIntRaster), ref _enableIntRaster);
ser.Sync(nameof(_enableIntSpriteCollision), ref _enableIntSpriteCollision);
@ -234,7 +223,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
ser.EndSection();
}
ser.Sync(nameof(_sr), ref _sr);
ser.Sync(nameof(_vc), ref _vc);
ser.Sync(nameof(_vcbase), ref _vcbase);
ser.Sync(nameof(_vmli), ref _vmli);
@ -245,7 +233,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
ser.Sync(nameof(_pixBufferIndex), ref _pixBufferIndex);
ser.Sync(nameof(_pixBorderBuffer), ref _pixBorderBuffer, useNull: false);
ser.Sync(nameof(_pixBufferBorderIndex), ref _pixBufferBorderIndex);
if (ser.IsReader)
{
UpdateBorder();

View File

@ -36,7 +36,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private readonly int _totalCycles;
private readonly int _totalLines;
private int _cyclesExecuted;
private int _hblankStartCheckXRaster;
private int _hblankEndCheckXRaster;
@ -81,7 +80,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_sprite7 = _sprites[7];
_bufferC = new int[40];
_bufferG = new int[40];
}
private void ConfigureBlanking(int lines, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd,
@ -228,7 +226,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_vc = 0;
_badlineEnable = false;
_refreshCounter = 0xFF;
_cyclesExecuted = 0;
}
}
@ -327,8 +324,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
// must always come last
UpdatePins();
_cyclesExecuted++;
}
private void UpdateBorder()