commodore64: add sprites (no collision or priority yet)

This commit is contained in:
saxxonpike 2012-12-02 23:57:10 +00:00
parent 0907de61cc
commit 5fcf41ebbc
2 changed files with 120 additions and 33 deletions

View File

@ -641,15 +641,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public byte Peek(int addr) public byte Peek(int addr)
{ {
return 0; return ReadRegister((ushort)(addr & 0x1F));
} }
public void Poke(int addr, byte val) public void Poke(int addr, byte val)
{ {
WriteRegister((ushort)(addr & 0x1F), val);
} }
public byte Read(ushort addr) public byte Read(ushort addr)
{ {
addr &= 0x1F;
byte result = 0x00; byte result = 0x00;
switch (addr) switch (addr)
{ {
@ -694,60 +696,75 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
(envelopes[0].Release) (envelopes[0].Release)
); );
break; break;
case 0x07: result = (byte)voices[0].FrequencyLo; break; case 0x07: result = (byte)voices[1].FrequencyLo; break;
case 0x08: result = (byte)voices[0].FrequencyHi; break; case 0x08: result = (byte)voices[1].FrequencyHi; break;
case 0x09: result = (byte)voices[0].PulseWidthLo; break; case 0x09: result = (byte)voices[1].PulseWidthLo; break;
case 0x0A: result = (byte)voices[0].PulseWidthHi; break; case 0x0A: result = (byte)voices[1].PulseWidthHi; break;
case 0x0B: case 0x0B:
result = (byte)( result = (byte)(
(envelopes[0].Gate ? 0x01 : 0x00) | (envelopes[1].Gate ? 0x01 : 0x00) |
(voices[0].Sync ? 0x02 : 0x00) | (voices[1].Sync ? 0x02 : 0x00) |
(voices[0].RingMod ? 0x04 : 0x00) | (voices[1].RingMod ? 0x04 : 0x00) |
(voices[0].Test ? 0x08 : 0x00) | (voices[1].Test ? 0x08 : 0x00) |
(byte)(voices[0].Waveform << 4) (byte)(voices[1].Waveform << 4)
); );
break; break;
case 0x0C: case 0x0C:
result = (byte)( result = (byte)(
(envelopes[0].Attack << 4) | (envelopes[1].Attack << 4) |
(envelopes[0].Decay) (envelopes[1].Decay)
); );
break; break;
case 0x0D: case 0x0D:
result = (byte)( result = (byte)(
(envelopes[0].Sustain << 4) | (envelopes[1].Sustain << 4) |
(envelopes[0].Release) (envelopes[1].Release)
); );
break; break;
case 0x0E: result = (byte)voices[0].FrequencyLo; break; case 0x0E: result = (byte)voices[2].FrequencyLo; break;
case 0x0F: result = (byte)voices[0].FrequencyHi; break; case 0x0F: result = (byte)voices[2].FrequencyHi; break;
case 0x10: result = (byte)voices[0].PulseWidthLo; break; case 0x10: result = (byte)voices[2].PulseWidthLo; break;
case 0x11: result = (byte)voices[0].PulseWidthHi; break; case 0x11: result = (byte)voices[2].PulseWidthHi; break;
case 0x12: case 0x12:
result = (byte)( result = (byte)(
(envelopes[0].Gate ? 0x01 : 0x00) | (envelopes[2].Gate ? 0x01 : 0x00) |
(voices[0].Sync ? 0x02 : 0x00) | (voices[2].Sync ? 0x02 : 0x00) |
(voices[0].RingMod ? 0x04 : 0x00) | (voices[2].RingMod ? 0x04 : 0x00) |
(voices[0].Test ? 0x08 : 0x00) | (voices[2].Test ? 0x08 : 0x00) |
(byte)(voices[0].Waveform << 4) (byte)(voices[2].Waveform << 4)
); );
break; break;
case 0x13: case 0x13:
result = (byte)( result = (byte)(
(envelopes[0].Attack << 4) | (envelopes[2].Attack << 4) |
(envelopes[0].Decay) (envelopes[2].Decay)
); );
break; break;
case 0x14: case 0x14:
result = (byte)( result = (byte)(
(envelopes[0].Sustain << 4) | (envelopes[2].Sustain << 4) |
(envelopes[0].Release) (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; break;
case 0x15: break;
case 0x16: break;
case 0x17: break;
case 0x18: break;
case 0x19: result = (byte)potX; break; case 0x19: result = (byte)potX; break;
case 0x1A: result = (byte)potY; break; case 0x1A: result = (byte)potY; break;
case 0x1B: result = (byte)(voices[2].Oscillator >> 4); 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) 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) private void WriteRegister(ushort addr, byte val)

View File

@ -20,10 +20,13 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
public uint mc; public uint mc;
public uint mcbase; public uint mcbase;
public bool multicolor; public bool multicolor;
public bool multicolorCrunch;
public uint pointer; public uint pointer;
public bool priority; public bool priority;
public bool shiftEnable;
public uint sr; public uint sr;
public uint x; public uint x;
public bool xCrunch;
public bool xExpand; public bool xExpand;
public uint y; public uint y;
public bool yCrunch; public bool yCrunch;
@ -42,8 +45,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
multicolor = false; multicolor = false;
pointer = 0; pointer = 0;
priority = false; priority = false;
shiftEnable = false;
sr = 0; sr = 0;
x = 0; x = 0;
xCrunch = false;
xExpand = false; xExpand = false;
y = 0; y = 0;
yCrunch = false; yCrunch = false;
@ -455,9 +460,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
{ {
case 0x00: case 0x00:
// fetch P // fetch P
addr = (ushort)(0x1F8 | (pointerVM << 10) | cycleFetchSpriteIndex); addr = (ushort)(0x3F8 | (pointerVM << 10) | cycleFetchSpriteIndex);
bus = chips.pla.ReadVic(addr); bus = chips.pla.ReadVic(addr);
sprites[cycleFetchSpriteIndex].pointer = bus; sprites[cycleFetchSpriteIndex].pointer = bus;
sprites[cycleFetchSpriteIndex].shiftEnable = false;
break; break;
case 0x10: case 0x10:
case 0x20: case 0x20:
@ -510,6 +516,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
Sprite spr = sprites[i]; Sprite spr = sprites[i];
if (spr.yCrunch) if (spr.yCrunch)
spr.mcbase += 2; spr.mcbase += 2;
spr.shiftEnable = false;
spr.xCrunch = !spr.xExpand;
} }
} }
if ((act & pipelineChkSprDisp) != 0) if ((act & pipelineChkSprDisp) != 0)
@ -607,8 +615,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
borderOnMain = true; borderOnMain = true;
} }
// render visible pixel // recall pixel from buffer
pixel = pixelBuffer[pixelBufferIndex]; pixel = pixelBuffer[pixelBufferIndex];
buf[bufOffset] = palette[pixel]; buf[bufOffset] = palette[pixel];
bufOffset++; bufOffset++;
if (bufOffset == bufLength) if (bufOffset == bufLength)
@ -617,10 +626,55 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
// put the pixel from the background buffer into the main buffer // put the pixel from the background buffer into the main buffer
pixel = pixelBackgroundBuffer[pixelBackgroundBufferIndex]; 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 // border doesn't work with the background buffer
if (borderOnMain || borderOnVertical) if (borderOnMain || borderOnVertical)
pixel = borderColor; pixel = borderColor;
// store pixel in buffer
pixelBuffer[pixelBufferIndex] = pixel; pixelBuffer[pixelBufferIndex] = pixel;
// fill shift register // fill shift register