diff --git a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Interface.cs b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Interface.cs index 5cb1592fd4..4155df0585 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Interface.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Interface.cs @@ -11,12 +11,12 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals public Func ReadColorRam; public Func ReadRam; - public bool AEC { get { return cachedAEC; } } - public bool BA { get { return cachedBA; } } - public bool IRQ { get { return cachedIRQ; } } + public bool AEC { get { return aec; } } + public bool BA { get { return ba; } } + public bool IRQ { get { return irq; } } - public bool OutputAEC() { return AEC; } - public bool OutputBA() { return BA; } - public bool OutputIRQ() { return IRQ; } + public bool OutputAEC() { return aec; } + public bool OutputBA() { return ba; } + public bool OutputIRQ() { return irq; } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Internal.cs b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Internal.cs index 7172cda03c..cf0849387e 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Internal.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Internal.cs @@ -7,10 +7,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals { sealed public partial class Vic { - bool cachedAEC; - bool cachedBA; - bool cachedIRQ; - class Sprite { public int Color; @@ -25,6 +21,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals public int Y; } + bool aec; bool ba; int[] backgroundColor; bool bitmapMode; @@ -34,20 +31,23 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals bool columnSelect; int data; bool dataCollisionInterrupt; + bool dataCollisionInterruptEnable; bool displayEnable; bool extraColorMode; - byte interruptEnableRegister; bool irq; bool lightPenInterrupt; + bool lightPenInterruptEnable; int lightPenX; int lightPenY; bool multiColorMode; bool rasterInterrupt; + bool rasterInterruptEnable; int rasterX; int rasterY; bool reset; bool rowSelect; bool spriteCollisionInterrupt; + bool spriteCollisionInterruptEnable; int[] spriteMultiColor; Sprite[] sprites; int videoMemory; diff --git a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Registers.cs b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Registers.cs index bf19894c25..4c19e7a007 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Registers.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Experimental/Chips/Internals/Vic.Registers.cs @@ -9,21 +9,370 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals { public int Peek(int addr) { - return 0xFF; + switch (addr) + { + case 0x00: return sprites[0].X & 0xFF; + case 0x01: return sprites[1].X & 0xFF; + case 0x02: return sprites[2].X & 0xFF; + case 0x03: return sprites[3].X & 0xFF; + case 0x04: return sprites[4].X & 0xFF; + case 0x05: return sprites[5].X & 0xFF; + case 0x06: return sprites[6].X & 0xFF; + case 0x07: return sprites[7].X & 0xFF; + case 0x08: return sprites[0].Y; + case 0x09: return sprites[1].Y; + case 0x0A: return sprites[2].Y; + case 0x0B: return sprites[3].Y; + case 0x0C: return sprites[4].Y; + case 0x0D: return sprites[5].Y; + case 0x0E: return sprites[6].Y; + case 0x0F: return sprites[7].Y; + case 0x10: return ( + ((sprites[0].X & 0x80) >> 7) | + ((sprites[1].X & 0x80) >> 6) | + ((sprites[2].X & 0x80) >> 5) | + ((sprites[3].X & 0x80) >> 4) | + ((sprites[4].X & 0x80) >> 3) | + ((sprites[5].X & 0x80) >> 2) | + ((sprites[6].X & 0x80) >> 1) | + (sprites[7].X & 0x80) + ); + case 0x11: return ( + yScroll | + (rowSelect ? 0x08 : 0x00) | + (displayEnable ? 0x10 : 0x00) | + (bitmapMode ? 0x20 : 0x00) | + (extraColorMode ? 0x40 : 0x00) | + ((rasterY & 0x100) >> 1) + ); + case 0x12: return (rasterY & 0xFF); + case 0x13: return lightPenX; + case 0x14: return lightPenY; + case 0x15: return ( + (sprites[0].Enabled ? 0x01 : 0x00) | + (sprites[1].Enabled ? 0x02 : 0x00) | + (sprites[2].Enabled ? 0x04 : 0x00) | + (sprites[3].Enabled ? 0x08 : 0x00) | + (sprites[4].Enabled ? 0x10 : 0x00) | + (sprites[5].Enabled ? 0x20 : 0x00) | + (sprites[6].Enabled ? 0x40 : 0x00) | + (sprites[7].Enabled ? 0x80 : 0x00) + ); + case 0x16: return ( + xScroll | + (columnSelect ? 0x08 : 0x00) | + (multiColorMode ? 0x10 : 0x00) | + (reset ? 0x20 : 0x00) | + 0xC0 + ); + case 0x17: return ( + (sprites[0].ExpandY ? 0x01 : 0x00) | + (sprites[1].ExpandY ? 0x02 : 0x00) | + (sprites[2].ExpandY ? 0x04 : 0x00) | + (sprites[3].ExpandY ? 0x08 : 0x00) | + (sprites[4].ExpandY ? 0x10 : 0x00) | + (sprites[5].ExpandY ? 0x20 : 0x00) | + (sprites[6].ExpandY ? 0x40 : 0x00) | + (sprites[7].ExpandY ? 0x80 : 0x00) + ); + case 0x18: return ( + (videoMemory >> 6) | + (characterBitmap >> 10) + ); + case 0x19: return ( + (rasterInterrupt ? 0x01 : 0x00) | + (dataCollisionInterrupt ? 0x02 : 0x00) | + (spriteCollisionInterrupt ? 0x04 : 0x00) | + (lightPenInterrupt ? 0x08 : 0x00) | + 0x70 | + (irq ? 0x80 : 0x00) + ); + case 0x1A: return ( + (rasterInterruptEnable ? 0x01 : 0x00) | + (dataCollisionInterruptEnable ? 0x02 : 0x00) | + (spriteCollisionInterruptEnable ? 0x04 : 0x00) | + (lightPenInterruptEnable ? 0x08 : 0x00) | + 0xF0 + ); + case 0x1B: return ( + (sprites[0].Priority ? 0x01 : 0x00) | + (sprites[1].Priority ? 0x02 : 0x00) | + (sprites[2].Priority ? 0x04 : 0x00) | + (sprites[3].Priority ? 0x08 : 0x00) | + (sprites[4].Priority ? 0x10 : 0x00) | + (sprites[5].Priority ? 0x20 : 0x00) | + (sprites[6].Priority ? 0x40 : 0x00) | + (sprites[7].Priority ? 0x80 : 0x00) + ); + case 0x1C: return ( + (sprites[0].Multicolor ? 0x01 : 0x00) | + (sprites[1].Multicolor ? 0x02 : 0x00) | + (sprites[2].Multicolor ? 0x04 : 0x00) | + (sprites[3].Multicolor ? 0x08 : 0x00) | + (sprites[4].Multicolor ? 0x10 : 0x00) | + (sprites[5].Multicolor ? 0x20 : 0x00) | + (sprites[6].Multicolor ? 0x40 : 0x00) | + (sprites[7].Multicolor ? 0x80 : 0x00) + ); + case 0x1D: return ( + (sprites[0].ExpandX ? 0x01 : 0x00) | + (sprites[1].ExpandX ? 0x02 : 0x00) | + (sprites[2].ExpandX ? 0x04 : 0x00) | + (sprites[3].ExpandX ? 0x08 : 0x00) | + (sprites[4].ExpandX ? 0x10 : 0x00) | + (sprites[5].ExpandX ? 0x20 : 0x00) | + (sprites[6].ExpandX ? 0x40 : 0x00) | + (sprites[7].ExpandX ? 0x80 : 0x00) + ); + case 0x1E: return ( + (sprites[0].SpriteCollision ? 0x01 : 0x00) | + (sprites[1].SpriteCollision ? 0x02 : 0x00) | + (sprites[2].SpriteCollision ? 0x04 : 0x00) | + (sprites[3].SpriteCollision ? 0x08 : 0x00) | + (sprites[4].SpriteCollision ? 0x10 : 0x00) | + (sprites[5].SpriteCollision ? 0x20 : 0x00) | + (sprites[6].SpriteCollision ? 0x40 : 0x00) | + (sprites[7].SpriteCollision ? 0x80 : 0x00) + ); + case 0x1F: return ( + (sprites[0].DataCollision ? 0x01 : 0x00) | + (sprites[1].DataCollision ? 0x02 : 0x00) | + (sprites[2].DataCollision ? 0x04 : 0x00) | + (sprites[3].DataCollision ? 0x08 : 0x00) | + (sprites[4].DataCollision ? 0x10 : 0x00) | + (sprites[5].DataCollision ? 0x20 : 0x00) | + (sprites[6].DataCollision ? 0x40 : 0x00) | + (sprites[7].DataCollision ? 0x80 : 0x00) + ); + case 0x20: return borderColor | 0xF0; + case 0x21: return backgroundColor[0] | 0xF0; + case 0x22: return backgroundColor[1] | 0xF0; + case 0x23: return backgroundColor[2] | 0xF0; + case 0x24: return backgroundColor[3] | 0xF0; + case 0x25: return spriteMultiColor[0] | 0xF0; + case 0x26: return spriteMultiColor[1] | 0xF0; + case 0x27: return sprites[0].Color | 0xF0; + case 0x28: return sprites[1].Color | 0xF0; + case 0x29: return sprites[2].Color | 0xF0; + case 0x2A: return sprites[3].Color | 0xF0; + case 0x2B: return sprites[4].Color | 0xF0; + case 0x2C: return sprites[5].Color | 0xF0; + case 0x2D: return sprites[6].Color | 0xF0; + case 0x2E: return sprites[7].Color | 0xF0; + default: return 0xFF; + } } public void Poke(int addr, int val) { + switch (addr) + { + case 0x00: sprites[0].X = (sprites[0].X & 0x100 | val); return; + case 0x01: sprites[1].X = (sprites[1].X & 0x100 | val); return; + case 0x02: sprites[2].X = (sprites[2].X & 0x100 | val); return; + case 0x03: sprites[3].X = (sprites[3].X & 0x100 | val); return; + case 0x04: sprites[4].X = (sprites[4].X & 0x100 | val); return; + case 0x05: sprites[5].X = (sprites[5].X & 0x100 | val); return; + case 0x06: sprites[6].X = (sprites[6].X & 0x100 | val); return; + case 0x07: sprites[7].X = (sprites[7].X & 0x100 | val); return; + case 0x08: sprites[0].Y = val; return; + case 0x09: sprites[1].Y = val; return; + case 0x0A: sprites[2].Y = val; return; + case 0x0B: sprites[3].Y = val; return; + case 0x0C: sprites[4].Y = val; return; + case 0x0D: sprites[5].Y = val; return; + case 0x0E: sprites[6].Y = val; return; + case 0x0F: sprites[7].Y = val; return; + case 0x10: + sprites[0].X = (sprites[0].X & 0xFF) | ((val & 0x01) << 8); + sprites[1].X = (sprites[1].X & 0xFF) | ((val & 0x02) << 7); + sprites[2].X = (sprites[2].X & 0xFF) | ((val & 0x04) << 6); + sprites[3].X = (sprites[3].X & 0xFF) | ((val & 0x08) << 5); + sprites[4].X = (sprites[4].X & 0xFF) | ((val & 0x10) << 4); + sprites[5].X = (sprites[5].X & 0xFF) | ((val & 0x20) << 3); + sprites[6].X = (sprites[6].X & 0xFF) | ((val & 0x40) << 2); + sprites[7].X = (sprites[7].X & 0xFF) | ((val & 0x80) << 1); + return; + case 0x11: + yScroll = (val & 0x07); + rowSelect = ((val & 0x08) != 0); + displayEnable = ((val & 0x10) != 0); + bitmapMode = ((val & 0x20) != 0); + extraColorMode = ((val & 0x40) != 0); + rasterY = (rasterY & 0xFF) | ((val & 0x80) << 1); + return; + case 0x12: rasterY = (rasterY & 0x100) | val; return; + case 0x13: lightPenX = val; return; + case 0x14: lightPenY = val; return; + case 0x15: + sprites[0].Enabled = ((val & 0x01) != 0); + sprites[1].Enabled = ((val & 0x02) != 0); + sprites[2].Enabled = ((val & 0x04) != 0); + sprites[3].Enabled = ((val & 0x08) != 0); + sprites[4].Enabled = ((val & 0x10) != 0); + sprites[5].Enabled = ((val & 0x20) != 0); + sprites[6].Enabled = ((val & 0x40) != 0); + sprites[7].Enabled = ((val & 0x80) != 0); + return; + case 0x16: + xScroll = (val & 0x07); + columnSelect = ((val & 0x08) != 0); + multiColorMode = ((val & 0x08) != 0); + reset = ((val & 0x08) != 0); + return; + case 0x17: + sprites[0].ExpandY = ((val & 0x01) != 0); + sprites[1].ExpandY = ((val & 0x02) != 0); + sprites[2].ExpandY = ((val & 0x04) != 0); + sprites[3].ExpandY = ((val & 0x08) != 0); + sprites[4].ExpandY = ((val & 0x10) != 0); + sprites[5].ExpandY = ((val & 0x20) != 0); + sprites[6].ExpandY = ((val & 0x40) != 0); + sprites[7].ExpandY = ((val & 0x80) != 0); + return; + case 0x18: + videoMemory = (val & 0xF0) << 6; + characterBitmap = (val & 0x0E) << 10; + return; + case 0x19: + rasterInterrupt = ((val & 0x01) != 0); + dataCollisionInterrupt = ((val & 0x02) != 0); + spriteCollisionInterrupt = ((val & 0x04) != 0); + lightPenInterrupt = ((val & 0x08) != 0); + irq = ((val & 0x80) != 0); + return; + case 0x1A: + rasterInterruptEnable = ((val & 0x01) != 0); + dataCollisionInterruptEnable = ((val & 0x02) != 0); + spriteCollisionInterruptEnable = ((val & 0x04) != 0); + lightPenInterruptEnable = ((val & 0x08) != 0); + return; + case 0x1B: + sprites[0].Priority = ((val & 0x01) != 0); + sprites[1].Priority = ((val & 0x02) != 0); + sprites[2].Priority = ((val & 0x04) != 0); + sprites[3].Priority = ((val & 0x08) != 0); + sprites[4].Priority = ((val & 0x10) != 0); + sprites[5].Priority = ((val & 0x20) != 0); + sprites[6].Priority = ((val & 0x40) != 0); + sprites[7].Priority = ((val & 0x80) != 0); + return; + case 0x1C: + sprites[0].Multicolor = ((val & 0x01) != 0); + sprites[1].Multicolor = ((val & 0x02) != 0); + sprites[2].Multicolor = ((val & 0x04) != 0); + sprites[3].Multicolor = ((val & 0x08) != 0); + sprites[4].Multicolor = ((val & 0x10) != 0); + sprites[5].Multicolor = ((val & 0x20) != 0); + sprites[6].Multicolor = ((val & 0x40) != 0); + sprites[7].Multicolor = ((val & 0x80) != 0); + return; + case 0x1D: + sprites[0].ExpandX = ((val & 0x01) != 0); + sprites[1].ExpandX = ((val & 0x02) != 0); + sprites[2].ExpandX = ((val & 0x04) != 0); + sprites[3].ExpandX = ((val & 0x08) != 0); + sprites[4].ExpandX = ((val & 0x10) != 0); + sprites[5].ExpandX = ((val & 0x20) != 0); + sprites[6].ExpandX = ((val & 0x40) != 0); + sprites[7].ExpandX = ((val & 0x80) != 0); + return; + case 0x1E: + sprites[0].SpriteCollision = ((val & 0x01) != 0); + sprites[1].SpriteCollision = ((val & 0x02) != 0); + sprites[2].SpriteCollision = ((val & 0x04) != 0); + sprites[3].SpriteCollision = ((val & 0x08) != 0); + sprites[4].SpriteCollision = ((val & 0x10) != 0); + sprites[5].SpriteCollision = ((val & 0x20) != 0); + sprites[6].SpriteCollision = ((val & 0x40) != 0); + sprites[7].SpriteCollision = ((val & 0x80) != 0); + return; + case 0x1F: + sprites[0].DataCollision = ((val & 0x01) != 0); + sprites[1].DataCollision = ((val & 0x02) != 0); + sprites[2].DataCollision = ((val & 0x04) != 0); + sprites[3].DataCollision = ((val & 0x08) != 0); + sprites[4].DataCollision = ((val & 0x10) != 0); + sprites[5].DataCollision = ((val & 0x20) != 0); + sprites[6].DataCollision = ((val & 0x40) != 0); + sprites[7].DataCollision = ((val & 0x80) != 0); + return; + case 0x20: borderColor = val & 0x0F; return; + case 0x21: backgroundColor[0] = val & 0x0F; return; + case 0x22: backgroundColor[1] = val & 0x0F; return; + case 0x23: backgroundColor[2] = val & 0x0F; return; + case 0x24: backgroundColor[3] = val & 0x0F; return; + case 0x25: spriteMultiColor[0] = val & 0x0F; return; + case 0x26: spriteMultiColor[1] = val & 0x0F; return; + case 0x27: sprites[0].Color = val & 0x0F; return; + case 0x28: sprites[1].Color = val & 0x0F; return; + case 0x29: sprites[2].Color = val & 0x0F; return; + case 0x2A: sprites[3].Color = val & 0x0F; return; + case 0x2B: sprites[4].Color = val & 0x0F; return; + case 0x2C: sprites[5].Color = val & 0x0F; return; + case 0x2D: sprites[6].Color = val & 0x0F; return; + case 0x2E: sprites[7].Color = val & 0x0F; return; + default: return; + } } public int Read(int addr) { - return Peek(addr); + int result; + addr &= 0x3F; + + switch (addr) + { + case 0x1E: + case 0x1F: + result = Peek(addr); + Poke(addr, 0); + return result; + default: + return Peek(addr & 0x3F); + } } public void Write(int addr, int val) { - Poke(addr, val); + addr &= 0x3F; + val &= 0xFF; + switch (addr) + { + case 0x19: + if ((val & 0x01) != 0) + rasterInterrupt = false; + if ((val & 0x02) != 0) + dataCollisionInterrupt = false; + if ((val & 0x04) != 0) + spriteCollisionInterrupt = false; + if ((val & 0x08) != 0) + lightPenInterrupt = false; + return; + case 0x1E: + case 0x1F: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + return; + default: + Poke(addr, val); + return; + } } } }