diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreSupporter.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreSupporter.cs index 57019b9..0c3fb5c 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreSupporter.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreSupporter.cs @@ -62,5 +62,7 @@ namespace AxibugEmuOnline.Client romName = Path.GetFileNameWithoutExtension(romName); File.WriteAllBytes($"{diskFileDirectoryPath}/{romName}.dsv", diskFileContent); } + + public EmulatorConfig Config { get; private set; } = new EmulatorConfig(); } } diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs index f06c119..a22cab9 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs @@ -10,8 +10,7 @@ namespace AxibugEmuOnline.Client private void Start() { - - //StartGame("Kirby.nes"); + StartGame("Kirby.nes"); } public void StartGame(string romName) diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/APU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/APU.cs index 429bc4c..1cb299e 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/APU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/APU.cs @@ -10,6 +10,12 @@ namespace VirtualNes.Core private NES nes; private byte exsound_select; private APU_INTERNAL @internal = new APU_INTERNAL(); + private APU_VRC6 vrc6 = new APU_VRC6(); + private APU_VRC7 vrc7 = new APU_VRC7(); + private APU_MMC5 mmc5 = new APU_MMC5(); + private APU_FDS fds = new APU_FDS(); + private APU_N106 n106 = new APU_N106(); + private APU_FME7 fme7 = new APU_FME7(); private int last_data; private int last_diff; protected short[] m_SoundBuffer = new short[256]; @@ -17,6 +23,7 @@ namespace VirtualNes.Core protected QUEUE queue = new QUEUE(); protected QUEUE exqueue = new QUEUE(); protected bool[] m_bMute = new bool[16]; + protected double elapsed_time; public APU(NES parent) { @@ -90,6 +97,81 @@ namespace VirtualNes.Core } return false; } + + public void SoundSetup() + { + float fClock = nes.nescfg.CpuClock; + int nRate = Supporter.Config.sound.nRate; + + @internal.Setup(fClock, nRate); + vrc6.Setup(fClock, nRate); + vrc7.Setup(fClock, nRate); + mmc5.Setup(fClock, nRate); + fds.Setup(fClock, nRate); + n106.Setup(fClock, nRate); + fme7.Setup(fClock, nRate); + } + + internal void SelectExSound(byte data) + { + exsound_select = data; + } + + internal void Reset() + { + queue = new QUEUE(); + exqueue = new QUEUE(); + + elapsed_time = 0; + + float fClock = nes.nescfg.CpuClock; + int nRate = Supporter.Config.sound.nRate; + + @internal.Reset(fClock, nRate); + vrc6.Reset(fClock, nRate); + vrc7.Reset(fClock, nRate); + mmc5.Reset(fClock, nRate); + fds.Reset(fClock, nRate); + n106.Reset(fClock, nRate); + fme7.Reset(fClock, nRate); + + SoundSetup(); + } + + internal void ExWrite(ushort addr, byte data) + { + SetExQueue(nes.cpu.GetTotalCycles(), addr, data); + + if ((exsound_select & 0x04) != 0) + { + if (addr >= 0x4040 && addr < 0x4100) + { + fds.SyncWrite(addr, data); + } + } + + if ((exsound_select & 0x08) != 0) + { + if (addr >= 0x5000 && addr <= 0x5015) + { + mmc5.SyncWrite(addr, data); + } + } + } + + private void SetExQueue(int writetime, ushort addr, byte data) + { + exqueue.data[exqueue.wrptr].time = writetime; + exqueue.data[exqueue.wrptr].addr = addr; + exqueue.data[exqueue.wrptr].data = data; + exqueue.wrptr++; + var temp = QUEUE_LENGTH - 1; + exqueue.wrptr = (int)(exqueue.wrptr & temp); + if (exqueue.wrptr == exqueue.rdptr) + { + Debuger.LogError("exqueue overflow."); + } + } } public struct QUEUEDATA diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs new file mode 100644 index 0000000..56943b5 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs @@ -0,0 +1,45 @@ +using System; + +namespace VirtualNes.Core +{ + public class APU_FDS : APU_INTERFACE + { + private FDSSOUND fds = new FDSSOUND(); + private FDSSOUND fds_sync = new FDSSOUND(); + + public override void Reset(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Setup(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Write(ushort addr, byte data) + { + throw new System.NotImplementedException(); + } + + public override int Process(int channel) + { + throw new System.NotImplementedException(); + } + + internal void SyncWrite(ushort addr, byte data) + { + WriteSub(addr, data, fds_sync, 1789772.5d); + } + + private void WriteSub(ushort addr, byte data, FDSSOUND ch, double rate) + { + throw new NotImplementedException(); + } + + private class FDSSOUND + { + //todo : 实现 + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs.meta new file mode 100644 index 0000000..5580ec2 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FDS.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e16912525198924a860e53ab4ef0c81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs new file mode 100644 index 0000000..e567bb2 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs @@ -0,0 +1,27 @@ +using System; + +namespace VirtualNes.Core +{ + public class APU_FME7 : APU_INTERFACE + { + public override void Reset(float fClock, int nRate) + { + throw new NotImplementedException(); + } + + public override void Setup(float fClock, int nRate) + { + throw new NotImplementedException(); + } + + public override void Write(ushort addr, byte data) + { + throw new NotImplementedException(); + } + + public override int Process(int channel) + { + throw new NotImplementedException(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs.meta new file mode 100644 index 0000000..4edc65e --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_FME7.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03e0258857a7134438a497aec27ea607 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERFACE.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERFACE.cs index 14f7d8b..391406c 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERFACE.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERFACE.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VirtualNes.Core +namespace VirtualNes.Core { public abstract class APU_INTERFACE { + public const float APU_CLOCK = 1789772.5f; + + public virtual void Dispose() { } + public abstract void Reset(float fClock, int nRate); public abstract void Setup(float fClock, int nRate); public abstract void Write(ushort addr, byte data); @@ -24,5 +22,15 @@ namespace VirtualNes.Core public virtual int GetStateSize() { return 0; } public virtual void SaveState(byte[] p) { } public virtual void LoadState(byte[] p) { } + + public static int INT2FIX(int x) + { + return x << 16; + } + + public static int FIX2INT(int x) + { + return x >> 16; + } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERNAL.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERNAL.cs index 033b9f8..5f1fb96 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERNAL.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_INTERNAL.cs @@ -1,5 +1,3 @@ -using System; - namespace VirtualNes.Core { public class APU_INTERNAL : APU_INTERFACE @@ -63,8 +61,43 @@ namespace VirtualNes.Core private bool SyncUpdateDPCM(int cycles) { - //TODO : ʵ - return false; + bool bIRQ = false; + + if (ch4.sync_enable != 0) + { + ch4.sync_cycles -= cycles; + while (ch4.sync_cycles < 0) + { + ch4.sync_cycles += ch4.sync_cache_cycles; + if (ch4.sync_dmalength != 0) + { + // if( !(--ch4.sync_dmalength) ) { + if (--ch4.sync_dmalength < 2) + { + if (ch4.sync_looping != 0) + { + ch4.sync_dmalength = ch4.sync_cache_dmalength; + } + else + { + ch4.sync_dmalength = 0; + + if (ch4.sync_irq_gen != 0) + { + ch4.sync_irq_enable = 0xFF; + nes.cpu.SetIRQ(CPU.IRQ_DPCM); + } + } + } + } + } + } + if (ch4.sync_irq_enable != 0) + { + bIRQ = true; + } + + return bIRQ; } private void UpdateFrame() diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs new file mode 100644 index 0000000..0b0d4de --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs @@ -0,0 +1,32 @@ +using System; + +namespace VirtualNes.Core +{ + public class APU_MMC5 : APU_INTERFACE + { + public override void Reset(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Setup(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Write(ushort addr, byte data) + { + throw new System.NotImplementedException(); + } + + public override int Process(int channel) + { + throw new System.NotImplementedException(); + } + + internal void SyncWrite(ushort addr, byte data) + { + throw new NotImplementedException(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs.meta new file mode 100644 index 0000000..250e590 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_MMC5.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15b983a12234c3c47baefb9fa2751351 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs new file mode 100644 index 0000000..e34a56f --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs @@ -0,0 +1,25 @@ +namespace VirtualNes.Core +{ + public class APU_N106 : APU_INTERFACE + { + public override void Reset(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Setup(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Write(ushort addr, byte data) + { + throw new System.NotImplementedException(); + } + + public override int Process(int channel) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs.meta new file mode 100644 index 0000000..692dc26 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_N106.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a47ed257e942d4478215338d8fe4c35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs new file mode 100644 index 0000000..0c42555 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs @@ -0,0 +1,310 @@ +using System; + +namespace VirtualNes.Core +{ + public class APU_VRC6 : APU_INTERFACE + { + public const int RECTANGLE_VOL_SHIFT = 8; + public const int SAWTOOTH_VOL_SHIFT = 6; + + private RECTANGLE ch0 = new RECTANGLE(); + private RECTANGLE ch1 = new RECTANGLE(); + private SAWTOOTH ch2 = new SAWTOOTH(); + + private int cycle_rate; + private float cpu_clock; + + public APU_VRC6() + { + Reset(APU_CLOCK, 22050); + } + + public override void Reset(float fClock, int nRate) + { + ch0.ZeroMemory(); + ch1.ZeroMemory(); + ch2.ZeroMemory(); + + Setup(fClock, nRate); + } + + public override void Setup(float fClock, int nRate) + { + cpu_clock = fClock; + cycle_rate = (int)(fClock * 65536.0f / nRate); + } + + public override void Write(ushort addr, byte data) + { + switch (addr) + { + // 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) + { + switch (channel) + { + case 0: + return RectangleRender(ch0); + case 1: + return RectangleRender(ch1); + case 2: + return SawtoothRender(ch2); + } + + 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.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; + } + + private 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 << 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 << 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; + } + + private 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 << 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 << SAWTOOTH_VOL_SHIFT; + num_times++; + } + ch.output_vol = (total / num_times); + } + + return ch.output_vol; + } + + private class RECTANGLE + { + public byte[] reg = new byte[3]; + + public byte enable; + public byte gate; + public byte volume; + + public int phaseacc; + public int freq; + public int output_vol; + + public byte adder; + public byte duty_pos; + + public void ZeroMemory() + { + Array.Clear(reg, 0, reg.Length); + enable = default; + gate = default; + volume = default; + + phaseacc = default; + freq = default; + output_vol = default; + + adder = default; + duty_pos = default; + } + } + + private class SAWTOOTH + { + public byte[] reg = new byte[3]; + + public byte enable; + public byte volume; + + public int phaseacc; + public int freq; + public int output_vol; + + public byte adder; + public byte accum; + public byte phaseaccum; + + public void ZeroMemory() + { + Array.Clear(reg, 0, reg.Length); + enable = default; + volume = default; + + phaseacc = default; + freq = default; + output_vol = default; + + adder = default; + accum = default; + phaseaccum = default; + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs.meta new file mode 100644 index 0000000..e9b6f8a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 190f3271accd30f4eb5b13590417d265 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs new file mode 100644 index 0000000..f15b9d2 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs @@ -0,0 +1,25 @@ +namespace VirtualNes.Core +{ + public class APU_VRC7 : APU_INTERFACE + { + public override void Reset(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Setup(float fClock, int nRate) + { + throw new System.NotImplementedException(); + } + + public override void Write(ushort addr, byte data) + { + throw new System.NotImplementedException(); + } + + public override int Process(int channel) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs.meta new file mode 100644 index 0000000..15e1c81 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 180a87918f9d49e4fad978014f1d594f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/DPCM.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/DPCM.cs index 1f48eb1..54246a2 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/DPCM.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/DPCM.cs @@ -1,11 +1,4 @@ -using Codice.CM.Client.Differences; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VirtualNes.Core +namespace VirtualNes.Core { public class DPCM { diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/NOISE.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/NOISE.cs index 709483d..8b2dc0e 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/NOISE.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/NOISE.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VirtualNes.Core +namespace VirtualNes.Core { public class NOISE { diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/RECTANGLE.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/RECTANGLE.cs index 69abd8f..8d3688e 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/RECTANGLE.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/RECTANGLE.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace VirtualNes.Core { @@ -47,5 +43,43 @@ namespace VirtualNes.Core 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; + } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs index 0fca7d8..2b5fad9 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs @@ -1,7 +1,6 @@ #undef DPCM_SYNCCLOCK using System; -using UnityEngine.UI; namespace VirtualNes.Core { @@ -45,6 +44,7 @@ namespace VirtualNes.Core private APU apu; private R6502 R = new R6502(); private byte[] ZN_Table = new byte[256]; + private Memory STACK; public CPU(NES parent) { @@ -55,17 +55,24 @@ namespace VirtualNes.Core public void Dispose() { } + ushort EA = 0; + ushort ET = 0; + ushort WT = 0; + byte DT = 0; + int exec_cycles = 0; + internal long EXEC(int request_cycles) { byte opcode = 0; int OLD_cycles = TOTAL_cycles; - int exec_cycles = 0; byte nmi_request = 0, irq_request = 0; + bool bClockProcess = m_bClockProcess; - ushort EA = 0; - ushort ET = 0; - ushort WT = 0; - byte DT = 0; + exec_cycles = 0; + EA = 0; + ET = 0; + WT = 0; + DT = 0; while (request_cycles > 0) { @@ -126,81 +133,1008 @@ namespace VirtualNes.Core switch (opcode) { case 0x69: - MR_IM(ref DT); ADC(ref WT, ref DT); - ADD_CYCLE(2, ref exec_cycles); + MR_IM(); ADC(); + ADD_CYCLE(2); break; case 0x65: - MR_ZP(ref EA, ref DT); ADC(ref WT, ref DT); - ADD_CYCLE(3, ref exec_cycles); + MR_ZP(); ADC(); + ADD_CYCLE(3); break; case 0x75: - MR_ZX(ref DT, ref EA); ADC(ref WT, ref DT); - ADD_CYCLE(4, ref exec_cycles); + MR_ZX(); ADC(); + ADD_CYCLE(4); break; case 0x6D: - MR_AB(ref EA, ref DT); ADC(ref WT, ref DT); - ADD_CYCLE(4, ref exec_cycles); + MR_AB(); ADC(); + ADD_CYCLE(4); break; case 0x7D: - MR_AX(ref ET, ref EA, ref DT); ADC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(4, ref exec_cycles); + MR_AX(); ADC(); CHECK_EA(); + ADD_CYCLE(4); break; case 0x79: - MR_AY(ref ET, ref EA, ref DT); ADC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(4, ref exec_cycles); + MR_AY(); ADC(); CHECK_EA(); + ADD_CYCLE(4); break; case 0x61: - MR_IX(ref DT, ref EA); ADC(ref WT, ref DT); - ADD_CYCLE(6, ref exec_cycles); + MR_IX(); ADC(); + ADD_CYCLE(6); break; case 0x71: - MR_IY(ref DT, ref ET, ref EA); ADC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(4, ref exec_cycles); + MR_IY(); ADC(); CHECK_EA(); + ADD_CYCLE(4); break; case 0xE9: - MR_IM(ref DT); SBC(ref WT, ref DT); - ADD_CYCLE(2, ref exec_cycles); + MR_IM(); SBC(); + ADD_CYCLE(2); break; case 0xE5: - MR_ZP(ref EA, ref DT); SBC(ref WT, ref DT); - ADD_CYCLE(3, ref exec_cycles); + MR_ZP(); SBC(); + ADD_CYCLE(3); break; case 0xF5: - MR_ZX(ref DT, ref EA); SBC(ref WT, ref DT); - ADD_CYCLE(4, ref exec_cycles); + MR_ZX(); SBC(); + ADD_CYCLE(4); break; case 0xED: - MR_AB(ref EA, ref DT); SBC(ref WT, ref DT); - ADD_CYCLE(4, ref exec_cycles); + MR_AB(); SBC(); + ADD_CYCLE(4); break; case 0xFD: - MR_AX(ref ET, ref EA, ref DT); SBC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(4, ref exec_cycles); + MR_AX(); SBC(); CHECK_EA(); + ADD_CYCLE(4); break; - case 0xF9: // SBC $????,Y - MR_AY(ref ET, ref EA, ref DT); SBC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(4, ref exec_cycles); + case 0xF9: // SBC $????Y + MR_AY(); SBC(); CHECK_EA(); + ADD_CYCLE(4); break; - case 0xE1: // SBC ($??,X) - MR_IX(ref DT, ref EA); SBC(ref WT, ref DT); - ADD_CYCLE(6, ref exec_cycles); + case 0xE1: // SBC ($??X) + MR_IX(); SBC(); + ADD_CYCLE(6); break; - case 0xF1: // SBC ($??),Y - MR_IY(ref DT, ref ET, ref EA); SBC(ref WT, ref DT); CHECK_EA(ref EA, ref ET, ref exec_cycles); - ADD_CYCLE(5, ref exec_cycles); + case 0xF1: // SBC ($??)Y + MR_IY(); SBC(); CHECK_EA(); + ADD_CYCLE(5); break; case 0xC6: // DEC $?? - MR_ZP(ref EA, ref DT); DEC(ref DT); MW_ZP(EA, DT); - ADD_CYCLE(5, ref exec_cycles); + MR_ZP(); DEC(); MW_ZP(); + ADD_CYCLE(5); break; - case 0xD6: // DEC $??,X - MR_ZX(ref DT, ref EA); DEC(ref DT); MW_ZP(EA, DT); - ADD_CYCLE(6, ref exec_cycles); + case 0xD6: // DEC $??X + MR_ZX(); DEC(); MW_ZP(); + ADD_CYCLE(6); break; case 0xCE: // DEC $???? - MR_AB(ref EA, ref DT); DEC(ref DT); MW_EA(EA, DT); - ADD_CYCLE(6, ref exec_cycles); + MR_AB(); DEC(); MW_EA(); + ADD_CYCLE(6); break; + case 0xDE: // DEC $????X + MR_AX(); DEC(); MW_EA(); + ADD_CYCLE(7); + break; + case 0xCA: // DEX + DEX(); + ADD_CYCLE(2); + break; + case 0x88: // DEY + DEY(); + ADD_CYCLE(2); + break; + case 0xE6: // INC $?? + MR_ZP(); INC(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0xF6: // INC $??X + MR_ZX(); INC(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0xEE: // INC $???? + MR_AB(); INC(); MW_EA(); + ADD_CYCLE(6); + break; + case 0xFE: // INC $????X + MR_AX(); INC(); MW_EA(); + ADD_CYCLE(7); + break; + case 0xE8: // INX + INX(); + ADD_CYCLE(2); + break; + case 0xC8: // INY + INY(); + ADD_CYCLE(2); + break; + case 0x29: // AND #$?? + MR_IM(); AND(); + ADD_CYCLE(2); + break; + case 0x25: // AND $?? + MR_ZP(); AND(); + ADD_CYCLE(3); + break; + case 0x35: // AND $??X + MR_ZX(); AND(); + ADD_CYCLE(4); + break; + case 0x2D: // AND $???? + MR_AB(); AND(); + ADD_CYCLE(4); + break; + case 0x3D: // AND $????X + MR_AX(); AND(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x39: // AND $????Y + MR_AY(); AND(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x21: // AND ($??X) + MR_IX(); AND(); + ADD_CYCLE(6); + break; + case 0x31: // AND ($??)Y + MR_IY(); AND(); CHECK_EA(); + ADD_CYCLE(5); + break; + case 0x0A: // ASL A + ASL_A(); + ADD_CYCLE(2); + break; + case 0x06: // ASL $?? + MR_ZP(); ASL(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x16: // ASL $??,X + MR_ZX(); ASL(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x0E: // ASL $???? + MR_AB(); ASL(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x1E: // ASL $????,X + MR_AX(); ASL(); MW_EA(); + ADD_CYCLE(7); + break; + + case 0x24: // BIT $?? + MR_ZP(); BIT(); + ADD_CYCLE(3); + break; + case 0x2C: // BIT $???? + MR_AB(); BIT(); + ADD_CYCLE(4); + break; + + case 0x49: // EOR #$?? + MR_IM(); EOR(); + ADD_CYCLE(2); + break; + case 0x45: // EOR $?? + MR_ZP(); EOR(); + ADD_CYCLE(3); + break; + case 0x55: // EOR $??,X + MR_ZX(); EOR(); + ADD_CYCLE(4); + break; + case 0x4D: // EOR $???? + MR_AB(); EOR(); + ADD_CYCLE(4); + break; + case 0x5D: // EOR $????,X + MR_AX(); EOR(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x59: // EOR $????,Y + MR_AY(); EOR(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x41: // EOR ($??,X) + MR_IX(); EOR(); + ADD_CYCLE(6); + break; + case 0x51: // EOR ($??),Y + MR_IY(); EOR(); CHECK_EA(); + ADD_CYCLE(5); + break; + + case 0x4A: // LSR A + LSR_A(); + ADD_CYCLE(2); + break; + case 0x46: // LSR $?? + MR_ZP(); LSR(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x56: // LSR $??,X + MR_ZX(); LSR(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x4E: // LSR $???? + MR_AB(); LSR(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x5E: // LSR $????,X + MR_AX(); LSR(); MW_EA(); + ADD_CYCLE(7); + break; + + case 0x09: // ORA #$?? + MR_IM(); ORA(); + ADD_CYCLE(2); + break; + case 0x05: // ORA $?? + MR_ZP(); ORA(); + ADD_CYCLE(3); + break; + case 0x15: // ORA $??,X + MR_ZX(); ORA(); + ADD_CYCLE(4); + break; + case 0x0D: // ORA $???? + MR_AB(); ORA(); + ADD_CYCLE(4); + break; + case 0x1D: // ORA $????,X + MR_AX(); ORA(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x19: // ORA $????,Y + MR_AY(); ORA(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0x01: // ORA ($??,X) + MR_IX(); ORA(); + ADD_CYCLE(6); + break; + case 0x11: // ORA ($??),Y + MR_IY(); ORA(); CHECK_EA(); + ADD_CYCLE(5); + break; + + case 0x2A: // ROL A + ROL_A(); + ADD_CYCLE(2); + break; + case 0x26: // ROL $?? + MR_ZP(); ROL(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x36: // ROL $??,X + MR_ZX(); ROL(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x2E: // ROL $???? + MR_AB(); ROL(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x3E: // ROL $????,X + MR_AX(); ROL(); MW_EA(); + ADD_CYCLE(7); + break; + + case 0x6A: // ROR A + ROR_A(); + ADD_CYCLE(2); + break; + case 0x66: // ROR $?? + MR_ZP(); ROR(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x76: // ROR $??,X + MR_ZX(); ROR(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x6E: // ROR $???? + MR_AB(); ROR(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x7E: // ROR $????,X + MR_AX(); ROR(); MW_EA(); + ADD_CYCLE(7); + break; + + case 0xA9: // LDA #$?? + MR_IM(); LDA(); + ADD_CYCLE(2); + break; + case 0xA5: // LDA $?? + MR_ZP(); LDA(); + ADD_CYCLE(3); + break; + case 0xB5: // LDA $??,X + MR_ZX(); LDA(); + ADD_CYCLE(4); + break; + case 0xAD: // LDA $???? + MR_AB(); LDA(); + ADD_CYCLE(4); + break; + case 0xBD: // LDA $????,X + MR_AX(); LDA(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0xB9: // LDA $????,Y + MR_AY(); LDA(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0xA1: // LDA ($??,X) + MR_IX(); LDA(); + ADD_CYCLE(6); + break; + case 0xB1: // LDA ($??),Y + MR_IY(); LDA(); CHECK_EA(); + ADD_CYCLE(5); + break; + + case 0xA2: // LDX #$?? + MR_IM(); LDX(); + ADD_CYCLE(2); + break; + case 0xA6: // LDX $?? + MR_ZP(); LDX(); + ADD_CYCLE(3); + break; + case 0xB6: // LDX $??,Y + MR_ZY(); LDX(); + ADD_CYCLE(4); + break; + case 0xAE: // LDX $???? + MR_AB(); LDX(); + ADD_CYCLE(4); + break; + case 0xBE: // LDX $????,Y + MR_AY(); LDX(); CHECK_EA(); + ADD_CYCLE(4); + break; + + case 0xA0: // LDY #$?? + MR_IM(); LDY(); + ADD_CYCLE(2); + break; + case 0xA4: // LDY $?? + MR_ZP(); LDY(); + ADD_CYCLE(3); + break; + case 0xB4: // LDY $??,X + MR_ZX(); LDY(); + ADD_CYCLE(4); + break; + case 0xAC: // LDY $???? + MR_AB(); LDY(); + ADD_CYCLE(4); + break; + case 0xBC: // LDY $????,X + MR_AX(); LDY(); CHECK_EA(); + ADD_CYCLE(4); + break; + + case 0x85: // STA $?? + EA_ZP(); STA(); MW_ZP(); + ADD_CYCLE(3); + break; + case 0x95: // STA $??,X + EA_ZX(); STA(); MW_ZP(); + ADD_CYCLE(4); + break; + case 0x8D: // STA $???? + EA_AB(); STA(); MW_EA(); + ADD_CYCLE(4); + break; + case 0x9D: // STA $????,X + EA_AX(); STA(); MW_EA(); + ADD_CYCLE(5); + break; + case 0x99: // STA $????,Y + EA_AY(); STA(); MW_EA(); + ADD_CYCLE(5); + break; + case 0x81: // STA ($??,X) + EA_IX(); STA(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x91: // STA ($??),Y + EA_IY(); STA(); MW_EA(); + ADD_CYCLE(6); + break; + + case 0x86: // STX $?? + EA_ZP(); STX(); MW_ZP(); + ADD_CYCLE(3); + break; + case 0x96: // STX $??,Y + EA_ZY(); STX(); MW_ZP(); + ADD_CYCLE(4); + break; + case 0x8E: // STX $???? + EA_AB(); STX(); MW_EA(); + ADD_CYCLE(4); + break; + + case 0x84: // STY $?? + EA_ZP(); STY(); MW_ZP(); + ADD_CYCLE(3); + break; + case 0x94: // STY $??,X + EA_ZX(); STY(); MW_ZP(); + ADD_CYCLE(4); + break; + case 0x8C: // STY $???? + EA_AB(); STY(); MW_EA(); + ADD_CYCLE(4); + break; + + case 0xAA: // TAX + TAX(); + ADD_CYCLE(2); + break; + case 0x8A: // TXA + TXA(); + ADD_CYCLE(2); + break; + case 0xA8: // TAY + TAY(); + ADD_CYCLE(2); + break; + case 0x98: // TYA + TYA(); + ADD_CYCLE(2); + break; + case 0xBA: // TSX + TSX(); + ADD_CYCLE(2); + break; + case 0x9A: // TXS + TXS(); + ADD_CYCLE(2); + break; + + case 0xC9: // CMP #$?? + MR_IM(); CMP_(); + ADD_CYCLE(2); + break; + case 0xC5: // CMP $?? + MR_ZP(); CMP_(); + ADD_CYCLE(3); + break; + case 0xD5: // CMP $??,X + MR_ZX(); CMP_(); + ADD_CYCLE(4); + break; + case 0xCD: // CMP $???? + MR_AB(); CMP_(); + ADD_CYCLE(4); + break; + case 0xDD: // CMP $????,X + MR_AX(); CMP_(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0xD9: // CMP $????,Y + MR_AY(); CMP_(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0xC1: // CMP ($??,X) + MR_IX(); CMP_(); + ADD_CYCLE(6); + break; + case 0xD1: // CMP ($??),Y + MR_IY(); CMP_(); CHECK_EA(); + ADD_CYCLE(5); + break; + + case 0xE0: // CPX #$?? + MR_IM(); CPX(); + ADD_CYCLE(2); + break; + case 0xE4: // CPX $?? + MR_ZP(); CPX(); + ADD_CYCLE(3); + break; + case 0xEC: // CPX $???? + MR_AB(); CPX(); + ADD_CYCLE(4); + break; + + case 0xC0: // CPY #$?? + MR_IM(); CPY(); + ADD_CYCLE(2); + break; + case 0xC4: // CPY $?? + MR_ZP(); CPY(); + ADD_CYCLE(3); + break; + case 0xCC: // CPY $???? + MR_AB(); CPY(); + ADD_CYCLE(4); + break; + + case 0x90: // BCC + MR_IM(); BCC(); + ADD_CYCLE(2); + break; + case 0xB0: // BCS + MR_IM(); BCS(); + ADD_CYCLE(2); + break; + case 0xF0: // BEQ + MR_IM(); BEQ(); + ADD_CYCLE(2); + break; + case 0x30: // BMI + MR_IM(); BMI(); + ADD_CYCLE(2); + break; + case 0xD0: // BNE + MR_IM(); BNE(); + ADD_CYCLE(2); + break; + case 0x10: // BPL + MR_IM(); BPL(); + ADD_CYCLE(2); + break; + case 0x50: // BVC + MR_IM(); BVC(); + ADD_CYCLE(2); + break; + case 0x70: // BVS + MR_IM(); BVS(); + ADD_CYCLE(2); + break; + + case 0x4C: // JMP $???? + JMP(); + ADD_CYCLE(3); + break; + case 0x6C: // JMP ($????) + JMP_ID(); + ADD_CYCLE(5); + break; + + case 0x20: // JSR + JSR(); + ADD_CYCLE(6); + break; + + case 0x40: // RTI + RTI(); + ADD_CYCLE(6); + break; + case 0x60: // RTS + RTS(); + ADD_CYCLE(6); + break; + + // 僼儔僌惂屼宯 + case 0x18: // CLC + CLC(); + ADD_CYCLE(2); + break; + case 0xD8: // CLD + CLD(); + ADD_CYCLE(2); + break; + case 0x58: // CLI + CLI(); + ADD_CYCLE(2); + break; + case 0xB8: // CLV + CLV(); + ADD_CYCLE(2); + break; + + case 0x38: // SEC + SEC(); + ADD_CYCLE(2); + break; + case 0xF8: // SED + SED(); + ADD_CYCLE(2); + break; + case 0x78: // SEI + SEI(); + ADD_CYCLE(2); + break; + + // 僗僞僢僋宯 + case 0x48: // PHA + PUSH(R.A); + ADD_CYCLE(3); + break; + case 0x08: // PHP + PUSH((byte)(R.P | B_FLAG)); + ADD_CYCLE(3); + break; + case 0x68: // PLA (N-----Z-) + R.A = POP(); + SET_ZN_FLAG(R.A); + ADD_CYCLE(4); + break; + case 0x28: // PLP + R.P = (byte)(POP() | R_FLAG); + ADD_CYCLE(4); + break; + + // 偦偺懠 + case 0x00: // BRK + BRK(); + ADD_CYCLE(7); + break; + + case 0xEA: // NOP + ADD_CYCLE(2); + break; + + // 枹岞奐柦椷孮 + case 0x0B: // ANC #$?? + case 0x2B: // ANC #$?? + MR_IM(); ANC(); + ADD_CYCLE(2); + break; + + case 0x8B: // ANE #$?? + MR_IM(); ANE(); + ADD_CYCLE(2); + break; + + case 0x6B: // ARR #$?? + MR_IM(); ARR(); + ADD_CYCLE(2); + break; + + case 0x4B: // ASR #$?? + MR_IM(); ASR(); + ADD_CYCLE(2); + break; + + case 0xC7: // DCP $?? + MR_ZP(); DCP(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0xD7: // DCP $??,X + MR_ZX(); DCP(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0xCF: // DCP $???? + MR_AB(); DCP(); MW_EA(); + ADD_CYCLE(6); + break; + case 0xDF: // DCP $????,X + MR_AX(); DCP(); MW_EA(); + ADD_CYCLE(7); + break; + case 0xDB: // DCP $????,Y + MR_AY(); DCP(); MW_EA(); + ADD_CYCLE(7); + break; + case 0xC3: // DCP ($??,X) + MR_IX(); DCP(); MW_EA(); + ADD_CYCLE(8); + break; + case 0xD3: // DCP ($??),Y + MR_IY(); DCP(); MW_EA(); + ADD_CYCLE(8); + break; + + case 0xE7: // ISB $?? + MR_ZP(); ISB(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0xF7: // ISB $??,X + MR_ZX(); ISB(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0xEF: // ISB $???? + MR_AB(); ISB(); MW_EA(); + ADD_CYCLE(5); + break; + case 0xFF: // ISB $????,X + MR_AX(); ISB(); MW_EA(); + ADD_CYCLE(5); + break; + case 0xFB: // ISB $????,Y + MR_AY(); ISB(); MW_EA(); + ADD_CYCLE(5); + break; + case 0xE3: // ISB ($??,X) + MR_IX(); ISB(); MW_EA(); + ADD_CYCLE(5); + break; + case 0xF3: // ISB ($??),Y + MR_IY(); ISB(); MW_EA(); + ADD_CYCLE(5); + break; + + case 0xBB: // LAS $????,Y + MR_AY(); LAS(); CHECK_EA(); + ADD_CYCLE(4); + break; + + + case 0xA7: // LAX $?? + MR_ZP(); LAX(); + ADD_CYCLE(3); + break; + case 0xB7: // LAX $??,Y + MR_ZY(); LAX(); + ADD_CYCLE(4); + break; + case 0xAF: // LAX $???? + MR_AB(); LAX(); + ADD_CYCLE(4); + break; + case 0xBF: // LAX $????,Y + MR_AY(); LAX(); CHECK_EA(); + ADD_CYCLE(4); + break; + case 0xA3: // LAX ($??,X) + MR_IX(); LAX(); + ADD_CYCLE(6); + break; + case 0xB3: // LAX ($??),Y + MR_IY(); LAX(); CHECK_EA(); + ADD_CYCLE(5); + break; + + case 0xAB: // LXA #$?? + MR_IM(); LXA(); + ADD_CYCLE(2); + break; + + case 0x27: // RLA $?? + MR_ZP(); RLA(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x37: // RLA $??,X + MR_ZX(); RLA(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x2F: // RLA $???? + MR_AB(); RLA(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x3F: // RLA $????,X + MR_AX(); RLA(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x3B: // RLA $????,Y + MR_AY(); RLA(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x23: // RLA ($??,X) + MR_IX(); RLA(); MW_EA(); + ADD_CYCLE(8); + break; + case 0x33: // RLA ($??),Y + MR_IY(); RLA(); MW_EA(); + ADD_CYCLE(8); + break; + + case 0x67: // RRA $?? + MR_ZP(); RRA(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x77: // RRA $??,X + MR_ZX(); RRA(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x6F: // RRA $???? + MR_AB(); RRA(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x7F: // RRA $????,X + MR_AX(); RRA(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x7B: // RRA $????,Y + MR_AY(); RRA(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x63: // RRA ($??,X) + MR_IX(); RRA(); MW_EA(); + ADD_CYCLE(8); + break; + case 0x73: // RRA ($??),Y + MR_IY(); RRA(); MW_EA(); + ADD_CYCLE(8); + break; + + case 0x87: // SAX $?? + MR_ZP(); SAX(); MW_ZP(); + ADD_CYCLE(3); + break; + case 0x97: // SAX $??,Y + MR_ZY(); SAX(); MW_ZP(); + ADD_CYCLE(4); + break; + case 0x8F: // SAX $???? + MR_AB(); SAX(); MW_EA(); + ADD_CYCLE(4); + break; + case 0x83: // SAX ($??,X) + MR_IX(); SAX(); MW_EA(); + ADD_CYCLE(6); + break; + + case 0xCB: // SBX #$?? + MR_IM(); SBX(); + ADD_CYCLE(2); + break; + + case 0x9F: // SHA $????,Y + MR_AY(); SHA(); MW_EA(); + ADD_CYCLE(5); + break; + case 0x93: // SHA ($??),Y + MR_IY(); SHA(); MW_EA(); + ADD_CYCLE(6); + break; + + case 0x9B: // SHS $????,Y + MR_AY(); SHS(); MW_EA(); + ADD_CYCLE(5); + break; + + case 0x9E: // SHX $????,Y + MR_AY(); SHX(); MW_EA(); + ADD_CYCLE(5); + break; + + case 0x9C: // SHY $????,X + MR_AX(); SHY(); MW_EA(); + ADD_CYCLE(5); + break; + + case 0x07: // SLO $?? + MR_ZP(); SLO(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x17: // SLO $??,X + MR_ZX(); SLO(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x0F: // SLO $???? + MR_AB(); SLO(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x1F: // SLO $????,X + MR_AX(); SLO(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x1B: // SLO $????,Y + MR_AY(); SLO(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x03: // SLO ($??,X) + MR_IX(); SLO(); MW_EA(); + ADD_CYCLE(8); + break; + case 0x13: // SLO ($??),Y + MR_IY(); SLO(); MW_EA(); + ADD_CYCLE(8); + break; + + case 0x47: // SRE $?? + MR_ZP(); SRE(); MW_ZP(); + ADD_CYCLE(5); + break; + case 0x57: // SRE $??,X + MR_ZX(); SRE(); MW_ZP(); + ADD_CYCLE(6); + break; + case 0x4F: // SRE $???? + MR_AB(); SRE(); MW_EA(); + ADD_CYCLE(6); + break; + case 0x5F: // SRE $????,X + MR_AX(); SRE(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x5B: // SRE $????,Y + MR_AY(); SRE(); MW_EA(); + ADD_CYCLE(7); + break; + case 0x43: // SRE ($??,X) + MR_IX(); SRE(); MW_EA(); + ADD_CYCLE(8); + break; + case 0x53: // SRE ($??),Y + MR_IY(); SRE(); MW_EA(); + ADD_CYCLE(8); + break; + + case 0xEB: // SBC #$?? (Unofficial) + MR_IM(); SBC(); + ADD_CYCLE(2); + break; + + case 0x1A: // NOP (Unofficial) + case 0x3A: // NOP (Unofficial) + case 0x5A: // NOP (Unofficial) + case 0x7A: // NOP (Unofficial) + case 0xDA: // NOP (Unofficial) + case 0xFA: // NOP (Unofficial) + ADD_CYCLE(2); + break; + case 0x80: // DOP (CYCLES 2) + case 0x82: // DOP (CYCLES 2) + case 0x89: // DOP (CYCLES 2) + case 0xC2: // DOP (CYCLES 2) + case 0xE2: // DOP (CYCLES 2) + R.PC++; + ADD_CYCLE(2); + break; + case 0x04: // DOP (CYCLES 3) + case 0x44: // DOP (CYCLES 3) + case 0x64: // DOP (CYCLES 3) + R.PC++; + ADD_CYCLE(3); + break; + case 0x14: // DOP (CYCLES 4) + case 0x34: // DOP (CYCLES 4) + case 0x54: // DOP (CYCLES 4) + case 0x74: // DOP (CYCLES 4) + case 0xD4: // DOP (CYCLES 4) + case 0xF4: // DOP (CYCLES 4) + R.PC++; + ADD_CYCLE(4); + break; + case 0x0C: // TOP + case 0x1C: // TOP + case 0x3C: // TOP + case 0x5C: // TOP + case 0x7C: // TOP + case 0xDC: // TOP + case 0xFC: // TOP + R.PC += 2; + ADD_CYCLE(4); + break; + + case 0x02: /* JAM */ + case 0x12: /* JAM */ + case 0x22: /* JAM */ + case 0x32: /* JAM */ + case 0x42: /* JAM */ + case 0x52: /* JAM */ + case 0x62: /* JAM */ + case 0x72: /* JAM */ + case 0x92: /* JAM */ + case 0xB2: /* JAM */ + case 0xD2: /* JAM */ + case 0xF2: /* JAM */ + default: + if (!Supporter.Config.emulator.bIllegalOp) + { + throw new Exception("Illegal Opcode"); + } + else + { + R.PC--; + ADD_CYCLE(4); + } + break; + } + + if (nmi_request != 0) + { + _NMI(); + } + else + if (irq_request != 0) + { + _IRQ(); + } + + request_cycles -= exec_cycles; + TOTAL_cycles += exec_cycles; + + mapper.Clock(exec_cycles); +#if DPCM_SYNCCLOCK + apu->SyncDPCM( exec_cycles ); +#endif + if (bClockProcess) + { + nes.Clock(exec_cycles); } } _execute_exit: @@ -210,6 +1144,571 @@ namespace VirtualNes.Core return TOTAL_cycles - OLD_cycles; } + private void _IRQ() + { + PUSH((byte)(R.PC >> 8)); + PUSH((byte)(R.PC & 0xFF)); + CLR_FLAG(B_FLAG); + PUSH(R.P); + SET_FLAG(I_FLAG); + R.PC = RD6502W(IRQ_VECTOR); + exec_cycles += 7; + } + + + private ushort RD6502W(ushort addr) + { + if (addr < 0x2000) + { + // RAM (Mirror $0800, $1000, $1800) + return BitConverter.ToUInt16(MMU.RAM, addr & 0x07FF); + } + else if (addr < 0x8000) + { + // Others + return (ushort)(nes.Read(addr) + nes.Read((ushort)(addr + 1)) * 0x100); + } + + var temp = MMU.CPU_MEM_BANK[addr >> 13].Span; + shortTemp[0] = temp[addr & 0x1FFF]; + shortTemp[1] = temp[(addr & 0x1FFF) + 1]; + return BitConverter.ToUInt16(shortTemp, 0); + } + + private void SET_FLAG(byte V) + { + R.P |= (V); + } + + private void CLR_FLAG(byte V) + { + var temp = (byte)(~V); + R.P &= temp; + } + + private void _NMI() + { + PUSH((byte)(R.PC >> 8)); + PUSH((byte)(R.PC & 0xFF)); + CLR_FLAG(B_FLAG); + PUSH(R.P); + SET_FLAG(I_FLAG); + R.PC = RD6502W(NMI_VECTOR); + exec_cycles += 7; + } + + private void SRE() + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT >>= 1; + R.A ^= DT; + SET_ZN_FLAG(R.A); + } + + private void SLO() + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT <<= 1; + R.A |= DT; + SET_ZN_FLAG(R.A); + } + + private void SHY() + { + DT = (byte)(R.Y & ((EA >> 8) + 1)); + } + + private void SHX() + { + DT = (byte)(R.X & ((EA >> 8) + 1)); + } + + private void SHS() + { + R.S = (byte)(R.A & R.X); + DT = (byte)(R.S & ((EA >> 8) + 1)); + } + + private void SHA() + { + DT = (byte)(R.A & R.X & ((EA >> 8) + 1)); + } + + private void SBX() + { + WT = (ushort)((R.A & R.X) - DT); + TST_FLAG(WT < 0x100, C_FLAG); + R.X = (byte)(WT & 0xFF); + SET_ZN_FLAG(R.X); + } + + private void SAX() + { + DT = (byte)(R.A & R.X); + } + + private void RRA() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT = (byte)((DT >> 1) | 0x80); + } + else + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT >>= 1; + } + ADC(); + } + + private void RLA() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT = (byte)((DT << 1) | 1); + } + else + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT <<= 1; + } + R.A &= DT; + SET_ZN_FLAG(R.A); + } + + private void LXA() + { + R.A = R.X = (byte)((R.A | 0xEE) & DT); + SET_ZN_FLAG(R.A); + } + + private void LAX() + { + R.A = DT; + R.X = R.A; + SET_ZN_FLAG(R.A); + } + + private void LAS() + { + R.A = R.X = R.S = (byte)(R.S & DT); + SET_ZN_FLAG(R.A); + } + + private void ISB() + { + DT++; + SBC(); + } + + private void DCP() + { + DT--; + CMP_(); + } + + private void ASR() + { + DT &= R.A; + TST_FLAG((DT & 0x01) != 0, C_FLAG); + R.A = (byte)(DT >> 1); + SET_ZN_FLAG(R.A); + } + + private void ARR() + { + DT &= R.A; + R.A = (byte)((DT >> 1) | ((R.P & C_FLAG) << 7)); + SET_ZN_FLAG(R.A); + TST_FLAG((R.A & 0x40) != 0, C_FLAG); + TST_FLAG(((R.A >> 6) ^ (R.A >> 5)) != 0, V_FLAG); + } + + private void ANE() + { + R.A = (byte)((R.A | 0xEE) & R.X & DT); + SET_ZN_FLAG(R.A); + } + + private void ANC() + { + R.A &= DT; + SET_ZN_FLAG(R.A); + TST_FLAG((R.P & N_FLAG) != 0, C_FLAG); + } + + private void BRK() + { + R.PC++; + PUSH((byte)(R.PC >> 8)); + PUSH((byte)(R.PC & 0xFF)); + SET_FLAG(B_FLAG); + PUSH(R.P); + SET_FLAG(I_FLAG); + R.PC = RD6502W(IRQ_VECTOR); + } + + private byte POP() + { + return STACK.Span[(++R.S) & 0xFF]; + } + + private void PUSH(byte V) + { + STACK.Span[(R.S--) & 0xFF] = V; + } + + private void SEI() + { + R.P |= I_FLAG; + } + + private void SED() + { + R.P |= D_FLAG; + } + + private void SEC() + { + R.P |= C_FLAG; + } + + private void CLV() + { + var temp = unchecked((byte)(~V_FLAG)); + R.P &= temp; + } + + private void CLI() + { + var temp = unchecked((byte)(~I_FLAG)); + R.P &= temp; + } + + private void CLD() + { + var temp = unchecked((byte)(~D_FLAG)); + R.P &= temp; + } + + private void CLC() + { + var temp = unchecked((byte)(~C_FLAG)); + R.P &= temp; + } + + private void RTS() + { + R.PC = POP(); + R.PC |= (ushort)(POP() * 0x0100); + R.PC++; + } + + private void RTI() + { + R.P = (byte)(POP() | R_FLAG); + R.PC = POP(); + R.PC |= (ushort)(POP() * 0x0100); + } + + private void JSR() + { + EA = OP6502W(R.PC); + R.PC++; + PUSH((byte)(R.PC >> 8)); + PUSH((byte)(R.PC & 0xFF)); + R.PC = EA; + } + + private void JMP_ID() + { + WT = OP6502W(R.PC); + EA = RD6502(WT); + WT = (ushort)((WT & 0xFF00) | ((WT + 1) & 0x00FF)); + R.PC = (ushort)(EA + RD6502(WT) * 0x100); + } + + private void JMP() + { + R.PC = OP6502W(R.PC); + } + + private void BVS() + { + if ((R.P & V_FLAG) != 0) + REL_JUMP(); + } + + private void REL_JUMP() + { + ET = R.PC; + EA = (ushort)(R.PC + (sbyte)DT); + R.PC = EA; + ADD_CYCLE(1); + CHECK_EA(); + } + + private void BVC() + { + if ((R.P & V_FLAG) == 0) REL_JUMP(); + } + + private void BPL() + { + if ((R.P & N_FLAG) == 0) REL_JUMP(); + } + + private void BNE() + { + if ((R.P & Z_FLAG) == 0) REL_JUMP(); + } + + private void BMI() + { + if ((R.P & N_FLAG) != 0) REL_JUMP(); + } + + private void BEQ() + { + if ((R.P & Z_FLAG) != 0) REL_JUMP(); + } + + private void BCS() + { + if ((R.P & C_FLAG) != 0) REL_JUMP(); + } + + private void BCC() + { + if ((R.P & C_FLAG) == 0) REL_JUMP(); + } + + private void CPY() + { + WT = (ushort)(R.Y - DT); + TST_FLAG((WT & 0x8000) == 0, C_FLAG); + SET_ZN_FLAG((byte)WT); + } + + private void CPX() + { + WT = (ushort)(R.X - DT); + TST_FLAG((WT & 0x8000) == 0, C_FLAG); + SET_ZN_FLAG((byte)WT); + } + + private void CMP_() + { + WT = (ushort)(R.A - DT); + TST_FLAG((WT & 0x8000) == 0, C_FLAG); + SET_ZN_FLAG((byte)WT); + } + + private void TXS() + { + R.S = R.X; + } + + private void TSX() + { + R.X = R.S; SET_ZN_FLAG(R.X); + } + + private void TYA() + { + R.A = R.Y; SET_ZN_FLAG(R.A); + } + + private void TAY() + { + R.Y = R.A; SET_ZN_FLAG(R.Y); + } + + private void TXA() + { + R.A = R.X; SET_ZN_FLAG(R.A); + } + + private void TAX() + { + R.X = R.A; SET_ZN_FLAG(R.X); + } + + private void STY() + { + DT = R.Y; + } + + private void EA_ZY() + { + DT = OP6502(R.PC++); + EA = (byte)(DT + R.Y); + } + + private void STX() + { + DT = R.X; + } + + private void EA_IY() + { + DT = OP6502(R.PC++); + ET = ZPRDW(DT); + EA = (ushort)(ET + R.Y); + } + + private void EA_IX() + { + DT = OP6502(R.PC++); + EA = ZPRDW(DT + R.X); + } + + private void EA_AY() + { + ET = OP6502W(R.PC); + R.PC += 2; + EA = (ushort)(ET + R.Y); + } + + private void EA_AX() + { + ET = OP6502W(R.PC); + R.PC += 2; + EA = (ushort)(ET + R.X); + } + + private void EA_AB() + { + EA = OP6502W(R.PC); + R.PC += 2; + } + + private void EA_ZX() + { + DT = OP6502(R.PC++); + EA = (byte)(DT + R.X); + } + + private void STA() + { + DT = R.A; + } + + private void EA_ZP() + { + EA = OP6502(R.PC++); + } + + private void LDY() + { + R.Y = DT; SET_ZN_FLAG(R.Y); + } + + private void MR_ZY() + { + DT = OP6502(R.PC++); + EA = (byte)(DT + R.Y); + DT = ZPRD(EA); + } + + private void LDX() + { + R.X = DT; SET_ZN_FLAG(R.X); + } + + private void LDA() + { + R.A = DT; SET_ZN_FLAG(R.A); + } + + private void ROR() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT = (byte)((DT >> 1) | 0x80); + } + else + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT >>= 1; + } + SET_ZN_FLAG(DT); + } + + private void ROR_A() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((R.A & 0x01) != 0, C_FLAG); + R.A = (byte)((R.A >> 1) | 0x80); + } + else + { + TST_FLAG((R.A & 0x01) != 0, C_FLAG); + R.A >>= 1; + } + SET_ZN_FLAG(R.A); + } + + private void ROL() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT = (byte)((DT << 1) | 0x01); + } + else + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT <<= 1; + } + SET_ZN_FLAG(DT); + } + + private void ROL_A() + { + if ((R.P & C_FLAG) != 0) + { + TST_FLAG((R.A & 0x80) != 0, C_FLAG); + R.A = (byte)((R.A << 1) | 0x01); + } + else + { + TST_FLAG((R.A & 0x80) != 0, C_FLAG); + R.A <<= 1; + } + SET_ZN_FLAG(R.A); + } + + private void ORA() + { + R.A |= DT; + SET_ZN_FLAG(R.A); + } + + private void LSR_A() + { + TST_FLAG((R.A & 0x01) != 0, C_FLAG); + R.A >>= 1; + SET_ZN_FLAG(R.A); + } + + private void LSR() + { + TST_FLAG((DT & 0x01) != 0, C_FLAG); + DT >>= 1; + SET_ZN_FLAG(DT); + } + + private void EOR() + { + R.A ^= DT; + SET_ZN_FLAG(R.A); + } + internal void SetClockProcess(bool bEnable) { m_bClockProcess = bEnable; @@ -217,14 +1716,17 @@ namespace VirtualNes.Core internal byte OP6502(ushort addr) { - return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; } + private byte[] shortTemp = new byte[2]; internal ushort OP6502W(ushort addr) { var bytePage = MMU.CPU_MEM_BANK[addr >> 13]; - - return BitConverter.ToUInt16(bytePage, addr & 0x1FFF); + var spanByte = bytePage.Span; + shortTemp[0] = spanByte[addr & 0x1FFF]; + shortTemp[1] = spanByte[(addr & 0x1FFF) + 1]; + return BitConverter.ToUInt16(shortTemp, 0); } internal byte RD6502(ushort addr) @@ -242,19 +1744,32 @@ namespace VirtualNes.Core else { // Dummy access - mapper.Read(addr, MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]); + mapper.Read(addr, MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]); } // Quick bank read - return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; } - private void MR_IM(ref byte DT) + private void AND() + { + R.A &= DT; + SET_ZN_FLAG(R.A); + } + + private void MR_IM() { DT = OP6502(R.PC++); } - private void MR_ZP(ref ushort EA, ref byte DT) + private void BIT() + { + TST_FLAG((DT & R.A) == 0, Z_FLAG); + TST_FLAG((DT & 0x80) != 0, N_FLAG); + TST_FLAG((DT & 0x40) != 0, V_FLAG); + } + + private void MR_ZP() { EA = OP6502(R.PC++); DT = ZPRD(EA); @@ -273,7 +1788,7 @@ namespace VirtualNes.Core return (ushort)(ram1 + ram2); } - private void ADC(ref ushort WT, ref byte DT) + private void ADC() { WT = (ushort)(R.A + DT + (R.P & C_FLAG)); TST_FLAG(WT > 0xFF, C_FLAG); @@ -298,26 +1813,26 @@ namespace VirtualNes.Core R.P |= ZN_Table[A]; } - private void ADD_CYCLE(int V, ref int exec_cycles) + private void ADD_CYCLE(int V) { exec_cycles += V; } - private void MR_ZX(ref byte DT, ref ushort EA) + private void MR_ZX() { DT = OP6502(R.PC++); EA = (ushort)(DT + R.X); DT = ZPRD(EA); } - private void MR_AB(ref ushort EA, ref byte DT) + private void MR_AB() { EA = OP6502W(R.PC); R.PC += 2; DT = RD6502(EA); } - private void MR_AX(ref ushort ET, ref ushort EA, ref byte DT) + private void MR_AX() { ET = OP6502W(R.PC); R.PC += 2; @@ -325,12 +1840,12 @@ namespace VirtualNes.Core DT = RD6502(EA); } - private void CHECK_EA(ref ushort EA, ref ushort ET, ref int exec_cycles) + private void CHECK_EA() { - if ((ET & 0xFF00) != (EA & 0xFF00)) ADD_CYCLE(1, ref exec_cycles); + if ((ET & 0xFF00) != (EA & 0xFF00)) ADD_CYCLE(1); } - private void MR_AY(ref ushort ET, ref ushort EA, ref byte DT) + private void MR_AY() { ET = OP6502W(R.PC); R.PC += 2; @@ -338,22 +1853,35 @@ namespace VirtualNes.Core DT = RD6502(EA); } - private void MR_IX(ref byte DT, ref ushort EA) + private void MR_IX() { DT = OP6502(R.PC++); EA = ZPRDW(DT + R.X); DT = RD6502(EA); } - private void MR_IY(ref byte DT, ref ushort ET, ref ushort EA) + private void MR_IY() { DT = OP6502(R.PC++); ET = ZPRDW(DT); EA = (ushort)(ET + R.Y); DT = RD6502(EA); } + private void ASL_A() + { + TST_FLAG((R.A & 0x80) != 0, C_FLAG); + R.A <<= 1; + SET_ZN_FLAG(R.A); + } - private void SBC(ref ushort WT, ref byte DT) + private void ASL() + { + TST_FLAG((DT & 0x80) != 0, C_FLAG); + DT <<= 1; + SET_ZN_FLAG(DT); + } + + private void SBC() { WT = (ushort)(R.A - DT - (~R.P & C_FLAG)); bool f = ((R.A ^ DT) & (R.A ^ WT) & (0x80)) != 0; @@ -363,13 +1891,43 @@ namespace VirtualNes.Core SET_ZN_FLAG(R.A); } - private void DEC(ref byte DT) + private void DEC() { DT--; SET_ZN_FLAG(DT); } - private void MW_ZP(ushort EA, byte DT) + private void DEX() + { + R.X--; + SET_ZN_FLAG(R.X); + } + + private void DEY() + { + R.Y--; + SET_ZN_FLAG(R.Y); + } + + private void INC() + { + DT++; + SET_ZN_FLAG(DT); + } + + private void INX() + { + R.X++; + SET_ZN_FLAG(R.X); + } + + private void INY() + { + R.Y++; + SET_ZN_FLAG(R.Y); + } + + private void MW_ZP() { ZPWR(EA, DT); } @@ -379,7 +1937,7 @@ namespace VirtualNes.Core MMU.RAM[a] = v; } - private void MW_EA(ushort EA, byte DT) + private void MW_EA() { WR6502(EA, DT); } @@ -424,6 +1982,37 @@ namespace VirtualNes.Core { DMA_cycles += cycles; } + + internal void Reset() + { + apu = nes.apu; + mapper = nes.mapper; + + R.A = 0x00; + R.X = 0x00; + R.Y = 0x00; + R.S = 0xFF; + R.P = Z_FLAG | R_FLAG; + R.PC = RD6502W(RES_VECTOR); + + R.INT_pending = 0; + + TOTAL_cycles = 0; + DMA_cycles = 0; + + // STACK quick access + STACK = new Memory(MMU.RAM, 0x0100, MMU.RAM.Length - 0x100); + + // Zero/Negative FLAG + ZN_Table[0] = Z_FLAG; + for (int i = 1; i < 256; i++) + ZN_Table[i] = (byte)((i & 0x80) != 0 ? N_FLAG : 0); + } + + internal void GetContext(ref R6502 r) + { + r = R; + } } public enum StatusFlag6502 : int diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs new file mode 100644 index 0000000..f1d4766 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs @@ -0,0 +1,20 @@ +namespace VirtualNes.Core +{ + public class CHEATCODE + { + public byte enable; + public byte type; + public byte length; + public ushort address; + public uint data; + + public string comment; + } + + class GENIECODE + { + public ushort address; + public byte data; + public byte cmp; + }; +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CHEATCODE.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs.meta similarity index 100% rename from AxibugEmuOnline.Client/Assets/VirtualNes.Core/CHEATCODE.cs.meta rename to AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/CRC.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/CRC.cs index 4275dcf..c6dfd65 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/CRC.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/CRC.cs @@ -1,22 +1,17 @@ -using Codice.CM.Client.Differences; using System; -using System.Collections; -using System.Collections.Generic; -using Unity.VisualScripting.Antlr3.Runtime.Tree; -using UnityEngine; namespace VirtualNes.Core { public static class CRC { const int CHAR_BIT = 8; - const ulong CRCPOLY1 = 0x04C11DB7UL; - const ulong CRCPOLY2 = 0xEDB88320UL; + const uint CRCPOLY1 = 0x04C11DB7U; + const uint CRCPOLY2 = 0xEDB88320U; static bool m_Init; static bool m_InitRev; - static ulong[] m_CrcTable = new ulong[byte.MaxValue + 1]; - static ulong[] m_CrcTableRev = new ulong[byte.MaxValue + 1]; + static uint[] m_CrcTable = new uint[byte.MaxValue + 1]; + static uint[] m_CrcTableRev = new uint[byte.MaxValue + 1]; public static ulong Crc(int size, Span c) { @@ -35,7 +30,7 @@ namespace VirtualNes.Core } return ~r & 0xFFFFFFFFUL; } - public static ulong CrcRev(int size, Span c) + public static uint CrcRev(int size, Span c) { if (!m_InitRev) { @@ -43,41 +38,41 @@ namespace VirtualNes.Core m_InitRev = true; } - ulong r = 0xFFFFFFFFUL; + uint r = 0xFFFFFFFFU; int step = 0; while (--size >= 0) { r = (r >> CHAR_BIT) ^ m_CrcTableRev[(byte)r ^ c[step]]; step++; } - return r ^ 0xFFFFFFFFUL; + return r ^ 0xFFFFFFFFU; } static void MakeTable() { int i, j; - ulong r; + uint r; for (i = 0; i <= byte.MaxValue; i++) { - r = (ulong)i << (32 - CHAR_BIT); + r = (uint)i << (32 - CHAR_BIT); for (j = 0; j < CHAR_BIT; j++) { if ((r & 0x80000000UL) > 0) r = (r << 1) ^ CRCPOLY1; else r <<= 1; } - m_CrcTable[i] = r & 0xFFFFFFFFUL; + m_CrcTable[i] = r & 0xFFFFFFFFU; } } static void MakeTableRev() { int i, j; - ulong r; + uint r; for (i = 0; i <= byte.MaxValue; i++) { - r = (ulong)i; + r = (uint)i; for (j = 0; j < CHAR_BIT; j++) { if ((r & 1) > 0) r = (r >> 1) ^ CRCPOLY2; diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs new file mode 100644 index 0000000..964fa3b --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs @@ -0,0 +1,145 @@ +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 static class Emu2413API + { + public static void OPLL_init(UInt32 c, UInt32 r) + { + makePmTable(); + makeAmTable(); + makeDB2LinTable(); + makeAdjustTable(); + makeTllTable(); + makeRksTable(); + makeSinTable(); + makeDefaultPatch(); + OPLL_setClock(c, r); + } + + private 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() + { + throw new NotImplementedException(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs.meta new file mode 100644 index 0000000..c25181d --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/Emu2413.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5ecddbb6b69204478d799a484d8c47c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/EnumRenderMethod.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/EnumRenderMethod.cs index 8bdaf21..ae8adf4 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/EnumRenderMethod.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/EnumRenderMethod.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VirtualNes.Core +namespace VirtualNes.Core { // 昤夋曽幃 public enum EnumRenderMethod diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs new file mode 100644 index 0000000..71a82ca --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs @@ -0,0 +1,17 @@ +using System.Runtime.CompilerServices; + +namespace VirtualNes.Core +{ + public static class MemoryUtility + { + public static void ZEROMEMORY(byte[] array, uint length) + { + memset(array, 0, length); + } + + public static void memset(byte[] array, byte value, uint length) + { + Unsafe.InitBlock(ref array[0], value, length); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs.meta new file mode 100644 index 0000000..a9afc7a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8586eb710dc81124593eb5adfa08d73b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/NesConfig.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/NesConfig.cs index b4166fb..b23149f 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/NesConfig.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/NesConfig.cs @@ -1,11 +1,11 @@ namespace VirtualNes.Core { - public struct NesConfig + public class NesConfig { public float BaseClock; // NTSC:21477270.0 PAL:21281364.0 public float CpuClock; // NTSC: 1789772.5 PAL: 1773447.0 - public int TotalScanLines; // NTSC: 262 PAL: 312 + public int TotalScanlines; // NTSC: 262 PAL: 312 public int ScanlineCycles; // NTSC:1364 PAL:1362 @@ -19,40 +19,33 @@ public int FrameRate; // NTSC:60(59.94) PAL:50 public float FramePeriod; // NTSC:16.683 PAL:20.0 - public static NesConfig GetNTSC() + public static NesConfig NESCONFIG_NTSC = new NesConfig { - return new NesConfig - { - BaseClock = 21477270.0f, - CpuClock = 1789772.5f, - TotalScanLines = 262, - ScanlineCycles = 1364, - HDrawCycles = 1024, - HBlankCycles = 340, - ScanlineEndCycles = 4, - FrameCycles = 1364 * 262, - FrameIrqCycles = 29830, - FrameRate = 60, - FramePeriod = 1000.0f / 60.0f - }; - } - - public static NesConfig GetPAL() + BaseClock = 21477270.0f, + CpuClock = 1789772.5f, + TotalScanlines = 262, + ScanlineCycles = 1364, + HDrawCycles = 1024, + HBlankCycles = 340, + ScanlineEndCycles = 4, + FrameCycles = 1364 * 262, + FrameIrqCycles = 29830, + FrameRate = 60, + FramePeriod = 1000.0f / 60.0f + }; + public static NesConfig NESCONFIG_PAL = new NesConfig { - return new NesConfig - { - BaseClock = 26601714.0f, - CpuClock = 1662607.125f, - TotalScanLines = 312, - ScanlineCycles = 1278, - HDrawCycles = 960, - HBlankCycles = 318, - ScanlineEndCycles = 2, - FrameCycles = 1278 * 312, - FrameIrqCycles = 33252, - FrameRate = 50, - FramePeriod = 1000.0f / 50.0f - }; - } + BaseClock = 26601714.0f, + CpuClock = 1662607.125f, + TotalScanlines = 312, + ScanlineCycles = 1278, + HDrawCycles = 960, + HBlankCycles = 318, + ScanlineEndCycles = 2, + FrameCycles = 1278 * 312, + FrameIrqCycles = 33252, + FrameRate = 50, + FramePeriod = 1000.0f / 50.0f + }; } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ROMClasses.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ROMClasses.cs index e316501..bf81c40 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ROMClasses.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ROMClasses.cs @@ -1,7 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; namespace VirtualNes.Core { @@ -27,7 +24,7 @@ namespace VirtualNes.Core NSF } - public struct NSFHEADER + public class NSFHEADER { byte[] ID; byte Version; @@ -43,7 +40,7 @@ namespace VirtualNes.Core byte[] BankSwitch; ushort SpeedPAL; byte NTSC_PALbits; - byte ExtraChipSelect; + public byte ExtraChipSelect; byte[] Expansion; // must be 0 @@ -65,7 +62,7 @@ namespace VirtualNes.Core } } - public struct NESHEADER + public class NESHEADER { public byte[] ID; public byte PRG_PAGE_SIZE; diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/RomPatch.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/RomPatch.cs index ed4d453..2b309cd 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/RomPatch.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/RomPatch.cs @@ -1,13 +1,8 @@ -using System.Collections; -using System.Collections.Generic; -using System.Runtime.Remoting.Messaging; -using UnityEngine; - namespace VirtualNes.Core { public static class RomPatch { - public static void DoPatch(ref ulong crc, ref byte[] lpPRG, ref byte[] lpCHR, ref int mapper, ref NESHEADER header) + public static void DoPatch(ref uint crc, ref byte[] lpPRG, ref byte[] lpCHR, ref int mapper, ref NESHEADER header) { // Mapper 000 if (crc == 0x57970078) diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/State.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/State.cs index 3bbca28..2bbf1f0 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/State.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/State.cs @@ -1,9 +1,4 @@ -using Codice.CM.Client.Differences; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; namespace VirtualNes.Core { diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs index b8cf455..b3d409f 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs @@ -1,26 +1,22 @@ -using Codice.CM.Client.Differences; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; namespace VirtualNes { public static class MMU { // CPU 儊儌儕僶儞僋 - public static byte[][] CPU_MEM_BANK = new byte[8][]; // 8K扨埵 - + public static Memory[] CPU_MEM_BANK = new Memory[8]; // 8K扨埵 + public static byte[] CPU_MEM_TYPE = new byte[8]; + public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡 // PPU 儊儌儕僶儞僋 - public static byte[][] PPU_MEM_BANK = new byte[12][]; // 1K扨埵 + public static Memory[] PPU_MEM_BANK = new Memory[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]; // 僗僥乕僩僙乕僽梡 // NES儊儌儕 public static byte[] RAM = new byte[8 * 1024]; // NES撪憻RAM - public static byte[] WARM = new byte[128 * 1024]; // 儚乕僋/僶僢僋傾僢僾RAM + public static byte[] WRAM = new byte[128 * 1024]; // 儚乕僋/僶僢僋傾僢僾RAM public static byte[] DRAM = new byte[40 * 1024]; // 僨傿僗僋僔僗僥儉RAM public static byte[] XRAM = new byte[8 * 1024]; // 僟儈乕僶儞僋 public static byte[] ERAM = new byte[32 * 1024]; // 奼挘婡婍梡RAM @@ -42,6 +38,17 @@ namespace VirtualNes public static ushort loopy_v; // same as $2005/$2006 public static ushort loopy_x; // tile x offset + // ROM僨乕僞億僀儞僞 + public static byte[] PROM; // PROM ptr + public static byte[] VROM; // VROM ptr + + // For dis... + public static byte PROM_ACCESS; + + // ROM 僶儞僋僒僀僘 + public static int PROM_8K_SIZE, PROM_16K_SIZE, PROM_32K_SIZE; + public static int VROM_1K_SIZE, VROM_2K_SIZE, VROM_4K_SIZE, VROM_8K_SIZE; + // 儊儌儕僞僀僾 // For PROM (CPU) public const byte BANKTYPE_ROM = 0x00; @@ -60,5 +67,170 @@ namespace VirtualNes public const byte VRAM_MIRROR4L = 0x03; // PA10 L屌掕 $2000-$23FF偺儈儔乕 public const byte VRAM_MIRROR4H = 0x04; // PA10 H屌掕 $2400-$27FF偺儈儔乕 + internal static void SetPROM_Bank(byte page, Memory ptr, byte type) + { + CPU_MEM_BANK[page] = ptr; + CPU_MEM_TYPE[page] = type; + CPU_MEM_PAGE[page] = 0; + } + + internal static void SetPROM_8K_Bank(byte page, int bank) + { + bank %= PROM_8K_SIZE; + CPU_MEM_BANK[page] = new Memory(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank); + CPU_MEM_TYPE[page] = BANKTYPE_ROM; + CPU_MEM_PAGE[page] = bank; + } + + internal static void SetPROM_16K_Bank(byte page, int bank) + { + SetPROM_8K_Bank((byte)(page + 0), bank * 2 + 0); + SetPROM_8K_Bank((byte)(page + 1), bank * 2 + 1); + } + + internal static void SetPROM_32K_Bank(int bank) + { + SetPROM_8K_Bank(4, bank * 4 + 0); + SetPROM_8K_Bank(5, bank * 4 + 1); + SetPROM_8K_Bank(6, bank * 4 + 2); + SetPROM_8K_Bank(7, bank * 4 + 3); + } + + internal static void SetPROM_32K_Bank(int bank0, int bank1, int bank2, int bank3) + { + SetPROM_8K_Bank(4, bank0); + SetPROM_8K_Bank(5, bank1); + SetPROM_8K_Bank(6, bank2); + SetPROM_8K_Bank(7, bank3); + } + + // PPU VROM bank + internal static void SetVROM_Bank(byte page, Memory ptr, byte type) + { + PPU_MEM_BANK[page] = ptr; + PPU_MEM_TYPE[page] = type; + PPU_MEM_PAGE[page] = 0; + } + + internal static void SetVROM_1K_Bank(byte page, int bank) + { + bank %= VROM_1K_SIZE; + PPU_MEM_BANK[page] = new Memory(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank)); + PPU_MEM_TYPE[page] = BANKTYPE_VROM; + PPU_MEM_PAGE[page] = bank; + } + + internal static void SetVROM_2K_Bank(byte page, int bank) + { + SetVROM_1K_Bank((byte)(page + 0), bank * 2 + 0); + SetVROM_1K_Bank((byte)(page + 1), bank * 2 + 1); + } + + internal static void SetVROM_4K_Bank(byte page, int bank) + { + SetVROM_1K_Bank((byte)(page + 0), bank * 4 + 0); + SetVROM_1K_Bank((byte)(page + 1), bank * 4 + 1); + SetVROM_1K_Bank((byte)(page + 2), bank * 4 + 2); + SetVROM_1K_Bank((byte)(page + 3), bank * 4 + 3); + } + + internal static void SetVROM_8K_Bank(int bank) + { + for (byte i = 0; i < 8; i++) + { + SetVROM_1K_Bank(i, bank * 8 + i); + } + } + + internal static void SetVROM_8K_Bank(int bank0, int bank1, int bank2, int bank3, + int bank4, int bank5, int bank6, int bank7) + { + SetVROM_1K_Bank(0, bank0); + SetVROM_1K_Bank(1, bank1); + SetVROM_1K_Bank(2, bank2); + SetVROM_1K_Bank(3, bank3); + SetVROM_1K_Bank(4, bank4); + SetVROM_1K_Bank(5, bank5); + SetVROM_1K_Bank(6, bank6); + SetVROM_1K_Bank(7, bank7); + } + + internal static void SetCRAM_1K_Bank(byte page, int bank) + { + bank &= 0x1F; + PPU_MEM_BANK[page] = new Memory(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank); + PPU_MEM_TYPE[page] = BANKTYPE_CRAM; + PPU_MEM_PAGE[page] = bank; + + CRAM_USED[bank >> 2] = 0xFF; // CRAM巊梡僼儔僌 + } + + internal static void SetCRAM_2K_Bank(byte page, int bank) + { + SetCRAM_1K_Bank((byte)(page + 0), bank * 2 + 0); + SetCRAM_1K_Bank((byte)(page + 1), bank * 2 + 1); + } + + internal static void SetCRAM_4K_Bank(byte page, int bank) + { + SetCRAM_1K_Bank((byte)(page + 0), bank * 4 + 0); + SetCRAM_1K_Bank((byte)(page + 1), bank * 4 + 1); + SetCRAM_1K_Bank((byte)(page + 2), bank * 4 + 2); + SetCRAM_1K_Bank((byte)(page + 3), bank * 4 + 3); + } + + internal static void SetCRAM_8K_Bank(int bank) + { + for (byte i = 0; i < 8; i++) + { + SetCRAM_1K_Bank(i, bank * 8 + 1); + } + } + + internal static void SetVRAM_1K_Bank(byte page, int bank) + { + bank &= 3; + PPU_MEM_BANK[page] = new Memory(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank); + PPU_MEM_TYPE[page] = BANKTYPE_VRAM; + PPU_MEM_PAGE[page] = bank; + } + + internal static void SetVRAM_Bank(int bank0, int bank1, int bank2, int bank3) + { + SetVRAM_1K_Bank(8, bank0); + SetVRAM_1K_Bank(9, bank1); + SetVRAM_1K_Bank(10, bank2); + SetVRAM_1K_Bank(11, bank3); + } + + internal static void SetVRAM_Mirror(int type) + { + switch (type) + { + case VRAM_HMIRROR: + SetVRAM_Bank(0, 0, 1, 1); + break; + case VRAM_VMIRROR: + SetVRAM_Bank(0, 1, 0, 1); + break; + case VRAM_MIRROR4L: + SetVRAM_Bank(0, 0, 0, 0); + break; + case VRAM_MIRROR4H: + SetVRAM_Bank(1, 1, 1, 1); + break; + case VRAM_MIRROR4: + SetVRAM_Bank(0, 1, 2, 3); + break; + } + } + + internal static void SetVRAM_Mirror(int bank0, int bank1, int bank2, int bank3) + { + SetVRAM_1K_Bank(8, bank0); + SetVRAM_1K_Bank(9, bank1); + SetVRAM_1K_Bank(10, bank2); + SetVRAM_1K_Bank(11, bank3); + } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs index 132b313..75c6b55 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs @@ -1,9 +1,4 @@ -using Codice.CM.Client.Differences; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; namespace VirtualNes.Core { @@ -30,7 +25,7 @@ namespace VirtualNes.Core // $6000-$7FFF WRAM if (addr >= 0x6000 && addr <= 0x7FFF) { - return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; } return (byte)(addr >> 8); @@ -39,7 +34,7 @@ namespace VirtualNes.Core { if (addr >= 0x6000 && addr <= 0x7FFF) { - MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data; + MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = data; } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs index b1a30f9..118698e 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs @@ -1,4 +1,3 @@ -using Codice.CM.Client.Differences; using System; using System.Collections.Generic; using System.IO; @@ -18,10 +17,14 @@ namespace VirtualNes.Core public NesConfig nescfg; private List m_CheatCode = new List(); + private List m_GenieCode = new List(); private bool m_bDiskThrottle; private int m_CommandRequest; private int m_nSnapNo; private bool m_bNsfPlaying; + private bool m_bNsfInit; + private int m_nNsfSongNo; + private int m_nNsfSongMode; private bool m_bMoviePlay; private bool m_bMovieRec; private Stream m_fpMovie; @@ -96,7 +99,7 @@ namespace VirtualNes.Core bVideoMode = false; - nescfg = NesConfig.GetNTSC(); + nescfg = NesConfig.NESCONFIG_NTSC; CheatInitial(); @@ -203,18 +206,203 @@ namespace VirtualNes.Core SaveDISK(); SaveTurboFile(); - //todo : ʵ + // RAM Clear + MemoryUtility.ZEROMEMORY(MMU.RAM, (uint)MMU.RAM.Length); + if (rom.GetPROM_CRC() == 0x29401686) + { // Minna no Taabou no Nakayoshi Dai Sakusen(J) + MemoryUtility.memset(MMU.RAM, 0xFF, (uint)MMU.RAM.Length); + } + + // RAM set + if (!rom.IsSAVERAM() && rom.GetMapperNo() != 20) + { + MemoryUtility.memset(MMU.WRAM, 0xFF, (uint)MMU.WRAM.Length); + } + + MemoryUtility.ZEROMEMORY(MMU.CRAM, (uint)MMU.CRAM.Length); + MemoryUtility.ZEROMEMORY(MMU.VRAM, (uint)MMU.VRAM.Length); + + MemoryUtility.ZEROMEMORY(MMU.SPRAM, (uint)MMU.SPRAM.Length); + MemoryUtility.ZEROMEMORY(MMU.BGPAL, (uint)MMU.BGPAL.Length); + MemoryUtility.ZEROMEMORY(MMU.SPPAL, (uint)MMU.SPPAL.Length); + + MemoryUtility.ZEROMEMORY(MMU.CPUREG, (uint)MMU.CPUREG.Length); + MemoryUtility.ZEROMEMORY(MMU.PPUREG, (uint)MMU.PPUREG.Length); + + m_bDiskThrottle = false; + + SetRenderMethod(EnumRenderMethod.PRE_RENDER); + + if (rom.IsPAL()) + { + SetVideoMode(true); + } + + MMU.PROM = rom.GetPROM(); + MMU.VROM = rom.GetVROM(); + + MMU.PROM_8K_SIZE = rom.GetPROM_SIZE() * 2; + MMU.PROM_16K_SIZE = rom.GetPROM_SIZE(); + MMU.PROM_32K_SIZE = rom.GetPROM_SIZE() / 2; + + MMU.VROM_1K_SIZE = rom.GetVROM_SIZE() * 8; + MMU.VROM_2K_SIZE = rom.GetVROM_SIZE() * 4; + MMU.VROM_4K_SIZE = rom.GetVROM_SIZE() * 2; + MMU.VROM_8K_SIZE = rom.GetVROM_SIZE(); + + // ftHgoN + if (MMU.VROM_8K_SIZE != 0) + { + MMU.SetVROM_8K_Bank(0); + } + else + { + MMU.SetCRAM_8K_Bank(0); + } + + // ~[ + if (rom.Is4SCREEN()) + { + MMU.SetVRAM_Mirror(MMU.VRAM_MIRROR4); + } + else if (rom.IsVMIRROR()) + { + MMU.SetVRAM_Mirror(MMU.VRAM_VMIRROR); + } + else + { + MMU.SetVRAM_Mirror(MMU.VRAM_HMIRROR); + } + + apu.SelectExSound(0); + + ppu.Reset(); + mapper.Reset(); + + // Trainer + if (rom.IsTRAINER()) + { + Array.Copy(rom.GetTRAINER(), 0, MMU.WRAM, 0x1000, 512); + } + + pad.Reset(); + cpu.Reset(); + apu.Reset(); + + if (rom.IsNSF()) + { + mapper.Reset(); + } + + base_cycles = emul_cycles = 0; + } + + internal void SetVideoMode(bool bMode) + { + bVideoMode = bMode; + if (!bVideoMode) + { + nescfg = NesConfig.NESCONFIG_NTSC; + } + else + { + nescfg = NesConfig.NESCONFIG_PAL; + } + apu.SoundSetup(); + } + + public void SetRenderMethod(EnumRenderMethod type) + { + RenderMethod = type; } internal void SoftReset() { - //todo : ʵ + pad.Reset(); + cpu.Reset(); + apu.Reset(); + + if (rom.IsNSF()) + { + mapper.Reset(); + } + + m_bDiskThrottle = false; + + base_cycles = emul_cycles = 0; } internal void EmulateNSF() { - //todo : ʵNSFģ - throw new NotImplementedException("EmulateNSF"); + R6502 reg = null; + + ppu.Reset(); + mapper.VSync(); + + //DEBUGOUT( "Frame\n" ); + + if (m_bNsfPlaying) + { + if (m_bNsfInit) + { + MemoryUtility.ZEROMEMORY(MMU.RAM, (uint)MMU.RAM.Length); + if ((rom.GetNsfHeader().ExtraChipSelect & 0x04) == 0) + { + MemoryUtility.ZEROMEMORY(MMU.RAM, 0x2000); + } + + apu.Reset(); + apu.Write(0x4015, 0x0F); + apu.Write(0x4017, 0xC0); + apu.ExWrite(0x4080, 0x80); // FDS Volume 0 + apu.ExWrite(0x408A, 0xE8); // FDS Envelope Speed + + cpu.GetContext(ref reg); + reg.PC = 0x4710; // Init Address + reg.A = (byte)m_nNsfSongNo; + reg.X = (byte)m_nNsfSongMode; + reg.Y = 0; + reg.S = 0xFF; + reg.P = CPU.Z_FLAG | CPU.R_FLAG | CPU.I_FLAG; + + // S΍˂Ăă[v(1b) + for (int i = 0; i < nescfg.TotalScanlines * 60; i++) + { + EmulationCPU(nescfg.ScanlineCycles); + cpu.GetContext(ref reg); + + // [vɓƂmF甲 + if (reg.PC == 0x4700) + { + break; + } + } + + m_bNsfInit = false; + } + + cpu.GetContext(ref reg); + // [vɓĂĐݒ肷 + if (reg.PC == 0x4700) + { + reg.PC = 0x4720; // Play Address + reg.A = 0; + reg.S = 0xFF; + } + + for (int i = 0; i < nescfg.TotalScanlines; i++) + { + EmulationCPU(nescfg.ScanlineCycles); + } + } + else + { + cpu.GetContext(ref reg); + reg.PC = 0x4700; // [v + reg.S = 0xFF; + + EmulationCPU(nescfg.ScanlineCycles * nescfg.TotalScanlines); + } } internal void CheatCodeProcess() @@ -239,7 +427,7 @@ namespace VirtualNes.Core for (i = 0; i < SAVERAM_SIZE; i++) { - if (MMU.WARM[i] != 0x00) + if (MMU.WRAM[i] != 0x00) break; } @@ -249,7 +437,7 @@ namespace VirtualNes.Core Debuger.Log($"Saving SAVERAM...[{romName}]"); - Supporter.SaveSRAMToFile(MMU.WARM, romName); + Supporter.SaveSRAMToFile(MMU.WRAM, romName); } } @@ -382,7 +570,7 @@ namespace VirtualNes.Core case 0x05: // $A000-$BFFF case 0x06: // $C000-$DFFF case 0x07: // $E000-$FFFF - return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; } return 0x00; // Warning\h @@ -508,23 +696,47 @@ namespace VirtualNes.Core } else { - mapper->WriteLow(addr, data); + mapper.WriteLow(addr, data); } break; case 0x03: // $6000-$7FFF - mapper->WriteLow(addr, data); + mapper.WriteLow(addr, data); break; case 0x04: // $8000-$9FFF case 0x05: // $A000-$BFFF case 0x06: // $C000-$DFFF case 0x07: // $E000-$FFFF - mapper->Write(addr, data); + mapper.Write(addr, data); GenieCodeProcess(); break; } } + private void GenieCodeProcess() + { + ushort addr; + + for (int i = 0; i < m_GenieCode.Count; i++) + { + addr = m_GenieCode[i].address; + if ((addr & 0x8000) != 0) + { + // 8character codes + if (MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] == m_GenieCode[i].cmp) + { + MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = m_GenieCode[i].data; + } + } + else + { + // 6character codes + addr |= 0x8000; + MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = m_GenieCode[i].data; + } + } + } + private void WriteReg(ushort addr, byte data) { switch (addr & 0xFF) @@ -561,20 +773,20 @@ namespace VirtualNes.Core case 0x16: mapper.ExWrite(addr, data); // For VS-Unisystem pad.Write(addr, data); - CPUREG[addr & 0xFF] = data; + MMU.CPUREG[addr & 0xFF] = data; m_TapeIn = data; break; case 0x17: - CPUREG[addr & 0xFF] = data; - pad->Write(addr, data); - apu->Write(addr, data); + MMU.CPUREG[addr & 0xFF] = data; + pad.Write(addr, data); + apu.Write(addr, data); break; // VirtuaNESŗL|[g case 0x18: - apu->Write(addr, data); + apu.Write(addr, data); break; default: - mapper->ExWrite(addr, data); + mapper.ExWrite(addr, data); break; } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs index 7dba9d2..46aac06 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs @@ -1,4 +1,5 @@ -using System; +using Codice.CM.Client.Differences; +using System; namespace VirtualNes.Core { @@ -17,6 +18,10 @@ namespace VirtualNes.Core private byte[] padbitsync = new byte[4]; private byte micbitsync; private bool bBarcodeWorld; + private int[][] padcnt = new int[4][] + { + new int[2],new int[2],new int[2],new int[2], + }; public uint pad1bit, pad2bit, pad3bit, pad4bit; @@ -79,6 +84,326 @@ namespace VirtualNes.Core return data; } public void Dispose() { } + + internal void Write(ushort addr, byte data) + { + if (addr == 0x4016) + { + if ((data & 0x01) != 0) + { + bStrobe = true; + } + else if (bStrobe) + { + bStrobe = false; + + Strobe(); + if (expad != null) + { + expad.Strobe(); + } + } + + if (expad != null) + { + expad.Write4016(data); + } + } + if (addr == 0x4017) + { + if (expad != null) + { + expad.Write4017(data); + } + } + } + + private void Strobe() + { + // For VS-Unisystem + if (nes.rom.IsVSUNISYSTEM()) + { + uint pad1 = (uint)(padbitsync[0] & 0xF3); + uint pad2 = (uint)(padbitsync[1] & 0xF3); + uint st1 = (uint)(padbitsync[0] & 0x08) >> 3; + uint st2 = (uint)(padbitsync[1] & 0x08) >> 3; + + switch (nVSSwapType) + { + case VSType.VS_TYPE0: + pad1bit = pad1 | (st1 << 2); + pad2bit = pad2 | (st2 << 2); + break; + case VSType.VS_TYPE1: + pad1bit = pad2 | (st1 << 2); + pad2bit = pad1 | (st2 << 2); + break; + case VSType.VS_TYPE2: + pad1bit = pad1 | (st1 << 2) | (st2 << 3); + pad2bit = pad2; + break; + case VSType.VS_TYPE3: + pad1bit = pad2 | (st1 << 2) | (st2 << 3); + pad2bit = pad1; + break; + case VSType.VS_TYPE4: + pad1bit = pad1 | (st1 << 2) | 0x08; // 0x08=Start Protect + pad2bit = pad2 | (st2 << 2) | 0x08; // 0x08=Start Protect + break; + case VSType.VS_TYPE5: + pad1bit = pad2 | (st1 << 2) | 0x08; // 0x08=Start Protect + pad2bit = pad1 | (st2 << 2) | 0x08; // 0x08=Start Protect + break; + case VSType.VS_TYPE6: + pad1bit = pad1 | (st1 << 2) | (((uint)padbitsync[0] & 0x04) << 1); + pad2bit = pad2 | (st2 << 2) | (((uint)padbitsync[1] & 0x04) << 1); + break; + case VSType.VS_TYPEZ: + pad1bit = 0; + pad2bit = 0; + break; + } + + // Coin 2偲旐傞堊偵徚偡 + micbit = 0; + } + else + { + if (Supporter.Config.emulator.bFourPlayer) + { + // NES type + pad1bit = padbitsync[0] | ((uint)padbitsync[2] << 8) | 0x00080000; + pad2bit = padbitsync[1] | ((uint)padbitsync[3] << 8) | 0x00040000; + } + else + { + // Famicom type + pad1bit = padbitsync[0]; + pad2bit = padbitsync[1]; + } + } + pad3bit = padbitsync[2]; + pad4bit = padbitsync[3]; + } + + internal void Reset() + { + pad1bit = pad2bit = 0; + bStrobe = false; + + bBarcodeWorld = false; + + for (int x = 0; x < 4; x++) + { + for (int y = 0; y < 2; y++) + { + padcnt[x][y] = 0; + } + } + + // Select Extension Devices + uint crc = nes.rom.GetPROM_CRC(); + + if (crc == 0xfbfc6a6c // Adventures of Bayou Billy, The(E) + || crc == 0xcb275051 // Adventures of Bayou Billy, The(U) + || crc == 0xfb69c131 // Baby Boomer(Unl)(U) + || crc == 0xf2641ad0 // Barker Bill's Trick Shooting(U) + || crc == 0xbc1dce96 // Chiller (Unl)(U) + || crc == 0x90ca616d // Duck Hunt(JUE) + || crc == 0x59e3343f // Freedom Force(U) + || crc == 0x242a270c // Gotcha!(U) + || crc == 0x7b5bd2de // Gumshoe(UE) + || crc == 0x255b129c // Gun Sight(J) + || crc == 0x8963ae6e // Hogan's Alley(JU) + || crc == 0x51d2112f // Laser Invasion(U) + || crc == 0x0a866c94 // Lone Ranger, The(U) + // || crc == 0xe4c04eea // Mad City(J) + || crc == 0x9eef47aa // Mechanized Attack(U) + || crc == 0xc2db7551 // Shooting Range(U) + || crc == 0x163e86c0 // To The Earth(U) + || crc == 0x42d893e4 // Operation Wolf(J) + || crc == 0x1388aeb9 // Operation Wolf(U) + || crc == 0x0d3cf705 // Wild Gunman(J) + || crc == 0x389960db) + { // Wild Gunman(JUE) + SetExController(EXCONTROLLER.EXCONTROLLER_ZAPPER); + } + if (crc == 0x35893b67 // Arkanoid(J) + || crc == 0x6267fbd1) + { // Arkanoid 2(J) + SetExController(EXCONTROLLER.EXCONTROLLER_PADDLE); + } + if (crc == 0xff6621ce // Hyper Olympic(J) + || crc == 0xdb9418e8 // Hyper Olympic(Tonosama Ban)(J) + || crc == 0xac98cd70) + { // Hyper Sports(J) + SetExController(EXCONTROLLER.EXCONTROLLER_HYPERSHOT); + } + if (crc == 0xf9def527 // Family BASIC(Ver2.0) + || crc == 0xde34526e // Family BASIC(Ver2.1a) + || crc == 0xf050b611 // Family BASIC(Ver3) + || crc == 0x3aaeed3f // Family BASIC(Ver3)(Alt) + || crc == 0x868FCD89 // Family BASIC(Ver1.0) + || crc == 0x2D6B7E5A // PLAYBOX BASIC(J) (Prototype_v0.0) + || crc == 0xDA03D908) + { // PLAYBOX BASIC (J) + SetExController(EXCONTROLLER.EXCONTROLLER_KEYBOARD); + } + if (crc == 0x589b6b0d // Supor Computer V3.0 + || crc == 0x8b265862 // Supor English + || crc == 0x41401c6d // Supor Computer V4.0 + || crc == 0x82F1Fb96 // Supor Computer(Russia) V1.0 + || crc == 0xd5d6eac4) + { // EDU(C) Computer + SetExController(EXCONTROLLER.EXCONTROLLER_SUPOR_KEYBOARD); + nes.SetVideoMode(true); + } + if (crc == 0xc68363f6 // Crazy Climber(J) + || crc == 0x2989ead6 // Smash TV(U) [!] + || crc == 0x0b8f8128) + { // Smash TV(E) [!] + SetExController(EXCONTROLLER.EXCONTROLLER_CRAZYCLIMBER); + } + if (crc == 0x20d22251) + { // Top rider(J) + SetExController(EXCONTROLLER.EXCONTROLLER_TOPRIDER); + } + if (crc == 0x0cd00488) + { // Space Shadow(J) + SetExController(EXCONTROLLER.EXCONTROLLER_SPACESHADOWGUN); + } + + if (crc == 0x8c8fa83b // Family Trainer - Athletic World (J) + || crc == 0x7e704a14 // Family Trainer - Jogging Race (J) + || crc == 0x2330a5d3) + { // Family Trainer - Rairai Kyonshiizu (J) + SetExController(EXCONTROLLER.EXCONTROLLER_FAMILYTRAINER_A); + } + if (crc == 0xf8da2506 // Family Trainer - Aerobics Studio (J) + || crc == 0xca26a0f1 // Family Trainer - Dai Undoukai (J) + || crc == 0x28068b8c // Family Trainer - Fuuun Takeshi Jou 2 (J) + || crc == 0x10bb8f9a // Family Trainer - Manhattan Police (J) + || crc == 0xad3df455 // Family Trainer - Meiro Dai Sakusen (J) + || crc == 0x8a5b72c0 // Family Trainer - Running Stadium (J) + || crc == 0x59794f2d) + { // Family Trainer - Totsugeki Fuuun Takeshi Jou (J) + SetExController(EXCONTROLLER.EXCONTROLLER_FAMILYTRAINER_B); + } + if (crc == 0x9fae4d46 // Ide Yousuke Meijin no Jissen Mahjong (J) + || crc == 0x7b44fb2a) + { // Ide Yousuke Meijin no Jissen Mahjong 2 (J) + SetExController(EXCONTROLLER.EXCONTROLLER_MAHJANG); + } + if (crc == 0x786148b6) + { // Exciting Boxing (J) + SetExController(EXCONTROLLER.EXCONTROLLER_EXCITINGBOXING); + } + if (crc == 0xc3c0811d // Oeka Kids - Anpanman no Hiragana Daisuki (J) + || crc == 0x9d048ea4) + { // Oeka Kids - Anpanman to Oekaki Shiyou!! (J) + SetExController(EXCONTROLLER.EXCONTROLLER_OEKAKIDS_TABLET); + } + + if (crc == 0x67898319) + { // Barcode World (J) + bBarcodeWorld = true; + } + + // VS-Unisystem + if (nes.rom.IsVSUNISYSTEM()) + { + if (crc == 0xff5135a3 // VS Hogan's Alley + || crc == 0xed588f00 // VS Duck Hunt + || crc == 0x17ae56be) + { // VS Freedom Force + SetExController(EXCONTROLLER.EXCONTROLLER_VSZAPPER); + } + else + { + SetExController(EXCONTROLLER.EXCONTROLLER_VSUNISYSTEM); + } + } + + if (crc == 0x21b099f3) + { // Gyromite (JUE) + SetExController(EXCONTROLLER.EXCONTROLLER_GYROMITE); + } + } + + private void SetExController(EXCONTROLLER type) + { + excontroller_select = (int)type; + + expad?.Dispose(); + expad = null; + + bZapperMode = false; + + // ExPad Instance create + switch (type) + { + case EXCONTROLLER.EXCONTROLLER_ZAPPER: + expad = new EXPAD_Zapper(nes); + bZapperMode = true; + break; + case EXCONTROLLER.EXCONTROLLER_PADDLE: + expad = new EXPAD_Paddle(nes); + break; + case EXCONTROLLER.EXCONTROLLER_HYPERSHOT: + expad = new EXPAD_HyperShot(nes); + break; + case EXCONTROLLER.EXCONTROLLER_KEYBOARD: + expad = new EXPAD_Keyboard(nes); + break; + case EXCONTROLLER.EXCONTROLLER_SUPOR_KEYBOARD: + expad = new EXPAD_Supor_Keyboard(nes); + break; + case EXCONTROLLER.EXCONTROLLER_CRAZYCLIMBER: + expad = new EXPAD_CrazyClimber(nes); + break; + case EXCONTROLLER.EXCONTROLLER_TOPRIDER: + expad = new EXPAD_Toprider(nes); + break; + case EXCONTROLLER.EXCONTROLLER_SPACESHADOWGUN: + expad = new EXPAD_SpaceShadowGun(nes); + bZapperMode = true; + break; + case EXCONTROLLER.EXCONTROLLER_FAMILYTRAINER_A: + case EXCONTROLLER.EXCONTROLLER_FAMILYTRAINER_B: + expad = new EXPAD_FamlyTrainer(nes); + break; + case EXCONTROLLER.EXCONTROLLER_EXCITINGBOXING: + expad = new EXPAD_ExcitingBoxing(nes); + break; + case EXCONTROLLER.EXCONTROLLER_MAHJANG: + expad = new EXPAD_Mahjang(nes); + break; + case EXCONTROLLER.EXCONTROLLER_OEKAKIDS_TABLET: + expad = new EXPAD_OekakidsTablet(nes); + break; + case EXCONTROLLER.EXCONTROLLER_TURBOFILE: + expad = new EXPAD_TurboFile(nes); + break; + case EXCONTROLLER.EXCONTROLLER_VSUNISYSTEM: + expad = new EXPAD_VSUnisystem(nes); + break; + case EXCONTROLLER.EXCONTROLLER_VSZAPPER: + expad = new EXPAD_VSZapper(nes); + bZapperMode = true; + break; + + case EXCONTROLLER.EXCONTROLLER_GYROMITE: + expad = new EXPAD_Gyromite(nes); + break; + default: + break; + } + + if (expad != null) + { + expad.Reset(); + } + } } public enum VSType @@ -92,4 +417,31 @@ namespace VirtualNes.Core VS_TYPE6, // SELECT1P=START1P/SELECT2P=START2P 1P/2P Reverse (For Golf) VS_TYPEZ, // ZAPPER } + + public enum EXCONTROLLER + { + EXCONTROLLER_NONE = 0, + EXCONTROLLER_PADDLE, + EXCONTROLLER_HYPERSHOT, + EXCONTROLLER_ZAPPER, + EXCONTROLLER_KEYBOARD, + EXCONTROLLER_CRAZYCLIMBER, + EXCONTROLLER_TOPRIDER, + EXCONTROLLER_SPACESHADOWGUN, + + EXCONTROLLER_FAMILYTRAINER_A, + EXCONTROLLER_FAMILYTRAINER_B, + EXCONTROLLER_EXCITINGBOXING, + EXCONTROLLER_MAHJANG, + EXCONTROLLER_OEKAKIDS_TABLET, + EXCONTROLLER_TURBOFILE, + + EXCONTROLLER_VSUNISYSTEM, + EXCONTROLLER_VSZAPPER, + + EXCONTROLLER_GYROMITE, + EXCONTROLLER_STACKUP, + + EXCONTROLLER_SUPOR_KEYBOARD, + } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs index 4f608b3..f5b64b3 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs @@ -95,15 +95,26 @@ namespace VirtualNes.Core public const byte SP_COLOR_BIT = 0x03; private NES nes; + + private bool bExtLatch; // For MMC5 + private bool bChrLatch; // For MMC2/MMC4 + private bool bExtNameTable; // For Super Monkey no Dai Bouken + private bool bExtMono; // For Final Fantasy + + private ushort loopy_y; + private ushort loopy_shift; + private byte[] lpScreen; + /// 作为lpScreen数组的索引 + private int lpScanline; + private int ScanlineNo; private byte[] lpColormode; + private bool bVSMode; private int nVSColorMap; private byte VSSecurityData; private byte[] Bit2Rev = new byte[256]; - private int ScanlineNo; - /// 作为lpScreen数组的索引 - private int lpScanline; + public PPU(NES nes) { @@ -128,9 +139,7 @@ namespace VirtualNes.Core } } - public void Dispose() - { - } + public void Dispose() { } internal byte Read(ushort addr) { @@ -178,7 +187,7 @@ namespace VirtualNes.Core } addr &= 0xEFFF; } - MMU.PPU7_Temp = MMU.PPU_MEM_BANK[addr >> 10][addr & 0x03FF]; + MMU.PPU7_Temp = MMU.PPU_MEM_BANK[addr >> 10].Span[addr & 0x03FF]; break; } @@ -314,7 +323,7 @@ namespace VirtualNes.Core } if (MMU.PPU_MEM_TYPE[vaddr >> 10] != MMU.BANKTYPE_VROM) { - MMU.PPU_MEM_BANK[vaddr >> 10][vaddr & 0x03FF] = data; + MMU.PPU_MEM_BANK[vaddr >> 10].Span[vaddr & 0x03FF] = data; } break; } @@ -330,6 +339,30 @@ namespace VirtualNes.Core } } + internal void Reset() + { + bExtLatch = false; + bChrLatch = false; + bExtNameTable = false; + bExtMono = false; + + MMU.PPUREG[0] = MMU.PPUREG[1] = 0; + + MMU.PPU56Toggle = 0; + + MMU.PPU7_Temp = 0xFF; // VS Excitebike偱偍偐偟偔側傞($2006傪撉傒偵峴偔僶僌偑偁傞) + // PPU7_Temp = 0; + + MMU.loopy_v = MMU.loopy_t = 0; + MMU.loopy_x = loopy_y = 0; + loopy_shift = 0; + + if (lpScreen != null) + MemoryUtility.memset(lpScreen, 0x3F, (int)(Screen.SCREEN_WIDTH) * (int)(Screen.SCREEN_HEIGHT)); + if (lpColormode != null) + MemoryUtility.memset(lpColormode, 0, (int)(Screen.SCREEN_HEIGHT)); + } + private enum Screen { SCREEN_WIDTH = 256 + 16, diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD.cs index 56e5f6f..44105d1 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - namespace VirtualNes.Core { public class EXPAD @@ -23,7 +18,7 @@ namespace VirtualNes.Core public virtual void Write4016(byte data) { } public virtual void Write4017(byte data) { } public virtual void Sync() { } - public virtual void SetSyncData(int type,int data) { } + public virtual void SetSyncData(int type, int data) { } public virtual int GetSyncData(int type) { return 0x00; } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs new file mode 100644 index 0000000..5c8c274 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_CrazyClimber : EXPAD + { + public EXPAD_CrazyClimber(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs.meta new file mode 100644 index 0000000..e3a9670 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_CrazyClimber.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d7ac655210edb74ea198ad8802cb545 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs new file mode 100644 index 0000000..9a4d47e --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_ExcitingBoxing : EXPAD + { + public EXPAD_ExcitingBoxing(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs.meta new file mode 100644 index 0000000..8e05b0c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_ExcitingBoxing.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ac6f1c51a9c1b64e970bc5fe5e00b9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs new file mode 100644 index 0000000..d7ea8d6 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_FamlyTrainer : EXPAD + { + public EXPAD_FamlyTrainer(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs.meta new file mode 100644 index 0000000..7e30479 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_FamlyTrainer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a2cfbbbe2b90bd4ba754bc9a8f014af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs new file mode 100644 index 0000000..f16d93f --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_Gyromite : EXPAD + { + public EXPAD_Gyromite(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs.meta new file mode 100644 index 0000000..50334ac --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Gyromite.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c49edbe29e34f0245b621a7920d4981e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs new file mode 100644 index 0000000..e854ad6 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_HyperShot : EXPAD + { + public EXPAD_HyperShot(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs.meta new file mode 100644 index 0000000..cded73b --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_HyperShot.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac43bf6e282394c46b8ea717595d8664 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs new file mode 100644 index 0000000..4ade50a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_Keyboard : EXPAD + { + public EXPAD_Keyboard(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs.meta new file mode 100644 index 0000000..c894781 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Keyboard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f56b9a9d01afad4b967b5d606f7ef11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs new file mode 100644 index 0000000..765c262 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_Mahjang : EXPAD + { + public EXPAD_Mahjang(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs.meta new file mode 100644 index 0000000..b1541a1 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Mahjang.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 146c88b5d0fab5b43ba7e570f0ff116b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs new file mode 100644 index 0000000..679ce77 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_OekakidsTablet : EXPAD + { + public EXPAD_OekakidsTablet(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs.meta new file mode 100644 index 0000000..bdc8d51 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_OekakidsTablet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 47337ac29c001d047a911c028e305b43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs new file mode 100644 index 0000000..a35efbe --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + public class EXPAD_Paddle : EXPAD + { + public EXPAD_Paddle(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs.meta new file mode 100644 index 0000000..ab492a0 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Paddle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e48f82e9b202e64fa7ebe3816804ae9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs new file mode 100644 index 0000000..2ee29b4 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_SpaceShadowGun : EXPAD + { + public EXPAD_SpaceShadowGun(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs.meta new file mode 100644 index 0000000..a0bd98c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_SpaceShadowGun.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01ac1bc69454b414cb5a9db1d12f1aac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs new file mode 100644 index 0000000..633ab77 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_Supor_Keyboard : EXPAD + { + public EXPAD_Supor_Keyboard(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs.meta new file mode 100644 index 0000000..0060455 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Supor_Keyboard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5adc370589ec4bf42b7ea0c20acb2a48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs new file mode 100644 index 0000000..58b6fd8 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_Toprider : EXPAD + { + public EXPAD_Toprider(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs.meta new file mode 100644 index 0000000..8ec93a3 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Toprider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0b1053511d6f224a840b0e9df4f9889 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs new file mode 100644 index 0000000..283a583 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_TurboFile : EXPAD + { + public EXPAD_TurboFile(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs.meta new file mode 100644 index 0000000..ac3ba2e --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_TurboFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b6b41e81a80079489f60eaa5be220cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs new file mode 100644 index 0000000..1ba2c98 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_VSUnisystem : EXPAD + { + public EXPAD_VSUnisystem(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs.meta new file mode 100644 index 0000000..5f0b371 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSUnisystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d343a07cca05ea642be6db80607ea23a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs new file mode 100644 index 0000000..9058c4a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs @@ -0,0 +1,9 @@ +namespace VirtualNes.Core +{ + internal class EXPAD_VSZapper : EXPAD + { + public EXPAD_VSZapper(NES parent) : base(parent) + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs.meta new file mode 100644 index 0000000..34798b6 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_VSZapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6803ff5b7be6edc49ba2b71256aa16a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs new file mode 100644 index 0000000..5dd97fb --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VirtualNes.Core +{ + /// + /// 光枪 + /// + public class EXPAD_Zapper : EXPAD + { + public EXPAD_Zapper(NES parent) : base(parent) + { + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs.meta new file mode 100644 index 0000000..75db078 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PadEX/EXPAD_Zapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c378fd8c53bb8084f979b05d2405bb9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs index 46e12ff..51b6a87 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs @@ -1,9 +1,6 @@ -using Codice.CM.Client.Differences; -using System; +using System; using System.IO; -using System.Linq; using VirtualNes.Core.Debug; -using static UnityEditor.PlayerSettings; namespace VirtualNes.Core { @@ -22,13 +19,13 @@ namespace VirtualNes.Core protected byte[] lpTrainer; protected byte[] lpDiskBios; protected byte[] lpDisk; - protected ulong crc; - protected ulong crcall; - protected ulong crcvrom; + protected uint crc; + protected uint crcall; + protected uint crcvrom; protected int mapper; protected int diskno; - protected ulong fdsmakerID; - protected ulong fdsgameID; + protected uint fdsmakerID; + protected uint fdsgameID; public ROM(string fname) { @@ -256,7 +253,7 @@ namespace VirtualNes.Core crc = crcall = crcvrom = 0; fdsmakerID = lpPRG[0x1F]; - fdsgameID = (ulong)((lpPRG[0x20] << 24) | (lpPRG[0x21] << 16) | (lpPRG[0x22] << 8) | (lpPRG[0x23] << 0)); + fdsgameID = (uint)((lpPRG[0x20] << 24) | (lpPRG[0x21] << 16) | (lpPRG[0x22] << 8) | (lpPRG[0x23] << 0)); } } else //NSF @@ -301,6 +298,10 @@ namespace VirtualNes.Core { return bNSF; } + public bool IsPAL() + { + return bPAL; + } public bool IsSAVERAM() { @@ -331,6 +332,11 @@ namespace VirtualNes.Core return lpPRG; } + internal byte[] GetVROM() + { + return lpCHR; + } + internal byte[] GetDISK() { return lpDisk; @@ -355,6 +361,41 @@ namespace VirtualNes.Core { return (header.control2 & (byte)EnumRomControlByte2.ROM_VSUNISYSTEM) != 0; } + + internal uint GetPROM_CRC() + { + return crc; + } + + internal byte GetPROM_SIZE() + { + return header.PRG_PAGE_SIZE; + } + + internal byte GetVROM_SIZE() + { + return header.CHR_PAGE_SIZE; + } + + internal bool Is4SCREEN() + { + return (header.control1 & (byte)EnumRomControlByte1.ROM_4SCREEN) != 0; + } + + internal bool IsVMIRROR() + { + return (header.control1 & (byte)EnumRomControlByte1.ROM_VMIRROR) != 0; + } + + internal byte[] GetTRAINER() + { + return lpTrainer; + } + + internal NSFHEADER GetNsfHeader() + { + return nsfheader; + } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig.meta new file mode 100644 index 0000000..8a060f7 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd0714f580724604da063207fe69e274 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs new file mode 100644 index 0000000..9650980 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgController + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs.meta new file mode 100644 index 0000000..750d782 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3328948cdc73baa4fb90c995f39f454f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs new file mode 100644 index 0000000..ac0f43d --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs @@ -0,0 +1,18 @@ +namespace VirtualNes.Core +{ + public class CfgEmulator + { + public bool bIllegalOp { get; set; } = false; + public bool bAutoFrameSkip { get; set; } = true; + public bool bThrottle { get; set; } = true; + public int nThrottleFPS { get; set; } = 120; + public bool bBackground { get; set; } = false; + public int nPriority { get; set; } = 3; + public bool bFourPlayer { get; set; } = true; + public bool bCrcCheck { get; set; } = true; + public bool bDiskThrottle { get; set; } = true; + public bool bLoadFullscreen { get; set; } = false; + public bool bPNGsnapshot { get; set; } = false; + public bool bAutoIPS { get; set; } = false; + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs.meta new file mode 100644 index 0000000..1a5035c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgEmulator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aae682cf38878ae40a449ab1a13fc7fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs new file mode 100644 index 0000000..9698aee --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgExtraSound + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs.meta new file mode 100644 index 0000000..3a37df9 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgExtraSound.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c707e4c8c38fa2e40a884047d0582b7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CHEATCODE.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs similarity index 55% rename from AxibugEmuOnline.Client/Assets/VirtualNes.Core/CHEATCODE.cs rename to AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs index aaf5b92..ec6eb1d 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CHEATCODE.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs @@ -1,6 +1,7 @@ namespace VirtualNes.Core { - public class CHEATCODE + public class CfgGeneral { + } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs.meta new file mode 100644 index 0000000..84efe80 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGeneral.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 797171ffbac5b8748923ba914141781d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs new file mode 100644 index 0000000..21851f8 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgGraphics + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs.meta new file mode 100644 index 0000000..73cbd53 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgGraphics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5d72263cee06c74e94d67af00befbdf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs new file mode 100644 index 0000000..9ad0ca3 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgLanguage + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs.meta new file mode 100644 index 0000000..71f37e3 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLanguage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c23af0b4dd8a4e04a89d1a380c54688f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs new file mode 100644 index 0000000..cf1e5eb --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgLauncher + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs.meta new file mode 100644 index 0000000..e752de0 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgLauncher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a033c816849b204c8cda167cd1fddb0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs new file mode 100644 index 0000000..d8d718c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgMovie + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs.meta new file mode 100644 index 0000000..cb49734 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgMovie.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdbdc9850f494ad44a16ec1ec82157cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs new file mode 100644 index 0000000..d5efce1 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgNetPlay + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs.meta new file mode 100644 index 0000000..f781314 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgNetPlay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a81c95a03cbc4f4298e034f2b5cab7c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs new file mode 100644 index 0000000..a89aa6b --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgPath + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs.meta new file mode 100644 index 0000000..c9bd97a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgPath.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9368c1964e431040a469e2fb7b1c710 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs new file mode 100644 index 0000000..ac133b9 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs @@ -0,0 +1,6 @@ +namespace VirtualNes.Core +{ + public class CfgShortCut + { + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs.meta new file mode 100644 index 0000000..8af3ee4 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgShortCut.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4bc2f955a549544e9f03a73b98455fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs new file mode 100644 index 0000000..2db18fb --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs @@ -0,0 +1,19 @@ +namespace VirtualNes.Core +{ + public class CfgSound + { + public bool bEnable { get; set; } = true; + public int nRate { get; set; } = 22050; + public int nBits { get; set; } = 8; + public int nBufferSize { get; set; } = 4; + public int nFilterType { get; set; } = 0; + public bool bChangeTone { get; set; } = false; + public bool bDisableVolumeEffect { get; set; } = false; + public bool bExtraSoundEnable { get; set; } = true; + public short[] nVolume { get; set; } = new short[16] + { + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + }; + + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs.meta new file mode 100644 index 0000000..1ac8256 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/CfgSound.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f13850718ff124445ad8696ef491313d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs new file mode 100644 index 0000000..961e389 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs @@ -0,0 +1,20 @@ +namespace VirtualNes.Core +{ + public class EmulatorConfig + { + private bool m_bKeyboardDisable; + + public CfgGeneral general { get; private set; } = new CfgGeneral(); + public CfgPath path { get; private set; } = new CfgPath(); + public CfgEmulator emulator { get; private set; } = new CfgEmulator(); + public CfgGraphics graphics { get; private set; } = new CfgGraphics(); + public CfgSound sound { get; private set; } = new CfgSound(); + public CfgShortCut shortcut { get; private set; } = new CfgShortCut(); + public CfgLanguage language { get; private set; } = new CfgLanguage(); + public CfgController controller { get; private set; } = new CfgController(); + public CfgMovie movie { get; private set; } = new CfgMovie(); + public CfgLauncher launcher { get; private set; } = new CfgLauncher(); + public CfgExtraSound extsound { get; private set; } = new CfgExtraSound(); + public CfgNetPlay netplay { get; private set; } = new CfgNetPlay(); + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs.meta new file mode 100644 index 0000000..897ae92 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e0eb25b08646f64eaf7930288788c68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/Supporter.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/Supporter.cs index 8f07b85..cc417af 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/Supporter.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/Supporter.cs @@ -1,7 +1,4 @@ -using System.Collections; -using System.Collections.Generic; using System.IO; -using UnityEngine; namespace VirtualNes.Core { @@ -37,6 +34,8 @@ namespace VirtualNes.Core { s_support.SaveDISKToFile(diskFileContent, romName); } + + public static EmulatorConfig Config => s_support.Config; } public interface ISupporterImpl @@ -46,5 +45,6 @@ namespace VirtualNes.Core Stream OpenFile_DISKSYS(); void SaveSRAMToFile(byte[] sramContent, string romName); void SaveDISKToFile(byte[] diskFileContent, string romName); + EmulatorConfig Config { get; } } } diff --git a/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset b/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset index 8638a73..c3d97d1 100644 --- a/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset +++ b/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset @@ -649,7 +649,7 @@ PlayerSettings: managedStrippingLevel: {} incrementalIl2cppBuild: {} suppressCommonWarnings: 1 - allowUnsafeCode: 0 + allowUnsafeCode: 1 useDeterministicCompilation: 1 useReferenceAssemblies: 1 enableRoslynAnalyzers: 1