APU补全中
This commit is contained in:
parent
b8c116aa28
commit
8952b842b1
@ -60,7 +60,16 @@ namespace VirtualNes.Core
|
|||||||
m_bMute[i] = true;
|
m_bMute[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose()
|
||||||
|
{
|
||||||
|
@internal.Dispose();
|
||||||
|
vrc6.Dispose();
|
||||||
|
vrc7.Dispose();
|
||||||
|
mmc5.Dispose();
|
||||||
|
fds.Dispose();
|
||||||
|
n106.Dispose();
|
||||||
|
fme7.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private int[] vol = new int[24];
|
private int[] vol = new int[24];
|
||||||
static double cutofftemp = (2.0 * 3.141592653579 * 40.0);
|
static double cutofftemp = (2.0 * 3.141592653579 * 40.0);
|
||||||
|
@ -1,36 +1,219 @@
|
|||||||
using System;
|
using Codice.CM.Client.Differences;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class APU_MMC5 : APU_INTERFACE
|
public class APU_MMC5 : APU_INTERFACE
|
||||||
{
|
{
|
||||||
|
public const int RECTANGLE_VOL_SHIFT = 8;
|
||||||
|
public const int DAOUT_VOL_SHIFT = 6;
|
||||||
|
|
||||||
SYNCRECTANGLE sch0 = new SYNCRECTANGLE();
|
SYNCRECTANGLE sch0 = new SYNCRECTANGLE();
|
||||||
SYNCRECTANGLE sch1 = new SYNCRECTANGLE();
|
SYNCRECTANGLE sch1 = new SYNCRECTANGLE();
|
||||||
|
RECTANGLE ch0 = new RECTANGLE();
|
||||||
|
RECTANGLE ch1 = new RECTANGLE();
|
||||||
|
|
||||||
|
byte reg5010;
|
||||||
|
byte reg5011;
|
||||||
|
byte reg5015;
|
||||||
|
byte sync_reg5015;
|
||||||
|
int FrameCycle;
|
||||||
|
float cpu_clock;
|
||||||
|
int cycle_rate;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
static int[] vbl_length = new int[32];
|
||||||
|
static int[] duty_lut = new int[4];
|
||||||
|
|
||||||
|
static int[] decay_lut = new int[16];
|
||||||
|
static int[] vbl_lut = new int[32];
|
||||||
|
|
||||||
|
public APU_MMC5()
|
||||||
|
{
|
||||||
|
// 仮設定
|
||||||
|
Reset(APU_INTERFACE.APU_CLOCK, 22050);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Reset(float fClock, int nRate)
|
public override void Reset(float fClock, int nRate)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
sch0.ZeroMemory();
|
||||||
|
sch1.ZeroMemory();
|
||||||
|
|
||||||
|
reg5010 = reg5011 = reg5015 = 0;
|
||||||
|
|
||||||
|
sync_reg5015 = 0;
|
||||||
|
FrameCycle = 0;
|
||||||
|
|
||||||
|
Setup(fClock, nRate);
|
||||||
|
|
||||||
|
for (ushort addr = 0x5000; addr <= 0x5015; addr++)
|
||||||
|
{
|
||||||
|
Write(addr, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Setup(float fClock, int nRate)
|
public override void Setup(float fClock, int nRate)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
cpu_clock = fClock;
|
||||||
|
cycle_rate = (int)(fClock * 65536.0f / nRate);
|
||||||
|
|
||||||
|
// Create Tables
|
||||||
|
int i;
|
||||||
|
int samples = (int)(nRate / 60.0f);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
decay_lut[i] = (i + 1) * samples * 5;
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
vbl_lut[i] = vbl_length[i] * samples * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(ushort addr, byte data)
|
public override void Write(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
switch (addr)
|
||||||
}
|
{
|
||||||
|
// MMC5 CH0 rectangle
|
||||||
public override int Process(int channel)
|
case 0x5000:
|
||||||
{
|
ch0.reg[0] = data;
|
||||||
//todo : 实现
|
ch0.volume = (byte)(data & 0x0F);
|
||||||
return 0;
|
ch0.holdnote = (byte)(data & 0x20);
|
||||||
|
ch0.fixed_envelope = (byte)(data & 0x10);
|
||||||
|
ch0.env_decay = decay_lut[data & 0x0F];
|
||||||
|
ch0.duty_flip = duty_lut[data >> 6];
|
||||||
|
break;
|
||||||
|
case 0x5001:
|
||||||
|
ch0.reg[1] = data;
|
||||||
|
break;
|
||||||
|
case 0x5002:
|
||||||
|
ch0.reg[2] = data;
|
||||||
|
ch0.freq = INT2FIX(((ch0.reg[3] & 0x07) << 8) + data + 1);
|
||||||
|
break;
|
||||||
|
case 0x5003:
|
||||||
|
ch0.reg[3] = data;
|
||||||
|
ch0.vbl_length = vbl_lut[data >> 3];
|
||||||
|
ch0.env_vol = 0;
|
||||||
|
ch0.freq = INT2FIX(((data & 0x07) << 8) + ch0.reg[2] + 1);
|
||||||
|
if ((reg5015 & 0x01) != 0)
|
||||||
|
ch0.enable = 0xFF;
|
||||||
|
break;
|
||||||
|
// MMC5 CH1 rectangle
|
||||||
|
case 0x5004:
|
||||||
|
ch1.reg[0] = data;
|
||||||
|
ch1.volume = (byte)(data & 0x0F);
|
||||||
|
ch1.holdnote = (byte)(data & 0x20);
|
||||||
|
ch1.fixed_envelope = (byte)(data & 0x10);
|
||||||
|
ch1.env_decay = decay_lut[data & 0x0F];
|
||||||
|
ch1.duty_flip = duty_lut[data >> 6];
|
||||||
|
break;
|
||||||
|
case 0x5005:
|
||||||
|
ch1.reg[1] = data;
|
||||||
|
break;
|
||||||
|
case 0x5006:
|
||||||
|
ch1.reg[2] = data;
|
||||||
|
ch1.freq = INT2FIX(((ch1.reg[3] & 0x07) << 8) + data + 1);
|
||||||
|
break;
|
||||||
|
case 0x5007:
|
||||||
|
ch1.reg[3] = data;
|
||||||
|
ch1.vbl_length = vbl_lut[data >> 3];
|
||||||
|
ch1.env_vol = 0;
|
||||||
|
ch1.freq = INT2FIX(((data & 0x07) << 8) + ch1.reg[2] + 1);
|
||||||
|
if ((reg5015 & 0x02) != 0)
|
||||||
|
ch1.enable = 0xFF;
|
||||||
|
break;
|
||||||
|
case 0x5010:
|
||||||
|
reg5010 = data;
|
||||||
|
break;
|
||||||
|
case 0x5011:
|
||||||
|
reg5011 = data;
|
||||||
|
break;
|
||||||
|
case 0x5012:
|
||||||
|
case 0x5013:
|
||||||
|
case 0x5014:
|
||||||
|
break;
|
||||||
|
case 0x5015:
|
||||||
|
reg5015 = data;
|
||||||
|
if ((reg5015 & 0x01) != 0)
|
||||||
|
{
|
||||||
|
ch0.enable = 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch0.enable = 0;
|
||||||
|
ch0.vbl_length = 0;
|
||||||
|
}
|
||||||
|
if ((reg5015 & 0x02) != 0)
|
||||||
|
{
|
||||||
|
ch1.enable = 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch1.enable = 0;
|
||||||
|
ch1.vbl_length = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SyncWrite(ushort addr, byte data)
|
internal void SyncWrite(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
switch (addr)
|
||||||
|
{
|
||||||
|
// MMC5 CH0 rectangle
|
||||||
|
case 0x5000:
|
||||||
|
sch0.reg[0] = data;
|
||||||
|
sch0.holdnote = (byte)(data & 0x20);
|
||||||
|
break;
|
||||||
|
case 0x5001:
|
||||||
|
case 0x5002:
|
||||||
|
sch0.reg[addr & 3] = data;
|
||||||
|
break;
|
||||||
|
case 0x5003:
|
||||||
|
sch0.reg[3] = data;
|
||||||
|
sch0.vbl_length = vbl_length[data >> 3];
|
||||||
|
if ((sync_reg5015 & 0x01) != 0)
|
||||||
|
sch0.enable = 0xFF;
|
||||||
|
break;
|
||||||
|
// MMC5 CH1 rectangle
|
||||||
|
case 0x5004:
|
||||||
|
sch1.reg[0] = data;
|
||||||
|
sch1.holdnote = (byte)(data & 0x20);
|
||||||
|
break;
|
||||||
|
case 0x5005:
|
||||||
|
case 0x5006:
|
||||||
|
sch1.reg[addr & 3] = data;
|
||||||
|
break;
|
||||||
|
case 0x5007:
|
||||||
|
sch1.reg[3] = data;
|
||||||
|
sch1.vbl_length = vbl_length[data >> 3];
|
||||||
|
if ((sync_reg5015 & 0x02) != 0)
|
||||||
|
sch1.enable = 0xFF;
|
||||||
|
break;
|
||||||
|
case 0x5010:
|
||||||
|
case 0x5011:
|
||||||
|
case 0x5012:
|
||||||
|
case 0x5013:
|
||||||
|
case 0x5014:
|
||||||
|
break;
|
||||||
|
case 0x5015:
|
||||||
|
sync_reg5015 = data;
|
||||||
|
if ((sync_reg5015 & 0x01) != 0)
|
||||||
|
{
|
||||||
|
sch0.enable = 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sch0.enable = 0;
|
||||||
|
sch0.vbl_length = 0;
|
||||||
|
}
|
||||||
|
if ((sync_reg5015 & 0x02) != 0)
|
||||||
|
{
|
||||||
|
sch1.enable = 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sch1.enable = 0;
|
||||||
|
sch1.vbl_length = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal byte SyncRead(ushort addr)
|
internal byte SyncRead(ushort addr)
|
||||||
@ -46,6 +229,118 @@ namespace VirtualNes.Core
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Sync(int cycles)
|
||||||
|
{
|
||||||
|
FrameCycle += cycles;
|
||||||
|
if (FrameCycle >= 7457 * 5 / 2)
|
||||||
|
{
|
||||||
|
FrameCycle -= 7457 * 5 / 2;
|
||||||
|
|
||||||
|
if (sch0.enable != 0 && sch0.holdnote == 0)
|
||||||
|
{
|
||||||
|
if ((sch0.vbl_length) != 0)
|
||||||
|
{
|
||||||
|
sch0.vbl_length--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sch1.enable != 0 && sch1.holdnote == 0)
|
||||||
|
{
|
||||||
|
if ((sch1.vbl_length) != 0)
|
||||||
|
{
|
||||||
|
sch1.vbl_length--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Process(int channel)
|
||||||
|
{
|
||||||
|
switch (channel)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return RectangleRender(ch0);
|
||||||
|
case 1:
|
||||||
|
return RectangleRender(ch1);
|
||||||
|
case 2:
|
||||||
|
return reg5011 << DAOUT_VOL_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int RectangleRender(RECTANGLE ch)
|
||||||
|
{
|
||||||
|
if (ch.enable == 0 || ch.vbl_length <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// vbl length counter
|
||||||
|
if (ch.holdnote == 0)
|
||||||
|
ch.vbl_length -= 5;
|
||||||
|
|
||||||
|
// envelope unit
|
||||||
|
ch.env_phase -= 5 * 4;
|
||||||
|
while (ch.env_phase < 0)
|
||||||
|
{
|
||||||
|
ch.env_phase += ch.env_decay;
|
||||||
|
if ((ch.holdnote) != 0)
|
||||||
|
ch.env_vol = (byte)((ch.env_vol + 1) & 0x0F);
|
||||||
|
else if (ch.env_vol < 0x0F)
|
||||||
|
ch.env_vol++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch.freq < INT2FIX(8))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int volume;
|
||||||
|
if ((ch.fixed_envelope) != 0)
|
||||||
|
volume = ch.volume;
|
||||||
|
else
|
||||||
|
volume = (0x0F - ch.env_vol);
|
||||||
|
|
||||||
|
int output = volume << RECTANGLE_VOL_SHIFT;
|
||||||
|
|
||||||
|
ch.phaseacc -= cycle_rate;
|
||||||
|
if (ch.phaseacc >= 0)
|
||||||
|
{
|
||||||
|
if (ch.adder < ch.duty_flip)
|
||||||
|
ch.output_vol = output;
|
||||||
|
else
|
||||||
|
ch.output_vol = -output;
|
||||||
|
return ch.output_vol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch.freq > cycle_rate)
|
||||||
|
{
|
||||||
|
ch.phaseacc += ch.freq;
|
||||||
|
ch.adder = (ch.adder + 1) & 0x0F;
|
||||||
|
if (ch.adder < ch.duty_flip)
|
||||||
|
ch.output_vol = output;
|
||||||
|
else
|
||||||
|
ch.output_vol = -output;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 加重平均
|
||||||
|
int num_times, total;
|
||||||
|
num_times = total = 0;
|
||||||
|
while (ch.phaseacc < 0)
|
||||||
|
{
|
||||||
|
ch.phaseacc += ch.freq;
|
||||||
|
ch.adder = (ch.adder + 1) & 0x0F;
|
||||||
|
if (ch.adder < ch.duty_flip)
|
||||||
|
total += output;
|
||||||
|
else
|
||||||
|
total -= output;
|
||||||
|
num_times++;
|
||||||
|
}
|
||||||
|
ch.output_vol = total / num_times;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ch.output_vol;
|
||||||
|
}
|
||||||
|
|
||||||
public class SYNCRECTANGLE
|
public class SYNCRECTANGLE
|
||||||
{
|
{
|
||||||
// For sync
|
// For sync
|
||||||
@ -54,6 +349,38 @@ namespace VirtualNes.Core
|
|||||||
public byte holdnote;
|
public byte holdnote;
|
||||||
public byte[] dummy = new byte[2];
|
public byte[] dummy = new byte[2];
|
||||||
public int vbl_length;
|
public int vbl_length;
|
||||||
|
|
||||||
|
public void ZeroMemory()
|
||||||
|
{
|
||||||
|
Array.Clear(reg, 0, reg.Length);
|
||||||
|
enable = 0;
|
||||||
|
holdnote = 0;
|
||||||
|
Array.Clear(dummy, 0, dummy.Length);
|
||||||
|
vbl_length = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RECTANGLE
|
||||||
|
{
|
||||||
|
public byte[] reg = new byte[4];
|
||||||
|
public byte enable;
|
||||||
|
|
||||||
|
public int vbl_length;
|
||||||
|
|
||||||
|
public int phaseacc;
|
||||||
|
public int freq;
|
||||||
|
|
||||||
|
public int output_vol;
|
||||||
|
public byte fixed_envelope;
|
||||||
|
public byte holdnote;
|
||||||
|
public byte volume;
|
||||||
|
|
||||||
|
public byte env_vol;
|
||||||
|
public int env_phase;
|
||||||
|
public int env_decay;
|
||||||
|
|
||||||
|
public int adder;
|
||||||
|
public int duty_flip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,95 @@
|
|||||||
namespace VirtualNes.Core
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class APU_VRC7 : APU_INTERFACE
|
public class APU_VRC7 : APU_INTERFACE
|
||||||
{
|
{
|
||||||
|
OPLL VRC7_OPLL;
|
||||||
|
byte address;
|
||||||
|
|
||||||
|
public APU_VRC7()
|
||||||
|
{
|
||||||
|
Emu2413API.OPLL_init(3579545, 22050); // 仮のサンプリングレート
|
||||||
|
VRC7_OPLL = Emu2413API.OPLL_new();
|
||||||
|
|
||||||
|
if (VRC7_OPLL != null)
|
||||||
|
{
|
||||||
|
Emu2413API.OPLL_reset(VRC7_OPLL);
|
||||||
|
Emu2413API.OPLL_reset_patch(VRC7_OPLL, Emu2413API.OPLL_VRC7_TONE);
|
||||||
|
VRC7_OPLL.masterVolume = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仮設定
|
||||||
|
Reset(APU_CLOCK, 22050);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if (VRC7_OPLL != null)
|
||||||
|
{
|
||||||
|
Emu2413API.OPLL_delete(VRC7_OPLL);
|
||||||
|
VRC7_OPLL = null;
|
||||||
|
// OPLL_close(); // 無くても良い(中身無し)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Reset(float fClock, int nRate)
|
public override void Reset(float fClock, int nRate)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
if (VRC7_OPLL != null)
|
||||||
|
{
|
||||||
|
Emu2413API.OPLL_reset(VRC7_OPLL);
|
||||||
|
Emu2413API.OPLL_reset_patch(VRC7_OPLL, Emu2413API.OPLL_VRC7_TONE);
|
||||||
|
VRC7_OPLL.masterVolume = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
address = 0;
|
||||||
|
|
||||||
|
Setup(fClock, nRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Setup(float fClock, int nRate)
|
public override void Setup(float fClock, int nRate)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
Emu2413API.OPLL_setClock((UInt32)(fClock * 2.0f), (UInt32)nRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(ushort addr, byte data)
|
public override void Write(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
if (VRC7_OPLL != null)
|
||||||
|
{
|
||||||
|
if (addr == 0x9010)
|
||||||
|
{
|
||||||
|
address = data;
|
||||||
|
}
|
||||||
|
else if (addr == 0x9030)
|
||||||
|
{
|
||||||
|
Emu2413API.OPLL_writeReg(VRC7_OPLL, address, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Process(int channel)
|
public override int Process(int channel)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
if (VRC7_OPLL != null)
|
||||||
|
return Emu2413API.OPLL_calc(VRC7_OPLL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] blkmul = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f };
|
||||||
|
public override int GetFreq(int channel)
|
||||||
|
{
|
||||||
|
if (VRC7_OPLL != null && channel < 8)
|
||||||
|
{
|
||||||
|
int fno = ((VRC7_OPLL.reg[0x20 + channel] & 0x01) << 8) + VRC7_OPLL.reg[0x10 + channel];
|
||||||
|
int blk = (VRC7_OPLL.reg[0x20 + channel] >> 1) & 0x07;
|
||||||
|
|
||||||
|
if ((VRC7_OPLL.reg[0x20 + channel] & 0x10) != 0)
|
||||||
|
{
|
||||||
|
return (int)((256.0d * (double)fno * blkmul[blk]) / ((double)(1 << 18) / (3579545.0 / 72.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,36 @@ namespace VirtualNes.Core
|
|||||||
public UInt32 noiseB_idx;
|
public UInt32 noiseB_idx;
|
||||||
public UInt32 noiseA_dphase;
|
public UInt32 noiseA_dphase;
|
||||||
public UInt32 noiseB_dphase;
|
public UInt32 noiseB_dphase;
|
||||||
|
|
||||||
|
public int masterVolume; /* 0min -- 64 -- 127 max (Liner) */
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Emu2413API
|
public static class Emu2413API
|
||||||
{
|
{
|
||||||
|
/* Bits for Pitch and Amp modulator */
|
||||||
|
public const int PM_PG_BITS = 8;
|
||||||
|
public const int PM_PG_WIDTH = 1 << PM_PG_BITS;
|
||||||
|
public const int PM_DP_BITS = 16;
|
||||||
|
public const int PM_DP_WIDTH = (1 << PM_DP_BITS);
|
||||||
|
public const int AM_PG_BITS = 8;
|
||||||
|
public const int AM_PG_WIDTH = (1 << AM_PG_BITS);
|
||||||
|
public const int AM_DP_BITS = 16;
|
||||||
|
public const int AM_DP_WIDTH = (1 << AM_DP_BITS);
|
||||||
|
|
||||||
|
/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
|
||||||
|
public const int PM_AMP_BITS = 8;
|
||||||
|
public const int PM_AMP = (1 << PM_AMP_BITS);
|
||||||
|
|
||||||
|
/* PM speed(Hz) and depth(cent) */
|
||||||
|
public const double PM_SPEED = 6.4d;
|
||||||
|
public const double PM_DEPTH = 13.75d;
|
||||||
|
|
||||||
|
public const int OPLL_2413_TONE = 0;
|
||||||
|
public const int OPLL_VRC7_TONE = 1;
|
||||||
|
|
||||||
|
static int[] pmtable = new int[PM_PG_WIDTH];
|
||||||
|
static int[] amtable = new int[AM_PG_WIDTH];
|
||||||
|
|
||||||
public static void OPLL_init(UInt32 c, UInt32 r)
|
public static void OPLL_init(UInt32 c, UInt32 r)
|
||||||
{
|
{
|
||||||
makePmTable();
|
makePmTable();
|
||||||
@ -97,7 +123,7 @@ namespace VirtualNes.Core
|
|||||||
OPLL_setClock(c, r);
|
OPLL_setClock(c, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OPLL_setClock(uint c, uint r)
|
internal static void OPLL_setClock(uint c, uint r)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@ -138,6 +164,39 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void makePmTable()
|
private static void makePmTable()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < PM_PG_WIDTH; i++)
|
||||||
|
pmtable[i] = (int)(PM_AMP * Math.Pow(2, PM_DEPTH * Math.Sin(2.0 * Math.PI * i / PM_PG_WIDTH) / 1200));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static OPLL OPLL_new()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OPLL_reset(OPLL vRC7_OPLL)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OPLL_reset_patch(OPLL vRC7_OPLL, int oPLL_VRC7_TONE)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OPLL_delete(OPLL vRC7_OPLL)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OPLL_writeReg(OPLL opll, UInt32 reg, UInt32 data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int OPLL_calc(OPLL opll)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -437,8 +437,6 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private byte SyncSub(int no, ControllerState state)
|
private byte SyncSub(int no, ControllerState state)
|
||||||
{
|
{
|
||||||
ushort bit = 0;
|
ushort bit = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user