Compare commits

..

No commits in common. "73e3a744ae36836ec2f6f8fab8d941157a34792f" and "1e914679bb84cb4f40de103a8cdb039a76a5a38c" have entirely different histories.

34 changed files with 3249 additions and 2676 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a5222bc76eba99e4c9fc92b70f4103bc guid: 31d7b6b33f06e3d468b409ab9e71bf1f
DefaultImporter: TextScriptImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:

View File

@ -325,7 +325,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4232056521131536012, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} - target: {fileID: 4232056521131536012, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
propertyPath: RomName propertyPath: RomName
value: tstd2.nes value: tortoise4.nes
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4232056521131536013, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} - target: {fileID: 4232056521131536013, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
propertyPath: m_Name propertyPath: m_Name

View File

@ -1,6 +1,5 @@
using AxibugEmuOnline.Client.ClientCore; using AxibugEmuOnline.Client.ClientCore;
using System; using System;
using System.IO;
using System.Xml.Linq; using System.Xml.Linq;
using UnityEngine; using UnityEngine;
using VirtualNes.Core; using VirtualNes.Core;
@ -75,8 +74,8 @@ namespace AxibugEmuOnline.Client
var db = Resources.Load<RomDB>("NES/ROMDB"); var db = Resources.Load<RomDB>("NES/ROMDB");
db.Clear(); db.Clear();
var xmlStr = File.ReadAllText("nes20db.xml"); var dbFile = Resources.Load<TextAsset>("NES/nes20db");
var xml = XDocument.Parse(xmlStr); var xml = XDocument.Parse(dbFile.text);
var games = xml.Element("nes20db").Elements("game"); var games = xml.Element("nes20db").Elements("game");
foreach (var game in games) foreach (var game in games)
{ {
@ -85,11 +84,9 @@ namespace AxibugEmuOnline.Client
var mapper = int.Parse($"{game.Element("pcb").Attribute("mapper").Value}"); var mapper = int.Parse($"{game.Element("pcb").Attribute("mapper").Value}");
if (mapper > 255) continue;
db.AddInfo(new RomDB.RomInfo { CRC = crc, Mapper = mapper }); db.AddInfo(new RomDB.RomInfo { CRC = crc, Mapper = mapper });
} }
UnityEditor.EditorUtility.SetDirty(db);
UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.SaveAssets();
} }
#endif #endif

View File

@ -44,7 +44,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: a6a09b6a4cf4c2d4f994a13fd7e89d6f, type: 3} m_Script: {fileID: 11500000, guid: a6a09b6a4cf4c2d4f994a13fd7e89d6f, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
NesEmu: {fileID: 0}
m_as: {fileID: 8726979175317618791} m_as: {fileID: 8726979175317618791}
--- !u!82 &8726979175317618791 --- !u!82 &8726979175317618791
AudioSource: AudioSource:
@ -257,7 +256,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 83fbe375412d1af4482ae76e81c1dda2, type: 3} m_Script: {fileID: 11500000, guid: 83fbe375412d1af4482ae76e81c1dda2, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
NesEmu: {fileID: 0}
Image: {fileID: 4232056521759880274} Image: {fileID: 4232056521759880274}
--- !u!1 &4232056520494431712 --- !u!1 &4232056520494431712
GameObject: GameObject:

View File

@ -4,309 +4,28 @@ namespace VirtualNes.Core
{ {
public class APU_FDS : APU_INTERFACE public class APU_FDS : APU_INTERFACE
{ {
FDSSOUND fds = new FDSSOUND(); private FDSSOUND fds = new FDSSOUND();
FDSSOUND fds_sync = new FDSSOUND(); private 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) public override void Reset(float fClock, int nRate)
{ {
fds.ZeroMemory(); //todo : 实现
fds_sync.ZeroMemory();
sampling_rate = 22050;
} }
public override void Setup(float fClock, int nRate) public override void Setup(float fClock, int nRate)
{ {
sampling_rate = nRate; //todo : 实现
}
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) public override void Write(ushort addr, byte data)
{ {
WriteSub(addr, data, fds, sampling_rate); //todo : 实现
} }
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) public override int Process(int channel)
{ {
// Envelope unit //todo : 实现
if (fds.envelope_enable != 0 && fds.envelope_speed != 0) return 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) internal void SyncWrite(ushort addr, byte data)
@ -314,7 +33,10 @@ namespace VirtualNes.Core
WriteSub(addr, data, fds_sync, 1789772.5d); WriteSub(addr, data, fds_sync, 1789772.5d);
} }
private void WriteSub(ushort addr, byte data, FDSSOUND ch, double rate)
{
//todo : 实现
}
internal byte SyncRead(ushort addr) internal byte SyncRead(ushort addr)
{ {
@ -338,71 +60,6 @@ namespace VirtualNes.Core
return data; 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 private class FDSSOUND
{ {
public byte[] reg = new byte[0x80]; public byte[] reg = new byte[0x80];
@ -437,36 +94,6 @@ namespace VirtualNes.Core
public int now_volume; public int now_volume;
public int now_freq; public int now_freq;
public int output; public int output;
public void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
volenv_mode = 0;
volenv_gain = 0;
volenv_decay = 0;
volenv_phaseacc = 0.0;
swpenv_mode = 0;
swpenv_gain = 0;
swpenv_decay = 0;
swpenv_phaseacc = 0.0;
envelope_enable = 0;
envelope_speed = 0;
wave_setup = 0;
master_volume = 0;
Array.Clear(main_wavetable, 0, main_wavetable.Length);
main_enable = 0;
main_frequency = 0;
main_addr = 0;
Array.Clear(lfo_wavetable, 0, lfo_wavetable.Length);
lfo_enable = 0;
lfo_frequency = 0;
lfo_addr = 0;
lfo_phaseacc = 0.0;
sweep_bias = 0;
now_volume = 0;
now_freq = 0;
output = 0;
}
} }
} }
} }

View File

@ -1192,222 +1192,5 @@ namespace VirtualNes.Core
break; break;
} }
} }
public class RECTANGLE
{
public byte[] reg = new byte[4]; // register
public byte enable; // enable
public byte holdnote; // holdnote
public byte volume; // volume
public byte complement;
// For Render
public int phaseacc;
public int freq;
public int freqlimit;
public int adder;
public int duty;
public int len_count;
public int nowvolume;
// For Envelope
public byte env_fixed;
public byte env_decay;
public byte env_count;
public byte dummy0;
public int env_vol;
// For Sweep
public byte swp_on;
public byte swp_inc;
public byte swp_shift;
public byte swp_decay;
public byte swp_count;
public byte[] dummy1 = new byte[3];
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_output_enable;
public byte sync_enable;
public byte sync_holdnote;
public byte dummy2;
public int sync_len_count;
public void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
volume = 0;
complement = 0;
phaseacc = 0;
freq = 0;
freqlimit = 0;
adder = 0;
duty = 0;
len_count = 0;
nowvolume = 0;
env_fixed = 0;
env_decay = 0;
env_count = 0;
dummy0 = 0;
env_vol = 0;
swp_on = 0;
swp_inc = 0;
swp_shift = 0;
swp_decay = 0;
swp_count = 0;
Array.Clear(dummy1, 0, dummy1.Length);
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_output_enable = 0;
sync_enable = 0;
sync_holdnote = 0;
dummy2 = 0;
sync_len_count = 0;
}
}
public class TRIANGLE
{
public byte[] reg = new byte[4];
public byte enable;
public byte holdnote;
public byte counter_start;
public byte dummy0;
public int phaseacc;
public int freq;
public int len_count;
public int lin_count;
public int adder;
public int nowvolume;
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_enable;
public byte sync_holdnote;
public byte sync_counter_start;
// public byte dummy1;
public int sync_len_count;
public int sync_lin_count;
internal void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
counter_start = 0;
dummy0 = 0;
phaseacc = 0;
freq = 0;
len_count = 0;
lin_count = 0;
adder = 0;
nowvolume = 0;
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_enable = 0;
sync_holdnote = 0;
sync_counter_start = 0;
sync_len_count = 0;
sync_lin_count = 0;
}
}
public class DPCM
{
public byte[] reg = new byte[4];
public byte enable;
public byte looping;
public byte cur_byte;
public byte dpcm_value;
public int freq;
public int phaseacc;
public int output;
public ushort address, cache_addr;
public int dmalength, cache_dmalength;
public int dpcm_output_real, dpcm_output_fake, dpcm_output_old, dpcm_output_offset;
// For sync
public byte[] sync_reg = new byte[4];
public byte sync_enable;
public byte sync_looping;
public byte sync_irq_gen;
public byte sync_irq_enable;
public int sync_cycles, sync_cache_cycles;
public int sync_dmalength, sync_cache_dmalength;
}
public class NOISE
{
public byte[] reg = new byte[4]; // register
public byte enable; // enable
public byte holdnote; // holdnote
public byte volume; // volume
public byte xor_tap;
public int shift_reg;
// For Render
public int phaseacc;
public int freq;
public int len_count;
public int nowvolume;
public int output;
// For Envelope
public byte env_fixed;
public byte env_decay;
public byte env_count;
public byte dummy0;
public int env_vol;
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_output_enable;
public byte sync_enable;
public byte sync_holdnote;
public byte dummy1;
public int sync_len_count;
internal void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
volume = 0;
xor_tap = 0;
shift_reg = 0;
phaseacc = 0;
freq = 0;
len_count = 0;
nowvolume = 0;
output = 0;
env_fixed = 0;
env_decay = 0;
env_count = 0;
dummy0 = 0;
env_vol = 0;
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_output_enable = 0;
sync_enable = 0;
sync_holdnote = 0;
dummy1 = 0;
sync_len_count = 0;
}
}
} }
} }

View File

@ -270,35 +270,6 @@ namespace VirtualNes.Core
return 0; return 0;
} }
public override int GetFreq(int channel)
{
if (channel == 0 || channel == 1)
{
RECTANGLE ch = null;
if (channel == 0) ch = ch0;
else ch = ch1;
if (ch.enable == 0 || ch.vbl_length <= 0)
return 0;
if (ch.freq < INT2FIX(8))
return 0;
if (ch.fixed_envelope != 0)
{
if (ch.volume == 0)
return 0;
}
else
{
if ((0x0F - ch.env_vol) == 0)
return 0;
}
return (int)(256.0f * cpu_clock / (FIX2INT(ch.freq) * 16.0f));
}
return 0;
}
private int RectangleRender(RECTANGLE ch) private int RectangleRender(RECTANGLE ch)
{ {
if (ch.enable == 0 || ch.vbl_length <= 0) if (ch.enable == 0 || ch.vbl_length <= 0)

View File

@ -1,245 +1,26 @@
using RECTANGLE = VirtualNes.Core.APU_VRC6.RECTANGLE; namespace VirtualNes.Core
using SAWTOOTH = VirtualNes.Core.APU_VRC6.SAWTOOTH;
namespace VirtualNes.Core
{ {
public class APU_N106 : APU_INTERFACE public class APU_N106 : APU_INTERFACE
{ {
RECTANGLE ch0 = new RECTANGLE();
RECTANGLE ch1 = new RECTANGLE();
SAWTOOTH ch2 = new SAWTOOTH();
float cpu_clock;
int cycle_rate;
public APU_N106()
{
Reset(APU_CLOCK, 22050);
}
public override void Reset(float fClock, int nRate) public override void Reset(float fClock, int nRate)
{ {
ch0.ZeroMemory(); //todo : 实现
ch1.ZeroMemory();
ch2.ZeroMemory();
Setup(fClock, nRate);
} }
public override void Setup(float fClock, int nRate) public override void Setup(float fClock, int nRate)
{ {
cpu_clock = fClock; //todo : 实现
cycle_rate = (int)(fClock * 65536.0f / nRate);
} }
public override void Write(ushort addr, byte data) public override void Write(ushort addr, byte data)
{ {
switch (addr) //todo : 实现
{
// VRC6 CH0 rectangle
case 0x9000:
ch0.reg[0] = data;
ch0.gate = (byte)(data & 0x80);
ch0.volume = (byte)(data & 0x0F);
ch0.duty_pos = (byte)((data >> 4) & 0x07);
break;
case 0x9001:
ch0.reg[1] = data;
ch0.freq = INT2FIX((((ch0.reg[2] & 0x0F) << 8) | data) + 1);
break;
case 0x9002:
ch0.reg[2] = data;
ch0.enable = (byte)(data & 0x80);
ch0.freq = INT2FIX((((data & 0x0F) << 8) | ch0.reg[1]) + 1);
break;
// VRC6 CH1 rectangle
case 0xA000:
ch1.reg[0] = data;
ch1.gate = (byte)(data & 0x80);
ch1.volume = (byte)(data & 0x0F);
ch1.duty_pos = (byte)((data >> 4) & 0x07);
break;
case 0xA001:
ch1.reg[1] = data;
ch1.freq = INT2FIX((((ch1.reg[2] & 0x0F) << 8) | data) + 1);
break;
case 0xA002:
ch1.reg[2] = data;
ch1.enable = (byte)(data & 0x80);
ch1.freq = INT2FIX((((data & 0x0F) << 8) | ch1.reg[1]) + 1);
break;
// VRC6 CH2 sawtooth
case 0xB000:
ch2.reg[1] = data;
ch2.phaseaccum = (byte)(data & 0x3F);
break;
case 0xB001:
ch2.reg[1] = data;
ch2.freq = INT2FIX((((ch2.reg[2] & 0x0F) << 8) | data) + 1);
break;
case 0xB002:
ch2.reg[2] = data;
ch2.enable = (byte)(data & 0x80);
ch2.freq = INT2FIX((((data & 0x0F) << 8) | ch2.reg[1]) + 1);
// ch2.adder = 0; // クリアするとノイズの原因になる
// ch2.accum = 0; // クリアするとノイズの原因になる
break;
}
} }
public override int Process(int channel) public override int Process(int channel)
{ {
switch (channel) //todo : 实现
{
case 0:
return RectangleRender(ch0);
case 1:
return RectangleRender(ch1);
case 2:
return SawtoothRender(ch2);
}
return 0; return 0;
} }
public override int GetFreq(int channel)
{
if (channel == 0 || channel == 1)
{
RECTANGLE ch;
if (channel == 0) ch = ch0;
else ch = ch1;
if (ch.enable == 0 || ch.gate != 0 || ch.volume == 0)
return 0;
if (ch.freq < INT2FIX(8))
return 0;
return (int)((256.0f * cpu_clock / (FIX2INT(ch.freq) * 16.0f)));
}
if (channel == 2)
{
SAWTOOTH ch = ch2;
if (ch.enable == 0 || ch.phaseaccum == 0)
return 0;
if (ch.freq < INT2FIX(8))
return 0;
return (int)(256.0f * cpu_clock / (FIX2INT(ch.freq) * 14.0f));
}
return 0;
}
int RectangleRender(RECTANGLE ch)
{
// Enable?
if (ch.enable == 0)
{
ch.output_vol = 0;
ch.adder = 0;
return ch.output_vol;
}
// Digitized output
if (ch.gate != 0)
{
ch.output_vol = ch.volume << APU_VRC6.RECTANGLE_VOL_SHIFT;
return ch.output_vol;
}
// 一定以上の周波数は処理しない(無駄)
if (ch.freq < INT2FIX(8))
{
ch.output_vol = 0;
return ch.output_vol;
}
ch.phaseacc -= cycle_rate;
if (ch.phaseacc >= 0)
return ch.output_vol;
int output = ch.volume << APU_VRC6.RECTANGLE_VOL_SHIFT;
if (ch.freq > cycle_rate)
{
// add 1 step
ch.phaseacc += ch.freq;
ch.adder = (byte)((ch.adder + 1) & 0x0F);
if (ch.adder <= ch.duty_pos)
ch.output_vol = output;
else
ch.output_vol = -output;
}
else
{
// average calculate
int num_times, total;
num_times = total = 0;
while (ch.phaseacc < 0)
{
ch.phaseacc += ch.freq;
ch.adder = (byte)((ch.adder + 1) & 0x0F);
if (ch.adder <= ch.duty_pos)
total += output;
else
total += -output;
num_times++;
}
ch.output_vol = total / num_times;
}
return ch.output_vol;
}
int SawtoothRender(SAWTOOTH ch)
{
// Digitized output
if (ch.enable == 0)
{
ch.output_vol = 0;
return ch.output_vol;
}
// 一定以上の周波数は処理しない(無駄)
if (ch.freq < INT2FIX(9))
{
return ch.output_vol;
}
ch.phaseacc -= cycle_rate / 2;
if (ch.phaseacc >= 0)
return ch.output_vol;
if (ch.freq > cycle_rate / 2)
{
// add 1 step
ch.phaseacc += ch.freq;
if (++ch.adder >= 7)
{
ch.adder = 0;
ch.accum = 0;
}
ch.accum += ch.phaseaccum;
ch.output_vol = ch.accum << APU_VRC6.SAWTOOTH_VOL_SHIFT;
}
else
{
// average calculate
int num_times, total;
num_times = total = 0;
while (ch.phaseacc < 0)
{
ch.phaseacc += ch.freq;
if (++ch.adder >= 7)
{
ch.adder = 0;
ch.accum = 0;
}
ch.accum += ch.phaseaccum;
total += ch.accum << APU_VRC6.SAWTOOTH_VOL_SHIFT;
num_times++;
}
ch.output_vol = (total / num_times);
}
return ch.output_vol;
}
} }
} }

View File

@ -245,7 +245,7 @@ namespace VirtualNes.Core
return ch.output_vol; return ch.output_vol;
} }
public class RECTANGLE private class RECTANGLE
{ {
public byte[] reg = new byte[3]; public byte[] reg = new byte[3];
@ -276,7 +276,7 @@ namespace VirtualNes.Core
} }
} }
public class SAWTOOTH private class SAWTOOTH
{ {
public byte[] reg = new byte[3]; public byte[] reg = new byte[3];

View File

@ -1,5 +1,5 @@
using System; using System;
using VirtualNes.Core.Emu2413; using System.Net;
namespace VirtualNes.Core namespace VirtualNes.Core
{ {
@ -86,7 +86,7 @@ namespace VirtualNes.Core
if ((VRC7_OPLL.reg[0x20 + channel] & 0x10) != 0) if ((VRC7_OPLL.reg[0x20 + channel] & 0x10) != 0)
{ {
return (int)((256.0d * fno * blkmul[blk]) / ((1 << 18) / (3579545.0 / 72.0))); return (int)((256.0d * (double)fno * blkmul[blk]) / ((double)(1 << 18) / (3579545.0 / 72.0)));
} }
} }

View File

@ -0,0 +1,28 @@
namespace VirtualNes.Core
{
public class DPCM
{
public byte[] reg = new byte[4];
public byte enable;
public byte looping;
public byte cur_byte;
public byte dpcm_value;
public int freq;
public int phaseacc;
public int output;
public ushort address, cache_addr;
public int dmalength, cache_dmalength;
public int dpcm_output_real, dpcm_output_fake, dpcm_output_old, dpcm_output_offset;
// For sync
public byte[] sync_reg = new byte[4];
public byte sync_enable;
public byte sync_looping;
public byte sync_irq_gen;
public byte sync_irq_enable;
public int sync_cycles, sync_cache_cycles;
public int sync_dmalength, sync_cache_dmalength;
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 9c1aaa5374091a64a88e750483fe6f6b guid: e6289a516ac91b541b2b1807bb07e2b0
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,68 @@
using System;
namespace VirtualNes.Core
{
public class NOISE
{
public byte[] reg = new byte[4]; // register
public byte enable; // enable
public byte holdnote; // holdnote
public byte volume; // volume
public byte xor_tap;
public int shift_reg;
// For Render
public int phaseacc;
public int freq;
public int len_count;
public int nowvolume;
public int output;
// For Envelope
public byte env_fixed;
public byte env_decay;
public byte env_count;
public byte dummy0;
public int env_vol;
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_output_enable;
public byte sync_enable;
public byte sync_holdnote;
public byte dummy1;
public int sync_len_count;
internal void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
volume = 0;
xor_tap = 0;
shift_reg = 0;
phaseacc = 0;
freq = 0;
len_count = 0;
nowvolume = 0;
output = 0;
env_fixed = 0;
env_decay = 0;
env_count = 0;
dummy0 = 0;
env_vol = 0;
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_output_enable = 0;
sync_enable = 0;
sync_holdnote = 0;
dummy1 = 0;
sync_len_count = 0;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8680ce7dbdceb504dbda3b98dbdb1297
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,85 @@
using System;
namespace VirtualNes.Core
{
public class RECTANGLE
{
public byte[] reg = new byte[4]; // register
public byte enable; // enable
public byte holdnote; // holdnote
public byte volume; // volume
public byte complement;
// For Render
public int phaseacc;
public int freq;
public int freqlimit;
public int adder;
public int duty;
public int len_count;
public int nowvolume;
// For Envelope
public byte env_fixed;
public byte env_decay;
public byte env_count;
public byte dummy0;
public int env_vol;
// For Sweep
public byte swp_on;
public byte swp_inc;
public byte swp_shift;
public byte swp_decay;
public byte swp_count;
public byte[] dummy1 = new byte[3];
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_output_enable;
public byte sync_enable;
public byte sync_holdnote;
public byte dummy2;
public int sync_len_count;
public void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
volume = 0;
complement = 0;
phaseacc = 0;
freq = 0;
freqlimit = 0;
adder = 0;
duty = 0;
len_count = 0;
nowvolume = 0;
env_fixed = 0;
env_decay = 0;
env_count = 0;
dummy0 = 0;
env_vol = 0;
swp_on = 0;
swp_inc = 0;
swp_shift = 0;
swp_decay = 0;
swp_count = 0;
Array.Clear(dummy1, 0, dummy1.Length);
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_output_enable = 0;
sync_enable = 0;
sync_holdnote = 0;
dummy2 = 0;
sync_len_count = 0;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e50831f6c445fe489d7e1737269296e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,54 @@
using System;
namespace VirtualNes.Core
{
public class TRIANGLE
{
public byte[] reg = new byte[4];
public byte enable;
public byte holdnote;
public byte counter_start;
public byte dummy0;
public int phaseacc;
public int freq;
public int len_count;
public int lin_count;
public int adder;
public int nowvolume;
// For sync;
public byte[] sync_reg = new byte[4];
public byte sync_enable;
public byte sync_holdnote;
public byte sync_counter_start;
// public byte dummy1;
public int sync_len_count;
public int sync_lin_count;
internal void ZeroMemory()
{
Array.Clear(reg, 0, reg.Length);
enable = 0;
holdnote = 0;
counter_start = 0;
dummy0 = 0;
phaseacc = 0;
freq = 0;
len_count = 0;
lin_count = 0;
adder = 0;
nowvolume = 0;
Array.Clear(sync_reg, 0, sync_reg.Length);
sync_enable = 0;
sync_holdnote = 0;
sync_counter_start = 0;
sync_len_count = 0;
sync_lin_count = 0;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ed2788da33fe474facc1d7ce1b34d03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -45,7 +45,7 @@ namespace VirtualNes.Core
private APU apu; private APU apu;
internal R6502 R = new R6502(); internal R6502 R = new R6502();
private byte[] ZN_Table = new byte[256]; private byte[] ZN_Table = new byte[256];
private ArrayRef<byte> STACK; private ByteArrayRef STACK;
public CPU(NES parent) public CPU(NES parent)
{ {
@ -2010,7 +2010,7 @@ namespace VirtualNes.Core
DMA_cycles = 0; DMA_cycles = 0;
// STACK quick access // STACK quick access
STACK = new ArrayRef<byte>(MMU.RAM, 0x0100, MMU.RAM.Length - 0x100); STACK = new ByteArrayRef(MMU.RAM, 0x0100, MMU.RAM.Length - 0x100);
// Zero/Negative FLAG // Zero/Negative FLAG
ZN_Table[0] = Z_FLAG; ZN_Table[0] = Z_FLAG;

View File

@ -2,9 +2,9 @@
namespace VirtualNes.Core namespace VirtualNes.Core
{ {
public class ArrayRef<T> public class ByteArrayRef
{ {
private T[] m_rawArray; private byte[] m_rawArray;
private int m_offset; private int m_offset;
private int m_length; private int m_length;
@ -18,30 +18,30 @@ namespace VirtualNes.Core
} }
} }
public ArrayRef() { } public ByteArrayRef() { }
public ArrayRef(T[] array, int offset, int length) public ByteArrayRef(byte[] array, int offset, int length)
{ {
SetArray(array, offset, length); SetArray(array, offset, length);
} }
public ArrayRef(T[] array) : this(array, 0, array.Length) { } public ByteArrayRef(byte[] array) : this(array, 0, array.Length) { }
public ArrayRef(T[] array, int offset) : this(array, offset, array.Length - offset) { } public ByteArrayRef(byte[] array, int offset) : this(array, offset, array.Length - offset) { }
public void SetArray(T[] array, int offset, int length) public void SetArray(byte[] array, int offset, int length)
{ {
m_rawArray = array; m_rawArray = array;
m_offset = offset; m_offset = offset;
m_length = length; m_length = length;
} }
public void SetArray(T[] array, int offset) public void SetArray(byte[] array, int offset)
{ {
m_rawArray = array; m_rawArray = array;
m_offset = offset; m_offset = offset;
m_length = array.Length - offset; m_length = array.Length - offset;
} }
public T this[int index] public byte this[int index]
{ {
get get
{ {
@ -53,14 +53,14 @@ namespace VirtualNes.Core
} }
} }
public static implicit operator ArrayRef<T>(T[] array) public static implicit operator ByteArrayRef(byte[] array)
{ {
return new ArrayRef<T>(array); return new ByteArrayRef(array);
} }
public static implicit operator Span<T>(ArrayRef<T> array) public static implicit operator Span<byte>(ByteArrayRef array)
{ {
return new Span<T>(array.m_rawArray, array.Offset, array.m_length); return new Span<byte>(array.m_rawArray, array.Offset, array.m_length);
} }
} }
} }

View File

@ -0,0 +1,204 @@
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();
}
}
}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d5b90f721bfc1ac4ea985c0f564d1c6e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,208 +0,0 @@
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) */
}
}

View File

@ -6,11 +6,11 @@ namespace VirtualNes
public static class MMU public static class MMU
{ {
// CPU 儊儌儕僶儞僋 // CPU 儊儌儕僶儞僋
public static ArrayRef<byte>[] CPU_MEM_BANK = new ArrayRef<byte>[8]; // 8K扨埵 public static ByteArrayRef[] CPU_MEM_BANK = new ByteArrayRef[8]; // 8K扨埵
public static byte[] CPU_MEM_TYPE = new byte[8]; public static byte[] CPU_MEM_TYPE = new byte[8];
public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡 public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡
// PPU 儊儌儕僶儞僋 // PPU 儊儌儕僶儞僋
public static ArrayRef<byte>[] PPU_MEM_BANK = new ArrayRef<byte>[12]; // 1K扨埵 public static ByteArrayRef[] PPU_MEM_BANK = new ByteArrayRef[12]; // 1K扨埵
public static byte[] PPU_MEM_TYPE = new byte[12]; public static byte[] PPU_MEM_TYPE = new byte[12];
public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡 public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡
public static byte[] CRAM_USED = new byte[16]; // 僗僥乕僩僙乕僽梡 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) internal static void SetPROM_Bank(byte page, byte[] ptr, byte type)
{ {
CPU_MEM_BANK[page] = new ArrayRef<byte>(ptr, 0, ptr.Length); CPU_MEM_BANK[page] = new ByteArrayRef(ptr, 0, ptr.Length);
CPU_MEM_TYPE[page] = type; CPU_MEM_TYPE[page] = type;
CPU_MEM_PAGE[page] = 0; CPU_MEM_PAGE[page] = 0;
} }
internal static void SetPROM_Bank(byte page, ArrayRef<byte> ptr, byte type) internal static void SetPROM_Bank(byte page, ByteArrayRef ptr, byte type)
{ {
CPU_MEM_BANK[page] = ptr; CPU_MEM_BANK[page] = ptr;
CPU_MEM_TYPE[page] = type; CPU_MEM_TYPE[page] = type;
@ -88,7 +88,7 @@ namespace VirtualNes
internal static void SetPROM_8K_Bank(byte page, int bank) internal static void SetPROM_8K_Bank(byte page, int bank)
{ {
bank %= PROM_8K_SIZE; bank %= PROM_8K_SIZE;
CPU_MEM_BANK[page] = new ArrayRef<byte>(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank); CPU_MEM_BANK[page] = new ByteArrayRef(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank);
CPU_MEM_TYPE[page] = BANKTYPE_ROM; CPU_MEM_TYPE[page] = BANKTYPE_ROM;
CPU_MEM_PAGE[page] = bank; CPU_MEM_PAGE[page] = bank;
} }
@ -116,7 +116,7 @@ namespace VirtualNes
} }
// PPU VROM bank // PPU VROM bank
internal static void SetVROM_Bank(byte page, ArrayRef<byte> ptr, byte type) internal static void SetVROM_Bank(byte page, ByteArrayRef ptr, byte type)
{ {
PPU_MEM_BANK[page] = ptr; PPU_MEM_BANK[page] = ptr;
PPU_MEM_TYPE[page] = type; PPU_MEM_TYPE[page] = type;
@ -126,7 +126,7 @@ namespace VirtualNes
internal static void SetVROM_1K_Bank(byte page, int bank) internal static void SetVROM_1K_Bank(byte page, int bank)
{ {
bank %= VROM_1K_SIZE; bank %= VROM_1K_SIZE;
PPU_MEM_BANK[page] = new ArrayRef<byte>(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank)); PPU_MEM_BANK[page] = new ByteArrayRef(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank));
PPU_MEM_TYPE[page] = BANKTYPE_VROM; PPU_MEM_TYPE[page] = BANKTYPE_VROM;
PPU_MEM_PAGE[page] = bank; PPU_MEM_PAGE[page] = bank;
} }
@ -169,7 +169,7 @@ namespace VirtualNes
internal static void SetCRAM_1K_Bank(byte page, int bank) internal static void SetCRAM_1K_Bank(byte page, int bank)
{ {
bank &= 0x1F; bank &= 0x1F;
PPU_MEM_BANK[page] = new ArrayRef<byte>(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank); PPU_MEM_BANK[page] = new ByteArrayRef(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank);
PPU_MEM_TYPE[page] = BANKTYPE_CRAM; PPU_MEM_TYPE[page] = BANKTYPE_CRAM;
PPU_MEM_PAGE[page] = bank; PPU_MEM_PAGE[page] = bank;
@ -201,7 +201,7 @@ namespace VirtualNes
internal static void SetVRAM_1K_Bank(byte page, int bank) internal static void SetVRAM_1K_Bank(byte page, int bank)
{ {
bank &= 3; bank &= 3;
PPU_MEM_BANK[page] = new ArrayRef<byte>(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank); PPU_MEM_BANK[page] = new ByteArrayRef(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank);
PPU_MEM_TYPE[page] = BANKTYPE_VRAM; PPU_MEM_TYPE[page] = BANKTYPE_VRAM;
PPU_MEM_PAGE[page] = bank; PPU_MEM_PAGE[page] = bank;
} }

View File

@ -19,7 +19,7 @@ namespace VirtualNes.Core
byte sda; byte sda;
byte scl_old, sda_old; byte scl_old, sda_old;
ArrayRef<byte> pEEPDATA; ByteArrayRef pEEPDATA;
public X24C01() public X24C01()
{ {
@ -34,7 +34,7 @@ namespace VirtualNes.Core
pEEPDATA = null; pEEPDATA = null;
} }
public void Reset(ArrayRef<byte> ptr) public void Reset(ByteArrayRef ptr)
{ {
now_state = X24C01_IDLE; now_state = X24C01_IDLE;
next_state = X24C01_IDLE; next_state = X24C01_IDLE;
@ -220,7 +220,7 @@ namespace VirtualNes.Core
byte sda; byte sda;
byte scl_old, sda_old; byte scl_old, sda_old;
ArrayRef<byte> pEEPDATA; ByteArrayRef pEEPDATA;
public X24C02() public X24C02()
{ {
@ -236,7 +236,7 @@ namespace VirtualNes.Core
pEEPDATA = null; pEEPDATA = null;
} }
public void Reset(ArrayRef<byte> ptr) public void Reset(ByteArrayRef ptr)
{ {
now_state = X24C02_IDLE; now_state = X24C02_IDLE;
next_state = X24C02_IDLE; next_state = X24C02_IDLE;

View File

@ -132,7 +132,7 @@ namespace VirtualNes.Core
} }
} }
private ArrayRef<byte> _PROM_BANK = new ArrayRef<byte>(); private ByteArrayRef _PROM_BANK = new ByteArrayRef();
//void Mapper001::Write(WORD addr, BYTE data) //void Mapper001::Write(WORD addr, BYTE data)
public override void Write(ushort addr, byte data) public override void Write(ushort addr, byte data)
{ {

View File

@ -39,15 +39,15 @@ namespace VirtualNes.Core
//BYTE chr_page[2][8]; //BYTE chr_page[2][8];
BYTE[,] chr_page = new byte[2, 8]; // $5120-$512B BYTE[,] chr_page = new byte[2, 8]; // $5120-$512B
// BGパターン用バンク // BGパターン用バンク
ArrayRef<byte>[] BG_MEM_BANK = new ArrayRef<byte>[8]{ ByteArrayRef[] BG_MEM_BANK = new ByteArrayRef[8]{
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
new ArrayRef<byte>(), new ByteArrayRef(),
}; };
BYTE[] BG_MEM_PAGE = new byte[8]; BYTE[] BG_MEM_PAGE = new byte[8];
@ -433,7 +433,7 @@ namespace VirtualNes.Core
} }
} }
private ArrayRef<byte> _prom_bank = new ArrayRef<byte>(); private ByteArrayRef _prom_bank = new ByteArrayRef();
void SetBank_SRAM(BYTE page, BYTE data) void SetBank_SRAM(BYTE page, BYTE data)
{ {
if (sram_size == 0) data = (byte)((data > 3) ? 8 : 0); if (sram_size == 0) data = (byte)((data > 3) ? 8 : 0);

View File

@ -139,7 +139,7 @@ namespace VirtualNes.Core
{ {
nes.SetSAVERAM_SIZE(384); nes.SetSAVERAM_SIZE(384);
x24c02.Reset(WRAM); x24c02.Reset(WRAM);
x24c01.Reset(new ArrayRef<byte>(WRAM, 256)); x24c01.Reset(new ByteArrayRef(WRAM, 256));
} }
} }

View File

@ -1157,11 +1157,6 @@ namespace VirtualNes.Core
bExtMono = bMode; bExtMono = bMode;
} }
internal int GetScanlineNo()
{
return ScanlineNo;
}
public struct Sprite public struct Sprite
{ {
public byte y public byte y