Commodore64: Further development in the experimental Vic. The process in which the Vic puts graphics and sprite data into the shift regs should be replicated perfectly, and some graphics mode code can be combined as a result.

This commit is contained in:
saxxonpike 2013-08-31 22:54:44 +00:00
parent 2e178d84e1
commit d3687bb68d
5 changed files with 153 additions and 13 deletions

View File

@ -7,8 +7,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public partial class Vic
{
const int GRAPHICS_DATA_OUTPUT_MASK = 0xC000;
const int GRAPHICS_DATA_INPUT_SHIFT = 16;
const int GRAPHICS_DATA_00 = 0;
const int GRAPHICS_DATA_01 = 0x4000;
const int GRAPHICS_DATA_10 = GRAPHICS_DATA_01 << 1;
const int GRAPHICS_DATA_11 = GRAPHICS_DATA_01 | GRAPHICS_DATA_10;
const int GRAPHICS_DATA_OUTPUT_MASK = GRAPHICS_DATA_11;
enum GraphicsMode
{
@ -26,13 +29,14 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
int g_BufferG;
int g_DataC;
int g_DataG;
bool g_Idle;
int g_FillRasterX;
GraphicsMode g_Mode;
int g_OutData;
int g_OutPixel;
int g_ShiftRegister;
void RenderG()
void RenderGraphics()
{
if ((rasterX & 0x7) == g_FillRasterX)
{
@ -41,6 +45,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
if (multiColorMode && (bitmapMode || (g_DataC & 0x8) != 0))
{
// load multicolor bits
// xx00xx11xx22xx33
g_ShiftRegister =
((g_DataG & 0x03) << 0) |
((g_DataG & 0x0C) << 2) |
@ -49,11 +54,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
;
// duplicate bits
// 0000111122223333
g_ShiftRegister |= g_ShiftRegister << 2;
}
else
{
// load single color bits
// 0x1x2x3x4x5x6x7x
g_ShiftRegister =
((g_DataG & 0x01) << 1) |
((g_DataG & 0x02) << 2) |
@ -64,29 +71,59 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
((g_DataG & 0x40) << 7) |
((g_DataG & 0x80) << 8)
;
if (!bitmapMode)
{
// duplicate bits
// 0011223344556677
g_ShiftRegister |= g_ShiftRegister << 1;
}
else
{
// convert to bitmap format
g_ShiftRegister = (g_ShiftRegister | 0x5555) ^ (g_ShiftRegister >> 1);
}
}
}
g_OutData = g_ShiftRegister & GRAPHICS_DATA_OUTPUT_MASK;
switch (g_Mode)
{
default:
break;
case GraphicsMode.Mode000:
case GraphicsMode.Mode001:
if (g_OutData == GRAPHICS_DATA_00)
g_OutPixel = backgroundColor[0];
else if (g_OutData == GRAPHICS_DATA_11)
g_OutPixel = g_Idle ? 0 : ((g_DataC >> 8) & 0x7);
else if (g_OutData == GRAPHICS_DATA_01)
g_OutPixel = g_Idle ? 0 : backgroundColor[1];
else
g_OutPixel = g_Idle ? 0 : backgroundColor[2];
break;
case GraphicsMode.Mode010:
break;
case GraphicsMode.Mode011:
if (g_OutData == GRAPHICS_DATA_00)
g_OutPixel = backgroundColor[0];
else if (g_OutData == GRAPHICS_DATA_01)
g_OutPixel = (g_DataC >> 4) & 0xF;
else if (g_OutData == GRAPHICS_DATA_10)
g_OutPixel = g_DataC & 0xF;
else
g_OutPixel = g_DataC >> 8;
break;
case GraphicsMode.Mode100:
if (g_OutData == GRAPHICS_DATA_00)
g_OutPixel = backgroundColor[(g_DataC >> 6) & 0x3];
else
g_OutPixel = g_DataC >> 8;
break;
case GraphicsMode.Mode101:
break;
case GraphicsMode.Mode110:
break;
case GraphicsMode.Mode111:
default:
g_OutPixel = 0;
break;
}
g_ShiftRegister <<= 2;
}
void UpdateGraphicsMode()

View File

@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
public void Clock()
{
Render();
}
public void Reset()

View File

@ -31,7 +31,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
bool spriteCollisionInterrupt;
bool spriteCollisionInterruptEnable;
int[] spriteMultiColor;
Sprite[] sprites;
int videoMemory;
int xScroll;
int yScroll;

View File

@ -7,8 +7,21 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public partial class Vic
{
const int SPRITE_DATA_00 = 0;
const int SPRITE_DATA_01 = 0x400000;
const int SPRITE_DATA_10 = SPRITE_DATA_01 << 1;
const int SPRITE_DATA_11 = SPRITE_DATA_01 | SPRITE_DATA_10;
const int SPRITE_DATA_OUTPUT_MASK = SPRITE_DATA_11;
sealed class Sprite
{
public bool CrunchMC;
public bool CrunchX;
public bool CrunchY;
public bool Display;
public int ShiftRegister;
public bool ShiftRegisterEnable;
public int Color;
public bool DataCollision;
public bool Enabled;
@ -37,5 +50,76 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
}
}
Sprite s_CollideSprite;
int s_Data;
bool s_OutData;
int s_OutPixel;
bool s_Priority;
Sprite[] sprites;
void RenderSprites()
{
s_OutData = false;
s_CollideSprite = null;
foreach (Sprite sprite in sprites)
{
if (sprite.Display && rasterX == sprite.X)
sprite.ShiftRegisterEnable = true;
if (sprite.ShiftRegisterEnable)
{
if (sprite.ShiftRegister == 0)
{
sprite.ShiftRegisterEnable = false;
sprite.CrunchMC = true;
sprite.CrunchX = true;
}
else
{
sprite.CrunchX = !sprite.CrunchX || !sprite.ExpandX;
if (sprite.CrunchX)
sprite.CrunchMC = !sprite.CrunchMC || !sprite.Multicolor;
if (sprite.Multicolor)
s_Data = sprite.ShiftRegister & SPRITE_DATA_11;
else
s_Data = (sprite.ShiftRegister << 1) & SPRITE_DATA_10;
if (s_CollideSprite == null)
{
if (s_Data == SPRITE_DATA_10)
s_OutPixel = sprite.Color;
else if (s_Data == SPRITE_DATA_01)
s_OutPixel = spriteMultiColor[0];
else if (s_Data == SPRITE_DATA_11)
s_OutPixel = spriteMultiColor[1];
if (s_Data != SPRITE_DATA_00)
{
s_CollideSprite = sprite;
s_OutData = true;
s_Priority = sprite.Priority;
}
}
else if (s_Data != SPRITE_DATA_00)
{
s_CollideSprite.SpriteCollision = true;
sprite.SpriteCollision = true;
spriteCollisionInterrupt = true;
}
if (s_Data != SPRITE_DATA_00 && g_OutData >= GRAPHICS_DATA_10)
{
sprite.DataCollision = true;
dataCollisionInterrupt = true;
}
if (sprite.CrunchMC && sprite.CrunchX)
sprite.ShiftRegister <<= sprite.Multicolor ? 2 : 1;
}
}
}
}
}
}

View File

@ -7,5 +7,24 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
{
sealed public partial class Vic
{
int v_Pixel;
public void Render()
{
RenderGraphics();
RenderSprites();
if (s_OutData && (!s_Priority || g_OutData < GRAPHICS_DATA_10))
{
if (s_Priority && g_OutData < GRAPHICS_DATA_10)
v_Pixel = s_OutPixel;
else
v_Pixel = g_OutPixel;
}
else
{
v_Pixel = g_OutPixel;
}
}
}
}