mmc5: fix bug in pcm audio that i didn't even know about because nothing ever uses it at all. sunsoft 5b: implement audio. affects Gimmick(J). note that the audio emulation is rather incomplete.
This commit is contained in:
parent
c90d2dcd56
commit
bab873fa13
|
@ -442,6 +442,7 @@
|
|||
<Compile Include="QuickCollections.cs" />
|
||||
<Compile Include="Sound\CDAudio.cs" />
|
||||
<Compile Include="Sound\MMC5Audio.cs" />
|
||||
<Compile Include="Sound\Sunsoft5BAudio.cs" />
|
||||
<Compile Include="Sound\Utilities\BlipBuffer.cs" />
|
||||
<Compile Include="Sound\Utilities\DCFilter.cs" />
|
||||
<Compile Include="Sound\Utilities\Equalizer.cs" />
|
||||
|
|
|
@ -315,9 +315,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
bool ram;
|
||||
addr = MapPRG(addr, out ram);
|
||||
if (ram) return WRAM[addr];
|
||||
else return ROM[addr];
|
||||
byte ret;
|
||||
int mapaddr = MapPRG(addr, out ram);
|
||||
if (ram)
|
||||
ret = WRAM[mapaddr];
|
||||
else
|
||||
ret = ROM[mapaddr];
|
||||
if (addr < 0x4000)
|
||||
audio.ReadROMTrigger(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
class Sunsoft_5 : Sunsoft_FME7
|
||||
{
|
||||
Sound.Sunsoft5BAudio audio;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
//configure
|
||||
|
@ -22,14 +24,33 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
}
|
||||
|
||||
BaseConfigure();
|
||||
if (NES.apu != null)
|
||||
audio = new Sound.Sunsoft5BAudio(NES.apu.ExternalQueue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
//TODO - sound
|
||||
base.WritePRG(addr, value);
|
||||
int a = addr & 0xe000;
|
||||
if (a == 0x4000)
|
||||
audio.RegSelect(value);
|
||||
else if (a == 0x6000)
|
||||
audio.RegWrite(value);
|
||||
else
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
base.SyncState(ser);
|
||||
audio.SyncState(ser);
|
||||
}
|
||||
|
||||
public override void ClockCPU()
|
||||
{
|
||||
audio.Clock();
|
||||
base.ClockCPU();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Sound
|
||||
{
|
||||
// YM2149F variant
|
||||
// this implementation is quite incomplete
|
||||
// http://wiki.nesdev.com/w/index.php/Sunsoft_5B_audio
|
||||
public class Sunsoft5BAudio
|
||||
{
|
||||
class Pulse
|
||||
{
|
||||
Action<int> SendDiff;
|
||||
// regs
|
||||
int Period;
|
||||
bool Disable;
|
||||
int Volume;
|
||||
// state
|
||||
int clock;
|
||||
int sequence;
|
||||
int output;
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("Period", ref Period);
|
||||
ser.Sync("Disable", ref Disable);
|
||||
ser.Sync("Volume", ref Volume);
|
||||
ser.Sync("clock", ref clock);
|
||||
ser.Sync("sequence", ref sequence);
|
||||
ser.Sync("output", ref output);
|
||||
}
|
||||
|
||||
public Pulse(Action<int> SendDiff)
|
||||
{
|
||||
this.SendDiff = SendDiff;
|
||||
}
|
||||
|
||||
void CalcOut()
|
||||
{
|
||||
int newout = 1;
|
||||
if (!Disable)
|
||||
newout = sequence;
|
||||
newout *= Volume;
|
||||
if (newout != output)
|
||||
{
|
||||
SendDiff(newout - output);
|
||||
output = newout;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clock()
|
||||
{
|
||||
clock--;
|
||||
if (clock < 0)
|
||||
{
|
||||
clock = Period * 16;
|
||||
sequence ^= 1;
|
||||
CalcOut();
|
||||
}
|
||||
}
|
||||
public void WritePeriodLow(byte val)
|
||||
{
|
||||
Period &= 0xf00;
|
||||
Period |= val;
|
||||
}
|
||||
public void WritePeriodHigh(byte val)
|
||||
{
|
||||
Period &= 0x0ff;
|
||||
Period |= val << 8 & 0xf00;
|
||||
}
|
||||
public void SetToneDisable(bool disable)
|
||||
{
|
||||
Disable = disable;
|
||||
CalcOut();
|
||||
}
|
||||
public void SetVolume(byte val)
|
||||
{
|
||||
Volume = val & 15;
|
||||
CalcOut();
|
||||
}
|
||||
}
|
||||
|
||||
int RegNum;
|
||||
Pulse[] pulse = new Pulse[3];
|
||||
|
||||
public void RegSelect(byte val)
|
||||
{
|
||||
RegNum = val & 15;
|
||||
}
|
||||
public void RegWrite(byte val)
|
||||
{
|
||||
switch (RegNum)
|
||||
{
|
||||
case 0: pulse[0].WritePeriodLow(val); break;
|
||||
case 1: pulse[0].WritePeriodHigh(val); break;
|
||||
case 2: pulse[1].WritePeriodLow(val); break;
|
||||
case 3: pulse[1].WritePeriodHigh(val); break;
|
||||
case 4: pulse[2].WritePeriodLow(val); break;
|
||||
case 5: pulse[2].WritePeriodHigh(val); break;
|
||||
case 6: break; // noise period
|
||||
case 7: // also noise disable
|
||||
pulse[0].SetToneDisable(val.Bit(0));
|
||||
pulse[1].SetToneDisable(val.Bit(1));
|
||||
pulse[2].SetToneDisable(val.Bit(2));
|
||||
break;
|
||||
case 8: pulse[0].SetVolume(val); break; // also envelope enable
|
||||
case 9: pulse[1].SetVolume(val); break; // also envelope enable
|
||||
case 10: pulse[2].SetVolume(val); break; // also envelope enable
|
||||
case 11: break; // envelope low
|
||||
case 12: break; // envelope high
|
||||
case 13: break; // envelope params
|
||||
// ports 14 and 15 are not hooked up on Sunsoft 5B
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("Sunsoft5BAudio");
|
||||
ser.Sync("RegNum", ref RegNum);
|
||||
for (int i = 0; i < pulse.Length; i++)
|
||||
pulse[i].SyncState(ser);
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
Action<int> enqueuer;
|
||||
void PulseAddDiff(int val)
|
||||
{
|
||||
enqueuer(val * 250);
|
||||
}
|
||||
|
||||
public Sunsoft5BAudio(Action<int> enqueuer)
|
||||
{
|
||||
this.enqueuer = enqueuer;
|
||||
for (int i = 0; i < pulse.Length; i++)
|
||||
pulse[i] = new Pulse(PulseAddDiff);
|
||||
}
|
||||
|
||||
public void Clock()
|
||||
{
|
||||
for (int i = 0; i < pulse.Length; i++)
|
||||
pulse[i].Clock();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue