diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6567R56A.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6567R56A.cs index ae5f463683..c3f6606873 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6567R56A.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6567R56A.cs @@ -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; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6569.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6569.cs index 286a7250ad..9d3be80998 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6569.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6569.cs @@ -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; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.Render.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.Render.cs index f7fb628a8c..88982c7c1c 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.Render.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.Render.cs @@ -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; } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.State.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.State.cs index 59b05122a2..d56e742769 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.State.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.State.cs @@ -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); diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs index 0a89972356..01acdb852c 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs @@ -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,