diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
index 93f6a3b1ad..d7b2901d1e 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
@@ -126,10 +126,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private HMoveData _hmove;
private BallData _ball;
- private readonly Audio[] AUD = { new Audio(), new Audio() };
+ private readonly Audio AUD =new Audio();
// current audio register state used to sample correct positions in the scanline (clrclk 0 and 114)
- ////public byte[] current_audio_register = new byte[6];
public readonly short[] LocalAudioCycles = new short[2000];
private static int ReverseBits(int value, int bits)
@@ -809,8 +808,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
if (AudioClocks < 2000)
{
- LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2);
- LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2);
+ LocalAudioCycles[AudioClocks] += (short)(AUD.Cycle_L() / 2);
+ LocalAudioCycles[AudioClocks] += (short)(AUD.Cycle_R() / 2);
AudioClocks++;
}
}
@@ -1258,27 +1257,27 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (maskedAddr == 0x15) // AUDC0
{
- AUD[0].AUDC = (byte)(value & 15);
+ AUD.AUDC_L = (byte)(value & 15);
}
else if (maskedAddr == 0x16) // AUDC1
{
- AUD[1].AUDC = (byte)(value & 15);
+ AUD.AUDC_R = (byte)(value & 15);
}
else if (maskedAddr == 0x17) // AUDF0
{
- AUD[0].AUDF = (byte)((value & 31) + 1);
+ AUD.AUDF_L = (byte)((value & 31) + 1);
}
else if (maskedAddr == 0x18) // AUDF1
{
- AUD[1].AUDF = (byte)((value & 31) + 1);
+ AUD.AUDF_R = (byte)((value & 31) + 1);
}
else if (maskedAddr == 0x19) // AUDV0
{
- AUD[0].AUDV = (byte)(value & 15);
+ AUD.AUDV_L = (byte)(value & 15);
}
else if (maskedAddr == 0x1A) // AUDV1
{
- AUD[1].AUDV = (byte)(value & 15);
+ AUD.AUDV_R = (byte)(value & 15);
}
else if (maskedAddr == 0x1B) // GRP0
{
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
index 3c84e12bff..fa95102db1 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.Audio.cs
@@ -8,88 +8,98 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public class Audio
{
// noise/division control
- public byte AUDC = 0;
+ public byte AUDC_L = 0;
+ public byte AUDC_R = 0;
// frequency divider
- public byte AUDF = 1;
+ public byte AUDF_L = 1;
+ public byte AUDF_R = 1;
// volume
- public byte AUDV = 0;
+ public byte AUDV_L = 0;
+ public byte AUDV_R = 0;
// 2 state counter
- private bool sr1 = true;
+ private bool sr1_L = true;
+ private bool sr1_R = true;
// 4 bit shift register
- private int sr4 = 0x0f;
+ private int sr4_L = 0x0f;
+ private int sr4_R = 0x0f;
// 5 bit shift register
- private int sr5 = 0x1f;
+ private int sr5_L = 0x1f;
+ private int sr5_R = 0x1f;
// 9 bit shift register
- private int sr9 = 0x1ff;
+ private int sr9_L = 0x1ff;
+ private int sr9_R = 0x1ff;
// 3 state counter
- private int sr3 = 2;
+ private int sr3_L = 2;
+ private int sr3_R = 2;
// counter based off AUDF
- private byte freqcnt;
+ private byte freqcnt_L;
+ private byte freqcnt_R;
// latched audio value
- private bool on = true;
+ private bool on_L = true;
+ private bool on_R = true;
- private bool Run3()
+ private bool Run3_L()
{
- sr3++;
- if (sr3 == 3)
+ sr3_L++;
+ if (sr3_L == 3)
{
- sr3 = 0;
+ sr3_L = 0;
return true;
}
return false;
}
- private bool Run4()
+ private bool Run4_L()
{
- bool ret = (sr4 & 1) != 0;
- bool c = ((sr4 & 1) != 0) ^ ((sr4 & 2) != 0);
- sr4 = (sr4 >> 1) | (c ? 8 : 0);
+ bool ret = (sr4_L & 1) != 0;
+ bool c = ((sr4_L & 1) != 0) ^ ((sr4_L & 2) != 0);
+ sr4_L = (sr4_L >> 1) | (c ? 8 : 0);
return ret;
}
- private bool Run5()
+ private bool Run5_L()
{
- bool ret = (sr5 & 1) != 0;
- bool c = ((sr5 & 1) != 0) ^ ((sr5 & 4) != 0);
- sr5 = (sr5 >> 1) | (c ? 16 : 0);
+ bool ret = (sr5_L & 1) != 0;
+ bool c = ((sr5_L & 1) != 0) ^ ((sr5_L & 4) != 0);
+ sr5_L = (sr5_L >> 1) | (c ? 16 : 0);
return ret;
}
- private bool One4()
+ private bool One4_L()
{
- bool ret = (sr4 & 1) != 0;
- sr4 = (sr4 >> 1) | 8;
+ bool ret = (sr4_L & 1) != 0;
+ sr4_L = (sr4_L >> 1) | 8;
return ret;
}
- private bool One5()
+ private bool One5_L()
{
- bool ret = (sr5 & 1) != 0;
- sr5 = (sr5 >> 1) | 16;
+ bool ret = (sr5_L & 1) != 0;
+ sr5_L = (sr5_L >> 1) | 16;
return ret;
}
- private bool Run1()
+ private bool Run1_L()
{
- sr1 = !sr1;
- return !sr1;
+ sr1_L = !sr1_L;
+ return !sr1_L;
}
- private bool Run9()
+ private bool Run9_L()
{
- bool ret = (sr9 & 1) != 0;
- bool c = ((sr9 & 1) != 0) ^ ((sr9 & 16) != 0);
- sr9 = (sr9 >> 1) | (c ? 256 : 0);
+ bool ret = (sr9_L & 1) != 0;
+ bool c = ((sr9_L & 1) != 0) ^ ((sr9_L & 16) != 0);
+ sr9_L = (sr9_L >> 1) | (c ? 256 : 0);
return ret;
}
@@ -97,92 +107,92 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
/// call me approx 31k times a second
///
/// 16 bit audio sample
- public short Cycle()
+ public short Cycle_L()
{
- if (++freqcnt >= AUDF)
+ if (++freqcnt_L >= AUDF_L)
{
- freqcnt = 0;
- switch (AUDC)
+ freqcnt_L = 0;
+ switch (AUDC_L)
{
case 0x00:
case 0x0b:
// Both have a 1 s
- One5();
- on = One4();
+ One5_L();
+ on_L = One4_L();
break;
case 0x01:
// Both run, but the 5 bit is ignored
- on = Run4();
+ on_L = Run4_L();
//Run5();
break;
case 0x02:
- if ((sr5 & 0x0f) == 0 || (sr5 & 0x0f) == 0x0f)
+ if ((sr5_L & 0x0f) == 0 || (sr5_L & 0x0f) == 0x0f)
{
- on = Run4();
+ on_L = Run4_L();
}
- Run5();
+ Run5_L();
break;
case 0x03:
- if (Run5())
+ if (Run5_L())
{
- on = Run4();
+ on_L = Run4_L();
}
break;
case 0x04:
- Run5();
- One4();
- on = Run1();
+ Run5_L();
+ One4_L();
+ on_L = Run1_L();
break;
case 0x05:
- One5();
- Run4();
- on = Run1();
+ One5_L();
+ Run4_L();
+ on_L = Run1_L();
break;
case 0x06:
case 0x0a:
- Run5();
- if ((sr5 & 0x0f) == 0)
+ Run5_L();
+ if ((sr5_L & 0x0f) == 0)
{
- on = false;
+ on_L = false;
}
- else if ((sr5 & 0x0f) == 0x0f)
+ else if ((sr5_L & 0x0f) == 0x0f)
{
- on = true;
+ on_L = true;
}
break;
case 0x07:
case 0x09:
- on = Run5();
+ on_L = Run5_L();
break;
case 0x08:
- on = Run9();
+ on_L = Run9_L();
break;
case 0x0c:
case 0x0d:
- if (Run3())
+ if (Run3_L())
{
- on = Run1();
+ on_L = Run1_L();
}
break;
case 0x0e:
- if (Run3())
+ if (Run3_L())
{
goto case 0x06;
}
break;
case 0x0f:
- if (Run3())
+ if (Run3_L())
{
goto case 0x07;
}
@@ -191,21 +201,189 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
- return (short)(on ? AUDV * 1092 : 0);
+ return (short)(on_L ? AUDV_L * 1092 : 0);
+ }
+
+ private bool Run3_R()
+ {
+ sr3_R++;
+ if (sr3_R == 3)
+ {
+ sr3_R = 0;
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool Run4_R()
+ {
+ bool ret = (sr4_R & 1) != 0;
+ bool c = ((sr4_R & 1) != 0) ^ ((sr4_R & 2) != 0);
+ sr4_R = (sr4_R >> 1) | (c ? 8 : 0);
+ return ret;
+ }
+
+ private bool Run5_R()
+ {
+ bool ret = (sr5_R & 1) != 0;
+ bool c = ((sr5_R & 1) != 0) ^ ((sr5_R & 4) != 0);
+ sr5_R = (sr5_R >> 1) | (c ? 16 : 0);
+ return ret;
+ }
+
+ private bool One4_R()
+ {
+ bool ret = (sr4_R & 1) != 0;
+ sr4_R = (sr4_R >> 1) | 8;
+ return ret;
+ }
+
+ private bool One5_R()
+ {
+ bool ret = (sr5_R & 1) != 0;
+ sr5_R = (sr5_R >> 1) | 16;
+ return ret;
+ }
+
+ private bool Run1_R()
+ {
+ sr1_R = !sr1_R;
+ return !sr1_R;
+ }
+
+ private bool Run9_R()
+ {
+ bool ret = (sr9_R & 1) != 0;
+ bool c = ((sr9_R & 1) != 0) ^ ((sr9_R & 16) != 0);
+ sr9_R = (sr9_R >> 1) | (c ? 256 : 0);
+ return ret;
+ }
+
+ ///
+ /// call me approx 31k times a second
+ ///
+ /// 16 bit audio sample
+ public short Cycle_R()
+ {
+ if (++freqcnt_R >= AUDF_R)
+ {
+ freqcnt_R = 0;
+ switch (AUDC_R)
+ {
+ case 0x00:
+ case 0x0b:
+ // Both have a 1 s
+ One5_R();
+ on_R = One4_R();
+ break;
+
+ case 0x01:
+ // Both run, but the 5 bit is ignored
+ on_R = Run4_R();
+ //Run5();
+ break;
+ case 0x02:
+ if ((sr5_R & 0x0f) == 0 || (sr5_R & 0x0f) == 0x0f)
+ {
+ on_R = Run4_R();
+ }
+
+ Run5_R();
+ break;
+ case 0x03:
+ if (Run5_R())
+ {
+ on_R = Run4_R();
+ }
+
+ break;
+
+ case 0x04:
+ Run5_R();
+ One4_R();
+ on_R = Run1_R();
+ break;
+
+ case 0x05:
+ One5_R();
+ Run4_R();
+ on_R = Run1_R();
+ break;
+
+ case 0x06:
+ case 0x0a:
+ Run5_R();
+ if ((sr5_R & 0x0f) == 0)
+ {
+ on_R = false;
+ }
+ else if ((sr5_R & 0x0f) == 0x0f)
+ {
+ on_R = true;
+ }
+
+ break;
+
+ case 0x07:
+ case 0x09:
+ on_R = Run5_R();
+ break;
+
+ case 0x08:
+ on_R = Run9_R();
+ break;
+ case 0x0c:
+ case 0x0d:
+ if (Run3_R())
+ {
+ on_R = Run1_R();
+ }
+
+ break;
+ case 0x0e:
+ if (Run3_R())
+ {
+ goto case 0x06;
+ }
+
+ break;
+ case 0x0f:
+ if (Run3_R())
+ {
+ goto case 0x07;
+ }
+
+ break;
+ }
+ }
+
+ return (short)(on_R ? AUDV_R * 1092 : 0);
}
public void SyncState(Serializer ser)
{
- ser.Sync(nameof(AUDC), ref AUDC);
- ser.Sync(nameof(AUDF), ref AUDF);
- ser.Sync(nameof(AUDV), ref AUDV);
- ser.Sync(nameof(sr1), ref sr1);
- ser.Sync(nameof(sr3), ref sr3);
- ser.Sync(nameof(sr4), ref sr4);
- ser.Sync(nameof(sr5), ref sr5);
- ser.Sync(nameof(sr9), ref sr9);
- ser.Sync(nameof(freqcnt), ref freqcnt);
- ser.Sync(nameof(on), ref on);
+ ser.Sync(nameof(AUDC_L), ref AUDC_L);
+ ser.Sync(nameof(AUDF_L), ref AUDF_L);
+ ser.Sync(nameof(AUDV_L), ref AUDV_L);
+ ser.Sync(nameof(sr1_L), ref sr1_L);
+ ser.Sync(nameof(sr3_L), ref sr3_L);
+ ser.Sync(nameof(sr4_L), ref sr4_L);
+ ser.Sync(nameof(sr5_L), ref sr5_L);
+ ser.Sync(nameof(sr9_L), ref sr9_L);
+ ser.Sync(nameof(freqcnt_L), ref freqcnt_L);
+ ser.Sync(nameof(on_L), ref on_L);
+
+ ser.Sync(nameof(AUDC_R), ref AUDC_R);
+ ser.Sync(nameof(AUDF_R), ref AUDF_R);
+ ser.Sync(nameof(AUDV_R), ref AUDV_R);
+ ser.Sync(nameof(sr1_R), ref sr1_R);
+ ser.Sync(nameof(sr3_R), ref sr3_R);
+ ser.Sync(nameof(sr4_R), ref sr4_R);
+ ser.Sync(nameof(sr5_R), ref sr5_R);
+ ser.Sync(nameof(sr9_R), ref sr9_R);
+ ser.Sync(nameof(freqcnt_R), ref freqcnt_R);
+ ser.Sync(nameof(on_R), ref on_R);
}
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
index 43ad77adb1..252f74e644 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
@@ -72,6 +72,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync(nameof(AudioClocks), ref AudioClocks);
ser.Sync(nameof(New_Frame), ref New_Frame);
+ ser.BeginSection("Audio");
+ AUD.SyncState(ser);
+ ser.EndSection();
+
ser.BeginSection("Player0");
_player0.SyncState(ser);
ser.EndSection();