commodore64: added SID waveform generators (no sound output yet)
This commit is contained in:
parent
835084d812
commit
ee27ce7828
|
@ -5,6 +5,14 @@ using System.Text;
|
|||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public enum SidEnvelopeState
|
||||
{
|
||||
Disabled,
|
||||
Attack,
|
||||
Decay,
|
||||
Release
|
||||
}
|
||||
|
||||
public enum SidMode
|
||||
{
|
||||
Sid6581,
|
||||
|
@ -17,7 +25,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public bool BP;
|
||||
public bool D3;
|
||||
public int[] DCY = new int[3];
|
||||
public int ENV3;
|
||||
public int[] ENV = new int[3];
|
||||
public int[] F = new int[3];
|
||||
public int FC;
|
||||
public bool[] FILT = new bool[3];
|
||||
|
@ -26,7 +34,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public bool HP;
|
||||
public bool LP;
|
||||
public bool[] NOISE = new bool[3];
|
||||
public int OSC3;
|
||||
public int[] OSC = new int[3];
|
||||
public int POTX;
|
||||
public int POTY;
|
||||
public int[] PW = new int[3];
|
||||
|
@ -34,6 +42,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public int[] RLS = new int[3];
|
||||
public bool[] RMOD = new bool[3];
|
||||
public bool[] SAW = new bool[3];
|
||||
public int[] SR = new int[3];
|
||||
public bool[] SQU = new bool[3];
|
||||
public int[] STN = new int[3];
|
||||
public bool[] SYNC = new bool[3];
|
||||
|
@ -44,6 +53,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
public SidRegs()
|
||||
{
|
||||
// power on state
|
||||
SR[0] = 0x7FFFFF;
|
||||
SR[1] = 0x7FFFFF;
|
||||
SR[2] = 0x7FFFFF;
|
||||
}
|
||||
|
||||
public byte this[int addr]
|
||||
|
@ -131,10 +143,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
result = POTY;
|
||||
break;
|
||||
case 0x1B:
|
||||
result = OSC3;
|
||||
result = OSC[2] >> 4;
|
||||
break;
|
||||
case 0x1C:
|
||||
result = ENV3;
|
||||
result = ENV[2];
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
|
@ -234,10 +246,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
POTY = val;
|
||||
break;
|
||||
case 0x1B:
|
||||
OSC3 = val;
|
||||
OSC[2] = val << 4;
|
||||
break;
|
||||
case 0x1C:
|
||||
ENV3 = val;
|
||||
ENV[2] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -247,12 +259,28 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public class Sid
|
||||
{
|
||||
private int[] envRateIndex = {
|
||||
9, 32, 63, 95,
|
||||
149, 220, 267, 313,
|
||||
392, 977, 1954, 3126,
|
||||
3907, 11720, 19532, 31251
|
||||
};
|
||||
|
||||
private int[] syncIndex = { 2, 0, 1 };
|
||||
|
||||
public Func<int> ReadPotX;
|
||||
public Func<int> ReadPotY;
|
||||
|
||||
public int clock;
|
||||
public bool[] envEnable = new bool[3];
|
||||
public int[] envExpCounter = new int[3];
|
||||
public int[] envRate = new int[3];
|
||||
public int[] envRateCounter = new int[3];
|
||||
public SidEnvelopeState[] envState = new SidEnvelopeState[3];
|
||||
public bool[] gateLastCycle = new bool[3];
|
||||
public int output;
|
||||
public int potCycle;
|
||||
public SidRegs regs;
|
||||
public int[] waveClock = new int[3];
|
||||
|
||||
public Sid()
|
||||
{
|
||||
|
@ -273,13 +301,144 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
|
||||
public void PerformCycle()
|
||||
{
|
||||
output = 0;
|
||||
if (potCycle == 0)
|
||||
// accumulator is 24 bits
|
||||
clock = (clock + 1) & 0xFFFFFF;
|
||||
|
||||
ProcessVoice(0);
|
||||
ProcessVoice(1);
|
||||
ProcessVoice(2);
|
||||
|
||||
// query pots every 512 cycles
|
||||
if ((clock & 0x1FF) == 0x000)
|
||||
{
|
||||
regs.POTX = ReadPotX() & 0xFF;
|
||||
regs.POTY = ReadPotY() & 0xFF;
|
||||
}
|
||||
potCycle = (potCycle + 1) & 0x1FF;
|
||||
}
|
||||
|
||||
private void ProcessEnvelope(int index)
|
||||
{
|
||||
// envelope counter is 15 bits
|
||||
envRateCounter[index] &= 0x7FFF;
|
||||
|
||||
if (!gateLastCycle[index] && regs.GATE[index])
|
||||
{
|
||||
envState[index] = SidEnvelopeState.Attack;
|
||||
envEnable[index] = true;
|
||||
}
|
||||
else if (gateLastCycle[index] && !regs.GATE[index])
|
||||
{
|
||||
envState[index] = SidEnvelopeState.Release;
|
||||
}
|
||||
|
||||
if (envRateCounter[index] == envRate[index])
|
||||
{
|
||||
envExpCounter[index] = 0;
|
||||
if (envEnable[index])
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
gateLastCycle[index] = regs.GATE[index];
|
||||
}
|
||||
|
||||
private void ProcessShiftRegister(int index)
|
||||
{
|
||||
int newBit = ((regs.SR[index] >> 22) ^ (regs.SR[index] >> 17)) & 0x1;
|
||||
regs.SR[index] = ((regs.SR[index] << 1) | newBit) & 0x7FFFFF;
|
||||
}
|
||||
|
||||
private void ProcessVoice(int index)
|
||||
{
|
||||
int triOutput;
|
||||
int sawOutput;
|
||||
int squOutput;
|
||||
int noiseOutput;
|
||||
int finalOutput = 0xFFFFFF;
|
||||
bool outputEnabled = false;
|
||||
|
||||
// triangle waveform
|
||||
if (regs.TRI[index])
|
||||
{
|
||||
triOutput = waveClock[index] >> 12;
|
||||
if (regs.SYNC[index])
|
||||
triOutput ^= regs.OSC[syncIndex[index]] & 0x800;
|
||||
|
||||
if ((triOutput & 0x800) != 0x000)
|
||||
triOutput &= 0xFFF;
|
||||
|
||||
triOutput <<= 1;
|
||||
finalOutput &= triOutput;
|
||||
outputEnabled = true;
|
||||
}
|
||||
|
||||
// saw waveform
|
||||
if (regs.SAW[index])
|
||||
{
|
||||
sawOutput = waveClock[index] >> 12;
|
||||
finalOutput &= sawOutput;
|
||||
outputEnabled = true;
|
||||
}
|
||||
|
||||
// square waveform
|
||||
if (regs.SQU[index])
|
||||
{
|
||||
if (regs.TEST[index])
|
||||
{
|
||||
squOutput = 0xFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regs.PW[index] >= (waveClock[index] >> 12))
|
||||
squOutput = 0xFFF;
|
||||
else
|
||||
squOutput = 0x000;
|
||||
}
|
||||
finalOutput &= squOutput;
|
||||
outputEnabled = true;
|
||||
}
|
||||
|
||||
// noise waveform
|
||||
if (regs.NOISE[index])
|
||||
{
|
||||
int sr = regs.SR[index];
|
||||
noiseOutput = sr & 0x100000 >> 9;
|
||||
noiseOutput |= sr & 0x040000 >> 8;
|
||||
noiseOutput |= sr & 0x004000 >> 5;
|
||||
noiseOutput |= sr & 0x000800 >> 3;
|
||||
noiseOutput |= sr & 0x000200 >> 2;
|
||||
noiseOutput |= sr & 0x000020 << 1;
|
||||
noiseOutput |= sr & 0x000004 << 3;
|
||||
noiseOutput |= sr & 0x000001 << 4;
|
||||
finalOutput &= noiseOutput;
|
||||
outputEnabled = true;
|
||||
}
|
||||
|
||||
// test bit resets the oscillator and silences output
|
||||
if (regs.TEST[index])
|
||||
{
|
||||
waveClock[index] = 0x000000;
|
||||
outputEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// shift register for generating noise
|
||||
if ((waveClock[index] & 0x7FFFF) == 0x00000)
|
||||
ProcessShiftRegister(index);
|
||||
|
||||
// increment wave clock
|
||||
waveClock[index] = (waveClock[index] + regs.F[index]) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
// process the envelope generator
|
||||
//ProcessEnvelope(index);
|
||||
|
||||
// write to internal reg
|
||||
if (outputEnabled)
|
||||
regs.OSC[index] = finalOutput;
|
||||
else
|
||||
regs.OSC[index] = 0x000000;
|
||||
}
|
||||
|
||||
public byte Read(ushort addr)
|
||||
|
@ -298,6 +457,22 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateEnvelopeRateCounter(int index)
|
||||
{
|
||||
switch (envState[index])
|
||||
{
|
||||
case SidEnvelopeState.Attack:
|
||||
envRate[index] = envRateIndex[regs.ATK[index]];
|
||||
break;
|
||||
case SidEnvelopeState.Decay:
|
||||
envRate[index] = envRateIndex[regs.DCY[index]];
|
||||
break;
|
||||
case SidEnvelopeState.Release:
|
||||
envRate[index] = envRateIndex[regs.RLS[index]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(ushort addr, byte val)
|
||||
{
|
||||
addr &= 0x1F;
|
||||
|
|
|
@ -827,7 +827,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
if (!idle && cycle >= 16 && cycle < 56)
|
||||
{
|
||||
// todo: implement XSCROLL properly
|
||||
if (regs.XSCROLL == (rasterOffsetX & 0x7))
|
||||
// comparing to (rasterOffsetX & 0x7) seems to align
|
||||
// properly but smooth scrolling is not possible
|
||||
// comparing to i works but then the screen
|
||||
// is not aligned anymore...
|
||||
if (regs.XSCROLL == i)
|
||||
{
|
||||
characterColumn = 0;
|
||||
characterData = characterMemory[regs.VMLI];
|
||||
|
|
Loading…
Reference in New Issue