C64: Implement the color register decode / priority logic
This commit is contained in:
parent
0de5dedb3e
commit
f4c64ddf38
|
@ -8,7 +8,7 @@
|
|||
private static readonly int Lines = 262;
|
||||
private static readonly int Vblankstart = 0x00D % Lines;
|
||||
private static readonly int VblankEnd = 0x018 % Lines;
|
||||
private static readonly int HblankOffset = 0;
|
||||
private static readonly int HblankOffset = 4;
|
||||
private static readonly int HblankStart = (0x18C + HblankOffset) % ScanWidth;
|
||||
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
private static readonly int Lines = 312;
|
||||
private static readonly int VblankStart = 0x120 % Lines;
|
||||
private static readonly int VblankEnd = 0x00F % Lines;
|
||||
private static readonly int HblankOffset = 0;
|
||||
private static readonly int HblankOffset = 8;
|
||||
private static readonly int HblankStart = (0x178 + HblankOffset) % ScanWidth;
|
||||
private static readonly int HblankEnd = (0x1F0 + HblankOffset) % ScanWidth;
|
||||
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
{
|
||||
public sealed partial class Vic
|
||||
{
|
||||
private int _bufferPixel;
|
||||
private int _gfxData;
|
||||
private bool _gfxSense;
|
||||
private int _gfxJitter;
|
||||
private bool _gfxMc;
|
||||
private int _pixel;
|
||||
private int _pixelCounter;
|
||||
private ColorRegisterSelect _pixelDecode;
|
||||
private int[] _pixelDecodeBuffer;
|
||||
private ColorRegisterSelect _pixelDecodeTemp;
|
||||
private int _pixelDecodeBufferIndex;
|
||||
private int _sprOwner;
|
||||
private Sprite _spr;
|
||||
private int _sprData;
|
||||
private ColorRegisterSelect _sprDecode;
|
||||
private int _sprIndex;
|
||||
private int _sprPixel;
|
||||
private bool _sprSense;
|
||||
private bool _sprPriority;
|
||||
private int _srData1;
|
||||
|
@ -33,6 +36,42 @@
|
|||
private const int SrSpriteMask3 = SrSpriteMask1 | SrSpriteMask2;
|
||||
private const int SrSpriteMaskMc = SrSpriteMask3;
|
||||
|
||||
// the first 16 members of this must correspond directly to the 16 color palette
|
||||
private enum ColorRegisterSelect
|
||||
{
|
||||
Color0,
|
||||
Color1,
|
||||
Color2,
|
||||
Color3,
|
||||
Color4,
|
||||
Color5,
|
||||
Color6,
|
||||
Color7,
|
||||
Color8,
|
||||
Color9,
|
||||
ColorA,
|
||||
ColorB,
|
||||
ColorC,
|
||||
ColorD,
|
||||
ColorE,
|
||||
ColorF,
|
||||
Exterior,
|
||||
Background0,
|
||||
Background1,
|
||||
Background2,
|
||||
Background3,
|
||||
SpriteMc0,
|
||||
SpriteMc1,
|
||||
Sprite0,
|
||||
Sprite1,
|
||||
Sprite2,
|
||||
Sprite3,
|
||||
Sprite4,
|
||||
Sprite5,
|
||||
Sprite6,
|
||||
Sprite7
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
if (_rasterX == _hblankEndCheckXRaster)
|
||||
|
@ -42,6 +81,7 @@
|
|||
|
||||
_renderEnabled = !_hblank && !_vblank;
|
||||
_pixelCounter = 4;
|
||||
|
||||
while (--_pixelCounter >= 0)
|
||||
{
|
||||
#region PRE-RENDER BORDER
|
||||
|
@ -70,49 +110,47 @@
|
|||
if (_xScroll == (_rasterX & 0x7))
|
||||
{
|
||||
_displayC = _dataCPrev & 0xFFF;
|
||||
_gfxMc = _multicolorMode && (_bitmapMode || (_displayC & 0x800) != 0);
|
||||
}
|
||||
_gfxMc = _multicolorMode && (_bitmapMode || (_displayC & 0x800) != 0);
|
||||
|
||||
_pixel = _backgroundColor0;
|
||||
_gfxJitter = _gfxMc ? (_xScroll ^ _rasterX) & 1 : 0;
|
||||
_pixelDecode = ColorRegisterSelect.Background0;
|
||||
_gfxJitter = _gfxMc && _multicolorModeLatch ? (_xScroll ^ _rasterX) & 1 : 0;
|
||||
_srData1 <<= 1;
|
||||
_gfxData = _srData1 >> (18 + _gfxJitter); // bit 1-0 has the histogram
|
||||
_gfxSense = (_gfxData & 2) != 0; // bit 1 is used for foreground data purposes too
|
||||
_gfxData = (_srData1 >> (18 + _gfxJitter)) & (_gfxMc && _multicolorModeLatch ? 0x3 : 0x2); // data bits
|
||||
_gfxSense = (_gfxData & 2) != 0; // foreground bit
|
||||
|
||||
switch (_videoMode)
|
||||
{
|
||||
case VideoMode000:
|
||||
{
|
||||
if (_gfxSense)
|
||||
_pixel = _displayC >> 8;
|
||||
_pixelDecode = (ColorRegisterSelect) (_displayC >> 8);
|
||||
break;
|
||||
}
|
||||
case VideoMode001:
|
||||
{
|
||||
if (_gfxMc)
|
||||
if ((_displayC & 0x800) != 0)
|
||||
{
|
||||
switch (_gfxData & 0x3)
|
||||
{
|
||||
case 0x1:
|
||||
_pixel = _backgroundColor1;
|
||||
break;
|
||||
case 0x2:
|
||||
_pixel = _backgroundColor2;
|
||||
_pixelDecode = ColorRegisterSelect.Background0 + _gfxData;
|
||||
break;
|
||||
case 0x3:
|
||||
_pixel = (_displayC >> 8) & 7;
|
||||
_pixelDecode = (ColorRegisterSelect) ((_displayC >> 8) & 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (_gfxSense)
|
||||
{
|
||||
_pixel = _displayC >> 8;
|
||||
_pixelDecode = (ColorRegisterSelect) (_displayC >> 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VideoMode010:
|
||||
{
|
||||
_pixel = (_gfxSense ? _displayC >> 4 : _displayC) & 0xF;
|
||||
_pixelDecode = (ColorRegisterSelect) ((_gfxSense ? _displayC >> 4 : _displayC) & 0xF);
|
||||
break;
|
||||
}
|
||||
case VideoMode011:
|
||||
|
@ -120,13 +158,13 @@
|
|||
switch (_gfxData & 0x3)
|
||||
{
|
||||
case 0x1:
|
||||
_pixel = (_displayC >> 4) & 0xF;
|
||||
_pixelDecode = (ColorRegisterSelect) ((_displayC >> 4) & 0xF);
|
||||
break;
|
||||
case 0x2:
|
||||
_pixel = _displayC & 0xF;
|
||||
_pixelDecode = (ColorRegisterSelect) (_displayC & 0xF);
|
||||
break;
|
||||
case 0x3:
|
||||
_pixel = (_displayC >> 8) & 0xF;
|
||||
_pixelDecode = (ColorRegisterSelect) ((_displayC >> 8) & 0xF);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -135,34 +173,17 @@
|
|||
{
|
||||
if (_gfxSense)
|
||||
{
|
||||
_pixel = (_displayC >> 8) & 0xF;
|
||||
_pixelDecode = (ColorRegisterSelect) ((_displayC >> 8) & 0xF);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_displayC & 0xC0)
|
||||
{
|
||||
case 0x40:
|
||||
{
|
||||
_pixel = _backgroundColor1;
|
||||
break;
|
||||
}
|
||||
case 0x80:
|
||||
{
|
||||
_pixel = _backgroundColor2;
|
||||
break;
|
||||
}
|
||||
case 0xC0:
|
||||
{
|
||||
_pixel = _backgroundColor3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_pixelDecode = ColorRegisterSelect.Background0 + ((_displayC >> 6) & 0x3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
_pixel = 0;
|
||||
_pixelDecode = ColorRegisterSelect.Color0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -237,13 +258,13 @@
|
|||
switch (_sprData)
|
||||
{
|
||||
case SrSpriteMask1:
|
||||
_sprPixel = _spriteMulticolor0;
|
||||
_sprDecode = ColorRegisterSelect.SpriteMc0;
|
||||
break;
|
||||
case SrSpriteMask2:
|
||||
_sprPixel = _spr.Color;
|
||||
_sprDecode = ColorRegisterSelect.Sprite0 + _sprOwner;
|
||||
break;
|
||||
case SrSpriteMask3:
|
||||
_sprPixel = _spriteMulticolor1;
|
||||
_sprDecode = ColorRegisterSelect.SpriteMc1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -264,15 +285,49 @@
|
|||
|
||||
// sprite priority logic
|
||||
if (_sprSense && (!_sprPriority || !_gfxSense))
|
||||
_pixel = _sprPixel;
|
||||
_pixelDecode = _sprDecode;
|
||||
|
||||
#endregion Mux Color
|
||||
|
||||
#region Border Unit
|
||||
|
||||
if (_borderOnVertical || _borderOnMain)
|
||||
_pixelDecode = ColorRegisterSelect.Exterior;
|
||||
|
||||
#endregion Border Unit
|
||||
|
||||
// internal delay
|
||||
_pixelDecodeTemp = _pixelDecode;
|
||||
_pixelDecode = (ColorRegisterSelect) _pixelDecodeBuffer[_pixelDecodeBufferIndex];
|
||||
_pixelDecodeBuffer[_pixelDecodeBufferIndex] = (int) _pixelDecodeTemp;
|
||||
_pixelDecodeBufferIndex = (_pixelDecodeBufferIndex + 1) & 7;
|
||||
|
||||
// color register select decoder
|
||||
switch (_pixelDecode)
|
||||
{
|
||||
case ColorRegisterSelect.Background0: _pixel = _backgroundColor0; break;
|
||||
case ColorRegisterSelect.Background1: _pixel = _backgroundColor1; break;
|
||||
case ColorRegisterSelect.Background2: _pixel = _backgroundColor2; break;
|
||||
case ColorRegisterSelect.Background3: _pixel = _backgroundColor3; break;
|
||||
case ColorRegisterSelect.Exterior: _pixel = _borderColor; break;
|
||||
case ColorRegisterSelect.Sprite0: _pixel = _sprite0.Color; break;
|
||||
case ColorRegisterSelect.Sprite1: _pixel = _sprite1.Color; break;
|
||||
case ColorRegisterSelect.Sprite2: _pixel = _sprite2.Color; break;
|
||||
case ColorRegisterSelect.Sprite3: _pixel = _sprite3.Color; break;
|
||||
case ColorRegisterSelect.Sprite4: _pixel = _sprite4.Color; break;
|
||||
case ColorRegisterSelect.Sprite5: _pixel = _sprite5.Color; break;
|
||||
case ColorRegisterSelect.Sprite6: _pixel = _sprite6.Color; break;
|
||||
case ColorRegisterSelect.Sprite7: _pixel = _sprite7.Color; break;
|
||||
case ColorRegisterSelect.SpriteMc0: _pixel = _spriteMulticolor0; break;
|
||||
case ColorRegisterSelect.SpriteMc1: _pixel = _spriteMulticolor1; break;
|
||||
default: _pixel = (int) _pixelDecode; break;
|
||||
}
|
||||
|
||||
|
||||
// plot pixel if within viewing area
|
||||
if (_renderEnabled)
|
||||
{
|
||||
_bufferPixel = (_borderOnVertical || _borderOnMain) ? _borderColor : _pixel;
|
||||
_buf[_bufOffset++] = Palette[_bufferPixel & 0xF];
|
||||
_buf[_bufOffset++] = Palette[_pixel & 0xF];
|
||||
if (_bufOffset == _bufLength)
|
||||
_bufOffset = 0;
|
||||
}
|
||||
|
@ -280,6 +335,8 @@
|
|||
if (!_rasterXHold)
|
||||
_rasterX++;
|
||||
}
|
||||
|
||||
_multicolorModeLatch = _multicolorMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
private int _lightPenX;
|
||||
private int _lightPenY;
|
||||
private bool _multicolorMode;
|
||||
private bool _multicolorModeLatch;
|
||||
private bool _pinAec = true;
|
||||
private bool _pinBa = true;
|
||||
private int _pointerCb;
|
||||
|
@ -116,6 +117,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_lightPenX = 0;
|
||||
_lightPenY = 0;
|
||||
_multicolorMode = false;
|
||||
_multicolorModeLatch = false;
|
||||
_pinAec = true;
|
||||
_pinBa = true;
|
||||
_pointerCb = 0;
|
||||
|
@ -192,9 +194,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
ser.Sync(nameof(_lightPenX), ref _lightPenX);
|
||||
ser.Sync(nameof(_lightPenY), ref _lightPenY);
|
||||
ser.Sync(nameof(_multicolorMode), ref _multicolorMode);
|
||||
ser.Sync(nameof(_multicolorModeLatch), ref _multicolorModeLatch);
|
||||
ser.Sync(nameof(_parseIsSprCrunch), ref _parseIsSprCrunch);
|
||||
ser.Sync(nameof(_pinAec), ref _pinAec);
|
||||
ser.Sync(nameof(_pinBa), ref _pinBa);
|
||||
ser.Sync(nameof(_pixelDecodeBuffer), ref _pixelDecodeBuffer, useNull: false);
|
||||
ser.Sync(nameof(_pixelDecodeBufferIndex), ref _pixelDecodeBufferIndex);
|
||||
ser.Sync(nameof(_pointerCb), ref _pointerCb);
|
||||
ser.Sync(nameof(_pointerVm), ref _pointerVm);
|
||||
ser.Sync(nameof(_rasterInterruptLine), ref _rasterInterruptLine);
|
||||
|
|
|
@ -63,7 +63,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_baPipeline = new int[newPipeline[2].Length];
|
||||
Array.Copy(newPipeline[2], 1, _baPipeline, 0, _baPipeline.Length - 1);
|
||||
_baPipeline[_baPipeline.Length - 1] = newPipeline[2][0];
|
||||
//_baPipeline = newPipeline[2];
|
||||
_actPipeline = newPipeline[3];
|
||||
_totalCycles = newCycles;
|
||||
_totalLines = newLines;
|
||||
|
@ -85,6 +84,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_sprite6 = _sprites[6];
|
||||
_sprite7 = _sprites[7];
|
||||
_bufferC = new int[40];
|
||||
_pixelDecodeBuffer = new int[8];
|
||||
}
|
||||
|
||||
private void ConfigureBlanking(int lines, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd,
|
||||
|
|
Loading…
Reference in New Issue