Emu2413 库实现
This commit is contained in:
parent
d668f7d8df
commit
8bbe264f24
@ -325,7 +325,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536012, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: RomName
|
||||
value: tortoise4.nes
|
||||
value: tstd2.nes
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536013, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_Name
|
||||
|
@ -44,6 +44,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: a6a09b6a4cf4c2d4f994a13fd7e89d6f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
NesEmu: {fileID: 0}
|
||||
m_as: {fileID: 8726979175317618791}
|
||||
--- !u!82 &8726979175317618791
|
||||
AudioSource:
|
||||
@ -256,6 +257,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 83fbe375412d1af4482ae76e81c1dda2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
NesEmu: {fileID: 0}
|
||||
Image: {fileID: 4232056521759880274}
|
||||
--- !u!1 &4232056520494431712
|
||||
GameObject:
|
||||
|
BIN
AxibugEmuOnline.Client/Assets/StreamingAssets/NES/Roms/msg.nes
Normal file
BIN
AxibugEmuOnline.Client/Assets/StreamingAssets/NES/Roms/msg.nes
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5222bc76eba99e4c9fc92b70f4103bc
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -4,34 +4,309 @@ namespace VirtualNes.Core
|
||||
{
|
||||
public class APU_FDS : APU_INTERFACE
|
||||
{
|
||||
private FDSSOUND fds = new FDSSOUND();
|
||||
private FDSSOUND fds_sync = new FDSSOUND();
|
||||
FDSSOUND fds = new FDSSOUND();
|
||||
FDSSOUND fds_sync = new FDSSOUND();
|
||||
int[] output_buf = new int[8];
|
||||
int sampling_rate;
|
||||
|
||||
public APU_FDS()
|
||||
{
|
||||
fds.ZeroMemory();
|
||||
fds_sync.ZeroMemory();
|
||||
|
||||
Array.Clear(output_buf, 0, output_buf.Length);
|
||||
|
||||
sampling_rate = 22050;
|
||||
}
|
||||
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
//todo : 实现
|
||||
fds.ZeroMemory();
|
||||
fds_sync.ZeroMemory();
|
||||
|
||||
sampling_rate = 22050;
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
//todo : 实现
|
||||
sampling_rate = nRate;
|
||||
}
|
||||
|
||||
int[] tbl_writesub = { 30, 20, 15, 12 };
|
||||
|
||||
private void WriteSub(ushort addr, byte data, FDSSOUND ch, double rate)
|
||||
{
|
||||
if (addr < 0x4040 || addr > 0x40BF)
|
||||
return;
|
||||
|
||||
ch.reg[addr - 0x4040] = data;
|
||||
if (addr >= 0x4040 && addr <= 0x407F)
|
||||
{
|
||||
if (ch.wave_setup != 0)
|
||||
{
|
||||
ch.main_wavetable[addr - 0x4040] = 0x20 - (data & 0x3F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x4080: // Volume Envelope
|
||||
ch.volenv_mode = (byte)(data >> 6);
|
||||
if ((data & 0x80) != 0)
|
||||
{
|
||||
ch.volenv_gain = (byte)(data & 0x3F);
|
||||
|
||||
// 即時反映
|
||||
if (ch.main_addr == 0)
|
||||
{
|
||||
ch.now_volume = (ch.volenv_gain < 0x21) ? ch.volenv_gain : 0x20;
|
||||
}
|
||||
}
|
||||
// エンベロープ1段階の演算
|
||||
ch.volenv_decay = (byte)(data & 0x3F);
|
||||
ch.volenv_phaseacc = (double)ch.envelope_speed * (double)(ch.volenv_decay + 1) * rate / (232.0 * 960.0);
|
||||
break;
|
||||
|
||||
case 0x4082: // Main Frequency(Low)
|
||||
ch.main_frequency = (ch.main_frequency & ~0x00FF) | data;
|
||||
break;
|
||||
case 0x4083: // Main Frequency(High)
|
||||
ch.main_enable = (byte)((~data) & (1 << 7));
|
||||
ch.envelope_enable = (byte)((~data) & (1 << 6));
|
||||
if (ch.main_enable == 0)
|
||||
{
|
||||
ch.main_addr = 0;
|
||||
ch.now_volume = (ch.volenv_gain < 0x21) ? ch.volenv_gain : 0x20;
|
||||
}
|
||||
// ch.main_frequency = (ch.main_frequency&0x00FF)|(((INT)data&0x3F)<<8);
|
||||
ch.main_frequency = (ch.main_frequency & 0x00FF) | ((data & 0x0F) << 8);
|
||||
break;
|
||||
|
||||
case 0x4084: // Sweep Envelope
|
||||
ch.swpenv_mode = (byte)(data >> 6);
|
||||
if ((data & 0x80) != 0)
|
||||
{
|
||||
ch.swpenv_gain = (byte)(data & 0x3F);
|
||||
}
|
||||
// エンベロープ1段階の演算
|
||||
ch.swpenv_decay = (byte)(data & 0x3F);
|
||||
ch.swpenv_phaseacc = (double)ch.envelope_speed * (double)(ch.swpenv_decay + 1) * rate / (232.0 * 960.0);
|
||||
break;
|
||||
|
||||
case 0x4085: // Sweep Bias
|
||||
if ((data & 0x40) != 0) ch.sweep_bias = (data & 0x3f) - 0x40;
|
||||
else ch.sweep_bias = data & 0x3f;
|
||||
ch.lfo_addr = 0;
|
||||
break;
|
||||
|
||||
case 0x4086: // Effector(LFO) Frequency(Low)
|
||||
ch.lfo_frequency = (ch.lfo_frequency & (~0x00FF)) | data;
|
||||
break;
|
||||
case 0x4087: // Effector(LFO) Frequency(High)
|
||||
ch.lfo_enable = (byte)((~data & 0x80));
|
||||
ch.lfo_frequency = (ch.lfo_frequency & 0x00FF) | ((data & 0x0F) << 8);
|
||||
break;
|
||||
|
||||
case 0x4088: // Effector(LFO) wavetable
|
||||
if (ch.lfo_enable == 0)
|
||||
{
|
||||
// FIFO?
|
||||
for (byte i = 0; i < 31; i++)
|
||||
{
|
||||
ch.lfo_wavetable[i * 2 + 0] = ch.lfo_wavetable[(i + 1) * 2 + 0];
|
||||
ch.lfo_wavetable[i * 2 + 1] = ch.lfo_wavetable[(i + 1) * 2 + 1];
|
||||
}
|
||||
ch.lfo_wavetable[31 * 2 + 0] = (byte)(data & 0x07);
|
||||
ch.lfo_wavetable[31 * 2 + 1] = (byte)(data & 0x07);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4089: // Sound control
|
||||
{
|
||||
ch.master_volume = tbl_writesub[data & 3];
|
||||
ch.wave_setup = (byte)(data & 0x80);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x408A: // Sound control 2
|
||||
ch.envelope_speed = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
//todo : 实现
|
||||
WriteSub(addr, data, fds, sampling_rate);
|
||||
}
|
||||
|
||||
public override byte Read(ushort addr)
|
||||
{
|
||||
byte data = (byte)(addr >> 8);
|
||||
|
||||
if (addr >= 0x4040 && addr <= 0x407F)
|
||||
{
|
||||
data = (byte)(fds.main_wavetable[addr & 0x3F] | 0x40);
|
||||
}
|
||||
else
|
||||
if (addr == 0x4090)
|
||||
{
|
||||
data = (byte)((fds.volenv_gain & 0x3F) | 0x40);
|
||||
}
|
||||
else
|
||||
if (addr == 0x4092)
|
||||
{
|
||||
data = (byte)((fds.swpenv_gain & 0x3F) | 0x40);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int[] tbl_process = { 0, 1, 2, 4, 0, -4, -2, -1 };
|
||||
public override int Process(int channel)
|
||||
{
|
||||
//todo : 实现
|
||||
return 0;
|
||||
// Envelope unit
|
||||
if (fds.envelope_enable != 0 && fds.envelope_speed != 0)
|
||||
{
|
||||
// Volume envelope
|
||||
if (fds.volenv_mode < 2)
|
||||
{
|
||||
double decay = ((double)fds.envelope_speed * (double)(fds.volenv_decay + 1) * (double)sampling_rate) / (232.0 * 960.0);
|
||||
fds.volenv_phaseacc -= 1.0;
|
||||
while (fds.volenv_phaseacc < 0.0)
|
||||
{
|
||||
fds.volenv_phaseacc += decay;
|
||||
|
||||
if (fds.volenv_mode == 0)
|
||||
{
|
||||
// 減少モード
|
||||
if (fds.volenv_gain != 0)
|
||||
fds.volenv_gain--;
|
||||
}
|
||||
else
|
||||
if (fds.volenv_mode == 1)
|
||||
{
|
||||
if (fds.volenv_gain < 0x20)
|
||||
fds.volenv_gain++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sweep envelope
|
||||
if (fds.swpenv_mode < 2)
|
||||
{
|
||||
double decay = ((double)fds.envelope_speed * (double)(fds.swpenv_decay + 1) * (double)sampling_rate) / (232.0 * 960.0);
|
||||
fds.swpenv_phaseacc -= 1.0;
|
||||
while (fds.swpenv_phaseacc < 0.0)
|
||||
{
|
||||
fds.swpenv_phaseacc += decay;
|
||||
|
||||
if (fds.swpenv_mode == 0)
|
||||
{
|
||||
// 減少モード
|
||||
if (fds.swpenv_gain != 0)
|
||||
fds.swpenv_gain--;
|
||||
}
|
||||
else
|
||||
if (fds.swpenv_mode == 1)
|
||||
{
|
||||
if (fds.swpenv_gain < 0x20)
|
||||
fds.swpenv_gain++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Effector(LFO) unit
|
||||
int sub_freq = 0;
|
||||
// if( fds.lfo_enable && fds.envelope_speed && fds.lfo_frequency ) {
|
||||
if (fds.lfo_enable != 0)
|
||||
{
|
||||
if (fds.lfo_frequency != 0)
|
||||
{
|
||||
fds.lfo_phaseacc -= (1789772.5 * (double)fds.lfo_frequency) / 65536.0;
|
||||
while (fds.lfo_phaseacc < 0.0)
|
||||
{
|
||||
fds.lfo_phaseacc += (double)sampling_rate;
|
||||
|
||||
if (fds.lfo_wavetable[fds.lfo_addr] == 4)
|
||||
fds.sweep_bias = 0;
|
||||
else
|
||||
fds.sweep_bias += tbl_process[fds.lfo_wavetable[fds.lfo_addr]];
|
||||
|
||||
fds.lfo_addr = (fds.lfo_addr + 1) & 63;
|
||||
}
|
||||
}
|
||||
|
||||
if (fds.sweep_bias > 63)
|
||||
fds.sweep_bias -= 128;
|
||||
else if (fds.sweep_bias < -64)
|
||||
fds.sweep_bias += 128;
|
||||
|
||||
int sub_multi = fds.sweep_bias * fds.swpenv_gain;
|
||||
|
||||
if ((sub_multi & 0x0F) != 0)
|
||||
{
|
||||
// 16で割り切れない場合
|
||||
sub_multi = (sub_multi / 16);
|
||||
if (fds.sweep_bias >= 0)
|
||||
sub_multi += 2; // 正の場合
|
||||
else
|
||||
sub_multi -= 1; // 負の場合
|
||||
}
|
||||
else
|
||||
{
|
||||
// 16で割り切れる場合
|
||||
sub_multi = (sub_multi / 16);
|
||||
}
|
||||
// 193を超えると-258する(-64へラップ)
|
||||
if (sub_multi > 193)
|
||||
sub_multi -= 258;
|
||||
// -64を下回ると+256する(192へラップ)
|
||||
if (sub_multi < -64)
|
||||
sub_multi += 256;
|
||||
|
||||
sub_freq = (fds.main_frequency) * sub_multi / 64;
|
||||
}
|
||||
|
||||
// Main unit
|
||||
int output = 0;
|
||||
if (fds.main_enable != 0 && fds.main_frequency != 0 && fds.wave_setup == 0)
|
||||
{
|
||||
int freq;
|
||||
int main_addr_old = fds.main_addr;
|
||||
|
||||
freq = (int)((fds.main_frequency + sub_freq) * 1789772.5 / 65536.0);
|
||||
|
||||
fds.main_addr = (fds.main_addr + freq + 64 * sampling_rate) % (64 * sampling_rate);
|
||||
|
||||
// 1周期を超えたらボリューム更新
|
||||
if (main_addr_old > fds.main_addr)
|
||||
fds.now_volume = (fds.volenv_gain < 0x21) ? fds.volenv_gain : 0x20;
|
||||
|
||||
output = fds.main_wavetable[(fds.main_addr / sampling_rate) & 0x3f] * 8 * fds.now_volume * fds.master_volume / 30;
|
||||
|
||||
if (fds.now_volume != 0)
|
||||
fds.now_freq = freq * 4;
|
||||
else
|
||||
fds.now_freq = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fds.now_freq = 0;
|
||||
output = 0;
|
||||
}
|
||||
|
||||
// LPF
|
||||
output = (output_buf[0] * 2 + output) / 3;
|
||||
output_buf[0] = output;
|
||||
|
||||
fds.output = output;
|
||||
return fds.output;
|
||||
}
|
||||
|
||||
internal void SyncWrite(ushort addr, byte data)
|
||||
@ -39,10 +314,7 @@ namespace VirtualNes.Core
|
||||
WriteSub(addr, data, fds_sync, 1789772.5d);
|
||||
}
|
||||
|
||||
private void WriteSub(ushort addr, byte data, FDSSOUND ch, double rate)
|
||||
{
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
|
||||
internal byte SyncRead(ushort addr)
|
||||
{
|
||||
@ -66,6 +338,71 @@ namespace VirtualNes.Core
|
||||
return data;
|
||||
}
|
||||
|
||||
public override bool Sync(int cycles)
|
||||
{
|
||||
// Envelope unit
|
||||
if (fds_sync.envelope_enable != 0 && fds_sync.envelope_speed != 0)
|
||||
{
|
||||
// Volume envelope
|
||||
double decay;
|
||||
if (fds_sync.volenv_mode < 2)
|
||||
{
|
||||
decay = ((double)fds_sync.envelope_speed * (double)(fds_sync.volenv_decay + 1) * 1789772.5) / (232.0 * 960.0);
|
||||
fds_sync.volenv_phaseacc -= (double)cycles;
|
||||
while (fds_sync.volenv_phaseacc < 0.0)
|
||||
{
|
||||
fds_sync.volenv_phaseacc += decay;
|
||||
|
||||
if (fds_sync.volenv_mode == 0)
|
||||
{
|
||||
// 減少モード
|
||||
if (fds_sync.volenv_gain != 0)
|
||||
fds_sync.volenv_gain--;
|
||||
}
|
||||
else
|
||||
if (fds_sync.volenv_mode == 1)
|
||||
{
|
||||
// 増加モード
|
||||
if (fds_sync.volenv_gain < 0x20)
|
||||
fds_sync.volenv_gain++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sweep envelope
|
||||
if (fds_sync.swpenv_mode < 2)
|
||||
{
|
||||
decay = ((double)fds_sync.envelope_speed * (double)(fds_sync.swpenv_decay + 1) * 1789772.5) / (232.0 * 960.0);
|
||||
fds_sync.swpenv_phaseacc -= (double)cycles;
|
||||
while (fds_sync.swpenv_phaseacc < 0.0)
|
||||
{
|
||||
fds_sync.swpenv_phaseacc += decay;
|
||||
|
||||
if (fds_sync.swpenv_mode == 0)
|
||||
{
|
||||
// 減少モード
|
||||
if (fds_sync.swpenv_gain != 0)
|
||||
fds_sync.swpenv_gain--;
|
||||
}
|
||||
else
|
||||
if (fds_sync.swpenv_mode == 1)
|
||||
{
|
||||
// 増加モード
|
||||
if (fds_sync.swpenv_gain < 0x20)
|
||||
fds_sync.swpenv_gain++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetFreq(int channel)
|
||||
{
|
||||
return fds.now_freq;
|
||||
}
|
||||
|
||||
private class FDSSOUND
|
||||
{
|
||||
public byte[] reg = new byte[0x80];
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using VirtualNes.Core.Emu2413;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
@ -86,7 +86,7 @@ namespace VirtualNes.Core
|
||||
|
||||
if ((VRC7_OPLL.reg[0x20 + channel] & 0x10) != 0)
|
||||
{
|
||||
return (int)((256.0d * (double)fno * blkmul[blk]) / ((double)(1 << 18) / (3579545.0 / 72.0)));
|
||||
return (int)((256.0d * fno * blkmul[blk]) / ((1 << 18) / (3579545.0 / 72.0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace VirtualNes.Core
|
||||
private APU apu;
|
||||
internal R6502 R = new R6502();
|
||||
private byte[] ZN_Table = new byte[256];
|
||||
private ByteArrayRef STACK;
|
||||
private ArrayRef<byte> STACK;
|
||||
|
||||
public CPU(NES parent)
|
||||
{
|
||||
@ -2010,7 +2010,7 @@ namespace VirtualNes.Core
|
||||
DMA_cycles = 0;
|
||||
|
||||
// STACK quick access
|
||||
STACK = new ByteArrayRef(MMU.RAM, 0x0100, MMU.RAM.Length - 0x100);
|
||||
STACK = new ArrayRef<byte>(MMU.RAM, 0x0100, MMU.RAM.Length - 0x100);
|
||||
|
||||
// Zero/Negative FLAG
|
||||
ZN_Table[0] = Z_FLAG;
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class ByteArrayRef
|
||||
public class ArrayRef<T>
|
||||
{
|
||||
private byte[] m_rawArray;
|
||||
private T[] m_rawArray;
|
||||
private int m_offset;
|
||||
private int m_length;
|
||||
|
||||
@ -18,30 +18,30 @@ namespace VirtualNes.Core
|
||||
}
|
||||
}
|
||||
|
||||
public ByteArrayRef() { }
|
||||
public ByteArrayRef(byte[] array, int offset, int length)
|
||||
public ArrayRef() { }
|
||||
public ArrayRef(T[] array, int offset, int length)
|
||||
{
|
||||
SetArray(array, offset, length);
|
||||
}
|
||||
|
||||
public ByteArrayRef(byte[] array) : this(array, 0, array.Length) { }
|
||||
public ByteArrayRef(byte[] array, int offset) : this(array, offset, array.Length - offset) { }
|
||||
public ArrayRef(T[] array) : this(array, 0, array.Length) { }
|
||||
public ArrayRef(T[] array, int offset) : this(array, offset, array.Length - offset) { }
|
||||
|
||||
public void SetArray(byte[] array, int offset, int length)
|
||||
public void SetArray(T[] array, int offset, int length)
|
||||
{
|
||||
m_rawArray = array;
|
||||
m_offset = offset;
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
public void SetArray(byte[] array, int offset)
|
||||
public void SetArray(T[] array, int offset)
|
||||
{
|
||||
m_rawArray = array;
|
||||
m_offset = offset;
|
||||
m_length = array.Length - offset;
|
||||
}
|
||||
|
||||
public byte this[int index]
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -53,14 +53,14 @@ namespace VirtualNes.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator ByteArrayRef(byte[] array)
|
||||
public static implicit operator ArrayRef<T>(T[] array)
|
||||
{
|
||||
return new ByteArrayRef(array);
|
||||
return new ArrayRef<T>(array);
|
||||
}
|
||||
|
||||
public static implicit operator Span<byte>(ByteArrayRef array)
|
||||
public static implicit operator Span<T>(ArrayRef<T> array)
|
||||
{
|
||||
return new Span<byte>(array.m_rawArray, array.Offset, array.m_length);
|
||||
return new Span<T>(array.m_rawArray, array.Offset, array.m_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,204 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class OPLL_PATCH
|
||||
{
|
||||
public uint TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WF;
|
||||
}
|
||||
|
||||
public class OPLL_SLOT
|
||||
{
|
||||
public OPLL_PATCH patch;
|
||||
|
||||
public int type; /* 0 : modulator 1 : carrier */
|
||||
|
||||
/* OUTPUT */
|
||||
public Int32 feedback;
|
||||
public Int32[] output = new Int32[5]; /* Output value of slot */
|
||||
|
||||
/* for Phase Generator (PG) */
|
||||
public UInt32 sintbl; /* Wavetable */
|
||||
public UInt32 phase; /* Phase */
|
||||
public UInt32 dphase; /* Phase increment amount */
|
||||
public UInt32 pgout; /* output */
|
||||
|
||||
/* for Envelope Generator (EG) */
|
||||
public int fnum; /* F-Number */
|
||||
public int block; /* Block */
|
||||
public int volume; /* Current volume */
|
||||
public int sustine; /* Sustine 1 = ON, 0 = OFF */
|
||||
public UInt32 tll; /* Total Level + Key scale level*/
|
||||
public UInt32 rks; /* Key scale offset (Rks) */
|
||||
public int eg_mode; /* Current state */
|
||||
public UInt32 eg_phase; /* Phase */
|
||||
public UInt32 eg_dphase; /* Phase increment amount */
|
||||
public UInt32 egout; /* output */
|
||||
|
||||
|
||||
/* refer to opll-> */
|
||||
public UInt32 plfo_pm;
|
||||
public UInt32 plfo_am;
|
||||
}
|
||||
|
||||
public class OPLL_CH
|
||||
{
|
||||
public int patch_number;
|
||||
public int key_status;
|
||||
public OPLL_SLOT mod;
|
||||
public OPLL_SLOT car;
|
||||
}
|
||||
|
||||
public class OPLL
|
||||
{
|
||||
public UInt32 adr;
|
||||
public Int32[] output = new Int32[2];
|
||||
|
||||
/* Register */
|
||||
public byte[] reg = new byte[0x40];
|
||||
public int[] slot_on_flag = new int[18];
|
||||
|
||||
/* Rythm Mode : 0 = OFF, 1 = ON */
|
||||
public int rythm_mode;
|
||||
|
||||
/* Pitch Modulator */
|
||||
public UInt32 pm_phase;
|
||||
public Int32 lfo_pm;
|
||||
|
||||
/* Amp Modulator */
|
||||
public Int32 am_phase;
|
||||
public Int32 lfo_am;
|
||||
|
||||
/* Noise Generator */
|
||||
public UInt32 noise_seed;
|
||||
public UInt32 whitenoise;
|
||||
public UInt32 noiseA;
|
||||
public UInt32 noiseB;
|
||||
public UInt32 noiseA_phase;
|
||||
public UInt32 noiseB_phase;
|
||||
public UInt32 noiseA_idx;
|
||||
public UInt32 noiseB_idx;
|
||||
public UInt32 noiseA_dphase;
|
||||
public UInt32 noiseB_dphase;
|
||||
|
||||
public int masterVolume; /* 0min -- 64 -- 127 max (Liner) */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
makePmTable();
|
||||
makeAmTable();
|
||||
makeDB2LinTable();
|
||||
makeAdjustTable();
|
||||
makeTllTable();
|
||||
makeRksTable();
|
||||
makeSinTable();
|
||||
makeDefaultPatch();
|
||||
OPLL_setClock(c, r);
|
||||
}
|
||||
|
||||
internal static void OPLL_setClock(uint c, uint r)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeDefaultPatch()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeSinTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeRksTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeTllTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeAdjustTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeDB2LinTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void makeAmTable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5b90f721bfc1ac4ea985c0f564d1c6e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,208 @@
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core.Emu2413
|
||||
{
|
||||
public static class Const
|
||||
{
|
||||
internal static sbyte[][] Create_Default_Inst()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
sbyte[][] res = new sbyte[Emu2413API.OPLL_TONE_NUM][]
|
||||
{
|
||||
new sbyte[]
|
||||
{
|
||||
(sbyte)0x00,(sbyte) 0x00, (sbyte)0x00, (sbyte)0x00,(sbyte) 0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61,(sbyte) 0x61, (sbyte)0x1e, (sbyte)0x17,(sbyte) 0xf0, (sbyte)0x7f, (sbyte)0x07, (sbyte)0x17, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x13,(sbyte) 0x41, (sbyte)0x0f, (sbyte)0x0d,(sbyte) 0xce, (sbyte)0xd2, (sbyte)0x43, (sbyte)0x13, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x03,(sbyte) 0x01, (sbyte)0x99, (sbyte)0x04,(sbyte) 0xff, (sbyte)0xc3, (sbyte)0x03, (sbyte)0x73, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x21,(sbyte) 0x61, (sbyte)0x1b, (sbyte)0x07,(sbyte) 0xaf, (sbyte)0x63, (sbyte)0x40, (sbyte)0x28, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x22,(sbyte) 0x21, (sbyte)0x1e, (sbyte)0x06,(sbyte) 0xf0, (sbyte)0x76, (sbyte)0x08, (sbyte)0x28, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x31,(sbyte) 0x22, (sbyte)0x16, (sbyte)0x05,(sbyte) 0x90, (sbyte)0x71, (sbyte)0x00, (sbyte)0x18, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x21,(sbyte) 0x61, (sbyte)0x1d, (sbyte)0x07,(sbyte) 0x82, (sbyte)0x81, (sbyte)0x10, (sbyte)0x17, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x23,(sbyte) 0x21, (sbyte)0x2d, (sbyte)0x16,(sbyte) 0xc0, (sbyte)0x70, (sbyte)0x07, (sbyte)0x07, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61,(sbyte) 0x21, (sbyte)0x1b, (sbyte)0x06,(sbyte) 0x64, (sbyte)0x65, (sbyte)0x18, (sbyte)0x18, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61,(sbyte) 0x61, (sbyte)0x0c, (sbyte)0x18,(sbyte) 0x85, (sbyte)0xa0, (sbyte)0x79, (sbyte)0x07, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x23,(sbyte) 0x21, (sbyte)0x87, (sbyte)0x11,(sbyte) 0xf0, (sbyte)0xa4, (sbyte)0x00, (sbyte)0xf7, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x97,(sbyte) 0xe1, (sbyte)0x28, (sbyte)0x07,(sbyte) 0xff, (sbyte)0xf3, (sbyte)0x02, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61,(sbyte) 0x10, (sbyte)0x0c, (sbyte)0x05,(sbyte) 0xf2, (sbyte)0xc4, (sbyte)0x40, (sbyte)0xc8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x01,(sbyte) 0x01, (sbyte)0x56, (sbyte)0x03,(sbyte) 0xb4, (sbyte)0xb2, (sbyte)0x23, (sbyte)0x58, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61,(sbyte) 0x41, (sbyte)0x89, (sbyte)0x03,(sbyte) 0xf1, (sbyte)0xf4, (sbyte)0xf0, (sbyte)0x13, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x04,(sbyte) 0x21, (sbyte)0x28, (sbyte)0x00,(sbyte) 0xdf, (sbyte)0xf8, (sbyte)0xff, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x23,(sbyte) 0x22, (sbyte)0x00, (sbyte)0x00,(sbyte) 0xd8, (sbyte)0xf8, (sbyte)0xf8, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x25,(sbyte) 0x18, (sbyte)0x00, (sbyte)0x00,(sbyte) 0xf8, (sbyte)0xda, (sbyte)0xf8, (sbyte)0x55, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
},
|
||||
new sbyte[]
|
||||
{
|
||||
(sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x33, (sbyte)0x01, (sbyte)0x09, (sbyte)0x0e, (sbyte)0x94, (sbyte)0x90, (sbyte)0x40, (sbyte)0x01, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x13, (sbyte)0x41, (sbyte)0x0f, (sbyte)0x0d, (sbyte)0xce, (sbyte)0xd3, (sbyte)0x43, (sbyte)0x13, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x01, (sbyte)0x12, (sbyte)0x1b, (sbyte)0x06, (sbyte)0xff, (sbyte)0xd2, (sbyte)0x00, (sbyte)0x32, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x61, (sbyte)0x61, (sbyte)0x1b, (sbyte)0x07, (sbyte)0xaf, (sbyte)0x63, (sbyte)0x20, (sbyte)0x28, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x22, (sbyte)0x21, (sbyte)0x1e, (sbyte)0x06, (sbyte)0xf0, (sbyte)0x76, (sbyte)0x08, (sbyte)0x28, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x66, (sbyte)0x21, (sbyte)0x15, (sbyte)0x00, (sbyte)0x93, (sbyte)0x94, (sbyte)0x20, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x21, (sbyte)0x61, (sbyte)0x1c, (sbyte)0x07, (sbyte)0x82, (sbyte)0x81, (sbyte)0x10, (sbyte)0x17, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x23, (sbyte)0x21, (sbyte)0x20, (sbyte)0x1f, (sbyte)0xc0, (sbyte)0x71, (sbyte)0x07, (sbyte)0x47, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x25, (sbyte)0x31, (sbyte)0x26, (sbyte)0x05, (sbyte)0x64, (sbyte)0x41, (sbyte)0x18, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x17, (sbyte)0x21, (sbyte)0x28, (sbyte)0x07, (sbyte)0xff, (sbyte)0x83, (sbyte)0x02, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x97, (sbyte)0x81, (sbyte)0x25, (sbyte)0x07, (sbyte)0xcf, (sbyte)0xc8, (sbyte)0x02, (sbyte)0x14, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x21, (sbyte)0x21, (sbyte)0x54, (sbyte)0x0f, (sbyte)0x80, (sbyte)0x7f, (sbyte)0x07, (sbyte)0x07, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x01, (sbyte)0x01, (sbyte)0x56, (sbyte)0x03, (sbyte)0xd3, (sbyte)0xb2, (sbyte)0x43, (sbyte)0x58, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x31, (sbyte)0x21, (sbyte)0x0c, (sbyte)0x03, (sbyte)0x82, (sbyte)0xc0, (sbyte)0x40, (sbyte)0x07, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x21, (sbyte)0x01, (sbyte)0x0c, (sbyte)0x03, (sbyte)0xd4, (sbyte)0xd3, (sbyte)0x40, (sbyte)0x84, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x04, (sbyte)0x21, (sbyte)0x28, (sbyte)0x00, (sbyte)0xdf, (sbyte)0xf8, (sbyte)0xff, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x23, (sbyte)0x22, (sbyte)0x00, (sbyte)0x00, (sbyte)0xa8, (sbyte)0xf8, (sbyte)0xf8, (sbyte)0xf8, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
(sbyte)0x25, (sbyte)0x18, (sbyte)0x00, (sbyte)0x00, (sbyte)0xf8, (sbyte)0xa9, (sbyte)0xf8, (sbyte)0x55, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00, (sbyte)0x00,
|
||||
}
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
internal static OPLL_PATCH[][] Create_Default_Patch()
|
||||
{
|
||||
OPLL_PATCH[][] res = new OPLL_PATCH[Emu2413API.OPLL_TONE_NUM][]
|
||||
{
|
||||
new OPLL_PATCH[(16 + 3) * 2],
|
||||
new OPLL_PATCH[(16 + 3) * 2],
|
||||
};
|
||||
|
||||
for (int x = 0; x < Emu2413API.OPLL_TONE_NUM; x++)
|
||||
for (int y = 0; y < (16 + 3) * 2; y++)
|
||||
res[x][y] = new OPLL_PATCH();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static uint[,,,] Create_tllTable()
|
||||
{
|
||||
var res = new uint[16, 8, 1 << Emu2413API.TL_BITS, 4];
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static Int32[,,] Create_rksTable()
|
||||
{
|
||||
return new int[2, 8, 2];
|
||||
}
|
||||
|
||||
internal static UInt32[,,] Create_dphaseTable()
|
||||
{
|
||||
return new uint[512, 8, 16];
|
||||
}
|
||||
}
|
||||
public class OPLL_PATCH
|
||||
{
|
||||
public uint TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WF;
|
||||
|
||||
public void Copy(OPLL_PATCH other)
|
||||
{
|
||||
TL = other.TL;
|
||||
FB = other.FB;
|
||||
EG = other.EG;
|
||||
ML = other.ML;
|
||||
AR = other.AR;
|
||||
DR = other.DR;
|
||||
SL = other.SL;
|
||||
RR = other.RR;
|
||||
KR = other.KR;
|
||||
KL = other.KL;
|
||||
AM = other.AM;
|
||||
PM = other.PM;
|
||||
WF = other.WF;
|
||||
}
|
||||
}
|
||||
|
||||
public class OPLL_SLOT
|
||||
{
|
||||
public OPLL_PATCH patch;
|
||||
|
||||
public int type; /* 0 : modulator 1 : carrier */
|
||||
|
||||
/* OUTPUT */
|
||||
public Int32 feedback;
|
||||
public Int32[] output = new Int32[5]; /* Output value of slot */
|
||||
|
||||
/* for Phase Generator (PG) */
|
||||
public UInt32[] sintbl; /* Wavetable */
|
||||
public UInt32 phase; /* Phase */
|
||||
public UInt32 dphase; /* Phase increment amount */
|
||||
public UInt32 pgout; /* output */
|
||||
|
||||
/* for Envelope Generator (EG) */
|
||||
public int fnum; /* F-Number */
|
||||
public int block; /* Block */
|
||||
public int volume; /* Current volume */
|
||||
public int sustine; /* Sustine 1 = ON, 0 = OFF */
|
||||
public UInt32 tll; /* Total Level + Key scale level*/
|
||||
public UInt32 rks; /* Key scale offset (Rks) */
|
||||
public int eg_mode; /* Current state */
|
||||
public UInt32 eg_phase; /* Phase */
|
||||
public UInt32 eg_dphase; /* Phase increment amount */
|
||||
public UInt32 egout; /* output */
|
||||
|
||||
|
||||
/* refer to opll-> */
|
||||
public int plfo_pm => m_host.lfo_pm;
|
||||
public int plfo_am => m_host.lfo_am;
|
||||
|
||||
private OPLL m_host;
|
||||
public void SetHost(OPLL host)
|
||||
{
|
||||
m_host = host;
|
||||
}
|
||||
}
|
||||
|
||||
public class OPLL_CH
|
||||
{
|
||||
public int patch_number;
|
||||
public int key_status;
|
||||
public OPLL_SLOT mod;
|
||||
public OPLL_SLOT car;
|
||||
}
|
||||
|
||||
public class OPLL
|
||||
{
|
||||
public UInt32 adr;
|
||||
public Int32[] output = new Int32[2];
|
||||
|
||||
/* Register */
|
||||
public byte[] reg = new byte[0x40];
|
||||
public int[] slot_on_flag = new int[18];
|
||||
|
||||
/* Rythm Mode : 0 = OFF, 1 = ON */
|
||||
public int rythm_mode;
|
||||
|
||||
/* Pitch Modulator */
|
||||
public UInt32 pm_phase;
|
||||
public Int32 lfo_pm;
|
||||
|
||||
/* Amp Modulator */
|
||||
public Int32 am_phase;
|
||||
public Int32 lfo_am;
|
||||
|
||||
/* Noise Generator */
|
||||
public UInt32 noise_seed;
|
||||
public UInt32 whitenoise;
|
||||
public UInt32 noiseA;
|
||||
public UInt32 noiseB;
|
||||
public UInt32 noiseA_phase;
|
||||
public UInt32 noiseB_phase;
|
||||
public UInt32 noiseA_idx;
|
||||
public UInt32 noiseB_idx;
|
||||
public UInt32 noiseA_dphase;
|
||||
public UInt32 noiseB_dphase;
|
||||
|
||||
/* Channel & Slot */
|
||||
public OPLL_CH[] ch = new OPLL_CH[9];
|
||||
public OPLL_SLOT[] slot = new OPLL_SLOT[18];
|
||||
|
||||
/* Voice Data */
|
||||
public OPLL_PATCH[] patch = new OPLL_PATCH[19 * 2];
|
||||
public int[] patch_update = new int[2]; /* flag for check patch update */
|
||||
|
||||
public UInt32 mask;
|
||||
|
||||
public int masterVolume; /* 0min -- 64 -- 127 max (Liner) */
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c1aaa5374091a64a88e750483fe6f6b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -6,11 +6,11 @@ namespace VirtualNes
|
||||
public static class MMU
|
||||
{
|
||||
// CPU 儊儌儕僶儞僋
|
||||
public static ByteArrayRef[] CPU_MEM_BANK = new ByteArrayRef[8]; // 8K扨埵
|
||||
public static ArrayRef<byte>[] CPU_MEM_BANK = new ArrayRef<byte>[8]; // 8K扨埵
|
||||
public static byte[] CPU_MEM_TYPE = new byte[8];
|
||||
public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡
|
||||
// PPU 儊儌儕僶儞僋
|
||||
public static ByteArrayRef[] PPU_MEM_BANK = new ByteArrayRef[12]; // 1K扨埵
|
||||
public static ArrayRef<byte>[] PPU_MEM_BANK = new ArrayRef<byte>[12]; // 1K扨埵
|
||||
public static byte[] PPU_MEM_TYPE = new byte[12];
|
||||
public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡
|
||||
public static byte[] CRAM_USED = new byte[16]; // 僗僥乕僩僙乕僽梡
|
||||
@ -73,12 +73,12 @@ namespace VirtualNes
|
||||
|
||||
internal static void SetPROM_Bank(byte page, byte[] ptr, byte type)
|
||||
{
|
||||
CPU_MEM_BANK[page] = new ByteArrayRef(ptr, 0, ptr.Length);
|
||||
CPU_MEM_BANK[page] = new ArrayRef<byte>(ptr, 0, ptr.Length);
|
||||
CPU_MEM_TYPE[page] = type;
|
||||
CPU_MEM_PAGE[page] = 0;
|
||||
}
|
||||
|
||||
internal static void SetPROM_Bank(byte page, ByteArrayRef ptr, byte type)
|
||||
internal static void SetPROM_Bank(byte page, ArrayRef<byte> ptr, byte type)
|
||||
{
|
||||
CPU_MEM_BANK[page] = ptr;
|
||||
CPU_MEM_TYPE[page] = type;
|
||||
@ -88,7 +88,7 @@ namespace VirtualNes
|
||||
internal static void SetPROM_8K_Bank(byte page, int bank)
|
||||
{
|
||||
bank %= PROM_8K_SIZE;
|
||||
CPU_MEM_BANK[page] = new ByteArrayRef(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank);
|
||||
CPU_MEM_BANK[page] = new ArrayRef<byte>(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank);
|
||||
CPU_MEM_TYPE[page] = BANKTYPE_ROM;
|
||||
CPU_MEM_PAGE[page] = bank;
|
||||
}
|
||||
@ -116,7 +116,7 @@ namespace VirtualNes
|
||||
}
|
||||
|
||||
// PPU VROM bank
|
||||
internal static void SetVROM_Bank(byte page, ByteArrayRef ptr, byte type)
|
||||
internal static void SetVROM_Bank(byte page, ArrayRef<byte> ptr, byte type)
|
||||
{
|
||||
PPU_MEM_BANK[page] = ptr;
|
||||
PPU_MEM_TYPE[page] = type;
|
||||
@ -126,7 +126,7 @@ namespace VirtualNes
|
||||
internal static void SetVROM_1K_Bank(byte page, int bank)
|
||||
{
|
||||
bank %= VROM_1K_SIZE;
|
||||
PPU_MEM_BANK[page] = new ByteArrayRef(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank));
|
||||
PPU_MEM_BANK[page] = new ArrayRef<byte>(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank));
|
||||
PPU_MEM_TYPE[page] = BANKTYPE_VROM;
|
||||
PPU_MEM_PAGE[page] = bank;
|
||||
}
|
||||
@ -169,7 +169,7 @@ namespace VirtualNes
|
||||
internal static void SetCRAM_1K_Bank(byte page, int bank)
|
||||
{
|
||||
bank &= 0x1F;
|
||||
PPU_MEM_BANK[page] = new ByteArrayRef(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank);
|
||||
PPU_MEM_BANK[page] = new ArrayRef<byte>(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank);
|
||||
PPU_MEM_TYPE[page] = BANKTYPE_CRAM;
|
||||
PPU_MEM_PAGE[page] = bank;
|
||||
|
||||
@ -201,7 +201,7 @@ namespace VirtualNes
|
||||
internal static void SetVRAM_1K_Bank(byte page, int bank)
|
||||
{
|
||||
bank &= 3;
|
||||
PPU_MEM_BANK[page] = new ByteArrayRef(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank);
|
||||
PPU_MEM_BANK[page] = new ArrayRef<byte>(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank);
|
||||
PPU_MEM_TYPE[page] = BANKTYPE_VRAM;
|
||||
PPU_MEM_PAGE[page] = bank;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace VirtualNes.Core
|
||||
byte sda;
|
||||
byte scl_old, sda_old;
|
||||
|
||||
ByteArrayRef pEEPDATA;
|
||||
ArrayRef<byte> pEEPDATA;
|
||||
|
||||
public X24C01()
|
||||
{
|
||||
@ -34,7 +34,7 @@ namespace VirtualNes.Core
|
||||
pEEPDATA = null;
|
||||
}
|
||||
|
||||
public void Reset(ByteArrayRef ptr)
|
||||
public void Reset(ArrayRef<byte> ptr)
|
||||
{
|
||||
now_state = X24C01_IDLE;
|
||||
next_state = X24C01_IDLE;
|
||||
@ -220,7 +220,7 @@ namespace VirtualNes.Core
|
||||
byte sda;
|
||||
byte scl_old, sda_old;
|
||||
|
||||
ByteArrayRef pEEPDATA;
|
||||
ArrayRef<byte> pEEPDATA;
|
||||
|
||||
public X24C02()
|
||||
{
|
||||
@ -236,7 +236,7 @@ namespace VirtualNes.Core
|
||||
pEEPDATA = null;
|
||||
}
|
||||
|
||||
public void Reset(ByteArrayRef ptr)
|
||||
public void Reset(ArrayRef<byte> ptr)
|
||||
{
|
||||
now_state = X24C02_IDLE;
|
||||
next_state = X24C02_IDLE;
|
||||
|
@ -132,7 +132,7 @@ namespace VirtualNes.Core
|
||||
}
|
||||
}
|
||||
|
||||
private ByteArrayRef _PROM_BANK = new ByteArrayRef();
|
||||
private ArrayRef<byte> _PROM_BANK = new ArrayRef<byte>();
|
||||
//void Mapper001::Write(WORD addr, BYTE data)
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
|
@ -39,15 +39,15 @@ namespace VirtualNes.Core
|
||||
//BYTE chr_page[2][8];
|
||||
BYTE[,] chr_page = new byte[2, 8]; // $5120-$512B
|
||||
// BGパターン用バンク
|
||||
ByteArrayRef[] BG_MEM_BANK = new ByteArrayRef[8]{
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
new ByteArrayRef(),
|
||||
ArrayRef<byte>[] BG_MEM_BANK = new ArrayRef<byte>[8]{
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
new ArrayRef<byte>(),
|
||||
};
|
||||
BYTE[] BG_MEM_PAGE = new byte[8];
|
||||
|
||||
@ -433,7 +433,7 @@ namespace VirtualNes.Core
|
||||
}
|
||||
}
|
||||
|
||||
private ByteArrayRef _prom_bank = new ByteArrayRef();
|
||||
private ArrayRef<byte> _prom_bank = new ArrayRef<byte>();
|
||||
void SetBank_SRAM(BYTE page, BYTE data)
|
||||
{
|
||||
if (sram_size == 0) data = (byte)((data > 3) ? 8 : 0);
|
||||
|
@ -139,7 +139,7 @@ namespace VirtualNes.Core
|
||||
{
|
||||
nes.SetSAVERAM_SIZE(384);
|
||||
x24c02.Reset(WRAM);
|
||||
x24c01.Reset(new ByteArrayRef(WRAM, 256));
|
||||
x24c01.Reset(new ArrayRef<byte>(WRAM, 256));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,9 +146,11 @@ static unsigned char default_inst[OPLL_TONE_NUM][(16+3)*16]=
|
||||
/* Adjust envelope speed which depends on sampling rate. */
|
||||
#define rate_adjust(x) (uint32)((double)(x)*clk/72/rate + 0.5) /* +0.5 to round */
|
||||
|
||||
|
||||
#define MOD(x) ch[x]->mod
|
||||
#define CAR(x) ch[x]->car
|
||||
|
||||
|
||||
/* Sampling rate */
|
||||
static uint32 rate ;
|
||||
/* Input clock */
|
||||
@ -555,6 +557,7 @@ INLINE static void slotOff(OPLL_SLOT *slot)
|
||||
/* Channel key on */
|
||||
INLINE static void keyOn(OPLL *opll, int i)
|
||||
{
|
||||
|
||||
if(!opll->slot_on_flag[i*2]) slotOn(opll->MOD(i)) ;
|
||||
if(!opll->slot_on_flag[i*2+1]) slotOn(opll->CAR(i)) ;
|
||||
opll->ch[i]->key_status = 1 ;
|
||||
@ -894,6 +897,7 @@ void OPLL_setClock(uint32 c, uint32 r)
|
||||
|
||||
void OPLL_init(uint32 c, uint32 r)
|
||||
{
|
||||
|
||||
makePmTable() ;
|
||||
makeAmTable() ;
|
||||
makeDB2LinTable() ;
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user