110 lines
2.9 KiB
C#
110 lines
2.9 KiB
C#
using System;
|
|
using VirtualNes.Core.Debug;
|
|
|
|
namespace VirtualNes.Core
|
|
{
|
|
public class APU
|
|
{
|
|
public const uint QUEUE_LENGTH = 8192;
|
|
|
|
private NES nes;
|
|
private byte exsound_select;
|
|
private APU_INTERNAL @internal = new APU_INTERNAL();
|
|
private int last_data;
|
|
private int last_diff;
|
|
protected short[] m_SoundBuffer = new short[256];
|
|
protected int[] lowpass_filter = new int[4];
|
|
protected QUEUE queue = new QUEUE();
|
|
protected QUEUE exqueue = new QUEUE();
|
|
protected bool[] m_bMute = new bool[16];
|
|
|
|
public APU(NES parent)
|
|
{
|
|
exsound_select = 0;
|
|
|
|
nes = parent;
|
|
@internal.SetParent(parent);
|
|
|
|
last_data = last_diff = 0;
|
|
|
|
Array.Clear(m_SoundBuffer, 0, m_SoundBuffer.Length);
|
|
Array.Clear(lowpass_filter, 0, lowpass_filter.Length);
|
|
|
|
for (int i = 0; i < m_bMute.Length; i++)
|
|
m_bMute[i] = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
internal void SyncDPCM(int cycles)
|
|
{
|
|
@internal.Sync(cycles);
|
|
}
|
|
|
|
internal byte Read(ushort addr)
|
|
{
|
|
return @internal.SyncRead(addr);
|
|
}
|
|
|
|
internal void Write(ushort addr, byte data)
|
|
{
|
|
// $4018偼VirtuaNES屌桳億乕僩
|
|
if (addr >= 0x4000 && addr <= 0x401F)
|
|
{
|
|
@internal.SyncWrite(addr, data);
|
|
SetQueue(nes.cpu.GetTotalCycles(), addr, data);
|
|
}
|
|
}
|
|
|
|
private void SetQueue(int writetime, ushort addr, byte data)
|
|
{
|
|
queue.data[queue.wrptr].time = writetime;
|
|
queue.data[queue.wrptr].addr = addr;
|
|
queue.data[queue.wrptr].data = data;
|
|
queue.wrptr++;
|
|
|
|
var newwrptr = (int)(queue.wrptr & (QUEUE_LENGTH - 1));
|
|
queue.wrptr = newwrptr;
|
|
|
|
if (queue.wrptr == queue.rdptr)
|
|
{
|
|
Debuger.LogError("queue overflow.");
|
|
}
|
|
}
|
|
|
|
private bool GetQueue(int writetime, ref QUEUEDATA ret)
|
|
{
|
|
if (queue.wrptr == queue.rdptr)
|
|
{
|
|
return false;
|
|
}
|
|
if (queue.data[queue.rdptr].time <= writetime)
|
|
{
|
|
ret = queue.data[queue.rdptr];
|
|
queue.rdptr++;
|
|
var newrdptr = (int)(queue.rdptr & (QUEUE_LENGTH - 1));
|
|
queue.rdptr = newrdptr;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public struct QUEUEDATA
|
|
{
|
|
public int time;
|
|
public ushort addr;
|
|
public byte data;
|
|
public byte reserved;
|
|
}
|
|
|
|
public class QUEUE
|
|
{
|
|
public int rdptr;
|
|
public int wrptr;
|
|
public QUEUEDATA[] data = new QUEUEDATA[8192];
|
|
}
|
|
}
|