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

216 lines
4.7 KiB
C#

using System;
using System.Drawing;
namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
sealed public partial class Vic
{
public Func<int, byte> ReadColorRam;
public Func<int, byte> ReadMemory;
public bool ReadAECBuffer() { return pinAEC; }
public bool ReadBABuffer() { return pinBA; }
public bool ReadIRQBuffer() { return pinIRQ; }
int cyclesPerSec;
int irqShift;
int[][] pipeline;
int totalCycles;
int totalLines;
public Vic(int newCycles, int newLines, int[][] newPipeline, int newCyclesPerSec, int hblankStart, int hblankEnd, int vblankStart, int vblankEnd)
{
{
this.hblankStart = hblankStart;
this.hblankEnd = hblankEnd;
this.vblankStart = vblankStart;
this.vblankEnd = vblankEnd;
totalCycles = newCycles;
totalLines = newLines;
pipeline = newPipeline;
cyclesPerSec = newCyclesPerSec;
bufWidth = TimingBuilder_ScreenWidth(pipeline[0], hblankStart, hblankEnd);
bufHeight = TimingBuilder_ScreenHeight(vblankStart, vblankEnd, newLines);
buf = new int[bufWidth * bufHeight];
bufLength = buf.Length;
sprites = new SpriteGenerator[8];
for (int i = 0; i < 8; i++)
sprites[i] = new SpriteGenerator();
bufferC = new int[40];
bufferG = new int[40];
}
}
public int CyclesPerFrame
{
get
{
return (totalCycles * totalLines);
}
}
public int CyclesPerSecond
{
get
{
return cyclesPerSec;
}
}
public void ExecutePhase1()
{
//xScroll = 1;
{
// raster IRQ compare
if ((cycle == rasterIrqLineXCycle && rasterLine > 0) || (cycle == rasterIrqLine0Cycle && rasterLine == 0))
{
if (rasterLine != lastRasterLine)
if (rasterLine == rasterInterruptLine)
intRaster = true;
lastRasterLine = rasterLine;
}
// display enable compare
if (rasterLine == 0x030)
badlineEnable |= displayEnable;
// badline compare
if (badlineEnable && rasterLine >= 0x030 && rasterLine < 0x0F7 && ((rasterLine & 0x7) == yScroll))
{
badline = true;
}
else
{
badline = false;
}
// go into display state on a badline
if (badline)
idle = false;
// process some sprite crunch vars
foreach (SpriteGenerator spr in sprites)
if (!spr.yExpand) spr.yCrunch = true;
ParseCycle();
//xOffset = 0;
Render();
// if the BA counter is nonzero, allow CPU bus access
UpdateBA();
pinAEC = false;
// must always come last
//UpdatePins();
}
}
public void ExecutePhase2()
{
{
ParseCycle();
// advance cycle and optionally raster line
cycle++;
if (cycle == totalCycles)
{
if (rasterLine == borderB)
borderOnVertical = true;
if (rasterLine == borderT && displayEnable)
borderOnVertical = false;
if (rasterLine == vblankStart)
vblank = true;
if (rasterLine == vblankEnd)
vblank = false;
cycleIndex = 0;
cycle = 0;
rasterLine++;
if (rasterLine == totalLines)
{
rasterLine = 0;
vcbase = 0;
vc = 0;
}
}
Render();
UpdateBA();
pinAEC = (baCount > 0);
// must always come last
UpdatePins();
}
}
private void UpdateBA()
{
if (pinBA)
baCount = baResetCounter;
else if (baCount > 0)
baCount--;
}
private void UpdateBorder()
{
borderL = columnSelect ? 0x018 : 0x01F;
borderR = columnSelect ? 0x158 : 0x14F;
//borderL = columnSelect ? 28 : 35;
//borderR = columnSelect ? 348 : 339;
borderT = rowSelect ? 0x033 : 0x037;
borderB = rowSelect ? 0x0FB : 0x0F7;
}
private void UpdatePins()
{
bool irqTemp = !(
(enableIntRaster & intRaster) |
(enableIntSpriteDataCollision & intSpriteDataCollision) |
(enableIntSpriteCollision & intSpriteCollision) |
(enableIntLightPen & intLightPen));
irqShift <<= 1;
irqShift |= (irqTemp ? 0x1 : 0x0);
pinIRQ = (irqShift & 0x1) != 0;
}
private void UpdateVideoMode()
{
if (!extraColorMode && !bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode000;
return;
}
else if (!extraColorMode && !bitmapMode && multicolorMode)
{
videoMode = VicVideoMode.Mode001;
return;
}
else if (!extraColorMode && bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode010;
return;
}
else if (!extraColorMode && bitmapMode && multicolorMode)
{
videoMode = VicVideoMode.Mode011;
return;
}
else if (extraColorMode && !bitmapMode && !multicolorMode)
{
videoMode = VicVideoMode.Mode100;
return;
}
videoMode = VicVideoMode.ModeBad;
}
}
}