diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 8acaf4e95b..4e00fb1dfc 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -152,6 +152,10 @@ + + + + diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs new file mode 100644 index 0000000000..4ec039a631 --- /dev/null +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Parse.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS +{ + public abstract partial class Vic + { + private int parseaddr; + private int parsecycleBAsprite0; + private int parsecycleBAsprite1; + private int parsecycleBAsprite2; + private int parsecycleFetchSpriteIndex; + private int parsefetch; + private int parseba; + private int parseact; + + private void ParseCycle() + { + + { + parseaddr = 0x3FFF; + parsefetch = pipeline[1][cycleIndex]; + parseba = pipeline[2][cycleIndex]; + parseact = pipeline[3][cycleIndex]; + + // apply X location + rasterX = pipeline[0][cycleIndex]; + + // perform fetch + switch (parsefetch & 0xFF00) + { + case 0x0100: + // fetch R + refreshCounter = (refreshCounter - 1) & 0xFF; + parseaddr = (0x3F00 | refreshCounter); + ReadMemory(parseaddr); + break; + case 0x0200: + // fetch C + if (!idle) + { + if (badline) + { + parseaddr = ((pointerVM << 10) | vc); + dataC = ReadMemory(parseaddr); + dataC |= ((int)ReadColorRam(parseaddr) & 0xF) << 8; + bufferC[vmli] = dataC; + } + else + { + dataC = bufferC[vmli]; + } + } + else + { + dataC = 0; + bufferC[vmli] = dataC; + } + break; + case 0x0300: + // fetch G + if (idle) + parseaddr = 0x3FFF; + else + { + if (bitmapMode) + parseaddr = (rc | (vc << 3) | ((pointerCB & 0x4) << 11)); + else + parseaddr = (rc | ((dataC & 0xFF) << 3) | (pointerCB << 11)); + } + if (extraColorMode) + parseaddr &= 0x39FF; + dataG = ReadMemory(parseaddr); + if (!idle) + { + bufferG[vmli] = dataG; + vmli = (vmli + 1) & 0x3F; + vc = (vc + 1) & 0x3FF; + } + break; + case 0x0400: + // fetch I + parseaddr = (extraColorMode ? 0x39FF : 0x3FFF); + dataG = ReadMemory(parseaddr); + dataC = 0; + break; + case 0x0500: + // no fetch + break; + default: + parsecycleFetchSpriteIndex = (parsefetch & 0x7); + switch (parsefetch & 0xF0) + { + case 0x00: + // fetch P + parseaddr = (0x3F8 | (pointerVM << 10) | parsecycleFetchSpriteIndex); + sprites[parsecycleFetchSpriteIndex].pointer = ReadMemory(parseaddr); + sprites[parsecycleFetchSpriteIndex].shiftEnable = false; + break; + case 0x10: + case 0x20: + case 0x30: + // fetch S + if (sprites[parsecycleFetchSpriteIndex].dma) + { + Sprite spr = sprites[parsecycleFetchSpriteIndex]; + parseaddr = (spr.mc | (spr.pointer << 6)); + spr.sr <<= 8; + spr.sr |= ReadMemory(parseaddr); + spr.mc++; + } + break; + } + break; + } + + // perform BA flag manipulation + switch (parseba) + { + case 0x0000: + pinBA = true; + break; + case 0x1000: + pinBA = !badline; + break; + default: + parsecycleBAsprite0 = (parseba & 0x000F); + parsecycleBAsprite1 = (parseba & 0x00F0) >> 4; + parsecycleBAsprite2 = (parseba & 0x0F00) >> 8; + if ((parsecycleBAsprite0 < 8 && sprites[parsecycleBAsprite0].dma) || + (parsecycleBAsprite1 < 8 && sprites[parsecycleBAsprite1].dma) || + (parsecycleBAsprite2 < 8 && sprites[parsecycleBAsprite2].dma)) + pinBA = false; + else + pinBA = true; + break; + } + + // perform actions + borderCheckLEnable = true; + borderCheckREnable = true; + + if ((parseact & pipelineChkSprChunch) != 0) + { + //for (int i = 0; i < 8; i++) + foreach (Sprite spr in sprites) + { + //Sprite spr = sprites[i]; + if (spr.yCrunch) + spr.mcbase += 2; + spr.shiftEnable = false; + spr.xCrunch = !spr.xExpand; + spr.multicolorCrunch = !spr.multicolor; + } + } + if ((parseact & pipelineChkSprDisp) != 0) + { + //for (int i = 0; i < 8; i++) + foreach (Sprite spr in sprites) + { + //Sprite spr = sprites[i]; + spr.mc = spr.mcbase; + if (spr.dma && spr.y == (rasterLine & 0xFF)) + { + spr.display = true; + } + } + } + if ((parseact & pipelineChkSprDma) != 0) + { + //for (int i = 0; i < 8; i++) + foreach (Sprite spr in sprites) + { + //Sprite spr = sprites[i]; + if (spr.enable && spr.y == (rasterLine & 0xFF) && !spr.dma) + { + spr.dma = true; + spr.mcbase = 0; + spr.yCrunch = !spr.yExpand; + } + } + } + if ((parseact & pipelineChkSprExp) != 0) + { + if (sprites[0].yExpand) sprites[0].yCrunch ^= true; + if (sprites[1].yExpand) sprites[1].yCrunch ^= true; + if (sprites[2].yExpand) sprites[2].yCrunch ^= true; + if (sprites[3].yExpand) sprites[3].yCrunch ^= true; + if (sprites[4].yExpand) sprites[4].yCrunch ^= true; + if (sprites[5].yExpand) sprites[5].yCrunch ^= true; + if (sprites[6].yExpand) sprites[6].yCrunch ^= true; + if (sprites[7].yExpand) sprites[7].yCrunch ^= true; + } + if ((parseact & pipelineUpdateMcBase) != 0) + { + //for (int i = 0; i < 8; i++) + foreach (Sprite spr in sprites) + { + //Sprite spr = sprites[i]; + if (spr.yCrunch) + { + spr.mcbase++; + if (spr.mcbase == 63) + { + spr.dma = false; + spr.display = false; + } + } + } + } + if ((parseact & pipelineUpdateRc) != 0) + { + if (rc == 7) + { + idle = true; + vcbase = vc; + } + if (!idle) + rc = (rc + 1) & 0x7; + } + if ((parseact & pipelineUpdateVc) != 0) + { + vc = vcbase; + vmli = 0; + if (badline) + rc = 0; + } + + cycleIndex++; + } + } + } +} diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Registers.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Registers.cs new file mode 100644 index 0000000000..3b22a5484c --- /dev/null +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Registers.cs @@ -0,0 +1,528 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS +{ + public abstract partial class Vic + { + private int backgroundColor0; + private int backgroundColor1; + private int backgroundColor2; + private int backgroundColor3; + private bool bitmapMode; + private int borderColor; + private bool columnSelect; + private bool displayEnable; + private bool enableIntLightPen; + private bool enableIntRaster; + private bool enableIntSpriteCollision; + private bool enableIntSpriteDataCollision; + private bool extraColorMode; + private bool intLightPen; + private bool intRaster; + private bool intSpriteCollision; + private bool intSpriteDataCollision; + private int lightPenX; + private int lightPenY; + private bool multicolorMode; + private int pointerCB; + private int pointerVM; + private int rasterInterruptLine; + private int rasterLine; + private int rasterX; + private bool rowSelect; + private int spriteMulticolor0; + private int spriteMulticolor1; + private Sprite[] sprites; + private int xScroll; + private int yScroll; + + public byte Peek(int addr) + { + return ReadRegister((addr & 0x3F)); + } + + public void Poke(int addr, byte val) + { + WriteRegister((addr & 0x3F), val); + } + + public byte Read(int addr) + { + byte result; + addr &= 0x3F; + + switch (addr) + { + case 0x1E: + case 0x1F: + // reading clears these + result = ReadRegister(addr); + WriteRegister(addr, 0); + break; + default: + result = ReadRegister((addr & 0x3F)); + break; + } + return result; + } + + private byte ReadRegister(int addr) + { + byte result = 0xFF; //unused bit value + + switch (addr) + { + case 0x00: + case 0x02: + case 0x04: + case 0x06: + case 0x08: + case 0x0A: + case 0x0C: + case 0x0E: + result = (byte)(sprites[addr >> 1].x & 0xFF); + break; + case 0x01: + case 0x03: + case 0x05: + case 0x07: + case 0x09: + case 0x0B: + case 0x0D: + case 0x0F: + result = (byte)(sprites[addr >> 1].y & 0xFF); + break; + case 0x10: + result = (byte)( + ((sprites[0].x >> 8) & 0x01) | + ((sprites[1].x >> 7) & 0x02) | + ((sprites[2].x >> 6) & 0x04) | + ((sprites[3].x >> 5) & 0x08) | + ((sprites[4].x >> 4) & 0x10) | + ((sprites[5].x >> 3) & 0x20) | + ((sprites[6].x >> 2) & 0x40) | + ((sprites[7].x >> 1) & 0x80) + ); + break; + case 0x11: + result = (byte)( + (yScroll & 0x7) | + (rowSelect ? 0x08 : 0x00) | + (displayEnable ? 0x10 : 0x00) | + (bitmapMode ? 0x20 : 0x00) | + (extraColorMode ? 0x40 : 0x00) | + ((rasterLine & 0x100) >> 1) + ); + break; + case 0x12: + result = (byte)(rasterLine & 0xFF); + break; + case 0x13: + result = (byte)(lightPenX & 0xFF); + break; + case 0x14: + result = (byte)(lightPenY & 0xFF); + break; + case 0x15: + result = (byte)( + (sprites[0].enable ? 0x01 : 0x00) | + (sprites[1].enable ? 0x02 : 0x00) | + (sprites[2].enable ? 0x04 : 0x00) | + (sprites[3].enable ? 0x08 : 0x00) | + (sprites[4].enable ? 0x10 : 0x00) | + (sprites[5].enable ? 0x20 : 0x00) | + (sprites[6].enable ? 0x40 : 0x00) | + (sprites[7].enable ? 0x80 : 0x00) + ); + break; + case 0x16: + result &= 0xC0; + result |= (byte)( + (xScroll & 0x7) | + (columnSelect ? 0x08 : 0x00) | + (multicolorMode ? 0x10 : 0x00) + ); + break; + case 0x17: + result = (byte)( + (sprites[0].yExpand ? 0x01 : 0x00) | + (sprites[1].yExpand ? 0x02 : 0x00) | + (sprites[2].yExpand ? 0x04 : 0x00) | + (sprites[3].yExpand ? 0x08 : 0x00) | + (sprites[4].yExpand ? 0x10 : 0x00) | + (sprites[5].yExpand ? 0x20 : 0x00) | + (sprites[6].yExpand ? 0x40 : 0x00) | + (sprites[7].yExpand ? 0x80 : 0x00) + ); + break; + case 0x18: + result &= 0x01; + result |= (byte)( + ((pointerVM & 0xF) << 4) | + ((pointerCB & 0x7) << 1) + ); + break; + case 0x19: + result &= 0x70; + result |= (byte)( + (intRaster ? 0x01 : 0x00) | + (intSpriteDataCollision ? 0x02 : 0x00) | + (intSpriteCollision ? 0x04 : 0x00) | + (intLightPen ? 0x08 : 0x00) | + (pinIRQ ? 0x00 : 0x80) + ); + break; + case 0x1A: + result &= 0xF0; + result |= (byte)( + (enableIntRaster ? 0x01 : 0x00) | + (enableIntSpriteDataCollision ? 0x02 : 0x00) | + (enableIntSpriteCollision ? 0x04 : 0x00) | + (enableIntLightPen ? 0x08 : 0x00) + ); + break; + case 0x1B: + result = (byte)( + (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) + ); + break; + case 0x1C: + result = (byte)( + (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) + ); + break; + case 0x1D: + result = (byte)( + (sprites[0].xExpand ? 0x01 : 0x00) | + (sprites[1].xExpand ? 0x02 : 0x00) | + (sprites[2].xExpand ? 0x04 : 0x00) | + (sprites[3].xExpand ? 0x08 : 0x00) | + (sprites[4].xExpand ? 0x10 : 0x00) | + (sprites[5].xExpand ? 0x20 : 0x00) | + (sprites[6].xExpand ? 0x40 : 0x00) | + (sprites[7].xExpand ? 0x80 : 0x00) + ); + break; + case 0x1E: + result = (byte)( + (sprites[0].collideSprite ? 0x01 : 0x00) | + (sprites[1].collideSprite ? 0x02 : 0x00) | + (sprites[2].collideSprite ? 0x04 : 0x00) | + (sprites[3].collideSprite ? 0x08 : 0x00) | + (sprites[4].collideSprite ? 0x10 : 0x00) | + (sprites[5].collideSprite ? 0x20 : 0x00) | + (sprites[6].collideSprite ? 0x40 : 0x00) | + (sprites[7].collideSprite ? 0x80 : 0x00) + ); + break; + case 0x1F: + result = (byte)( + (sprites[0].collideData ? 0x01 : 0x00) | + (sprites[1].collideData ? 0x02 : 0x00) | + (sprites[2].collideData ? 0x04 : 0x00) | + (sprites[3].collideData ? 0x08 : 0x00) | + (sprites[4].collideData ? 0x10 : 0x00) | + (sprites[5].collideData ? 0x20 : 0x00) | + (sprites[6].collideData ? 0x40 : 0x00) | + (sprites[7].collideData ? 0x80 : 0x00) + ); + break; + case 0x20: + result &= 0xF0; + result |= (byte)(borderColor & 0x0F); + break; + case 0x21: + result &= 0xF0; + result |= (byte)(backgroundColor0 & 0x0F); + break; + case 0x22: + result &= 0xF0; + result |= (byte)(backgroundColor1 & 0x0F); + break; + case 0x23: + result &= 0xF0; + result |= (byte)(backgroundColor2 & 0x0F); + break; + case 0x24: + result &= 0xF0; + result |= (byte)(backgroundColor3 & 0x0F); + break; + case 0x25: + result &= 0xF0; + result |= (byte)(spriteMulticolor0 & 0x0F); + break; + case 0x26: + result &= 0xF0; + result |= (byte)(spriteMulticolor1 & 0x0F); + break; + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + result &= 0xF0; + result |= (byte)(sprites[addr - 0x27].color & 0xF); + break; + default: + // not connected + break; + } + + return result; + } + + public void Write(int addr, byte val) + { + addr &= 0x3F; + switch (addr) + { + case 0x19: + // interrupts are cleared by writing a 1 + if ((val & 0x01) != 0) + intRaster = false; + if ((val & 0x02) != 0) + intSpriteDataCollision = false; + if ((val & 0x04) != 0) + intSpriteCollision = false; + if ((val & 0x08) != 0) + intLightPen = false; + UpdatePins(); + break; + case 0x1A: + WriteRegister(addr, val); + break; + case 0x1E: + case 0x1F: + // can't write to these + break; + 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: + // not connected + break; + default: + WriteRegister(addr, val); + break; + } + } + + private void WriteRegister(int addr, byte val) + { + switch (addr) + { + case 0x00: + case 0x02: + case 0x04: + case 0x06: + case 0x08: + case 0x0A: + case 0x0C: + case 0x0E: + sprites[addr >> 1].x &= 0x100; + sprites[addr >> 1].x |= val; + break; + case 0x01: + case 0x03: + case 0x05: + case 0x07: + case 0x09: + case 0x0B: + case 0x0D: + case 0x0F: + sprites[addr >> 1].y = val; + break; + 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); + break; + case 0x11: + yScroll = (val & 0x07); + rowSelect = ((val & 0x08) != 0); + displayEnable = ((val & 0x10) != 0); + bitmapMode = ((val & 0x20) != 0); + extraColorMode = ((val & 0x40) != 0); + rasterInterruptLine &= 0xFF; + rasterInterruptLine |= (val & 0x80) << 1; + UpdateBorder(); + break; + case 0x12: + rasterInterruptLine &= 0x100; + rasterInterruptLine |= val; + break; + case 0x13: + lightPenX = val; + break; + case 0x14: + lightPenY = val; + break; + case 0x15: + sprites[0].enable = ((val & 0x01) != 0); + sprites[1].enable = ((val & 0x02) != 0); + sprites[2].enable = ((val & 0x04) != 0); + sprites[3].enable = ((val & 0x08) != 0); + sprites[4].enable = ((val & 0x10) != 0); + sprites[5].enable = ((val & 0x20) != 0); + sprites[6].enable = ((val & 0x40) != 0); + sprites[7].enable = ((val & 0x80) != 0); + break; + case 0x16: + xScroll = (val & 0x07); + columnSelect = ((val & 0x08) != 0); + multicolorMode = ((val & 0x10) != 0); + UpdateBorder(); + break; + case 0x17: + sprites[0].yExpand = ((val & 0x01) != 0); + sprites[1].yExpand = ((val & 0x02) != 0); + sprites[2].yExpand = ((val & 0x04) != 0); + sprites[3].yExpand = ((val & 0x08) != 0); + sprites[4].yExpand = ((val & 0x10) != 0); + sprites[5].yExpand = ((val & 0x20) != 0); + sprites[6].yExpand = ((val & 0x40) != 0); + sprites[7].yExpand = ((val & 0x80) != 0); + break; + case 0x18: + pointerVM = ((val >> 4) & 0xF); + pointerCB = ((val >> 1) & 0x7); + break; + case 0x19: + intRaster = ((val & 0x01) != 0); + intSpriteDataCollision = ((val & 0x02) != 0); + intSpriteCollision = ((val & 0x04) != 0); + intLightPen = ((val & 0x08) != 0); + UpdatePins(); + break; + case 0x1A: + enableIntRaster = ((val & 0x01) != 0); + enableIntSpriteDataCollision = ((val & 0x02) != 0); + enableIntSpriteCollision = ((val & 0x04) != 0); + enableIntLightPen = ((val & 0x08) != 0); + UpdatePins(); + break; + 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); + break; + 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); + break; + case 0x1D: + sprites[0].xExpand = ((val & 0x01) != 0); + sprites[1].xExpand = ((val & 0x02) != 0); + sprites[2].xExpand = ((val & 0x04) != 0); + sprites[3].xExpand = ((val & 0x08) != 0); + sprites[4].xExpand = ((val & 0x10) != 0); + sprites[5].xExpand = ((val & 0x20) != 0); + sprites[6].xExpand = ((val & 0x40) != 0); + sprites[7].xExpand = ((val & 0x80) != 0); + break; + case 0x1E: + sprites[0].collideSprite = ((val & 0x01) != 0); + sprites[1].collideSprite = ((val & 0x02) != 0); + sprites[2].collideSprite = ((val & 0x04) != 0); + sprites[3].collideSprite = ((val & 0x08) != 0); + sprites[4].collideSprite = ((val & 0x10) != 0); + sprites[5].collideSprite = ((val & 0x20) != 0); + sprites[6].collideSprite = ((val & 0x40) != 0); + sprites[7].collideSprite = ((val & 0x80) != 0); + break; + case 0x1F: + sprites[0].collideData = ((val & 0x01) != 0); + sprites[1].collideData = ((val & 0x02) != 0); + sprites[2].collideData = ((val & 0x04) != 0); + sprites[3].collideData = ((val & 0x08) != 0); + sprites[4].collideData = ((val & 0x10) != 0); + sprites[5].collideData = ((val & 0x20) != 0); + sprites[6].collideData = ((val & 0x40) != 0); + sprites[7].collideData = ((val & 0x80) != 0); + break; + case 0x20: + borderColor = (val & 0xF); + break; + case 0x21: + backgroundColor0 = (val & 0xF); + break; + case 0x22: + backgroundColor1 = (val & 0xF); + break; + case 0x23: + backgroundColor2 = (val & 0xF); + break; + case 0x24: + backgroundColor3 = (val & 0xF); + break; + case 0x25: + spriteMulticolor0 = (val & 0xF); + break; + case 0x26: + spriteMulticolor1 = (val & 0xF); + break; + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + sprites[addr - 0x27].color = (val & 0xF); + break; + default: + break; + } + } + } +} diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs new file mode 100644 index 0000000000..8d767a5539 --- /dev/null +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Render.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS +{ + public abstract partial class Vic + { + private void Render() + { + + { + renderEnabled = bufRect.Contains(bufPoint); + + for (int i = 0; i < 4; i++) + { + if (borderCheckLEnable && rasterX == borderL) + { + if (rasterLine == borderB) + borderOnVertical = true; + if (rasterLine == borderT && displayEnable) + borderOnVertical = false; + if (!borderOnVertical) + borderOnMain = false; + } + if (borderCheckREnable && rasterX == borderR) + { + borderOnMain = true; + } + + // recall pixel from buffer + pixel = pixelBuffer[pixelBufferIndex]; + + // plot pixel if within viewing area + if (renderEnabled) + { + buf[bufOffset] = palette[pixel]; + bufOffset++; + if (bufOffset == bufLength) + bufOffset = 0; + } + bufPoint.X++; + if (bufPoint.X == bufWidth) + { + bufPoint.X = 0; + bufPoint.Y++; + if (bufPoint.Y == bufHeight) + bufPoint.Y = 0; + } + + // put the pixel from the background buffer into the main buffer + pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; + + // render sprite + int pixelOwner = 8; + for (int j = 0; j < 8; j++) + { + int sprData; + int sprPixel = pixel; + + Sprite spr = sprites[j]; + + if (spr.x == rasterX) + spr.shiftEnable = true; + + if (spr.shiftEnable) + { + if (spr.multicolor) + { + sprData = (spr.sr & 0xC00000) >> 22; + if (spr.multicolorCrunch && spr.xCrunch) + spr.sr <<= 2; + spr.multicolorCrunch ^= spr.xCrunch; + } + else + { + sprData = (spr.sr & 0x800000) >> 22; + if (spr.xCrunch) + spr.sr <<= 1; + } + spr.xCrunch ^= spr.xExpand; + switch (sprData) + { + case 1: sprPixel = spriteMulticolor0; break; + case 2: sprPixel = spr.color; break; + case 3: sprPixel = spriteMulticolor1; break; + } + if (sprData != 0) + { + // sprite-sprite collision + if (pixelOwner >= 8) + { + if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x2)) + pixel = sprPixel; + pixelOwner = j; + } + else + { + if (!borderOnVertical) + { + spr.collideSprite = true; + sprites[pixelOwner].collideSprite = true; + } + } + + // sprite-data collision + if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] >= 0x2)) + { + spr.collideData = true; + } + } + if (spr.sr == 0) + spr.shiftEnable = false; //optimization + } + } + + // border doesn't work with the background buffer + if (borderOnMain || borderOnVertical) + pixel = borderColor; + + // store pixel in buffer + pixelBuffer[pixelBufferIndex] = pixel; + + // fill shift register + if (xOffset == xScroll) + { + if (displayIndex < 40 && !idle) + { + displayC = bufferC[displayIndex]; + sr |= bufferG[displayIndex]; + } + bitmapColumn = 0; + } + + if (!extraColorMode && !bitmapMode & !multicolorMode) + { + // 000 + pixelData = (sr & 0x80) >> 6; + sr <<= 1; + pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0; + } + else if (!extraColorMode && !bitmapMode & multicolorMode) + { + // 001 + if ((displayC & 0x800) != 0) + { + // multicolor 001 + pixelData = (sr & 0xC0) >> 6; + if ((bitmapColumn & 1) != 0) + sr <<= 2; + switch (pixelData) + { + case 0x00: pixel = backgroundColor0; break; + case 0x01: pixel = backgroundColor1; break; + case 0x02: pixel = backgroundColor2; break; + default: pixel = (displayC & 0x700) >> 8; break; + } + } + else + { + // standard 001 + pixelData = (sr & 0x80) >> 6; + sr <<= 1; + pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0; + } + } + else if (!extraColorMode && bitmapMode & !multicolorMode) + { + // 010 + pixelData = (sr & 0x80) >> 6; + sr <<= 1; + pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF); + } + else if (!extraColorMode && bitmapMode & multicolorMode) + { + // 011 + pixelData = (sr & 0xC0) >> 6; + if ((bitmapColumn & 1) != 0) + sr <<= 2; + switch (pixelData) + { + case 0x00: pixel = backgroundColor0; break; + case 0x01: pixel = (displayC >> 4) & 0xF; break; + case 0x02: pixel = displayC & 0xF; break; + default: pixel = (displayC >> 8) & 0xF; break; + } + } + else if (extraColorMode && !bitmapMode & !multicolorMode) + { + // 100 + pixelData = (sr & 0x80) >> 6; + sr <<= 1; + if (pixelData != 0) + { + pixel = displayC >> 8; + } + else + { + switch ((displayC >> 6) & 0x3) + { + case 0x00: pixel = backgroundColor0; break; + case 0x01: pixel = backgroundColor1; break; + case 0x02: pixel = backgroundColor2; break; + default: pixel = backgroundColor3; break; + } + } + } + else if (extraColorMode && !bitmapMode & multicolorMode) + { + // 101 + pixelData = 0; + pixel = 0; + } + else if (extraColorMode && bitmapMode & !multicolorMode) + { + // 110 + pixelData = 0; + pixel = 0; + } + else + { + // 111 + pixelData = 0; + pixel = 0; + } + + // put the rendered pixel into the background buffer + pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData; + pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel; + pixelBackgroundBufferIndex++; + if (pixelBackgroundBufferIndex == pixelBackgroundBufferDelay) + pixelBackgroundBufferIndex = 0; + + // advance pixel buffer + pixelBufferIndex++; + if (pixelBufferIndex == pixelBufferDelay) + pixelBufferIndex = 0; + + rasterX++; + xOffset++; + bitmapColumn++; + } + } + } + } +} diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Sprite.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Sprite.cs new file mode 100644 index 0000000000..6d25edfb90 --- /dev/null +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.Sprite.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Computers.Commodore64.MOS +{ + public abstract partial class Vic + { + private class Sprite + { + public bool collideData; + public bool collideSprite; + public int color; + public bool display; + public bool dma; + public bool enable; + public int mc; + public int mcbase; + public bool multicolor; + public bool multicolorCrunch; + public int pointer; + public bool priority; + public bool shiftEnable; + public int sr; + public int x; + public bool xCrunch; + public bool xExpand; + public int y; + public bool yCrunch; + public bool yExpand; + + public void HardReset() + { + collideData = false; + collideSprite = false; + color = 0; + display = false; + dma = false; + enable = false; + mc = 0; + mcbase = 0; + multicolor = false; + multicolorCrunch = false; + pointer = 0; + priority = false; + shiftEnable = false; + sr = 0; + x = 0; + xCrunch = false; + xExpand = false; + y = 0; + yCrunch = false; + yExpand = false; + } + + public void SyncState(Serializer ser) + { + ser.Sync("collideData", ref collideData); + ser.Sync("collideSprite", ref collideSprite); + ser.Sync("color", ref color); + ser.Sync("display", ref display); + ser.Sync("dma", ref dma); + ser.Sync("enable", ref enable); + ser.Sync("mc", ref mc); + ser.Sync("mcbase", ref mcbase); + ser.Sync("multicolor", ref multicolor); + ser.Sync("multicolorCrunch", ref multicolorCrunch); + ser.Sync("pointer", ref pointer); + ser.Sync("priority", ref priority); + ser.Sync("shiftEnable", ref shiftEnable); + ser.Sync("sr", ref sr); + ser.Sync("x", ref x); + ser.Sync("xCrunch", ref xCrunch); + ser.Sync("xExpand", ref xExpand); + ser.Sync("y", ref y); + ser.Sync("yCrunch", ref yCrunch); + ser.Sync("yExpand", ref yExpand); + } + } + } +} diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs index a9f8ab0a4d..4df5a00da1 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs @@ -7,92 +7,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { // ------------------------------------ - private class Sprite - { - public bool collideData; - public bool collideSprite; - public int color; - public bool display; - public bool dma; - public bool enable; - public int mc; - public int mcbase; - public bool multicolor; - public bool multicolorCrunch; - public int pointer; - public bool priority; - public bool shiftEnable; - public int sr; - public int x; - public bool xCrunch; - public bool xExpand; - public int y; - public bool yCrunch; - public bool yExpand; - - public void HardReset() - { - collideData = false; - collideSprite = false; - color = 0; - display = false; - dma = false; - enable = false; - mc = 0; - mcbase = 0; - multicolor = false; - multicolorCrunch = false; - pointer = 0; - priority = false; - shiftEnable = false; - sr = 0; - x = 0; - xCrunch = false; - xExpand = false; - y = 0; - yCrunch = false; - yExpand = false; - } - - public void SyncState(Serializer ser) - { - ser.Sync("collideData", ref collideData); - ser.Sync("collideSprite", ref collideSprite); - ser.Sync("color", ref color); - ser.Sync("display", ref display); - ser.Sync("dma", ref dma); - ser.Sync("enable", ref enable); - ser.Sync("mc", ref mc); - ser.Sync("mcbase", ref mcbase); - ser.Sync("multicolor", ref multicolor); - ser.Sync("multicolorCrunch", ref multicolorCrunch); - ser.Sync("pointer", ref pointer); - ser.Sync("priority", ref priority); - ser.Sync("shiftEnable", ref shiftEnable); - ser.Sync("sr", ref sr); - ser.Sync("x", ref x); - ser.Sync("xCrunch", ref xCrunch); - ser.Sync("xExpand", ref xExpand); - ser.Sync("y", ref y); - ser.Sync("yCrunch", ref yCrunch); - ser.Sync("yExpand", ref yExpand); - } - } - private Sprite[] sprites; - - private int backgroundColor0; - private int backgroundColor1; - private int backgroundColor2; - private int backgroundColor3; private int baCount; private bool badline; private bool badlineEnable; private int bitmapColumn; - private bool bitmapMode; private int borderB; private bool borderCheckLEnable; private bool borderCheckREnable; - private int borderColor; private int borderL; private bool borderOnMain; private bool borderOnVertical; @@ -100,37 +21,15 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private int borderT; private int[] bufferC; private int[] bufferG; - private bool columnSelect; private int cycle; private int cycleIndex; private int dataC; private int dataG; private bool debugScreen; private int displayC; - private bool displayEnable; private int displayIndex; - private bool enableIntLightPen; - private bool enableIntRaster; - private bool enableIntSpriteCollision; - private bool enableIntSpriteDataCollision; - private bool extraColorMode; private bool idle; - private bool intLightPen; - private bool intRaster; - private bool intSpriteCollision; - private bool intSpriteDataCollision; private int lastRasterLine; - private int lightPenX; - private int lightPenY; - private bool multicolorMode; - private int parseaddr; - private int parsecycleBAsprite0; - private int parsecycleBAsprite1; - private int parsecycleBAsprite2; - private int parsecycleFetchSpriteIndex; - private int parsefetch; - private int parseba; - private int parseact; private int pixel; private int[] pixelBackgroundBuffer; private int pixelBackgroundBufferDelay; @@ -140,24 +39,14 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS private int pixelBufferIndex; private int pixelData; private int[] pixelDataBuffer; - private int pointerCB; - private int pointerVM; - private int rasterInterruptLine; - private int rasterLine; - private int rasterX; private int rc; private int refreshCounter; private bool renderEnabled; - private bool rowSelect; - private int spriteMulticolor0; - private int spriteMulticolor1; private int sr; private int vc; private int vcbase; private int vmli; private int xOffset; - private int xScroll; - private int yScroll; // ------------------------------------ @@ -443,459 +332,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS } } - private void ParseCycle() - { - - { - parseaddr = 0x3FFF; - parsefetch = pipeline[1][cycleIndex]; - parseba = pipeline[2][cycleIndex]; - parseact = pipeline[3][cycleIndex]; - - // apply X location - rasterX = pipeline[0][cycleIndex]; - - // perform fetch - switch (parsefetch & 0xFF00) - { - case 0x0100: - // fetch R - refreshCounter = (refreshCounter - 1) & 0xFF; - parseaddr = (0x3F00 | refreshCounter); - ReadMemory(parseaddr); - break; - case 0x0200: - // fetch C - if (!idle) - { - if (badline) - { - parseaddr = ((pointerVM << 10) | vc); - dataC = ReadMemory(parseaddr); - dataC |= ((int)ReadColorRam(parseaddr) & 0xF) << 8; - bufferC[vmli] = dataC; - } - else - { - dataC = bufferC[vmli]; - } - } - else - { - dataC = 0; - bufferC[vmli] = dataC; - } - break; - case 0x0300: - // fetch G - if (idle) - parseaddr = 0x3FFF; - else - { - if (bitmapMode) - parseaddr = (rc | (vc << 3) | ((pointerCB & 0x4) << 11)); - else - parseaddr = (rc | ((dataC & 0xFF) << 3) | (pointerCB << 11)); - } - if (extraColorMode) - parseaddr &= 0x39FF; - dataG = ReadMemory(parseaddr); - if (!idle) - { - bufferG[vmli] = dataG; - vmli = (vmli + 1) & 0x3F; - vc = (vc + 1) & 0x3FF; - } - break; - case 0x0400: - // fetch I - parseaddr = (extraColorMode ? 0x39FF : 0x3FFF); - dataG = ReadMemory(parseaddr); - dataC = 0; - break; - case 0x0500: - // no fetch - break; - default: - parsecycleFetchSpriteIndex = (parsefetch & 0x7); - switch (parsefetch & 0xF0) - { - case 0x00: - // fetch P - parseaddr = (0x3F8 | (pointerVM << 10) | parsecycleFetchSpriteIndex); - sprites[parsecycleFetchSpriteIndex].pointer = ReadMemory(parseaddr); - sprites[parsecycleFetchSpriteIndex].shiftEnable = false; - break; - case 0x10: - case 0x20: - case 0x30: - // fetch S - if (sprites[parsecycleFetchSpriteIndex].dma) - { - Sprite spr = sprites[parsecycleFetchSpriteIndex]; - parseaddr = (spr.mc | (spr.pointer << 6)); - spr.sr <<= 8; - spr.sr |= ReadMemory(parseaddr); - spr.mc++; - } - break; - } - break; - } - - // perform BA flag manipulation - switch (parseba) - { - case 0x0000: - pinBA = true; - break; - case 0x1000: - pinBA = !badline; - break; - default: - parsecycleBAsprite0 = (parseba & 0x000F); - parsecycleBAsprite1 = (parseba & 0x00F0) >> 4; - parsecycleBAsprite2 = (parseba & 0x0F00) >> 8; - if ((parsecycleBAsprite0 < 8 && sprites[parsecycleBAsprite0].dma) || - (parsecycleBAsprite1 < 8 && sprites[parsecycleBAsprite1].dma) || - (parsecycleBAsprite2 < 8 && sprites[parsecycleBAsprite2].dma)) - pinBA = false; - else - pinBA = true; - break; - } - - // perform actions - borderCheckLEnable = true; - borderCheckREnable = true; - - if ((parseact & pipelineChkSprChunch) != 0) - { - //for (int i = 0; i < 8; i++) - foreach (Sprite spr in sprites) - { - //Sprite spr = sprites[i]; - if (spr.yCrunch) - spr.mcbase += 2; - spr.shiftEnable = false; - spr.xCrunch = !spr.xExpand; - spr.multicolorCrunch = !spr.multicolor; - } - } - if ((parseact & pipelineChkSprDisp) != 0) - { - //for (int i = 0; i < 8; i++) - foreach (Sprite spr in sprites) - { - //Sprite spr = sprites[i]; - spr.mc = spr.mcbase; - if (spr.dma && spr.y == (rasterLine & 0xFF)) - { - spr.display = true; - } - } - } - if ((parseact & pipelineChkSprDma) != 0) - { - //for (int i = 0; i < 8; i++) - foreach (Sprite spr in sprites) - { - //Sprite spr = sprites[i]; - if (spr.enable && spr.y == (rasterLine & 0xFF) && !spr.dma) - { - spr.dma = true; - spr.mcbase = 0; - spr.yCrunch = !spr.yExpand; - } - } - } - if ((parseact & pipelineChkSprExp) != 0) - { - if (sprites[0].yExpand) sprites[0].yCrunch ^= true; - if (sprites[1].yExpand) sprites[1].yCrunch ^= true; - if (sprites[2].yExpand) sprites[2].yCrunch ^= true; - if (sprites[3].yExpand) sprites[3].yCrunch ^= true; - if (sprites[4].yExpand) sprites[4].yCrunch ^= true; - if (sprites[5].yExpand) sprites[5].yCrunch ^= true; - if (sprites[6].yExpand) sprites[6].yCrunch ^= true; - if (sprites[7].yExpand) sprites[7].yCrunch ^= true; - } - if ((parseact & pipelineUpdateMcBase) != 0) - { - //for (int i = 0; i < 8; i++) - foreach (Sprite spr in sprites) - { - //Sprite spr = sprites[i]; - if (spr.yCrunch) - { - spr.mcbase++; - if (spr.mcbase == 63) - { - spr.dma = false; - spr.display = false; - } - } - } - } - if ((parseact & pipelineUpdateRc) != 0) - { - if (rc == 7) - { - idle = true; - vcbase = vc; - } - if (!idle) - rc = (rc + 1) & 0x7; - } - if ((parseact & pipelineUpdateVc) != 0) - { - vc = vcbase; - vmli = 0; - if (badline) - rc = 0; - } - - cycleIndex++; - } - } - - private void Render() - { - - { - renderEnabled = bufRect.Contains(bufPoint); - - for (int i = 0; i < 4; i++) - { - if (borderCheckLEnable && rasterX == borderL) - { - if (rasterLine == borderB) - borderOnVertical = true; - if (rasterLine == borderT && displayEnable) - borderOnVertical = false; - if (!borderOnVertical) - borderOnMain = false; - } - if (borderCheckREnable && rasterX == borderR) - { - borderOnMain = true; - } - - // recall pixel from buffer - pixel = pixelBuffer[pixelBufferIndex]; - - // plot pixel if within viewing area - if (renderEnabled) - { - buf[bufOffset] = palette[pixel]; - bufOffset++; - if (bufOffset == bufLength) - bufOffset = 0; - } - bufPoint.X++; - if (bufPoint.X == bufWidth) - { - bufPoint.X = 0; - bufPoint.Y++; - if (bufPoint.Y == bufHeight) - bufPoint.Y = 0; - } - - // put the pixel from the background buffer into the main buffer - pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; - - // render sprite - int pixelOwner = 8; - for (int j = 0; j < 8; j++) - { - int sprData; - int sprPixel = pixel; - - Sprite spr = sprites[j]; - - if (spr.x == rasterX) - spr.shiftEnable = true; - - if (spr.shiftEnable) - { - if (spr.multicolor) - { - sprData = (spr.sr & 0xC00000) >> 22; - if (spr.multicolorCrunch && spr.xCrunch) - spr.sr <<= 2; - spr.multicolorCrunch ^= spr.xCrunch; - } - else - { - sprData = (spr.sr & 0x800000) >> 22; - if (spr.xCrunch) - spr.sr <<= 1; - } - spr.xCrunch ^= spr.xExpand; - switch (sprData) - { - case 1: sprPixel = spriteMulticolor0; break; - case 2: sprPixel = spr.color; break; - case 3: sprPixel = spriteMulticolor1; break; - } - if (sprData != 0) - { - // sprite-sprite collision - if (pixelOwner >= 8) - { - if (!spr.priority || (pixelDataBuffer[pixelBackgroundBufferIndex] < 0x2)) - pixel = sprPixel; - pixelOwner = j; - } - else - { - if (!borderOnVertical) - { - spr.collideSprite = true; - sprites[pixelOwner].collideSprite = true; - } - } - - // sprite-data collision - if (!borderOnVertical && (pixelDataBuffer[pixelBackgroundBufferIndex] >= 0x2)) - { - spr.collideData = true; - } - } - if (spr.sr == 0) - spr.shiftEnable = false; //optimization - } - } - - // border doesn't work with the background buffer - if (borderOnMain || borderOnVertical) - pixel = borderColor; - - // store pixel in buffer - pixelBuffer[pixelBufferIndex] = pixel; - - // fill shift register - if (xOffset == xScroll) - { - if (displayIndex < 40 && !idle) - { - displayC = bufferC[displayIndex]; - sr |= bufferG[displayIndex]; - } - bitmapColumn = 0; - } - - if (!extraColorMode && !bitmapMode & !multicolorMode) - { - // 000 - pixelData = (sr & 0x80) >> 6; - sr <<= 1; - pixel = (pixelData != 0) ? displayC >> 8 : backgroundColor0; - } - else if (!extraColorMode && !bitmapMode & multicolorMode) - { - // 001 - if ((displayC & 0x800) != 0) - { - // multicolor 001 - pixelData = (sr & 0xC0) >> 6; - if ((bitmapColumn & 1) != 0) - sr <<= 2; - switch (pixelData) - { - case 0x00: pixel = backgroundColor0; break; - case 0x01: pixel = backgroundColor1; break; - case 0x02: pixel = backgroundColor2; break; - default: pixel = (displayC & 0x700) >> 8; break; - } - } - else - { - // standard 001 - pixelData = (sr & 0x80) >> 6; - sr <<= 1; - pixel = (pixelData != 0) ? (displayC >> 8) : backgroundColor0; - } - } - else if (!extraColorMode && bitmapMode & !multicolorMode) - { - // 010 - pixelData = (sr & 0x80) >> 6; - sr <<= 1; - pixel = (pixelData != 0) ? ((displayC >> 4) & 0xF) : (displayC & 0xF); - } - else if (!extraColorMode && bitmapMode & multicolorMode) - { - // 011 - pixelData = (sr & 0xC0) >> 6; - if ((bitmapColumn & 1) != 0) - sr <<= 2; - switch (pixelData) - { - case 0x00: pixel = backgroundColor0; break; - case 0x01: pixel = (displayC >> 4) & 0xF; break; - case 0x02: pixel = displayC & 0xF; break; - default: pixel = (displayC >> 8) & 0xF; break; - } - } - else if (extraColorMode && !bitmapMode & !multicolorMode) - { - // 100 - pixelData = (sr & 0x80) >> 6; - sr <<= 1; - if (pixelData != 0) - { - pixel = displayC >> 8; - } - else - { - switch ((displayC >> 6) & 0x3) - { - case 0x00: pixel = backgroundColor0; break; - case 0x01: pixel = backgroundColor1; break; - case 0x02: pixel = backgroundColor2; break; - default: pixel = backgroundColor3; break; - } - } - } - else if (extraColorMode && !bitmapMode & multicolorMode) - { - // 101 - pixelData = 0; - pixel = 0; - } - else if (extraColorMode && bitmapMode & !multicolorMode) - { - // 110 - pixelData = 0; - pixel = 0; - } - else - { - // 111 - pixelData = 0; - pixel = 0; - } - - // put the rendered pixel into the background buffer - pixelDataBuffer[pixelBackgroundBufferIndex] = pixelData; - pixelBackgroundBuffer[pixelBackgroundBufferIndex] = pixel; - pixelBackgroundBufferIndex++; - if (pixelBackgroundBufferIndex == pixelBackgroundBufferDelay) - pixelBackgroundBufferIndex = 0; - - // advance pixel buffer - pixelBufferIndex++; - if (pixelBufferIndex == pixelBufferDelay) - pixelBufferIndex = 0; - - rasterX++; - xOffset++; - bitmapColumn++; - } - } - } - // ------------------------------------ public bool ReadAECBuffer() { return pinAEC; } @@ -922,492 +358,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // ------------------------------------ - public byte Peek(int addr) - { - return ReadRegister((addr & 0x3F)); - } - - public void Poke(int addr, byte val) - { - WriteRegister((addr & 0x3F), val); - } - - public byte Read(int addr) - { - byte result; - addr &= 0x3F; - - switch (addr) - { - case 0x1E: - case 0x1F: - // reading clears these - result = ReadRegister(addr); - WriteRegister(addr, 0); - break; - default: - result = ReadRegister((addr & 0x3F)); - break; - } - return result; - } - - private byte ReadRegister(int addr) - { - byte result = 0xFF; //unused bit value - - switch (addr) - { - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0x08: - case 0x0A: - case 0x0C: - case 0x0E: - result = (byte)(sprites[addr >> 1].x & 0xFF); - break; - case 0x01: - case 0x03: - case 0x05: - case 0x07: - case 0x09: - case 0x0B: - case 0x0D: - case 0x0F: - result = (byte)(sprites[addr >> 1].y & 0xFF); - break; - case 0x10: - result = (byte)( - ((sprites[0].x >> 8) & 0x01) | - ((sprites[1].x >> 7) & 0x02) | - ((sprites[2].x >> 6) & 0x04) | - ((sprites[3].x >> 5) & 0x08) | - ((sprites[4].x >> 4) & 0x10) | - ((sprites[5].x >> 3) & 0x20) | - ((sprites[6].x >> 2) & 0x40) | - ((sprites[7].x >> 1) & 0x80) - ); - break; - case 0x11: - result = (byte)( - (yScroll & 0x7) | - (rowSelect ? 0x08 : 0x00) | - (displayEnable ? 0x10 : 0x00) | - (bitmapMode ? 0x20 : 0x00) | - (extraColorMode ? 0x40 : 0x00) | - ((rasterLine & 0x100) >> 1) - ); - break; - case 0x12: - result = (byte)(rasterLine & 0xFF); - break; - case 0x13: - result = (byte)(lightPenX & 0xFF); - break; - case 0x14: - result = (byte)(lightPenY & 0xFF); - break; - case 0x15: - result = (byte)( - (sprites[0].enable ? 0x01 : 0x00) | - (sprites[1].enable ? 0x02 : 0x00) | - (sprites[2].enable ? 0x04 : 0x00) | - (sprites[3].enable ? 0x08 : 0x00) | - (sprites[4].enable ? 0x10 : 0x00) | - (sprites[5].enable ? 0x20 : 0x00) | - (sprites[6].enable ? 0x40 : 0x00) | - (sprites[7].enable ? 0x80 : 0x00) - ); - break; - case 0x16: - result &= 0xC0; - result |= (byte)( - (xScroll & 0x7) | - (columnSelect ? 0x08 : 0x00) | - (multicolorMode ? 0x10 : 0x00) - ); - break; - case 0x17: - result = (byte)( - (sprites[0].yExpand ? 0x01 : 0x00) | - (sprites[1].yExpand ? 0x02 : 0x00) | - (sprites[2].yExpand ? 0x04 : 0x00) | - (sprites[3].yExpand ? 0x08 : 0x00) | - (sprites[4].yExpand ? 0x10 : 0x00) | - (sprites[5].yExpand ? 0x20 : 0x00) | - (sprites[6].yExpand ? 0x40 : 0x00) | - (sprites[7].yExpand ? 0x80 : 0x00) - ); - break; - case 0x18: - result &= 0x01; - result |= (byte)( - ((pointerVM & 0xF) << 4) | - ((pointerCB & 0x7) << 1) - ); - break; - case 0x19: - result &= 0x70; - result |= (byte)( - (intRaster ? 0x01 : 0x00) | - (intSpriteDataCollision ? 0x02 : 0x00) | - (intSpriteCollision ? 0x04 : 0x00) | - (intLightPen ? 0x08 : 0x00) | - (pinIRQ ? 0x00 : 0x80) - ); - break; - case 0x1A: - result &= 0xF0; - result |= (byte)( - (enableIntRaster ? 0x01 : 0x00) | - (enableIntSpriteDataCollision ? 0x02 : 0x00) | - (enableIntSpriteCollision ? 0x04 : 0x00) | - (enableIntLightPen ? 0x08 : 0x00) - ); - break; - case 0x1B: - result = (byte)( - (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) - ); - break; - case 0x1C: - result = (byte)( - (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) - ); - break; - case 0x1D: - result = (byte)( - (sprites[0].xExpand ? 0x01 : 0x00) | - (sprites[1].xExpand ? 0x02 : 0x00) | - (sprites[2].xExpand ? 0x04 : 0x00) | - (sprites[3].xExpand ? 0x08 : 0x00) | - (sprites[4].xExpand ? 0x10 : 0x00) | - (sprites[5].xExpand ? 0x20 : 0x00) | - (sprites[6].xExpand ? 0x40 : 0x00) | - (sprites[7].xExpand ? 0x80 : 0x00) - ); - break; - case 0x1E: - result = (byte)( - (sprites[0].collideSprite ? 0x01 : 0x00) | - (sprites[1].collideSprite ? 0x02 : 0x00) | - (sprites[2].collideSprite ? 0x04 : 0x00) | - (sprites[3].collideSprite ? 0x08 : 0x00) | - (sprites[4].collideSprite ? 0x10 : 0x00) | - (sprites[5].collideSprite ? 0x20 : 0x00) | - (sprites[6].collideSprite ? 0x40 : 0x00) | - (sprites[7].collideSprite ? 0x80 : 0x00) - ); - break; - case 0x1F: - result = (byte)( - (sprites[0].collideData ? 0x01 : 0x00) | - (sprites[1].collideData ? 0x02 : 0x00) | - (sprites[2].collideData ? 0x04 : 0x00) | - (sprites[3].collideData ? 0x08 : 0x00) | - (sprites[4].collideData ? 0x10 : 0x00) | - (sprites[5].collideData ? 0x20 : 0x00) | - (sprites[6].collideData ? 0x40 : 0x00) | - (sprites[7].collideData ? 0x80 : 0x00) - ); - break; - case 0x20: - result &= 0xF0; - result |= (byte)(borderColor & 0x0F); - break; - case 0x21: - result &= 0xF0; - result |= (byte)(backgroundColor0 & 0x0F); - break; - case 0x22: - result &= 0xF0; - result |= (byte)(backgroundColor1 & 0x0F); - break; - case 0x23: - result &= 0xF0; - result |= (byte)(backgroundColor2 & 0x0F); - break; - case 0x24: - result &= 0xF0; - result |= (byte)(backgroundColor3 & 0x0F); - break; - case 0x25: - result &= 0xF0; - result |= (byte)(spriteMulticolor0 & 0x0F); - break; - case 0x26: - result &= 0xF0; - result |= (byte)(spriteMulticolor1 & 0x0F); - break; - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - result &= 0xF0; - result |= (byte)(sprites[addr - 0x27].color & 0xF); - break; - default: - // not connected - break; - } - - return result; - } - - public void Write(int addr, byte val) - { - addr &= 0x3F; - switch (addr) - { - case 0x19: - // interrupts are cleared by writing a 1 - if ((val & 0x01) != 0) - intRaster = false; - if ((val & 0x02) != 0) - intSpriteDataCollision = false; - if ((val & 0x04) != 0) - intSpriteCollision = false; - if ((val & 0x08) != 0) - intLightPen = false; - UpdatePins(); - break; - case 0x1A: - WriteRegister(addr, val); - break; - case 0x1E: - case 0x1F: - // can't write to these - break; - 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: - // not connected - break; - default: - WriteRegister(addr, val); - break; - } - } - - private void WriteRegister(int addr, byte val) - { - switch (addr) - { - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0x08: - case 0x0A: - case 0x0C: - case 0x0E: - sprites[addr >> 1].x &= 0x100; - sprites[addr >> 1].x |= val; - break; - case 0x01: - case 0x03: - case 0x05: - case 0x07: - case 0x09: - case 0x0B: - case 0x0D: - case 0x0F: - sprites[addr >> 1].y = val; - break; - 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); - break; - case 0x11: - yScroll = (val & 0x07); - rowSelect = ((val & 0x08) != 0); - displayEnable = ((val & 0x10) != 0); - bitmapMode = ((val & 0x20) != 0); - extraColorMode = ((val & 0x40) != 0); - rasterInterruptLine &= 0xFF; - rasterInterruptLine |= (val & 0x80) << 1; - UpdateBorder(); - break; - case 0x12: - rasterInterruptLine &= 0x100; - rasterInterruptLine |= val; - break; - case 0x13: - lightPenX = val; - break; - case 0x14: - lightPenY = val; - break; - case 0x15: - sprites[0].enable = ((val & 0x01) != 0); - sprites[1].enable = ((val & 0x02) != 0); - sprites[2].enable = ((val & 0x04) != 0); - sprites[3].enable = ((val & 0x08) != 0); - sprites[4].enable = ((val & 0x10) != 0); - sprites[5].enable = ((val & 0x20) != 0); - sprites[6].enable = ((val & 0x40) != 0); - sprites[7].enable = ((val & 0x80) != 0); - break; - case 0x16: - xScroll = (val & 0x07); - columnSelect = ((val & 0x08) != 0); - multicolorMode = ((val & 0x10) != 0); - UpdateBorder(); - break; - case 0x17: - sprites[0].yExpand = ((val & 0x01) != 0); - sprites[1].yExpand = ((val & 0x02) != 0); - sprites[2].yExpand = ((val & 0x04) != 0); - sprites[3].yExpand = ((val & 0x08) != 0); - sprites[4].yExpand = ((val & 0x10) != 0); - sprites[5].yExpand = ((val & 0x20) != 0); - sprites[6].yExpand = ((val & 0x40) != 0); - sprites[7].yExpand = ((val & 0x80) != 0); - break; - case 0x18: - pointerVM = ((val >> 4) & 0xF); - pointerCB = ((val >> 1) & 0x7); - break; - case 0x19: - intRaster = ((val & 0x01) != 0); - intSpriteDataCollision = ((val & 0x02) != 0); - intSpriteCollision = ((val & 0x04) != 0); - intLightPen = ((val & 0x08) != 0); - UpdatePins(); - break; - case 0x1A: - enableIntRaster = ((val & 0x01) != 0); - enableIntSpriteDataCollision = ((val & 0x02) != 0); - enableIntSpriteCollision = ((val & 0x04) != 0); - enableIntLightPen = ((val & 0x08) != 0); - UpdatePins(); - break; - 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); - break; - 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); - break; - case 0x1D: - sprites[0].xExpand = ((val & 0x01) != 0); - sprites[1].xExpand = ((val & 0x02) != 0); - sprites[2].xExpand = ((val & 0x04) != 0); - sprites[3].xExpand = ((val & 0x08) != 0); - sprites[4].xExpand = ((val & 0x10) != 0); - sprites[5].xExpand = ((val & 0x20) != 0); - sprites[6].xExpand = ((val & 0x40) != 0); - sprites[7].xExpand = ((val & 0x80) != 0); - break; - case 0x1E: - sprites[0].collideSprite = ((val & 0x01) != 0); - sprites[1].collideSprite = ((val & 0x02) != 0); - sprites[2].collideSprite = ((val & 0x04) != 0); - sprites[3].collideSprite = ((val & 0x08) != 0); - sprites[4].collideSprite = ((val & 0x10) != 0); - sprites[5].collideSprite = ((val & 0x20) != 0); - sprites[6].collideSprite = ((val & 0x40) != 0); - sprites[7].collideSprite = ((val & 0x80) != 0); - break; - case 0x1F: - sprites[0].collideData = ((val & 0x01) != 0); - sprites[1].collideData = ((val & 0x02) != 0); - sprites[2].collideData = ((val & 0x04) != 0); - sprites[3].collideData = ((val & 0x08) != 0); - sprites[4].collideData = ((val & 0x10) != 0); - sprites[5].collideData = ((val & 0x20) != 0); - sprites[6].collideData = ((val & 0x40) != 0); - sprites[7].collideData = ((val & 0x80) != 0); - break; - case 0x20: - borderColor = (val & 0xF); - break; - case 0x21: - backgroundColor0 = (val & 0xF); - break; - case 0x22: - backgroundColor1 = (val & 0xF); - break; - case 0x23: - backgroundColor2 = (val & 0xF); - break; - case 0x24: - backgroundColor3 = (val & 0xF); - break; - case 0x25: - spriteMulticolor0 = (val & 0xF); - break; - case 0x26: - spriteMulticolor1 = (val & 0xF); - break; - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - sprites[addr - 0x27].color = (val & 0xF); - break; - default: - break; - } - } - // -------------------------- public void SyncState(Serializer ser)