BizHawk/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.Render.cs

262 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
sealed public partial class Vic
{
private int delayC;
private int ecmPixel;
private int pixel;
private int pixelCounter;
private int pixelData;
private int pixelOwner;
private int sprData;
private int sprIndex;
private int sprPixel;
private int srC = 0;
private int srSync = 0;
private int videoMode;
private void Render()
{
if (hblankCheckEnableL)
{
if (rasterX == hblankEnd)
hblank = false;
}
else if (hblankCheckEnableR)
{
if (rasterX == hblankStart)
hblank = true;
}
renderEnabled = (!hblank && !vblank);
pixelCounter = -1;
while (pixelCounter++ < 3)
{
if (delayC > 0)
delayC--;
else
displayC = (srC >> 12) & 0xFFF;
#region PRE-RENDER BORDER
if (borderCheckLEnable && (rasterX == borderL))
{
if (rasterLine == borderB)
borderOnVertical = true;
if (rasterLine == borderT && displayEnable)
borderOnVertical = false;
if (!borderOnVertical)
borderOnMain = false;
}
#endregion
#region CHARACTER GRAPHICS
switch (videoMode)
{
case 0:
pixelData = sr & srMask2;
pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0;
break;
case 1:
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 2:
pixelData = sr & srMask2;
pixel = (pixelData != 0) ? (displayC >> 4) : (displayC);
break;
case 3:
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 4:
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;
#endregion
#region SPRITES
// render sprites
pixelOwner = -1;
sprIndex = 0;
foreach (var spr in sprites)
{
sprData = 0;
sprPixel = pixel;
if (spr.x == rasterX)
{
spr.shiftEnable = spr.display;
spr.xCrunch = !spr.xExpand;
spr.multicolorCrunch = false;
}
else
{
spr.xCrunch |= !spr.xExpand;
}
if (spr.shiftEnable) // sprite rule 6
{
if (spr.multicolor)
{
sprData = (spr.sr & srSpriteMaskMC);
if (spr.multicolorCrunch && spr.xCrunch && !rasterXHold)
{
if (spr.loaded == 0)
{
spr.shiftEnable = false;
}
spr.sr <<= 2;
spr.loaded >>= 2;
}
spr.multicolorCrunch ^= spr.xCrunch;
}
else
{
sprData = (spr.sr & srSpriteMask);
if (spr.xCrunch && !rasterXHold)
{
if (spr.loaded == 0)
{
spr.shiftEnable = false;
}
spr.sr <<= 1;
spr.loaded >>= 1;
}
}
spr.xCrunch ^= spr.xExpand;
if (sprData != 0)
{
// sprite-sprite collision
if (pixelOwner < 0)
{
if (sprData == srSpriteMask1)
sprPixel = spriteMulticolor0;
else if (sprData == srSpriteMask2)
sprPixel = spr.color;
else if (sprData == srSpriteMask3)
sprPixel = spriteMulticolor1;
pixelOwner = sprIndex;
}
else
{
if (!borderOnVertical)
{
spr.collideSprite = true;
sprites[pixelOwner].collideSprite = true;
}
}
// sprite-data collision
if (!borderOnVertical && (pixelData >= srMask2))
{
spr.collideData = true;
}
// sprite priority logic
if (spr.priority)
{
pixel = (pixelData >= srMask2) ? pixel : sprPixel;
}
else
{
pixel = sprPixel;
}
}
}
sprIndex++;
}
#endregion
#region POST-RENDER BORDER
if (borderCheckREnable && (rasterX == borderR))
borderOnMain = true;
// border doesn't work with the background buffer
if (borderOnMain || borderOnVertical)
pixel = borderColor;
#endregion
// 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;
}
}
}