dev_4VirtualNes #23
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,7 @@ namespace AxibugEmuOnline.Client
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
//StartGame("Kirby.nes");
|
||||
StartGame("Kirby.nes");
|
||||
}
|
||||
|
||||
public void StartGame(string romName)
|
||||
|
@ -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
|
||||
|
@ -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 : 实现
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e16912525198924a860e53ab4ef0c81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03e0258857a7134438a497aec27ea607
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15b983a12234c3c47baefb9fa2751351
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a47ed257e942d4478215338d8fe4c35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
310
AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs
Normal file
310
AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC6.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 190f3271accd30f4eb5b13590417d265
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 180a87918f9d49e4fad978014f1d594f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
20
AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs
Normal file
20
AxibugEmuOnline.Client/Assets/VirtualNes.Core/Cheat.cs
Normal file
@ -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;
|
||||
};
|
||||
}
|
@ -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<byte> c)
|
||||
{
|
||||
@ -35,7 +30,7 @@ namespace VirtualNes.Core
|
||||
}
|
||||
return ~r & 0xFFFFFFFFUL;
|
||||
}
|
||||
public static ulong CrcRev(int size, Span<byte> c)
|
||||
public static uint CrcRev(int size, Span<byte> 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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5ecddbb6b69204478d799a484d8c47c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8586eb710dc81124593eb5adfa08d73b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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,13 +19,11 @@
|
||||
public int FrameRate; // NTSC:60(59.94) PAL:50
|
||||
public float FramePeriod; // NTSC:16.683 PAL:20.0
|
||||
|
||||
public static NesConfig GetNTSC()
|
||||
{
|
||||
return new NesConfig
|
||||
public static NesConfig NESCONFIG_NTSC = new NesConfig
|
||||
{
|
||||
BaseClock = 21477270.0f,
|
||||
CpuClock = 1789772.5f,
|
||||
TotalScanLines = 262,
|
||||
TotalScanlines = 262,
|
||||
ScanlineCycles = 1364,
|
||||
HDrawCycles = 1024,
|
||||
HBlankCycles = 340,
|
||||
@ -35,15 +33,11 @@
|
||||
FrameRate = 60,
|
||||
FramePeriod = 1000.0f / 60.0f
|
||||
};
|
||||
}
|
||||
|
||||
public static NesConfig GetPAL()
|
||||
{
|
||||
return new NesConfig
|
||||
public static NesConfig NESCONFIG_PAL = new NesConfig
|
||||
{
|
||||
BaseClock = 26601714.0f,
|
||||
CpuClock = 1662607.125f,
|
||||
TotalScanLines = 312,
|
||||
TotalScanlines = 312,
|
||||
ScanlineCycles = 1278,
|
||||
HDrawCycles = 960,
|
||||
HBlankCycles = 318,
|
||||
@ -55,4 +49,3 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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<byte>[] CPU_MEM_BANK = new Memory<byte>[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<byte>[] PPU_MEM_BANK = new Memory<byte>[12]; // 1K扨埵
|
||||
public static byte[] PPU_MEM_TYPE = new byte[12];
|
||||
public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡
|
||||
public static byte[] CRAM_USED = new byte[16]; // 僗僥乕僩僙乕僽梡
|
||||
|
||||
// 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<byte> 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<byte>(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<byte> 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<byte>(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<byte>(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<byte>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<CHEATCODE> m_CheatCode = new List<CHEATCODE>();
|
||||
private List<GENIECODE> m_GenieCode = new List<GENIECODE>();
|
||||
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();
|
||||
|
||||
// デフォルトバンク
|
||||
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;
|
||||
|
||||
// 安全対策を兼ねてあえてループに(1秒分)
|
||||
for (int i = 0; i < nescfg.TotalScanlines * 60; i++)
|
||||
{
|
||||
EmulationCPU(nescfg.ScanlineCycles);
|
||||
cpu.GetContext(ref reg);
|
||||
|
||||
// 無限ループに入ったことを確認したら抜ける
|
||||
if (reg.PC == 0x4700)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_bNsfInit = false;
|
||||
}
|
||||
|
||||
cpu.GetContext(ref reg);
|
||||
// 無限ループに入っていたら再設定する
|
||||
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; // 無限ループ
|
||||
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ƒ|<7C>[ƒg
|
||||
case 0x18:
|
||||
apu->Write(addr, data);
|
||||
apu.Write(addr, data);
|
||||
break;
|
||||
default:
|
||||
mapper->ExWrite(addr, data);
|
||||
mapper.ExWrite(addr, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
/// <summary> 作为lpScreen数组的索引 </summary>
|
||||
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;
|
||||
/// <summary> 作为lpScreen数组的索引 </summary>
|
||||
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,
|
||||
|
@ -1,8 +1,3 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class EXPAD
|
||||
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_CrazyClimber : EXPAD
|
||||
{
|
||||
public EXPAD_CrazyClimber(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d7ac655210edb74ea198ad8802cb545
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_ExcitingBoxing : EXPAD
|
||||
{
|
||||
public EXPAD_ExcitingBoxing(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ac6f1c51a9c1b64e970bc5fe5e00b9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_FamlyTrainer : EXPAD
|
||||
{
|
||||
public EXPAD_FamlyTrainer(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a2cfbbbe2b90bd4ba754bc9a8f014af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_Gyromite : EXPAD
|
||||
{
|
||||
public EXPAD_Gyromite(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c49edbe29e34f0245b621a7920d4981e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_HyperShot : EXPAD
|
||||
{
|
||||
public EXPAD_HyperShot(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac43bf6e282394c46b8ea717595d8664
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_Keyboard : EXPAD
|
||||
{
|
||||
public EXPAD_Keyboard(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f56b9a9d01afad4b967b5d606f7ef11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_Mahjang : EXPAD
|
||||
{
|
||||
public EXPAD_Mahjang(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 146c88b5d0fab5b43ba7e570f0ff116b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_OekakidsTablet : EXPAD
|
||||
{
|
||||
public EXPAD_OekakidsTablet(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47337ac29c001d047a911c028e305b43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class EXPAD_Paddle : EXPAD
|
||||
{
|
||||
public EXPAD_Paddle(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e48f82e9b202e64fa7ebe3816804ae9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_SpaceShadowGun : EXPAD
|
||||
{
|
||||
public EXPAD_SpaceShadowGun(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ac1bc69454b414cb5a9db1d12f1aac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_Supor_Keyboard : EXPAD
|
||||
{
|
||||
public EXPAD_Supor_Keyboard(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5adc370589ec4bf42b7ea0c20acb2a48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_Toprider : EXPAD
|
||||
{
|
||||
public EXPAD_Toprider(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0b1053511d6f224a840b0e9df4f9889
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_TurboFile : EXPAD
|
||||
{
|
||||
public EXPAD_TurboFile(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b6b41e81a80079489f60eaa5be220cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_VSUnisystem : EXPAD
|
||||
{
|
||||
public EXPAD_VSUnisystem(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d343a07cca05ea642be6db80607ea23a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
internal class EXPAD_VSZapper : EXPAD
|
||||
{
|
||||
public EXPAD_VSZapper(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6803ff5b7be6edc49ba2b71256aa16a3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 光枪
|
||||
/// </summary>
|
||||
public class EXPAD_Zapper : EXPAD
|
||||
{
|
||||
public EXPAD_Zapper(NES parent) : base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c378fd8c53bb8084f979b05d2405bb9c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd0714f580724604da063207fe69e274
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgController
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3328948cdc73baa4fb90c995f39f454f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aae682cf38878ae40a449ab1a13fc7fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgExtraSound
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c707e4c8c38fa2e40a884047d0582b7e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,6 +1,7 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CHEATCODE
|
||||
public class CfgGeneral
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 797171ffbac5b8748923ba914141781d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgGraphics
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5d72263cee06c74e94d67af00befbdf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgLanguage
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c23af0b4dd8a4e04a89d1a380c54688f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgLauncher
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a033c816849b204c8cda167cd1fddb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgMovie
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdbdc9850f494ad44a16ec1ec82157cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgNetPlay
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a81c95a03cbc4f4298e034f2b5cab7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgPath
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9368c1964e431040a469e2fb7b1c710
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,6 @@
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgShortCut
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4bc2f955a549544e9f03a73b98455fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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,
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f13850718ff124445ad8696ef491313d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e0eb25b08646f64eaf7930288788c68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user