commodore64: savestates implemented on all chips and connected

This commit is contained in:
saxxonpike 2012-11-21 01:30:54 +00:00
parent 5b3de57fca
commit bc06a1c59a
9 changed files with 363 additions and 512 deletions

View File

@ -100,6 +100,7 @@
<Compile Include="Computers\Commodore64\Sid.cs" />
<Compile Include="Computers\Commodore64\SidEnvelopeGenerator.cs" />
<Compile Include="Computers\Commodore64\SidSoundProvider.cs" />
<Compile Include="Computers\Commodore64\SidState.cs" />
<Compile Include="Computers\Commodore64\SidWaveformCalculator.cs" />
<Compile Include="Computers\Commodore64\SidWaveformGenerator.cs" />
<Compile Include="Computers\Commodore64\Timing.cs" />

View File

@ -150,12 +150,5 @@ namespace BizHawk.Emulation.Computers.Commodore64
domains.Add(new MemoryDomain("DISKVIA1", 0x10, Endian.Little, new Func<int, byte>(PeekVia1), new Action<int, byte>(PokeVia1)));
memoryDomains = domains.AsReadOnly();
}
void SyncState(Serializer ser) //TODO
{
ser.Sync("Lag", ref _lagcount);
ser.Sync("Frame", ref _frame);
ser.Sync("IsLag", ref _islag);
}
}
}

View File

@ -7,150 +7,83 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class Cia
{
public StateParameters State
public void SyncState(Serializer ser)
{
get
ser.Sync("ALARM", ref regs.ALARM);
ser.Sync("ALARM10", ref regs.ALARM10);
ser.Sync("ALARMHR", ref regs.ALARMHR);
ser.Sync("ALARMMIN", ref regs.ALARMMIN);
ser.Sync("ALARMPM", ref regs.ALARMPM);
ser.Sync("ALARMSEC", ref regs.ALARMSEC);
ser.Sync("CNT", ref regs.CNT);
ser.Sync("EIALARM", ref regs.EIALARM);
ser.Sync("EIFLG", ref regs.EIFLG);
ser.Sync("EISP", ref regs.EISP);
ser.Sync("EIT0", ref regs.EIT[0]);
ser.Sync("EIT1", ref regs.EIT[1]);
ser.Sync("FLG", ref regs.FLG);
ser.Sync("IALARM", ref regs.IALARM);
ser.Sync("IFLG", ref regs.IFLG);
ser.Sync("INMODE0", ref regs.INMODE[0]);
ser.Sync("INMODE1", ref regs.INMODE[1]);
ser.Sync("IRQ", ref regs.IRQ);
ser.Sync("ISP", ref regs.ISP);
ser.Sync("IT0", ref regs.IT[0]);
ser.Sync("IT1", ref regs.IT[1]);
ser.Sync("LOAD0", ref regs.LOAD[0]);
ser.Sync("LOAD1", ref regs.LOAD[1]);
ser.Sync("OUTMODE0", ref regs.OUTMODE[0]);
ser.Sync("OUTMODE1", ref regs.OUTMODE[1]);
ser.Sync("PBON0", ref regs.PBON[0]);
ser.Sync("PBON1", ref regs.PBON[1]);
ser.Sync("RUNMODE0", ref regs.RUNMODE[0]);
ser.Sync("RUNMODE1", ref regs.RUNMODE[1]);
ser.Sync("SDR", ref regs.SDR);
ser.Sync("SDRCOUNT", ref regs.SDRCOUNT);
ser.Sync("SPMODE", ref regs.SPMODE);
ser.Sync("START0", ref regs.START[0]);
ser.Sync("START1", ref regs.START[1]);
ser.Sync("T0", ref regs.T[0]);
ser.Sync("T1", ref regs.T[1]);
ser.Sync("TICK0", ref regs.TICK[0]);
ser.Sync("TICK1", ref regs.TICK[1]);
ser.Sync("TLATCH0", ref regs.TLATCH[0]);
ser.Sync("TLATCH1", ref regs.TLATCH[1]);
ser.Sync("TOD10", ref regs.TOD10);
ser.Sync("TODHR", ref regs.TODHR);
ser.Sync("TODMIN", ref regs.TODMIN);
ser.Sync("TODPM", ref regs.TODPM);
ser.Sync("TODREADLATCH", ref regs.TODREADLATCH);
ser.Sync("TODREADLATCH10", ref regs.TODREADLATCH10);
ser.Sync("TODREADLATCHSEC", ref regs.TODREADLATCHSEC);
ser.Sync("TODREADLATCHMIN", ref regs.TODREADLATCHMIN);
ser.Sync("TODREADLATCHHR", ref regs.TODREADLATCHHR);
ser.Sync("TODSEC", ref regs.TODSEC);
// ports
byte dir0 = regs.connectors[0].Direction;
byte dir1 = regs.connectors[1].Direction;
byte latch0 = regs.connectors[0].Latch;
byte latch1 = regs.connectors[0].Latch;
ser.Sync("DIR0", ref dir0);
ser.Sync("DIR1", ref dir1);
ser.Sync("PORT0", ref latch0);
ser.Sync("PORT1", ref latch1);
if (ser.IsReader)
{
StateParameters result = new StateParameters();
// registers
result.Save("ALARM", regs.ALARM);
result.Save("ALARM10", regs.ALARM10);
result.Save("ALARMHR", regs.ALARMHR);
result.Save("ALARMMIN", regs.ALARMMIN);
result.Save("ALARMPM", regs.ALARMPM);
result.Save("ALARMSEC", regs.ALARMSEC);
result.Save("CNT", regs.CNT);
result.Save("EIALARM", regs.EIALARM);
result.Save("EIFLG", regs.EIFLG);
result.Save("EISP", regs.EISP);
result.Save("EIT0", regs.EIT[0]);
result.Save("EIT1", regs.EIT[1]);
result.Save("FLG", regs.FLG);
result.Save("IALARM", regs.IALARM);
result.Save("IFLG", regs.IFLG);
result.Save("INMODE0", regs.INMODE[0]);
result.Save("INMODE1", regs.INMODE[1]);
result.Save("IRQ", regs.IRQ);
result.Save("ISP", regs.ISP);
result.Save("IT0", regs.IT[0]);
result.Save("IT1", regs.IT[1]);
result.Save("LOAD0", regs.LOAD[0]);
result.Save("LOAD1", regs.LOAD[1]);
result.Save("OUTMODE0", regs.OUTMODE[0]);
result.Save("OUTMODE1", regs.OUTMODE[1]);
result.Save("PBON0", regs.PBON[0]);
result.Save("PBON1", regs.PBON[1]);
result.Save("RUNMODE0", regs.RUNMODE[0]);
result.Save("RUNMODE1", regs.RUNMODE[1]);
result.Save("SDR", regs.SDR);
result.Save("SDRCOUNT", regs.SDRCOUNT);
result.Save("SPMODE", regs.SPMODE);
result.Save("START0", regs.START[0]);
result.Save("START1", regs.START[1]);
result.Save("T0", regs.T[0]);
result.Save("T1", regs.T[1]);
result.Save("TICK0", regs.TICK[0]);
result.Save("TICK1", regs.TICK[1]);
result.Save("TLATCH0", regs.TLATCH[0]);
result.Save("TLATCH1", regs.TLATCH[1]);
result.Save("TOD10", regs.TOD10);
result.Save("TODHR", regs.TODHR);
result.Save("TODMIN", regs.TODMIN);
result.Save("TODPM", regs.TODPM);
result.Save("TODREADLATCH", regs.TODREADLATCH);
result.Save("TODREADLATCH10", regs.TODREADLATCH10);
result.Save("TODREADLATCHSEC", regs.TODREADLATCHSEC);
result.Save("TODREADLATCHMIN", regs.TODREADLATCHMIN);
result.Save("TODREADLATCHHR", regs.TODREADLATCHHR);
result.Save("TODSEC", regs.TODSEC);
// ports
result.Save("DIR0", regs.connectors[0].Direction);
result.Save("DIR1", regs.connectors[1].Direction);
result.Save("PORT0", regs.connectors[0].Latch);
result.Save("PORT1", regs.connectors[1].Latch);
// state
result.Save("INTMASK", intMask);
result.Save("LASTCNT", lastCNT);
result.Save("TODCOUNTER", todCounter);
result.Save("TODFREQUENCY", todFrequency);
result.Save("UNDERFLOW0", underflow[0]);
result.Save("UNDERFLOW1", underflow[1]);
return result;
regs.connectors[0].Direction = dir0;
regs.connectors[0].Latch = latch0;
regs.connectors[1].Direction = dir1;
regs.connectors[1].Latch = latch1;
}
set
{
StateParameters result = value;
// registers
result.Load("ALARM", out regs.ALARM);
result.Load("ALARM10", out regs.ALARM10);
result.Load("ALARMHR", out regs.ALARMHR);
result.Load("ALARMMIN", out regs.ALARMMIN);
result.Load("ALARMPM", out regs.ALARMPM);
result.Load("ALARMSEC", out regs.ALARMSEC);
result.Load("CNT", out regs.CNT);
result.Load("EIALARM", out regs.EIALARM);
result.Load("EIFLG", out regs.EIFLG);
result.Load("EISP", out regs.EISP);
result.Load("EIT0", out regs.EIT[0]);
result.Load("EIT1", out regs.EIT[1]);
result.Load("FLG", out regs.FLG);
result.Load("IALARM", out regs.IALARM);
result.Load("IFLG", out regs.IFLG);
result.Load("INMODE0", out regs.INMODE[0]);
result.Load("INMODE1", out regs.INMODE[1]);
result.Load("IRQ", out regs.IRQ);
result.Load("ISP", out regs.ISP);
result.Load("IT0", out regs.IT[0]);
result.Load("IT1", out regs.IT[1]);
result.Load("LOAD0", out regs.LOAD[0]);
result.Load("LOAD1", out regs.LOAD[1]);
result.Load("OUTMODE0", out regs.OUTMODE[0]);
result.Load("OUTMODE1", out regs.OUTMODE[1]);
result.Load("PBON0", out regs.PBON[0]);
result.Load("PBON1", out regs.PBON[1]);
result.Load("RUNMODE0", out regs.RUNMODE[0]);
result.Load("RUNMODE1", out regs.RUNMODE[1]);
result.Load("SDR", out regs.SDR);
result.Load("SDRCOUNT", out regs.SDRCOUNT);
result.Load("SPMODE", out regs.SPMODE);
result.Load("START0", out regs.START[0]);
result.Load("START1", out regs.START[1]);
result.Load("T0", out regs.T[0]);
result.Load("T1", out regs.T[1]);
result.Load("TICK0", out regs.TICK[0]);
result.Load("TICK1", out regs.TICK[1]);
result.Load("TLATCH0", out regs.TLATCH[0]);
result.Load("TLATCH1", out regs.TLATCH[1]);
result.Load("TOD10", out regs.TOD10);
result.Load("TODHR", out regs.TODHR);
result.Load("TODMIN", out regs.TODMIN);
result.Load("TODPM", out regs.TODPM);
result.Load("TODREADLATCH", out regs.TODREADLATCH);
result.Load("TODREADLATCH10", out regs.TODREADLATCH10);
result.Load("TODREADLATCHSEC", out regs.TODREADLATCHSEC);
result.Load("TODREADLATCHMIN", out regs.TODREADLATCHMIN);
result.Load("TODREADLATCHHR", out regs.TODREADLATCHHR);
result.Load("TODSEC", out regs.TODSEC);
// ports
regs.connectors[0].Direction = (byte)result["DIR0"];
regs.connectors[1].Direction = (byte)result["DIR1"];
regs.connectors[0].Latch = (byte)result["LATCH0"];
regs.connectors[1].Latch = (byte)result["LATCH1"];
// state
result.Load("INTMASK", out intMask);
result.Load("LASTCNT", out lastCNT);
result.Load("TODCOUNTER", out todCounter);
result.Load("TODFREQUENCY", out todFrequency);
result.Load("UNDERFLOW0", out underflow[0]);
result.Load("UNDERFLOW1", out underflow[1]);
}
// state
ser.Sync("INTMASK", ref intMask);
ser.Sync("LASTCNT", ref lastCNT);
ser.Sync("TODCOUNTER", ref todCounter);
ser.Sync("TODFREQUENCY", ref todFrequency);
ser.Sync("UNDERFLOW0", ref underflow[0]);
ser.Sync("UNDERFLOW1", ref underflow[1]);
}
}
}

View File

@ -407,6 +407,30 @@ namespace BizHawk.Emulation.Computers.Commodore64
return (byte)((busData & 0xF0) | (colorRam[addr & 0x03FF]));
}
public void SyncState(Serializer ser)
{
ser.Sync("BUSDATA", ref busData);
ser.Sync("EXROMPIN", ref exRomPin);
ser.Sync("GAMEPIN", ref gamePin);
ser.Sync("INPUTWASREAD", ref inputWasRead);
ser.Sync("COLORRAM", ref colorRam, false);
ser.Sync("RAM", ref ram, false);
byte cpuData = cpuPort.Latch;
byte cpuDir = cpuPort.Direction;
ser.Sync("CPUPORT", ref cpuData);
ser.Sync("CPUDIR", ref cpuDir);
if (ser.IsReader)
{
cpuPort.Latch = cpuData;
cpuPort.Direction = cpuDir;
UpdateLayout();
UpdateVicOffset();
}
}
public void UpdateLayout()
{
byte cpuData = cpuPort.Data;

View File

@ -14,10 +14,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void LoadStateBinary(BinaryReader br)
{
SyncState(new Serializer(br));
}
public void LoadStateText(TextReader reader)
{
SyncState(new Serializer(reader));
}
public byte[] ReadSaveRam()
@ -39,165 +41,51 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void SaveStateBinary(BinaryWriter bw)
{
Dictionary<string, StateParameters> state = new Dictionary<string, StateParameters>();
SyncState(new Serializer(bw));
}
public void SaveStateText(TextWriter writer)
{
{
SyncState(new Serializer(writer));
}
public void StoreSaveRam(byte[] data)
{
}
}
public class StateParameters
{
private Dictionary<string, int> integerList = new Dictionary<string, int>();
public int this[string key]
void SyncState(Serializer ser)
{
get
{
if (integerList.ContainsKey(key))
{
return integerList[key];
}
return 0;
}
set
{
integerList[key] = value;
}
}
// global stuffs
ser.BeginSection("GAME");
ser.Sync("Lag", ref _lagcount);
ser.Sync("Frame", ref _frame);
ser.Sync("IsLag", ref _islag);
ser.EndSection();
public void ExportBinary(Stream target)
{
BinaryWriter writer = new BinaryWriter(target);
// cpu creates its own section..
cpu.SyncState(ser);
writer.Write((Int32)integerList.Count);
foreach (KeyValuePair<string, int> kv in integerList)
{
writer.Write(kv.Key);
writer.Write(kv.Value);
}
ser.BeginSection("MEM");
mem.SyncState(ser);
ser.EndSection();
writer.Flush();
}
ser.BeginSection("VIC");
vic.SyncState(ser);
ser.EndSection();
public void ExportText(Stream target)
{
StringBuilder sb = new StringBuilder();
ser.BeginSection("SID");
sid.SyncState(ser);
ser.EndSection();
foreach (KeyValuePair<string, int> kv in integerList)
{
sb.Append(kv.Key + "=");
sb.AppendLine(kv.Value.ToString());
}
ser.BeginSection("CIA0");
cia0.SyncState(ser);
ser.EndSection();
StreamWriter writer = new StreamWriter(target);
writer.Write(sb.ToString());
writer.Flush();
}
ser.BeginSection("CIA1");
cia1.SyncState(ser);
ser.EndSection();
public void ImportBinary(Stream source)
{
BinaryReader reader = new BinaryReader(source);
int count = reader.ReadInt32();
for (int i = 0; i < count; i++)
{
string key = reader.ReadString();
int val = reader.ReadInt32();
integerList[key] = val;
}
}
public void ImportText(Stream source)
{
StreamReader reader = new StreamReader(source);
string line = "";
while (!reader.EndOfStream && !(line.Contains("[") && line.Contains("]")))
{
line = reader.ReadLine();
int equalsIndex = line.IndexOf("=");
if (equalsIndex >= 0 && equalsIndex < (line.Length - 1))
{
string key = line.Substring(0, equalsIndex - 1);
string val = line.Substring(equalsIndex + 1);
if (val.Length > 0 && key.Length > 0)
{
integerList[key] = int.Parse(val);
}
}
}
}
public void Load(string key, out byte val)
{
val = (byte)(this[key] & 0xFF);
}
public void Load(string key, out int val)
{
val = this[key];
}
public void Load(string key, out bool val)
{
val = this[key] != 0;
}
public void Load(string key, out byte[] val, int length)
{
byte[] result = new byte[length];
for (int i = 0; i < length; i++)
{
result[i] = (byte)(this[key + i.ToString()] & 0xFF);
}
val = result;
}
public void Load(string key, out int[] val, int length)
{
int[] result = new int[length];
for (int i = 0; i < length; i++)
{
result[i] = (int)(this[key + i.ToString()] & 0xFF);
}
val = result;
}
public void Save(string key, byte val)
{
this[key] = (int)val;
}
public void Save(string key, int val)
{
this[key] = val;
}
public void Save(string key, bool val)
{
this[key] = val ? 1 : 0;
}
public void Save(string key, byte[] val, int length)
{
for (int i = 0; i < length; i++)
{
this[key + i.ToString()] = val[i];
}
}
public void Save(string key, int[] val, int length)
{
for (int i = 0; i < length; i++)
{
this[key + i.ToString()] = (int)val[i];
}
// TODO: drive
}
}
}

View File

@ -9,9 +9,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
// constants for the EnvelopeGenerator and calculation
// methods are based from the libsidplayfp residfp library.
public class EnvelopeGenerator
public partial class EnvelopeGenerator
{
enum State
public enum EnvelopeState
{
Attack, Decay, Release
}
@ -27,18 +27,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
int attack;
int decay;
byte envelopeCounter;
bool envelopeProcessEnabled;
int exponentialCounter;
int exponentialCounterPeriod;
bool freeze;
bool gate;
int lfsr;
int rate;
int release;
State state;
int sustain;
public byte envelopeCounter;
public bool envelopeProcessEnabled;
public int exponentialCounter;
public int exponentialCounterPeriod;
public bool freeze;
public int lfsr;
public int rate;
public EnvelopeState state;
public EnvelopeGenerator()
{
Reset();
@ -53,7 +54,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
set
{
attack = value;
if (state == State.Attack)
if (state == EnvelopeState.Attack)
rate = adsrTable[attack];
}
}
@ -76,22 +77,22 @@ namespace BizHawk.Emulation.Computers.Commodore64
lfsr = 0x7FFF;
if ((state == State.Attack) || (++exponentialCounter == exponentialCounterPeriod))
if ((state == EnvelopeState.Attack) || (++exponentialCounter == exponentialCounterPeriod))
{
exponentialCounter = 0;
if (!freeze)
{
switch (state)
{
case State.Attack:
case EnvelopeState.Attack:
++envelopeCounter;
if (envelopeCounter == 0xFF)
{
state = State.Decay;
state = EnvelopeState.Decay;
rate = adsrTable[decay];
}
break;
case State.Decay:
case EnvelopeState.Decay:
if (envelopeCounter == ((sustain << 4) | sustain))
{
return;
@ -103,7 +104,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
}
envelopeCounter--;
break;
case State.Release:
case EnvelopeState.Release:
if (exponentialCounterPeriod != 1)
{
envelopeProcessEnabled = true;
@ -127,7 +128,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
set
{
decay = value;
if (state == State.Decay)
if (state == EnvelopeState.Decay)
rate = adsrTable[decay];
}
}
@ -144,14 +145,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
if (!gate && gateThis)
{
state = State.Attack;
state = EnvelopeState.Attack;
rate = adsrTable[attack];
freeze = false;
envelopeProcessEnabled = false;
}
else if (gate && !gateThis)
{
state = State.Release;
state = EnvelopeState.Release;
rate = adsrTable[release];
}
@ -176,7 +177,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
set
{
release = value;
if (state == State.Release)
if (state == EnvelopeState.Release)
rate = adsrTable[release];
}
}
@ -195,11 +196,21 @@ namespace BizHawk.Emulation.Computers.Commodore64
exponentialCounterPeriod = 1;
lfsr = 0x7FFF;
state = State.Release;
state = EnvelopeState.Release;
rate = adsrTable[release];
freeze = true;
}
public void SetState(int stateAtk, int stateDcy, int stateSus, int stateRls, bool stateGate, EnvelopeState stateState)
{
attack = stateAtk;
decay = stateDcy;
sustain = stateSus;
release = stateRls;
gate = stateGate;
state = stateState;
}
public int Sustain
{
get

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class Sid : ISoundProvider
{
public void SyncState(Serializer ser)
{
// voices
for (int i = 0; i < 3; i++)
{
string iTag = i.ToString();
ser.Sync("GENACCUM" + iTag, ref regs.Voices[i].Generator.accumulator);
ser.Sync("GENFOTTL" + iTag, ref regs.Voices[i].Generator.floatingOutputTtl);
ser.Sync("GENMSBRISING" + iTag, ref regs.Voices[i].Generator.msbRising);
ser.Sync("GENNOISEOUT" + iTag, ref regs.Voices[i].Generator.noiseOutput);
ser.Sync("GENPULSEOUT" + iTag, ref regs.Voices[i].Generator.pulseOutput);
ser.Sync("GENSR" + iTag, ref regs.Voices[i].Generator.shiftRegister);
ser.Sync("GENSRDELAY" + iTag, ref regs.Voices[i].Generator.shiftRegisterDelay);
ser.Sync("GENSRRESETDELAY" + iTag, ref regs.Voices[i].Generator.shiftRegisterResetDelay);
ser.Sync("GENWAVEFORMOUT" + iTag, ref regs.Voices[i].Generator.waveformOutput);
ser.Sync("ENVCOUNTER" + iTag, ref regs.Voices[i].Envelope.envelopeCounter);
ser.Sync("ENVENABLE" + iTag, ref regs.Voices[i].Envelope.envelopeProcessEnabled);
ser.Sync("ENVEXPCOUNTER" + iTag, ref regs.Voices[i].Envelope.exponentialCounter);
ser.Sync("ENVEXPCOUNTERPERIOD" + iTag, ref regs.Voices[i].Envelope.exponentialCounterPeriod);
ser.Sync("ENVFREEZE" + iTag, ref regs.Voices[i].Envelope.freeze);
ser.Sync("ENVLFSR" + iTag, ref regs.Voices[i].Envelope.lfsr);
ser.Sync("ENVRATE" + iTag, ref regs.Voices[i].Envelope.rate);
byte control = regs.Voices[i].Generator.Control;
int freq = regs.Voices[i].Generator.Frequency;
int pw = regs.Voices[i].Generator.PulseWidth;
int attack = regs.Voices[i].Envelope.Attack;
int decay = regs.Voices[i].Envelope.Decay;
int sustain = regs.Voices[i].Envelope.Sustain;
int release = regs.Voices[i].Envelope.Release;
bool gate = regs.Voices[i].Envelope.Gate;
int state = (int)regs.Voices[i].Envelope.state;
ser.Sync("GENCONTROL" + iTag, ref control);
ser.Sync("GENFREQ" + iTag, ref freq);
ser.Sync("GENPW" + iTag, ref pw);
ser.Sync("ENVATTACK" + iTag, ref attack);
ser.Sync("ENVDECAY" + iTag, ref decay);
ser.Sync("ENVSUSTAIN" + iTag, ref sustain);
ser.Sync("ENVRELEASE" + iTag, ref release);
ser.Sync("ENVGATE" + iTag, ref gate);
ser.Sync("ENVSTATE" + iTag, ref state);
if (ser.IsReader)
{
regs.Voices[i].Generator.SetState(control, freq, pw);
regs.Voices[i].Envelope.SetState(attack, decay, sustain, release, gate, (EnvelopeGenerator.EnvelopeState)state);
}
}
// regs
ser.Sync("BP", ref regs.BP);
ser.Sync("D3", ref regs.D3);
ser.Sync("FC", ref regs.FC);
ser.Sync("FILT0", ref regs.FILT[0]);
ser.Sync("FILT1", ref regs.FILT[1]);
ser.Sync("FILT2", ref regs.FILT[2]);
ser.Sync("FILTEX", ref regs.FILTEX);
ser.Sync("HP", ref regs.HP);
ser.Sync("LP", ref regs.LP);
ser.Sync("POTX", ref regs.POTX);
ser.Sync("POTY", ref regs.POTY);
ser.Sync("RES", ref regs.RES);
ser.Sync("VOL", ref regs.VOL);
// vars
ser.Sync("CLOCK", ref clock);
ser.Sync("CYCLESPERSAMPLE", ref cyclesPerSample);
ser.Sync("OUTPUT", ref output);
}
}
}

View File

@ -11,23 +11,25 @@ namespace BizHawk.Emulation.Computers.Commodore64
public partial class WaveformGenerator
{
private int accumulator;
// internal
private byte control;
private int floatingOutputTtl;
private int freq;
private bool msbRising;
private int noiseOutput;
private int pulseOutput;
private int pw;
private int ringMsbMask;
private int shiftRegister;
private int shiftRegisterDelay;
private int shiftRegisterResetDelay;
private bool sync;
private bool test;
public int accumulator;
public int floatingOutputTtl;
public bool msbRising;
public int noiseOutput;
public int pulseOutput;
public int ringMsbMask;
public int shiftRegister;
public int shiftRegisterDelay;
public int shiftRegisterResetDelay;
public bool sync;
public bool test;
private short[] wave;
private int waveform;
private int waveformOutput;
public int waveform;
public int waveformOutput;
// these are temp values used to speed up calculation
private int noNoise;
@ -196,6 +198,21 @@ namespace BizHawk.Emulation.Computers.Commodore64
UpdateNoiseOutput();
}
public void SetState(byte stateControl, int stateFreq, int statePulseWidth)
{
pw = statePulseWidth;
freq = stateFreq;
control = stateControl;
noNoise = (waveform & 0x8) != 0 ? 0x000 : 0xFFF;
noNoiseOrNoiseOutput = noNoise | noiseOutput;
noPulse = (waveform & 0x4) != 0 ? 0x000 : 0xFFF;
ringMsbMask = ((~control >> 5) & (control >> 2) & 0x1) << 23;
waveform = (control >> 4) & 0x0F;
test = (control & 0x08) != 0;
sync = (control & 0x02) != 0;
wave = WaveformSamples[waveform & 0x7];
}
public void Synchronize(WaveformGenerator syncDest, WaveformGenerator syncSource)
{
if (msbRising && syncDest.sync && !(sync && syncSource.msbRising))

View File

@ -7,200 +7,102 @@ namespace BizHawk.Emulation.Computers.Commodore64
{
public partial class VicIINew : IVideoProvider
{
public StateParameters State
public void SyncState(Serializer ser)
{
get
// internal
ser.Sync("RC", ref RC);
ser.Sync("VC", ref VC);
ser.Sync("VCBASE", ref VCBASE);
ser.Sync("VMLI", ref VMLI);
// external
ser.Sync("BMM", ref BMM);
ser.Sync("BxC", ref BxC, false);
ser.Sync("CB", ref CB);
ser.Sync("CSEL", ref CSEL);
ser.Sync("DEN", ref DEN);
ser.Sync("EC", ref EC);
ser.Sync("ECM", ref ECM);
ser.Sync("ELP", ref ELP);
ser.Sync("EMBC", ref EMBC);
ser.Sync("EMMC", ref EMMC);
ser.Sync("ERST", ref ERST);
ser.Sync("ILP", ref ILP);
ser.Sync("IMBC", ref IMBC);
ser.Sync("IMMC", ref IMMC);
ser.Sync("IRQ", ref IRQ);
ser.Sync("IRST", ref IRST);
ser.Sync("LPX", ref LPX);
ser.Sync("LPY", ref LPY);
ser.Sync("MCM", ref MCM);
ser.Sync("MMx", ref MMx, false);
ser.Sync("RASTER", ref RASTER);
ser.Sync("RES", ref RES);
ser.Sync("RSEL", ref RSEL);
ser.Sync("VM", ref VM);
ser.Sync("XSCROLL", ref XSCROLL);
ser.Sync("YSCROLL", ref YSCROLL);
// state
ser.Sync("BADLINE", ref badline);
ser.Sync("BITMAPCOLUMN", ref bitmapColumn);
ser.Sync("BITMAPDATA", ref bitmapData);
ser.Sync("BORDERONMAIN", ref borderOnMain);
ser.Sync("BORDERONVERTICAL", ref borderOnVertical);
ser.Sync("CENTERENABLED", ref centerEnabled);
ser.Sync("CHARACTERDATA", ref characterData);
ser.Sync("CHARACTERDATABUS", ref characterDataBus);
ser.Sync("CHARMEM", ref characterMemory, false);
ser.Sync("COLORDATA", ref colorData);
ser.Sync("COLORDATABUS", ref colorDataBus);
ser.Sync("COLORMEM", ref colorMemory, false);
ser.Sync("DISPLAYENABLED", ref displayEnabled);
ser.Sync("IDLE", ref idle);
ser.Sync("PLOTTERBUFFERINDEX", ref plotterBufferIndex);
ser.Sync("PLOTTERDATA", ref plotterData);
ser.Sync("PLOTTERDATABUFFER", ref plotterDataBuffer, false);
ser.Sync("PLOTTERDELAY", ref plotterDelay);
ser.Sync("PLOTTERPIXEL", ref plotterPixel);
ser.Sync("PLOTTERPIXELBUFFER", ref plotterPixelBuffer, false);
ser.Sync("RASTERINTERRUPTLINE", ref rasterInterruptLine);
ser.Sync("RASTERX", ref rasterX);
ser.Sync("REFRESHADDRESS", ref refreshAddress);
// pipeline
ser.Sync("CYCLE", ref cycle);
ser.Sync("PIPELINEGACCESS", ref pipelineGAccess);
ser.Sync("PIPELINEMEMORYBUSY", ref pipelineMemoryBusy);
// sprites
for (int i = 0; i < 8; i++)
{
StateParameters result = new StateParameters();
string iTag = i.ToString();
ser.Sync("MC" + iTag, ref sprites[i].MC);
ser.Sync("MCBASE" + iTag, ref sprites[i].MCBASE);
ser.Sync("MD" + iTag, ref sprites[i].MD);
ser.Sync("MDMA" + iTag, ref sprites[i].MDMA);
ser.Sync("MPTR" + iTag, ref sprites[i].MPTR);
ser.Sync("MSR" + iTag, ref sprites[i].MSR);
ser.Sync("MxXEToggle" + iTag, ref sprites[i].MxXEToggle);
ser.Sync("MxYEToggle" + iTag, ref sprites[i].MxYEToggle);
// internal
result.Save("RC", RC);
result.Save("VC", VC);
result.Save("VCBASE", VCBASE);
result.Save("VMLI", VMLI);
// external
result.Save("BMM", BMM);
result.Save("BxC", BxC, BxC.Length);
result.Save("CB", CB);
result.Save("CSEL", CSEL);
result.Save("DEN", DEN);
result.Save("EC", EC);
result.Save("ECM", ECM);
result.Save("ELP", ELP);
result.Save("EMBC", EMBC);
result.Save("EMMC", EMMC);
result.Save("ERST", ERST);
result.Save("ILP", ILP);
result.Save("IMBC", IMBC);
result.Save("IMMC", IMMC);
result.Save("IRQ", IRQ);
result.Save("IRST", IRST);
result.Save("LPX", LPX);
result.Save("LPY", LPY);
result.Save("MCM", MCM);
result.Save("MMx", MMx, MMx.Length);
result.Save("RASTER", RASTER);
result.Save("RES", RES);
result.Save("RSEL", RSEL);
result.Save("VM", VM);
result.Save("XSCROLL", XSCROLL);
result.Save("YSCROLL", YSCROLL);
// state
result.Save("BADLINE", badline);
result.Save("BITMAPCOLUMN", bitmapColumn);
result.Save("BITMAPDATA", bitmapData);
result.Save("BORDERONMAIN", borderOnMain);
result.Save("BORDERONVERTICAL", borderOnVertical);
result.Save("CENTERENABLED", centerEnabled);
result.Save("CHARACTERDATA", characterData);
result.Save("CHARACTERDATABUS", characterDataBus);
result.Save("CHARMEM", characterMemory, characterMemory.Length);
result.Save("COLORDATA", colorData);
result.Save("COLORDATABUS", colorDataBus);
result.Save("COLORMEM", colorMemory, colorMemory.Length);
result.Save("DISPLAYENABLED", displayEnabled);
result.Save("IDLE", idle);
result.Save("PLOTTERBUFFERINDEX", plotterBufferIndex);
result.Save("PLOTTERDATA", plotterData);
result.Save("PLOTTERDATABUFFER", plotterDataBuffer, plotterDataBuffer.Length);
result.Save("PLOTTERDELAY", plotterDelay);
result.Save("PLOTTERPIXEL", plotterPixel);
result.Save("PLOTTERPIXELBUFFER", plotterPixelBuffer, plotterPixelBuffer.Length);
result.Save("RASTERINTERRUPTLINE", rasterInterruptLine);
result.Save("RASTERX", rasterX);
result.Save("REFRESHADDRESS", refreshAddress);
// pipeline
result.Save("CYCLE", cycle);
result.Save("PIPELINEGACCESS", pipelineGAccess);
result.Save("PIPELINEMEMORYBUSY", pipelineMemoryBusy);
// sprites
for (int i = 0; i < 8; i++)
{
string iTag = i.ToString();
result.Save("MC" + iTag, sprites[i].MC);
result.Save("MCBASE" + iTag, sprites[i].MCBASE);
result.Save("MD" + iTag, sprites[i].MD);
result.Save("MDMA" + iTag, sprites[i].MDMA);
result.Save("MPTR" + iTag, sprites[i].MPTR);
result.Save("MSR" + iTag, sprites[i].MSR);
result.Save("MxXEToggle" + iTag, sprites[i].MxXEToggle);
result.Save("MxYEToggle" + iTag, sprites[i].MxYEToggle);
result.Save("MxC" + iTag, sprites[i].MxC);
result.Save("MxD" + iTag, sprites[i].MxD);
result.Save("MxDP" + iTag, sprites[i].MxDP);
result.Save("MxE" + iTag, sprites[i].MxE);
result.Save("MxM" + iTag, sprites[i].MxM);
result.Save("MxMC" + iTag, sprites[i].MxMC);
result.Save("MxX" + iTag, sprites[i].MxX);
result.Save("MxXE" + iTag, sprites[i].MxXE);
result.Save("MxY" + iTag, sprites[i].MxY);
result.Save("MxYE" + iTag, sprites[i].MxYE);
}
return result;
ser.Sync("MxC" + iTag, ref sprites[i].MxC);
ser.Sync("MxD" + iTag, ref sprites[i].MxD);
ser.Sync("MxDP" + iTag, ref sprites[i].MxDP);
ser.Sync("MxE" + iTag, ref sprites[i].MxE);
ser.Sync("MxM" + iTag, ref sprites[i].MxM);
ser.Sync("MxMC" + iTag, ref sprites[i].MxMC);
ser.Sync("MxX" + iTag, ref sprites[i].MxX);
ser.Sync("MxXE" + iTag, ref sprites[i].MxXE);
ser.Sync("MxY" + iTag, ref sprites[i].MxY);
ser.Sync("MxYE" + iTag, ref sprites[i].MxYE);
}
set
if (ser.IsReader)
{
StateParameters result = value;
// internal
result.Load("RC", out RC);
result.Load("VC", out VC);
result.Load("VCBASE", out VCBASE);
result.Load("VMLI", out VMLI);
// external
result.Load("BMM", out BMM);
result.Load("BxC", out BxC, BxC.Length);
result.Load("CB", out CB);
result.Load("CSEL", out CSEL);
result.Load("DEN", out DEN);
result.Load("EC", out EC);
result.Load("ECM", out ECM);
result.Load("ELP", out ELP);
result.Load("EMBC", out EMBC);
result.Load("EMMC", out EMMC);
result.Load("ERST", out ERST);
result.Load("ILP", out ILP);
result.Load("IMBC", out IMBC);
result.Load("IMMC", out IMMC);
result.Load("IRQ", out IRQ);
result.Load("IRST", out IRST);
result.Load("LPX", out LPX);
result.Load("LPY", out LPY);
result.Load("MCM", out MCM);
result.Load("MMx", out MMx, MMx.Length);
result.Load("RASTER", out RASTER);
result.Load("RES", out RES);
result.Load("RSEL", out RSEL);
result.Load("VM", out VM);
result.Load("XSCROLL", out XSCROLL);
result.Load("YSCROLL", out YSCROLL);
// state
result.Load("BADLINE", out badline);
result.Load("BITMAPCOLUMN", out bitmapColumn);
result.Load("BITMAPDATA", out bitmapData);
result.Load("BORDERONMAIN", out borderOnMain);
result.Load("BORDERONVERTICAL", out borderOnVertical);
result.Load("CENTERENABLED", out centerEnabled);
result.Load("CHARACTERDATA", out characterData);
result.Load("CHARACTERDATABUS", out characterDataBus);
result.Load("CHARMEM", out characterMemory, characterMemory.Length);
result.Load("COLORDATA", out colorData);
result.Load("COLORDATABUS", out colorDataBus);
result.Load("COLORMEM", out colorMemory, colorMemory.Length);
result.Load("DISPLAYENABLED", out displayEnabled);
result.Load("IDLE", out idle);
result.Load("PLOTTERBUFFERINDEX", out plotterBufferIndex);
result.Load("PLOTTERDATA", out plotterData);
result.Load("PLOTTERDATABUFFER", out plotterDataBuffer, plotterDataBuffer.Length);
result.Load("PLOTTERDELAY", out plotterDelay);
result.Load("PLOTTERPIXEL", out plotterPixel);
result.Load("PLOTTERPIXELBUFFER", out plotterPixelBuffer, plotterPixelBuffer.Length);
result.Load("RASTERINTERRUPTLINE", out rasterInterruptLine);
result.Load("RASTERX", out rasterX);
result.Load("REFRESHADDRESS", out refreshAddress);
// pipeline
result.Load("CYCLE", out cycle);
result.Load("PIPELINEGACCESS", out pipelineGAccess);
result.Load("PIPELINEMEMORYBUSY", out pipelineMemoryBusy);
// sprites
for (int i = 0; i < 8; i++)
{
string iTag = i.ToString();
result.Load("MC" + iTag, out sprites[i].MC);
result.Load("MCBASE" + iTag, out sprites[i].MCBASE);
result.Load("MD" + iTag, out sprites[i].MD);
result.Load("MDMA" + iTag, out sprites[i].MDMA);
result.Load("MPTR" + iTag, out sprites[i].MPTR);
result.Load("MSR" + iTag, out sprites[i].MSR);
result.Load("MxXEToggle" + iTag, out sprites[i].MxXEToggle);
result.Load("MxYEToggle" + iTag, out sprites[i].MxYEToggle);
result.Load("MxC" + iTag, out sprites[i].MxC);
result.Load("MxD" + iTag, out sprites[i].MxD);
result.Load("MxDP" + iTag, out sprites[i].MxDP);
result.Load("MxE" + iTag, out sprites[i].MxE);
result.Load("MxM" + iTag, out sprites[i].MxM);
result.Load("MxMC" + iTag, out sprites[i].MxMC);
result.Load("MxX" + iTag, out sprites[i].MxX);
result.Load("MxXE" + iTag, out sprites[i].MxXE);
result.Load("MxY" + iTag, out sprites[i].MxY);
result.Load("MxYE" + iTag, out sprites[i].MxYE);
}
UpdateInterrupts();
UpdateBorder();
UpdatePlotter();
}
}
}
}
}