using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BizHawk.Emulation.Cores.Computers.Commodore64 { sealed public partial class Vic { int delayC; int ecmPixel; int pixel; int pixelData; SpriteGenerator pixelOwner; int sprData; int sprPixel; int srC = 0; int srSync = 0; VicVideoMode videoMode; enum VicVideoMode : int { Mode000, Mode001, Mode010, Mode011, Mode100, ModeBad } private void Render() { if (hblankCheckEnableL) { if (rasterX == hblankEnd) hblank = false; } else if (hblankCheckEnableR) { if (rasterX == hblankStart) hblank = true; } renderEnabled = (!hblank && !vblank); for (int i = 0; i < 4; i++) { if (delayC > 0) delayC--; else displayC = (srC >> 12) & 0xFFF; if (borderCheckLEnable && (rasterX == borderL)) { if (rasterLine == borderB) borderOnVertical = true; if (rasterLine == borderT && displayEnable) borderOnVertical = false; if (!borderOnVertical) borderOnMain = false; } switch (videoMode) { case VicVideoMode.Mode000: pixelData = sr & srMask2; pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0; break; case VicVideoMode.Mode001: if ((displayC & 0x800) != 0) { // multicolor 001 if ((srSync & srMask2) != 0) pixelData = sr & srMask3; if (pixelData == 0) pixel = backgroundColor0; else if (pixelData == srMask1) pixel = backgroundColor1; else if (pixelData == srMask2) pixel = backgroundColor2; else pixel = (displayC & 0x700) >> 8; } else { // standard 001 pixelData = sr & srMask2; pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0; } break; case VicVideoMode.Mode010: pixelData = sr & srMask2; pixel = (pixelData != 0) ? (displayC >> 4) : (displayC); break; case VicVideoMode.Mode011: if ((srSync & srMask2) != 0) pixelData = sr & srMask3; if (pixelData == 0) pixel = backgroundColor0; else if (pixelData == srMask1) pixel = (displayC >> 4); else if (pixelData == srMask2) pixel = displayC; else pixel = (displayC >> 8); break; case VicVideoMode.Mode100: pixelData = sr & srMask2; 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; } pixel &= 0xF; sr <<= 1; srSync <<= 1; // render sprite pixelOwner = null; foreach (SpriteGenerator spr in sprites) { sprData = 0; sprPixel = pixel; if (spr.x == rasterX) spr.shiftEnable = true; if (spr.shiftEnable) { if (spr.multicolor) { sprData = (spr.sr & srSpriteMaskMC); if (spr.multicolorCrunch && spr.xCrunch && !rasterXHold) spr.sr <<= 2; spr.multicolorCrunch ^= spr.xCrunch; } else { sprData = (spr.sr & srSpriteMask); if (spr.xCrunch && !rasterXHold) spr.sr <<= 1; } spr.xCrunch ^= spr.xExpand; if (sprData != 0) { // sprite-sprite collision if (pixelOwner == null) { if (!spr.priority || (pixelData == 0)) { if (sprData == srSpriteMask1) pixel = spriteMulticolor0; else if (sprData == srSpriteMask2) pixel = spr.color; else if (sprData == srSpriteMask3) pixel = spriteMulticolor1; } pixelOwner = spr; } else { if (!borderOnVertical) { spr.collideSprite = true; pixelOwner.collideSprite = true; } } // sprite-data collision if (!borderOnVertical && (pixelData < srMask2)) { spr.collideData = true; } } if (spr.sr == 0) spr.shiftEnable = false; //optimization } } if (borderCheckREnable && (rasterX == borderR)) borderOnMain = true; // border doesn't work with the background buffer if (borderOnMain || borderOnVertical) pixel = borderColor; // plot pixel if within viewing area if (renderEnabled) { buf[bufOffset] = palette[pixBuffer[pixBufferIndex]]; bufOffset++; if (bufOffset == bufLength) bufOffset = 0; } pixBuffer[pixBufferIndex] = pixel; pixBufferIndex++; if (!rasterXHold) rasterX++; bitmapColumn++; } if (pixBufferIndex >= pixBufferSize) pixBufferIndex = 0; } } }