A7800: Audio Overhaul
This commit is contained in:
parent
6dbbc9256a
commit
ca52715673
|
@ -7,6 +7,9 @@
|
||||||
;5 = Rescue on Fractulus
|
;5 = Rescue on Fractulus
|
||||||
;6 = Dev Cart
|
;6 = Dev Cart
|
||||||
|
|
||||||
|
md5:03DAA19B7AAE2D27E61F2A4DBE3B9B79 MUSIC A78 PAL=true;board=0;Pokey=true
|
||||||
|
md5:F5150C0FC1948832211E57852ABB0C6E Utility Cart A78 NTSC=true;board=0;Pokey=true
|
||||||
|
md5:F9FA5107ED213E709858D8876359309E Pokey Test A78 NTSC=true;board=0;Pokey=true
|
||||||
md5:0D9452D4DB4D1E1CF843F4F10605EB7D Dev Cart A78 NTSC=true;board=0
|
md5:0D9452D4DB4D1E1CF843F4F10605EB7D Dev Cart A78 NTSC=true;board=0
|
||||||
md5:31FBCF03946E804FC2D77CCA5D61C928 Mode Test A78 NTSC=true;board=0
|
md5:31FBCF03946E804FC2D77CCA5D61C928 Mode Test A78 NTSC=true;board=0
|
||||||
md5:91041AADD1700A7A4076F4005F2C362F Diagnostics A78 NTSC=true;board=0
|
md5:91041AADD1700A7A4076F4005F2C362F Diagnostics A78 NTSC=true;board=0
|
||||||
|
|
|
@ -46,6 +46,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
public byte lg_1_trigger_hit;
|
public byte lg_1_trigger_hit;
|
||||||
public byte lg_2_trigger_hit;
|
public byte lg_2_trigger_hit;
|
||||||
|
|
||||||
|
public int temp_s_tia;
|
||||||
|
public int temp_s_pokey;
|
||||||
|
public int samp_l, samp_c;
|
||||||
|
public uint master_audio_clock;
|
||||||
|
public int temp;
|
||||||
|
|
||||||
// there are 4 maria cycles in a CPU cycle (fast access, both NTSC and PAL)
|
// there are 4 maria cycles in a CPU cycle (fast access, both NTSC and PAL)
|
||||||
// if the 6532 or TIA are accessed (PC goes to one of those addresses) the next access will be slower by 1/2 a CPU cycle
|
// if the 6532 or TIA are accessed (PC goes to one of those addresses) the next access will be slower by 1/2 a CPU cycle
|
||||||
// i.e. it will take 6 Maria cycles instead of 4
|
// i.e. it will take 6 Maria cycles instead of 4
|
||||||
|
@ -159,10 +165,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
// do the audio sampling
|
// do the audio sampling
|
||||||
if (tia._hsyncCnt == 113 || tia._hsyncCnt == 340)
|
if (tia._hsyncCnt == 113 || tia._hsyncCnt == 340)
|
||||||
{
|
{
|
||||||
tia.Execute(0);
|
temp_s_tia = tia.Execute(0);
|
||||||
|
|
||||||
// even though its clocked seperately, we sample the Pokey here
|
// even though its clocked seperately, we sample the Pokey here
|
||||||
if (is_pokey) { pokey.sample(); }
|
//if (is_pokey) { pokey.sample(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// tick the m6532 timer, which is still active although not recommended to use
|
// tick the m6532 timer, which is still active although not recommended to use
|
||||||
|
@ -173,12 +179,29 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
m6532.Timer.Tick();
|
m6532.Timer.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the pokey chip ticks at the nominal clock rate (same as maria)
|
samp_l = temp_s_tia + 3 * temp_s_pokey;
|
||||||
|
|
||||||
|
if (samp_l != samp_c)
|
||||||
|
{
|
||||||
|
_blip.AddDelta(master_audio_clock, samp_l - samp_c);
|
||||||
|
samp_c = samp_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp++;
|
||||||
|
if (temp == 4)
|
||||||
|
{
|
||||||
|
// the pokey chip ticks at the nominal cpu speed, but is unaffected by cpu slowdown (I think)
|
||||||
if (is_pokey)
|
if (is_pokey)
|
||||||
{
|
{
|
||||||
pokey.Tick();
|
pokey.Tick();
|
||||||
|
temp_s_pokey = pokey.sample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
master_audio_clock++;
|
||||||
|
temp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (cpu_cycle <= (2 + (slow_access ? 1 : 0)))
|
if (cpu_cycle <= (2 + (slow_access ? 1 : 0)))
|
||||||
{
|
{
|
||||||
cpu_is_haltable = true;
|
cpu_is_haltable = true;
|
||||||
|
@ -312,6 +335,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
maria = null;
|
maria = null;
|
||||||
tia = null;
|
tia = null;
|
||||||
m6532 = null;
|
m6532 = null;
|
||||||
|
DisposeSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,7 +381,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
#region Sound provider
|
#region Sound provider
|
||||||
|
|
||||||
private int _spf;
|
private BlipBuffer _blip = new BlipBuffer(4096);
|
||||||
|
|
||||||
public bool CanProvideAsync => false;
|
public bool CanProvideAsync => false;
|
||||||
|
|
||||||
|
@ -373,21 +397,21 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||||
{
|
{
|
||||||
short[] ret = new short[_spf * 2];
|
_blip.EndFrame(master_audio_clock);
|
||||||
|
|
||||||
nsamp = _spf;
|
nsamp = _blip.SamplesAvailable();
|
||||||
tia.GetSamples(ret);
|
|
||||||
if (is_pokey)
|
samples = new short[nsamp * 2];
|
||||||
|
|
||||||
|
_blip.ReadSamples(samples, nsamp, true);
|
||||||
|
|
||||||
|
for (int i = 0; i < nsamp * 2; i += 2)
|
||||||
{
|
{
|
||||||
short[] ret2 = new short[_spf * 2];
|
samples[i + 1] = samples[i];
|
||||||
pokey.GetSamples(ret2);
|
|
||||||
for (int i = 0; i < _spf * 2; i ++)
|
|
||||||
{
|
|
||||||
ret[i] += (short)(ret2[i] * 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
samples = ret;
|
master_audio_clock = 0;
|
||||||
|
temp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetSamplesAsync(short[] samples)
|
public void GetSamplesAsync(short[] samples)
|
||||||
|
@ -398,7 +422,16 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
public void DiscardSamples()
|
public void DiscardSamples()
|
||||||
{
|
{
|
||||||
tia.AudioClocks = 0;
|
tia.AudioClocks = 0;
|
||||||
if (is_pokey) { pokey.AudioClocks = 0; }
|
master_audio_clock = 0;
|
||||||
|
_blip.Clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisposeSound()
|
||||||
|
{
|
||||||
|
_blip.Clear();
|
||||||
|
_blip.Dispose();
|
||||||
|
_blip = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -40,21 +40,14 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
private void SyncState(Serializer ser)
|
private void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
byte[] core = null;
|
|
||||||
if (ser.IsWriter)
|
|
||||||
{
|
|
||||||
var ms = new MemoryStream();
|
|
||||||
ms.Close();
|
|
||||||
core = ms.ToArray();
|
|
||||||
}
|
|
||||||
cpu.SyncState(ser);
|
cpu.SyncState(ser);
|
||||||
tia.SyncState(ser);
|
tia.SyncState(ser);
|
||||||
maria.SyncState(ser);
|
maria.SyncState(ser);
|
||||||
m6532.SyncState(ser);
|
m6532.SyncState(ser);
|
||||||
mapper.SyncState(ser);
|
mapper.SyncState(ser);
|
||||||
|
pokey.SyncState(ser);
|
||||||
|
|
||||||
ser.BeginSection("Atari7800");
|
ser.BeginSection("Atari7800");
|
||||||
ser.Sync("core", ref core, false);
|
|
||||||
ser.Sync("Lag", ref _lagcount);
|
ser.Sync("Lag", ref _lagcount);
|
||||||
ser.Sync("Frame", ref _frame);
|
ser.Sync("Frame", ref _frame);
|
||||||
ser.Sync("IsLag", ref _islag);
|
ser.Sync("IsLag", ref _islag);
|
||||||
|
@ -62,7 +55,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
ser.Sync("A7800_control_register", ref A7800_control_register);
|
ser.Sync("A7800_control_register", ref A7800_control_register);
|
||||||
ser.Sync("_isPAL", ref _isPAL);
|
ser.Sync("_isPAL", ref _isPAL);
|
||||||
ser.Sync("_spf", ref _spf);
|
|
||||||
|
|
||||||
ser.Sync("Maria_regs", ref Maria_regs, false);
|
ser.Sync("Maria_regs", ref Maria_regs, false);
|
||||||
ser.Sync("RAM", ref RAM, false);
|
ser.Sync("RAM", ref RAM, false);
|
||||||
|
@ -87,6 +79,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
ser.Sync("left_was_pressed", ref left_was_pressed);
|
ser.Sync("left_was_pressed", ref left_was_pressed);
|
||||||
ser.Sync("right_was_pressed", ref right_was_pressed);
|
ser.Sync("right_was_pressed", ref right_was_pressed);
|
||||||
|
|
||||||
|
ser.Sync("temp_s_tia", ref temp_s_tia);
|
||||||
|
ser.Sync("temp_s_pokey", ref temp_s_pokey);
|
||||||
|
ser.Sync("samp_l", ref samp_l);
|
||||||
|
ser.Sync("samp_c", ref samp_c);
|
||||||
|
ser.Sync("master_audio_clock", ref master_audio_clock);
|
||||||
|
ser.Sync("temp", ref temp);
|
||||||
|
|
||||||
ser.EndSection();
|
ser.EndSection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
CoreComm = comm;
|
CoreComm = comm;
|
||||||
|
|
||||||
|
_blip.SetRates(1789773, 44100);
|
||||||
|
|
||||||
_settings = (A7800Settings)settings ?? new A7800Settings();
|
_settings = (A7800Settings)settings ?? new A7800Settings();
|
||||||
_syncSettings = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings();
|
_syncSettings = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings();
|
||||||
_controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);
|
_controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);
|
||||||
|
@ -280,7 +282,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
_vidbuffer = new int[VirtualWidth * VirtualHeight];
|
_vidbuffer = new int[VirtualWidth * VirtualHeight];
|
||||||
|
|
||||||
_spf = (_frameHz > 55) ? 740 : 880;
|
master_audio_clock = 0;
|
||||||
|
samp_c = samp_l = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecFetch(ushort addr)
|
private void ExecFetch(ushort addr)
|
||||||
|
|
|
@ -22,8 +22,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
{
|
{
|
||||||
public A7800Hawk Core { get; set; }
|
public A7800Hawk Core { get; set; }
|
||||||
|
|
||||||
public readonly short[] LocalAudioCycles = new short[2000];
|
public int LocalAudioCycles;
|
||||||
public int AudioClocks;
|
|
||||||
|
|
||||||
// state variables
|
// state variables
|
||||||
public byte[] Regs = new byte[16];
|
public byte[] Regs = new byte[16];
|
||||||
|
@ -45,33 +44,15 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sample()
|
public int sample()
|
||||||
{
|
{
|
||||||
LocalAudioCycles[AudioClocks] += (short)(ch_vol[0] + ch_vol[1] + ch_vol[2] + ch_vol[3]);
|
LocalAudioCycles = 0;
|
||||||
AudioClocks++;
|
LocalAudioCycles += ch_vol[0];
|
||||||
}
|
LocalAudioCycles += ch_vol[1];
|
||||||
|
LocalAudioCycles += ch_vol[2];
|
||||||
|
LocalAudioCycles += ch_vol[3];
|
||||||
|
|
||||||
public void GetSamples(short[] samples)
|
return LocalAudioCycles;
|
||||||
{
|
|
||||||
if (AudioClocks > 0)
|
|
||||||
{
|
|
||||||
var samples31Khz = new short[AudioClocks]; // mono
|
|
||||||
|
|
||||||
for (int i = 0; i < AudioClocks; i++)
|
|
||||||
{
|
|
||||||
samples31Khz[i] = LocalAudioCycles[i];
|
|
||||||
LocalAudioCycles[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert from 31khz to 44khz
|
|
||||||
for (var i = 0; i < samples.Length / 2; i++)
|
|
||||||
{
|
|
||||||
samples[i * 2] = samples31Khz[(int)(((double)samples31Khz.Length / (double)(samples.Length / 2)) * i)];
|
|
||||||
samples[(i * 2) + 1] = samples[i * 2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioClocks = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ReadReg(int reg)
|
public byte ReadReg(int reg)
|
||||||
|
@ -136,20 +117,33 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
if (Regs[8].Bit(6))
|
if (Regs[8].Bit(6))
|
||||||
{
|
{
|
||||||
clock_ch[0] = true;
|
clock_ch[0] = true;
|
||||||
clock_ch[2] = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inc_ch[0]++;
|
inc_ch[0]++;
|
||||||
inc_ch[2]++;
|
|
||||||
if (Regs[8].Bit(0))
|
if (Regs[8].Bit(0))
|
||||||
{
|
{
|
||||||
if (inc_ch[0] >= 114) { inc_ch[0] = 0; clock_ch[0] = true; }
|
if (inc_ch[0] >= 114) { inc_ch[0] = 0; clock_ch[0] = true; }
|
||||||
if (inc_ch[2] >= 114) { inc_ch[2] = 0; clock_ch[2] = true; }
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inc_ch[0] >= 28) { inc_ch[0] = 0; clock_ch[0] = true; }
|
if (inc_ch[0] >= 28) { inc_ch[0] = 0; clock_ch[0] = true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Regs[8].Bit(5))
|
||||||
|
{
|
||||||
|
clock_ch[2] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inc_ch[2]++;
|
||||||
|
if (Regs[8].Bit(0))
|
||||||
|
{
|
||||||
|
if (inc_ch[2] >= 114) { inc_ch[2] = 0; clock_ch[2] = true; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (inc_ch[2] >= 28) { inc_ch[2] = 0; clock_ch[2] = true; }
|
if (inc_ch[2] >= 28) { inc_ch[2] = 0; clock_ch[2] = true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,6 +158,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
if (Regs[8].Bit(0))
|
if (Regs[8].Bit(0))
|
||||||
{
|
{
|
||||||
if (inc_ch[1] >= 114) { inc_ch[1] = 0; clock_ch[1] = true; }
|
if (inc_ch[1] >= 114) { inc_ch[1] = 0; clock_ch[1] = true; }
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -251,11 +246,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
else if ((Regs[i * 2 + 1] & 0xF0) == 0xA0)
|
else if ((Regs[i * 2 + 1] & 0xF0) == 0xA0)
|
||||||
{
|
{
|
||||||
// tone
|
// tone
|
||||||
if (ch_src[i])
|
|
||||||
{
|
|
||||||
ch_out[i] = !ch_out[i];
|
ch_out[i] = !ch_out[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if ((Regs[i * 2 + 1] & 0xF0) == 0xC0)
|
else if ((Regs[i * 2 + 1] & 0xF0) == 0xC0)
|
||||||
{
|
{
|
||||||
// 4 bit poly
|
// 4 bit poly
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
// current audio register state used to sample correct positions in the scanline (clrclk 0 and 114)
|
// 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 byte[] current_audio_register = new byte[6];
|
||||||
public readonly short[] LocalAudioCycles = new short[2000];
|
public int LocalAudioCycles;
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
|
@ -34,13 +34,16 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute TIA cycles
|
// Execute TIA cycles
|
||||||
public void Execute(int cycles)
|
public int Execute(int cycles)
|
||||||
{
|
{
|
||||||
LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2);
|
LocalAudioCycles = 0;
|
||||||
LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2);
|
LocalAudioCycles += (AUD[0].Cycle() / 2);
|
||||||
AudioClocks++;
|
LocalAudioCycles += (AUD[1].Cycle() / 2);
|
||||||
}
|
//AudioClocks++;
|
||||||
|
|
||||||
|
return LocalAudioCycles;
|
||||||
|
}
|
||||||
|
/*
|
||||||
public void GetSamples(short[] samples)
|
public void GetSamples(short[] samples)
|
||||||
{
|
{
|
||||||
if (AudioClocks > 0)
|
if (AudioClocks > 0)
|
||||||
|
@ -63,7 +66,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
||||||
|
|
||||||
AudioClocks = 0;
|
AudioClocks = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
public byte ReadMemory(ushort addr, bool peek)
|
public byte ReadMemory(ushort addr, bool peek)
|
||||||
{
|
{
|
||||||
var maskedAddr = (ushort)(addr & 0x000F);
|
var maskedAddr = (ushort)(addr & 0x000F);
|
||||||
|
|
|
@ -1073,8 +1073,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
|
|
||||||
public bool CanProvideAsync => false;
|
public bool CanProvideAsync => false;
|
||||||
|
|
||||||
public short[] AudioSamples = new short[150000];
|
|
||||||
|
|
||||||
public void SetSyncMode(SyncSoundMode mode)
|
public void SetSyncMode(SyncSoundMode mode)
|
||||||
{
|
{
|
||||||
if (mode != SyncSoundMode.Sync)
|
if (mode != SyncSoundMode.Sync)
|
||||||
|
|
Loading…
Reference in New Issue