Commodore64: Split Sid classes into three files, up from one. Fixed border timing in TimingBuilder. Renamed Sync class to SaveState.
This commit is contained in:
parent
ba25e7045f
commit
6fdc7284bd
|
@ -155,7 +155,8 @@
|
||||||
<Compile Include="Computers\Commodore64\MOS\Port.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Port.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\SerialPort.cs" />
|
<Compile Include="Computers\Commodore64\MOS\SerialPort.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Sid.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Sid.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Timer.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Sid.Envelope.cs" />
|
||||||
|
<Compile Include="Computers\Commodore64\MOS\Sid.Voice.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\UserPort.cs" />
|
<Compile Include="Computers\Commodore64\MOS\UserPort.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.Parse.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.Parse.cs" />
|
||||||
|
@ -165,7 +166,7 @@
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.State.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.State.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.TimingBuilder.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.TimingBuilder.cs" />
|
||||||
<Compile Include="Computers\Commodore64\MOS\Vic.VideoProvider.cs" />
|
<Compile Include="Computers\Commodore64\MOS\Vic.VideoProvider.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Sync.cs" />
|
<Compile Include="Computers\Commodore64\SaveState.cs" />
|
||||||
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />
|
<Compile Include="Computers\Commodore64\Tape\VIC1530.cs" />
|
||||||
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />
|
<Compile Include="Consoles\Atari\2600\Atari2600.cs" />
|
||||||
<Compile Include="Consoles\Atari\2600\Atari2600.Core.cs" />
|
<Compile Include="Consoles\Atari\2600\Atari2600.Core.cs" />
|
||||||
|
|
|
@ -197,7 +197,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
ser.BeginSection("motherboard");
|
ser.BeginSection("motherboard");
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
ser.EndSection();
|
ser.EndSection();
|
||||||
|
|
||||||
ser.BeginSection("cartridge");
|
ser.BeginSection("cartridge");
|
||||||
|
|
|
@ -236,7 +236,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridge
|
||||||
|
|
||||||
public virtual void SyncState(Serializer ser)
|
public virtual void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Valid
|
public bool Valid
|
||||||
|
|
|
@ -14,6 +14,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public bool OutputData() { return Data; }
|
public bool OutputData() { return Data; }
|
||||||
public bool OutputSense() { return Sense; }
|
public bool OutputSense() { return Sense; }
|
||||||
virtual public bool Sense { get { return true; } }
|
virtual public bool Sense { get { return true; } }
|
||||||
virtual public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
virtual public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public bool SP { get { return true; } }
|
public bool SP { get { return true; } }
|
||||||
|
|
||||||
public void Clock() { }
|
public void Clock() { }
|
||||||
public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public bool Port5 { get { return (Port & 0x20) != 0; } }
|
public bool Port5 { get { return (Port & 0x20) != 0; } }
|
||||||
public bool Port6 { get { return (Port & 0x40) != 0; } }
|
public bool Port6 { get { return (Port & 0x40) != 0; } }
|
||||||
public bool Port7 { get { return (Port & 0x80) != 0; } }
|
public bool Port7 { get { return (Port & 0x80) != 0; } }
|
||||||
public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public bool OutputGame() { return Game; }
|
public bool OutputGame() { return Game; }
|
||||||
public bool OutputIRQ() { return IRQ; }
|
public bool OutputIRQ() { return IRQ; }
|
||||||
public bool OutputNMI() { return NMI; }
|
public bool OutputNMI() { return NMI; }
|
||||||
virtual public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
virtual public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public int OutputData() { return Data; }
|
public int OutputData() { return Data; }
|
||||||
public int OutputPot() { return Pot; }
|
public int OutputPot() { return Pot; }
|
||||||
virtual public int Pot { get { return 0xFF; } }
|
virtual public int Pot { get { return 0xFF; } }
|
||||||
virtual public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
virtual public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public int OutputRow() { return Row; }
|
public int OutputRow() { return Row; }
|
||||||
virtual public bool Restore { get { return true; } }
|
virtual public bool Restore { get { return true; } }
|
||||||
virtual public int Row { get { return 0xFF; } }
|
virtual public int Row { get { return 0xFF; } }
|
||||||
virtual public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
virtual public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
memory[addr & addressMask] = val & dataMask;
|
memory[addr & addressMask] = val & dataMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
return memory[addr & addressMask];
|
return memory[addr & addressMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.Experimental.Chips.Internals
|
||||||
public bool OutputData() { return Data; }
|
public bool OutputData() { return Data; }
|
||||||
public bool OutputSRQ() { return SRQ; }
|
public bool OutputSRQ() { return SRQ; }
|
||||||
virtual public bool SRQ { get { return true; } }
|
virtual public bool SRQ { get { return true; } }
|
||||||
virtual public void SyncState(Serializer ser) { Sync.SyncObject(ser, this); }
|
virtual public void SyncState(Serializer ser) { SaveState.SyncObject(ser, this); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using BizHawk.Emulation.Computers.Commodore64.Cartridge;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
public class CartridgePort
|
sealed public class CartridgePort
|
||||||
{
|
{
|
||||||
public Func<bool> ReadIRQ;
|
public Func<bool> ReadIRQ;
|
||||||
public Func<bool> ReadNMI;
|
public Func<bool> ReadNMI;
|
||||||
|
@ -80,7 +80,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,19 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadDataInputBuffer()
|
virtual public bool ReadDataInputBuffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadSenseBuffer()
|
virtual public bool ReadSenseBuffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(int addr, byte val)
|
public void Write(int addr, byte val)
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(int addr, byte val)
|
public void Write(int addr, byte val)
|
||||||
|
|
|
@ -142,7 +142,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
cpu.SyncState(ser);
|
cpu.SyncState(ser);
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(ushort addr, byte val)
|
public void Write(ushort addr, byte val)
|
||||||
|
|
|
@ -546,7 +546,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(int addr, byte val)
|
public void Write(int addr, byte val)
|
||||||
|
|
|
@ -282,7 +282,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte VicRead(int addr)
|
public byte VicRead(int addr)
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
// the functions on this port are at the point of
|
// the functions on this port are at the point of
|
||||||
// view of an external device.
|
// view of an external device.
|
||||||
|
|
||||||
public class SerialPort
|
sealed public class SerialPort
|
||||||
{
|
{
|
||||||
public Func<bool> ReadAtnOut;
|
public Func<bool> ReadAtnOut;
|
||||||
public Func<bool> ReadClockOut;
|
public Func<bool> ReadClockOut;
|
||||||
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteClockIn()
|
public bool WriteClockIn()
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
{
|
||||||
|
sealed public partial class Sid
|
||||||
|
{
|
||||||
|
sealed class Envelope
|
||||||
|
{
|
||||||
|
const int stateAttack = 0;
|
||||||
|
const int stateDecay = 1;
|
||||||
|
const int stateRelease = 2;
|
||||||
|
|
||||||
|
int attack;
|
||||||
|
int decay;
|
||||||
|
bool delay;
|
||||||
|
int envCounter;
|
||||||
|
int expCounter;
|
||||||
|
int expPeriod;
|
||||||
|
bool freeze;
|
||||||
|
int lfsr;
|
||||||
|
bool gate;
|
||||||
|
int rate;
|
||||||
|
int release;
|
||||||
|
int state;
|
||||||
|
int sustain;
|
||||||
|
|
||||||
|
static int[] adsrTable = new int[]
|
||||||
|
{
|
||||||
|
0x7F00, 0x0006, 0x003C, 0x0330,
|
||||||
|
0x20C0, 0x6755, 0x3800, 0x500E,
|
||||||
|
0x1212, 0x0222, 0x1848, 0x59B8,
|
||||||
|
0x3840, 0x77E2, 0x7625, 0x0A93
|
||||||
|
};
|
||||||
|
|
||||||
|
static int[] expCounterTable = new int[]
|
||||||
|
{
|
||||||
|
0xFF, 0x5D, 0x36, 0x1A, 0x0E, 0x06, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static int[] expPeriodTable = new int[]
|
||||||
|
{
|
||||||
|
0x01, 0x02, 0x04, 0x08, 0x10, 0x1E, 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
static int[] sustainTable = new int[]
|
||||||
|
{
|
||||||
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||||
|
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
public Envelope()
|
||||||
|
{
|
||||||
|
HardReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecutePhase2()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
if (!delay)
|
||||||
|
{
|
||||||
|
envCounter--;
|
||||||
|
delay = true;
|
||||||
|
UpdateExpCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lfsr != rate)
|
||||||
|
{
|
||||||
|
int feedback = ((lfsr >> 14) ^ (lfsr >> 13)) & 0x1;
|
||||||
|
lfsr = ((lfsr << 1) & 0x7FFF) | feedback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lfsr = 0x7FFF;
|
||||||
|
|
||||||
|
if (state == stateAttack || ++expCounter == expPeriod)
|
||||||
|
{
|
||||||
|
expCounter = 0;
|
||||||
|
if (freeze)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case stateAttack:
|
||||||
|
envCounter++;
|
||||||
|
if (envCounter == 0xFF)
|
||||||
|
{
|
||||||
|
state = stateDecay;
|
||||||
|
rate = adsrTable[decay];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case stateDecay:
|
||||||
|
if (envCounter == sustainTable[sustain])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (expPeriod != 1)
|
||||||
|
{
|
||||||
|
delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
envCounter--;
|
||||||
|
break;
|
||||||
|
case stateRelease:
|
||||||
|
if (expPeriod != 1)
|
||||||
|
{
|
||||||
|
delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
envCounter--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
envCounter &= 0xFF;
|
||||||
|
UpdateExpCounter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HardReset()
|
||||||
|
{
|
||||||
|
attack = 0;
|
||||||
|
decay = 0;
|
||||||
|
delay = true;
|
||||||
|
envCounter = 0;
|
||||||
|
expCounter = 0;
|
||||||
|
expPeriod = expPeriodTable[0];
|
||||||
|
freeze = false;
|
||||||
|
gate = false;
|
||||||
|
lfsr = 0x7FFF;
|
||||||
|
rate = adsrTable[release];
|
||||||
|
release = 0;
|
||||||
|
state = stateRelease;
|
||||||
|
sustain = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateExpCounter()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (envCounter == expCounterTable[i])
|
||||||
|
expPeriod = expPeriodTable[i];
|
||||||
|
}
|
||||||
|
if (envCounter == 0)
|
||||||
|
freeze = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
public int Attack
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return attack;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
attack = (value & 0xF);
|
||||||
|
if (state == stateAttack)
|
||||||
|
rate = adsrTable[attack];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Decay
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return decay;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
decay = (value & 0xF);
|
||||||
|
if (state == stateDecay)
|
||||||
|
rate = adsrTable[decay];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Gate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return gate;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
bool nextGate = value;
|
||||||
|
if (nextGate && !gate)
|
||||||
|
{
|
||||||
|
state = stateAttack;
|
||||||
|
rate = adsrTable[attack];
|
||||||
|
delay = true;
|
||||||
|
freeze = false;
|
||||||
|
}
|
||||||
|
else if (!nextGate && gate)
|
||||||
|
{
|
||||||
|
state = stateRelease;
|
||||||
|
rate = adsrTable[release];
|
||||||
|
}
|
||||||
|
gate = nextGate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Level
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return envCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Release
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
release = (value & 0xF);
|
||||||
|
if (state == stateRelease)
|
||||||
|
rate = adsrTable[release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Sustain
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sustain;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sustain = (value & 0xF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
public void SyncState(Serializer ser)
|
||||||
|
{
|
||||||
|
SaveState.SyncObject(ser, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,344 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
{
|
||||||
|
sealed public partial class Sid
|
||||||
|
{
|
||||||
|
sealed class Voice
|
||||||
|
{
|
||||||
|
int accBits;
|
||||||
|
int accNext;
|
||||||
|
int accumulator;
|
||||||
|
bool controlTestPrev;
|
||||||
|
int controlWavePrev;
|
||||||
|
int delay;
|
||||||
|
int floatOutputTTL;
|
||||||
|
int frequency;
|
||||||
|
bool msbRising;
|
||||||
|
int noise;
|
||||||
|
int noNoise;
|
||||||
|
int noNoiseOrNoise;
|
||||||
|
int noPulse;
|
||||||
|
int output;
|
||||||
|
int pulse;
|
||||||
|
int pulseWidth;
|
||||||
|
bool ringMod;
|
||||||
|
int ringMsbMask;
|
||||||
|
int shiftRegister;
|
||||||
|
int shiftRegisterReset;
|
||||||
|
bool sync;
|
||||||
|
bool test;
|
||||||
|
int[] wave;
|
||||||
|
int waveform;
|
||||||
|
int waveformIndex;
|
||||||
|
int[][] waveTable;
|
||||||
|
|
||||||
|
public Voice(int[][] newWaveTable)
|
||||||
|
{
|
||||||
|
waveTable = newWaveTable;
|
||||||
|
HardReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HardReset()
|
||||||
|
{
|
||||||
|
accumulator = 0;
|
||||||
|
delay = 0;
|
||||||
|
floatOutputTTL = 0;
|
||||||
|
frequency = 0;
|
||||||
|
msbRising = false;
|
||||||
|
noNoise = 0xFFF;
|
||||||
|
noPulse = 0xFFF;
|
||||||
|
output = 0x000;
|
||||||
|
pulse = 0xFFF;
|
||||||
|
pulseWidth = 0;
|
||||||
|
ringMsbMask = 0;
|
||||||
|
sync = false;
|
||||||
|
test = false;
|
||||||
|
wave = waveTable[0];
|
||||||
|
waveform = 0;
|
||||||
|
|
||||||
|
ResetShiftReg();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecutePhase2()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
if (test)
|
||||||
|
{
|
||||||
|
if (shiftRegisterReset != 0 && --shiftRegisterReset == 0)
|
||||||
|
{
|
||||||
|
ResetShiftReg();
|
||||||
|
}
|
||||||
|
pulse = 0xFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
accNext = (accumulator + frequency) & 0xFFFFFF;
|
||||||
|
accBits = ~accumulator & accNext;
|
||||||
|
accumulator = accNext;
|
||||||
|
msbRising = ((accBits & 0x800000) != 0);
|
||||||
|
|
||||||
|
if ((accBits & 0x080000) != 0)
|
||||||
|
delay = 2;
|
||||||
|
else if (delay != 0 && --delay == 0)
|
||||||
|
ClockShiftReg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
private void ClockShiftReg()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
shiftRegister = ((shiftRegister << 1) |
|
||||||
|
(((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1)
|
||||||
|
) & 0x7FFFFF;
|
||||||
|
SetNoise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetShiftReg()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
shiftRegister = 0x7FFFFF;
|
||||||
|
shiftRegisterReset = 0;
|
||||||
|
SetNoise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetNoise()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
noise =
|
||||||
|
((shiftRegister & 0x100000) >> 9) |
|
||||||
|
((shiftRegister & 0x040000) >> 8) |
|
||||||
|
((shiftRegister & 0x004000) >> 5) |
|
||||||
|
((shiftRegister & 0x000800) >> 3) |
|
||||||
|
((shiftRegister & 0x000200) >> 2) |
|
||||||
|
((shiftRegister & 0x000020) << 1) |
|
||||||
|
((shiftRegister & 0x000004) << 3) |
|
||||||
|
((shiftRegister & 0x000001) << 4);
|
||||||
|
noNoiseOrNoise = noNoise | noise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteShiftReg()
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
output &=
|
||||||
|
0xBB5DA |
|
||||||
|
((output & 0x800) << 9) |
|
||||||
|
((output & 0x400) << 8) |
|
||||||
|
((output & 0x200) << 5) |
|
||||||
|
((output & 0x100) << 3) |
|
||||||
|
((output & 0x040) >> 1) |
|
||||||
|
((output & 0x020) >> 3) |
|
||||||
|
((output & 0x010) >> 4);
|
||||||
|
noise &= output;
|
||||||
|
noNoiseOrNoise = noNoise | noise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
public int Control
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
controlWavePrev = waveform;
|
||||||
|
controlTestPrev = test;
|
||||||
|
|
||||||
|
sync = ((value & 0x02) != 0);
|
||||||
|
ringMod = ((value & 0x04) != 0);
|
||||||
|
test = ((value & 0x08) != 0);
|
||||||
|
waveform = (value >> 4) & 0x0F;
|
||||||
|
wave = waveTable[waveform & 0x07];
|
||||||
|
ringMsbMask = ((~value >> 5) & (value >> 2) & 0x1) << 23;
|
||||||
|
noNoise = ((waveform & 0x8) != 0) ? 0x000 : 0xFFF;
|
||||||
|
noNoiseOrNoise = noNoise | noise;
|
||||||
|
noPulse = ((waveform & 0x4) != 0) ? 0x000 : 0xFFF;
|
||||||
|
|
||||||
|
if (!controlTestPrev && test)
|
||||||
|
{
|
||||||
|
accumulator = 0;
|
||||||
|
delay = 0;
|
||||||
|
shiftRegisterReset = 0x8000;
|
||||||
|
}
|
||||||
|
else if (controlTestPrev && !test)
|
||||||
|
{
|
||||||
|
shiftRegister = ((shiftRegister << 1) |
|
||||||
|
((~shiftRegister >> 17) & 0x1)
|
||||||
|
) & 0x7FFFFF;
|
||||||
|
SetNoise();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waveform == 0 && controlWavePrev != 0)
|
||||||
|
floatOutputTTL = 0x28000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Frequency
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
frequency = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int FrequencyLo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (frequency & 0xFF);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
frequency &= 0xFF00;
|
||||||
|
frequency |= value & 0x00FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int FrequencyHi
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (frequency >> 8);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
frequency &= 0x00FF;
|
||||||
|
frequency |= (value & 0x00FF) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Oscillator
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Output(Voice ringModSource)
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
if (waveform != 0)
|
||||||
|
{
|
||||||
|
waveformIndex = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12;
|
||||||
|
output = wave[waveformIndex] & (noPulse | pulse) & noNoiseOrNoise;
|
||||||
|
if (waveform > 8)
|
||||||
|
WriteShiftReg();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (floatOutputTTL != 0 && --floatOutputTTL == 0)
|
||||||
|
output = 0x000;
|
||||||
|
}
|
||||||
|
pulse = ((accumulator >> 12) >= pulseWidth) ? 0xFFF : 0x000;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PulseWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return pulseWidth;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pulseWidth = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PulseWidthLo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (pulseWidth & 0xFF);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pulseWidth &= 0x0F00;
|
||||||
|
pulseWidth |= value & 0x00FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PulseWidthHi
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (pulseWidth >> 8);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
pulseWidth &= 0x00FF;
|
||||||
|
pulseWidth |= (value & 0x000F) << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RingMod
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ringMod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Sync
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sync;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Synchronize(Voice target, Voice source)
|
||||||
|
{
|
||||||
|
if (msbRising && target.sync && !(sync && source.msbRising))
|
||||||
|
target.accumulator = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Test
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Waveform
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return waveform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
public void SyncState(Serializer ser)
|
||||||
|
{
|
||||||
|
SaveState.SyncObject(ser, this);
|
||||||
|
|
||||||
|
if (ser.IsReader)
|
||||||
|
wave = waveTable[waveform];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,579 +6,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
sealed class Envelope
|
|
||||||
{
|
|
||||||
const int stateAttack = 0;
|
|
||||||
const int stateDecay = 1;
|
|
||||||
const int stateRelease = 2;
|
|
||||||
|
|
||||||
int attack;
|
|
||||||
int decay;
|
|
||||||
bool delay;
|
|
||||||
int envCounter;
|
|
||||||
int expCounter;
|
|
||||||
int expPeriod;
|
|
||||||
bool freeze;
|
|
||||||
int lfsr;
|
|
||||||
bool gate;
|
|
||||||
int rate;
|
|
||||||
int release;
|
|
||||||
int state;
|
|
||||||
int sustain;
|
|
||||||
|
|
||||||
static int[] adsrTable = new int[]
|
|
||||||
{
|
|
||||||
0x7F00, 0x0006, 0x003C, 0x0330,
|
|
||||||
0x20C0, 0x6755, 0x3800, 0x500E,
|
|
||||||
0x1212, 0x0222, 0x1848, 0x59B8,
|
|
||||||
0x3840, 0x77E2, 0x7625, 0x0A93
|
|
||||||
};
|
|
||||||
|
|
||||||
static int[] expCounterTable = new int[]
|
|
||||||
{
|
|
||||||
0xFF, 0x5D, 0x36, 0x1A, 0x0E, 0x06, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static int[] expPeriodTable = new int[]
|
|
||||||
{
|
|
||||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x1E, 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
static int[] sustainTable = new int[]
|
|
||||||
{
|
|
||||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
||||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
|
||||||
};
|
|
||||||
|
|
||||||
public Envelope()
|
|
||||||
{
|
|
||||||
HardReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ExecutePhase2()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
if (!delay)
|
|
||||||
{
|
|
||||||
envCounter--;
|
|
||||||
delay = true;
|
|
||||||
UpdateExpCounter();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lfsr != rate)
|
|
||||||
{
|
|
||||||
int feedback = ((lfsr >> 14) ^ (lfsr >> 13)) & 0x1;
|
|
||||||
lfsr = ((lfsr << 1) & 0x7FFF) | feedback;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lfsr = 0x7FFF;
|
|
||||||
|
|
||||||
if (state == stateAttack || ++expCounter == expPeriod)
|
|
||||||
{
|
|
||||||
expCounter = 0;
|
|
||||||
if (freeze)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case stateAttack:
|
|
||||||
envCounter++;
|
|
||||||
if (envCounter == 0xFF)
|
|
||||||
{
|
|
||||||
state = stateDecay;
|
|
||||||
rate = adsrTable[decay];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case stateDecay:
|
|
||||||
if (envCounter == sustainTable[sustain])
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (expPeriod != 1)
|
|
||||||
{
|
|
||||||
delay = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
envCounter--;
|
|
||||||
break;
|
|
||||||
case stateRelease:
|
|
||||||
if (expPeriod != 1)
|
|
||||||
{
|
|
||||||
delay = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
envCounter--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
envCounter &= 0xFF;
|
|
||||||
UpdateExpCounter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HardReset()
|
|
||||||
{
|
|
||||||
attack = 0;
|
|
||||||
decay = 0;
|
|
||||||
delay = true;
|
|
||||||
envCounter = 0;
|
|
||||||
expCounter = 0;
|
|
||||||
expPeriod = expPeriodTable[0];
|
|
||||||
freeze = false;
|
|
||||||
gate = false;
|
|
||||||
lfsr = 0x7FFF;
|
|
||||||
rate = adsrTable[release];
|
|
||||||
release = 0;
|
|
||||||
state = stateRelease;
|
|
||||||
sustain = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateExpCounter()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 7; i++)
|
|
||||||
{
|
|
||||||
if (envCounter == expCounterTable[i])
|
|
||||||
expPeriod = expPeriodTable[i];
|
|
||||||
}
|
|
||||||
if (envCounter == 0)
|
|
||||||
freeze = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
public int Attack
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return attack;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
attack = (value & 0xF);
|
|
||||||
if (state == stateAttack)
|
|
||||||
rate = adsrTable[attack];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Decay
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return decay;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
decay = (value & 0xF);
|
|
||||||
if (state == stateDecay)
|
|
||||||
rate = adsrTable[decay];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Gate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return gate;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
bool nextGate = value;
|
|
||||||
if (nextGate && !gate)
|
|
||||||
{
|
|
||||||
state = stateAttack;
|
|
||||||
rate = adsrTable[attack];
|
|
||||||
delay = true;
|
|
||||||
freeze = false;
|
|
||||||
}
|
|
||||||
else if (!nextGate && gate)
|
|
||||||
{
|
|
||||||
state = stateRelease;
|
|
||||||
rate = adsrTable[release];
|
|
||||||
}
|
|
||||||
gate = nextGate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Level
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return envCounter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Release
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return release;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
release = (value & 0xF);
|
|
||||||
if (state == stateRelease)
|
|
||||||
rate = adsrTable[release];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Sustain
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return sustain;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
sustain = (value & 0xF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
|
||||||
{
|
|
||||||
Sync.SyncObject(ser, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Voice
|
|
||||||
{
|
|
||||||
int accBits;
|
|
||||||
int accNext;
|
|
||||||
int accumulator;
|
|
||||||
bool controlTestPrev;
|
|
||||||
int controlWavePrev;
|
|
||||||
int delay;
|
|
||||||
int floatOutputTTL;
|
|
||||||
int frequency;
|
|
||||||
bool msbRising;
|
|
||||||
int noise;
|
|
||||||
int noNoise;
|
|
||||||
int noNoiseOrNoise;
|
|
||||||
int noPulse;
|
|
||||||
int output;
|
|
||||||
int pulse;
|
|
||||||
int pulseWidth;
|
|
||||||
bool ringMod;
|
|
||||||
int ringMsbMask;
|
|
||||||
int shiftRegister;
|
|
||||||
int shiftRegisterReset;
|
|
||||||
bool sync;
|
|
||||||
bool test;
|
|
||||||
int[] wave;
|
|
||||||
int waveform;
|
|
||||||
int waveformIndex;
|
|
||||||
int[][] waveTable;
|
|
||||||
|
|
||||||
public Voice(int[][] newWaveTable)
|
|
||||||
{
|
|
||||||
waveTable = newWaveTable;
|
|
||||||
HardReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HardReset()
|
|
||||||
{
|
|
||||||
accumulator = 0;
|
|
||||||
delay = 0;
|
|
||||||
floatOutputTTL = 0;
|
|
||||||
frequency = 0;
|
|
||||||
msbRising = false;
|
|
||||||
noNoise = 0xFFF;
|
|
||||||
noPulse = 0xFFF;
|
|
||||||
output = 0x000;
|
|
||||||
pulse = 0xFFF;
|
|
||||||
pulseWidth = 0;
|
|
||||||
ringMsbMask = 0;
|
|
||||||
sync = false;
|
|
||||||
test = false;
|
|
||||||
wave = waveTable[0];
|
|
||||||
waveform = 0;
|
|
||||||
|
|
||||||
ResetShiftReg();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ExecutePhase2()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
if (test)
|
|
||||||
{
|
|
||||||
if (shiftRegisterReset != 0 && --shiftRegisterReset == 0)
|
|
||||||
{
|
|
||||||
ResetShiftReg();
|
|
||||||
}
|
|
||||||
pulse = 0xFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
accNext = (accumulator + frequency) & 0xFFFFFF;
|
|
||||||
accBits = ~accumulator & accNext;
|
|
||||||
accumulator = accNext;
|
|
||||||
msbRising = ((accBits & 0x800000) != 0);
|
|
||||||
|
|
||||||
if ((accBits & 0x080000) != 0)
|
|
||||||
delay = 2;
|
|
||||||
else if (delay != 0 && --delay == 0)
|
|
||||||
ClockShiftReg();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
private void ClockShiftReg()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
shiftRegister = ((shiftRegister << 1) |
|
|
||||||
(((shiftRegister >> 22) ^ (shiftRegister >> 17)) & 0x1)
|
|
||||||
) & 0x7FFFFF;
|
|
||||||
SetNoise();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetShiftReg()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
shiftRegister = 0x7FFFFF;
|
|
||||||
shiftRegisterReset = 0;
|
|
||||||
SetNoise();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetNoise()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
noise =
|
|
||||||
((shiftRegister & 0x100000) >> 9) |
|
|
||||||
((shiftRegister & 0x040000) >> 8) |
|
|
||||||
((shiftRegister & 0x004000) >> 5) |
|
|
||||||
((shiftRegister & 0x000800) >> 3) |
|
|
||||||
((shiftRegister & 0x000200) >> 2) |
|
|
||||||
((shiftRegister & 0x000020) << 1) |
|
|
||||||
((shiftRegister & 0x000004) << 3) |
|
|
||||||
((shiftRegister & 0x000001) << 4);
|
|
||||||
noNoiseOrNoise = noNoise | noise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteShiftReg()
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
output &=
|
|
||||||
0xBB5DA |
|
|
||||||
((output & 0x800) << 9) |
|
|
||||||
((output & 0x400) << 8) |
|
|
||||||
((output & 0x200) << 5) |
|
|
||||||
((output & 0x100) << 3) |
|
|
||||||
((output & 0x040) >> 1) |
|
|
||||||
((output & 0x020) >> 3) |
|
|
||||||
((output & 0x010) >> 4);
|
|
||||||
noise &= output;
|
|
||||||
noNoiseOrNoise = noNoise | noise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
public int Control
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
controlWavePrev = waveform;
|
|
||||||
controlTestPrev = test;
|
|
||||||
|
|
||||||
sync = ((value & 0x02) != 0);
|
|
||||||
ringMod = ((value & 0x04) != 0);
|
|
||||||
test = ((value & 0x08) != 0);
|
|
||||||
waveform = (value >> 4) & 0x0F;
|
|
||||||
wave = waveTable[waveform & 0x07];
|
|
||||||
ringMsbMask = ((~value >> 5) & (value >> 2) & 0x1) << 23;
|
|
||||||
noNoise = ((waveform & 0x8) != 0) ? 0x000 : 0xFFF;
|
|
||||||
noNoiseOrNoise = noNoise | noise;
|
|
||||||
noPulse = ((waveform & 0x4) != 0) ? 0x000 : 0xFFF;
|
|
||||||
|
|
||||||
if (!controlTestPrev && test)
|
|
||||||
{
|
|
||||||
accumulator = 0;
|
|
||||||
delay = 0;
|
|
||||||
shiftRegisterReset = 0x8000;
|
|
||||||
}
|
|
||||||
else if (controlTestPrev && !test)
|
|
||||||
{
|
|
||||||
shiftRegister = ((shiftRegister << 1) |
|
|
||||||
((~shiftRegister >> 17) & 0x1)
|
|
||||||
) & 0x7FFFFF;
|
|
||||||
SetNoise();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waveform == 0 && controlWavePrev != 0)
|
|
||||||
floatOutputTTL = 0x28000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Frequency
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return frequency;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
frequency = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int FrequencyLo
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (frequency & 0xFF);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
frequency &= 0xFF00;
|
|
||||||
frequency |= value & 0x00FF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int FrequencyHi
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (frequency >> 8);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
frequency &= 0x00FF;
|
|
||||||
frequency |= (value & 0x00FF) << 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Oscillator
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Output(Voice ringModSource)
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
if (waveform != 0)
|
|
||||||
{
|
|
||||||
waveformIndex = (accumulator ^ (ringModSource.accumulator & ringMsbMask)) >> 12;
|
|
||||||
output = wave[waveformIndex] & (noPulse | pulse) & noNoiseOrNoise;
|
|
||||||
if (waveform > 8)
|
|
||||||
WriteShiftReg();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (floatOutputTTL != 0 && --floatOutputTTL == 0)
|
|
||||||
output = 0x000;
|
|
||||||
}
|
|
||||||
pulse = ((accumulator >> 12) >= pulseWidth) ? 0xFFF : 0x000;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int PulseWidth
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return pulseWidth;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
pulseWidth = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int PulseWidthLo
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (pulseWidth & 0xFF);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
pulseWidth &= 0x0F00;
|
|
||||||
pulseWidth |= value & 0x00FF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int PulseWidthHi
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (pulseWidth >> 8);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
pulseWidth &= 0x00FF;
|
|
||||||
pulseWidth |= (value & 0x000F) << 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RingMod
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return ringMod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Sync
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return sync;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Synchronize(Voice target, Voice source)
|
|
||||||
{
|
|
||||||
if (msbRising && target.sync && !(sync && source.msbRising))
|
|
||||||
target.accumulator = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Test
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Waveform
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return waveform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
|
||||||
{
|
|
||||||
BizHawk.Emulation.Computers.Commodore64.Sync.SyncObject(ser, this);
|
|
||||||
|
|
||||||
if (ser.IsReader)
|
|
||||||
wave = waveTable[waveform];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
|
@ -930,7 +357,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
ser.BeginSection("env0");
|
ser.BeginSection("env0");
|
||||||
envelopes[0].SyncState(ser);
|
envelopes[0].SyncState(ser);
|
||||||
ser.EndSection();
|
ser.EndSection();
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -14,59 +14,59 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HardReset()
|
virtual public void HardReset()
|
||||||
{
|
{
|
||||||
// note: this will not disconnect any attached media
|
// note: this will not disconnect any attached media
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadAtn()
|
virtual public bool ReadAtn()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadCounter1Buffer()
|
virtual public bool ReadCounter1Buffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadCounter2Buffer()
|
virtual public bool ReadCounter2Buffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ReadData()
|
virtual public byte ReadData()
|
||||||
{
|
{
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadFlag2()
|
virtual public bool ReadFlag2()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadPA2()
|
virtual public bool ReadPA2()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadReset()
|
virtual public bool ReadReset()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadSerial1Buffer()
|
virtual public bool ReadSerial1Buffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadSerial2Buffer()
|
virtual public bool ReadSerial2Buffer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
sealed public partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
class Sprite
|
sealed class Sprite
|
||||||
{
|
{
|
||||||
public bool collideData;
|
public bool collideData;
|
||||||
public bool collideSprite;
|
public bool collideSprite;
|
||||||
|
|
|
@ -196,11 +196,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
Sync.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
ser.BeginSection("sprite" + i.ToString());
|
ser.BeginSection("sprite" + i.ToString());
|
||||||
Sync.SyncObject(ser, sprites[i]);
|
SaveState.SyncObject(ser, sprites[i]);
|
||||||
ser.EndSection();
|
ser.EndSection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
sealed public partial class Vic
|
sealed public partial class Vic
|
||||||
{
|
{
|
||||||
|
const int BORDER_LEFT_38 = 0x01F;
|
||||||
|
const int BORDER_LEFT_40 = 0x018;
|
||||||
|
const int BORDER_RIGHT_38 = 0x14F;
|
||||||
|
const int BORDER_RIGHT_40 = 0x158;
|
||||||
|
|
||||||
static int[] TimingBuilder_Cycle14Act = new int[]
|
static int[] TimingBuilder_Cycle14Act = new int[]
|
||||||
{
|
{
|
||||||
pipelineUpdateVc, 0,
|
pipelineUpdateVc, 0,
|
||||||
|
@ -45,17 +50,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
result[i] |= pipelineHoldX;
|
result[i] |= pipelineHoldX;
|
||||||
|
|
||||||
// pipeline border checks
|
// pipeline border checks
|
||||||
if (timing[i] == 0x018)
|
if (timing[i] == (BORDER_LEFT_40 & 0xFFC))
|
||||||
result[i] |= pipelineChkBrdL1;
|
result[i] |= pipelineChkBrdL1;
|
||||||
if (timing[i] == 0x01C)
|
if (timing[i] == (BORDER_LEFT_38 & 0xFFC))
|
||||||
result[i] |= pipelineChkBrdL0;
|
result[i] |= pipelineChkBrdL0;
|
||||||
if (timing[i] == 0x14C)
|
if (timing[i] == (BORDER_RIGHT_38 & 0xFFC))
|
||||||
result[i] |= pipelineChkBrdR0;
|
result[i] |= pipelineChkBrdR0;
|
||||||
if (timing[i] == 0x158)
|
if (timing[i] == (BORDER_RIGHT_40 & 0xFFC))
|
||||||
result[i] |= pipelineChkBrdR1;
|
result[i] |= pipelineChkBrdR1;
|
||||||
if (timing[i] == (hblankStart & 0xFFD))
|
if (timing[i] == (hblankStart & 0xFFC))
|
||||||
result[i] |= pipelineHBlankR;
|
result[i] |= pipelineHBlankR;
|
||||||
if (timing[i] == (hblankEnd & 0xFFD))
|
if (timing[i] == (hblankEnd & 0xFFC))
|
||||||
result[i] |= pipelineHBlankL;
|
result[i] |= pipelineHBlankL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,8 +173,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateBorder()
|
private void UpdateBorder()
|
||||||
{
|
|
||||||
|
|
||||||
{
|
{
|
||||||
borderL = columnSelect ? 0x018 : 0x01F;
|
borderL = columnSelect ? 0x018 : 0x01F;
|
||||||
borderR = columnSelect ? 0x158 : 0x14F;
|
borderR = columnSelect ? 0x158 : 0x14F;
|
||||||
|
@ -183,7 +181,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
||||||
borderT = rowSelect ? 0x033 : 0x037;
|
borderT = rowSelect ? 0x033 : 0x037;
|
||||||
borderB = rowSelect ? 0x0FB : 0x0F7;
|
borderB = rowSelect ? 0x0FB : 0x0F7;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePins()
|
private void UpdatePins()
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Computers.Commodore64
|
namespace BizHawk.Emulation.Computers.Commodore64
|
||||||
{
|
{
|
||||||
static class Sync
|
static class SaveState
|
||||||
{
|
{
|
||||||
static public void SyncObject(Serializer ser, object obj)
|
static public void SyncObject(Serializer ser, object obj)
|
||||||
{
|
{
|
Loading…
Reference in New Issue