diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs index 577b8224fb..0d2c6c3ebc 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Sid.cs @@ -641,15 +641,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public byte Peek(int addr) { - return 0; + return ReadRegister((ushort)(addr & 0x1F)); } public void Poke(int addr, byte val) { + WriteRegister((ushort)(addr & 0x1F), val); } public byte Read(ushort addr) { + addr &= 0x1F; byte result = 0x00; switch (addr) { @@ -694,60 +696,75 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS (envelopes[0].Release) ); break; - case 0x07: result = (byte)voices[0].FrequencyLo; break; - case 0x08: result = (byte)voices[0].FrequencyHi; break; - case 0x09: result = (byte)voices[0].PulseWidthLo; break; - case 0x0A: result = (byte)voices[0].PulseWidthHi; break; + case 0x07: result = (byte)voices[1].FrequencyLo; break; + case 0x08: result = (byte)voices[1].FrequencyHi; break; + case 0x09: result = (byte)voices[1].PulseWidthLo; break; + case 0x0A: result = (byte)voices[1].PulseWidthHi; break; case 0x0B: result = (byte)( - (envelopes[0].Gate ? 0x01 : 0x00) | - (voices[0].Sync ? 0x02 : 0x00) | - (voices[0].RingMod ? 0x04 : 0x00) | - (voices[0].Test ? 0x08 : 0x00) | - (byte)(voices[0].Waveform << 4) + (envelopes[1].Gate ? 0x01 : 0x00) | + (voices[1].Sync ? 0x02 : 0x00) | + (voices[1].RingMod ? 0x04 : 0x00) | + (voices[1].Test ? 0x08 : 0x00) | + (byte)(voices[1].Waveform << 4) ); break; case 0x0C: result = (byte)( - (envelopes[0].Attack << 4) | - (envelopes[0].Decay) + (envelopes[1].Attack << 4) | + (envelopes[1].Decay) ); break; case 0x0D: result = (byte)( - (envelopes[0].Sustain << 4) | - (envelopes[0].Release) + (envelopes[1].Sustain << 4) | + (envelopes[1].Release) ); break; - case 0x0E: result = (byte)voices[0].FrequencyLo; break; - case 0x0F: result = (byte)voices[0].FrequencyHi; break; - case 0x10: result = (byte)voices[0].PulseWidthLo; break; - case 0x11: result = (byte)voices[0].PulseWidthHi; break; + case 0x0E: result = (byte)voices[2].FrequencyLo; break; + case 0x0F: result = (byte)voices[2].FrequencyHi; break; + case 0x10: result = (byte)voices[2].PulseWidthLo; break; + case 0x11: result = (byte)voices[2].PulseWidthHi; break; case 0x12: result = (byte)( - (envelopes[0].Gate ? 0x01 : 0x00) | - (voices[0].Sync ? 0x02 : 0x00) | - (voices[0].RingMod ? 0x04 : 0x00) | - (voices[0].Test ? 0x08 : 0x00) | - (byte)(voices[0].Waveform << 4) + (envelopes[2].Gate ? 0x01 : 0x00) | + (voices[2].Sync ? 0x02 : 0x00) | + (voices[2].RingMod ? 0x04 : 0x00) | + (voices[2].Test ? 0x08 : 0x00) | + (byte)(voices[2].Waveform << 4) ); break; case 0x13: result = (byte)( - (envelopes[0].Attack << 4) | - (envelopes[0].Decay) + (envelopes[2].Attack << 4) | + (envelopes[2].Decay) ); break; case 0x14: result = (byte)( - (envelopes[0].Sustain << 4) | - (envelopes[0].Release) + (envelopes[2].Sustain << 4) | + (envelopes[2].Release) + ); + break; + case 0x15: result = (byte)(filterFrequency & 0x7); break; + case 0x16: result = (byte)((filterFrequency >> 3) & 0xFF); break; + case 0x17: + result = (byte)( + (filterEnable[0] ? 0x01 : 0x00) | + (filterEnable[1] ? 0x02 : 0x00) | + (filterEnable[2] ? 0x04 : 0x00) | + (byte)(filterResonance << 4) + ); + break; + case 0x18: + result = (byte)( + (byte)volume | + (filterSelectLoPass ? 0x10 : 0x00) | + (filterSelectBandPass ? 0x20 : 0x00) | + (filterSelectHiPass ? 0x40 : 0x00) | + (disableVoice3 ? 0x80 : 0x00) ); break; - case 0x15: break; - case 0x16: break; - case 0x17: break; - case 0x18: break; case 0x19: result = (byte)potX; break; case 0x1A: result = (byte)potY; break; case 0x1B: result = (byte)(voices[2].Oscillator >> 4); break; @@ -759,6 +776,22 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public void Write(ushort addr, byte val) { + addr &= 0x1F; + switch (addr) + { + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + // can't write to these + break; + default: + WriteRegister(addr, val); + break; + } } private void WriteRegister(ushort addr, byte val) diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs index 8bb2cddba0..b778840c15 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs @@ -20,10 +20,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS public uint mc; public uint mcbase; public bool multicolor; + public bool multicolorCrunch; public uint pointer; public bool priority; + public bool shiftEnable; public uint sr; public uint x; + public bool xCrunch; public bool xExpand; public uint y; public bool yCrunch; @@ -42,8 +45,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS multicolor = false; pointer = 0; priority = false; + shiftEnable = false; sr = 0; x = 0; + xCrunch = false; xExpand = false; y = 0; yCrunch = false; @@ -455,9 +460,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS { case 0x00: // fetch P - addr = (ushort)(0x1F8 | (pointerVM << 10) | cycleFetchSpriteIndex); + addr = (ushort)(0x3F8 | (pointerVM << 10) | cycleFetchSpriteIndex); bus = chips.pla.ReadVic(addr); sprites[cycleFetchSpriteIndex].pointer = bus; + sprites[cycleFetchSpriteIndex].shiftEnable = false; break; case 0x10: case 0x20: @@ -510,6 +516,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS Sprite spr = sprites[i]; if (spr.yCrunch) spr.mcbase += 2; + spr.shiftEnable = false; + spr.xCrunch = !spr.xExpand; } } if ((act & pipelineChkSprDisp) != 0) @@ -607,8 +615,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS borderOnMain = true; } - // render visible pixel + // recall pixel from buffer pixel = pixelBuffer[pixelBufferIndex]; + buf[bufOffset] = palette[pixel]; bufOffset++; if (bufOffset == bufLength) @@ -617,10 +626,55 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS // put the pixel from the background buffer into the main buffer pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; + // render sprite + uint pixelOwner = 8; + for (uint j = 0; j < 8; j++) + { + uint sprData; + uint 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 && pixelOwner >= 8) + { + pixel = sprPixel; + pixelOwner = j; + } + 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