Mapper补全 #21
@ -502,6 +502,35 @@ namespace VirtualNes.Core
|
|||||||
Debuger.LogError("exqueue overflow.");
|
Debuger.LogError("exqueue overflow.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal byte ExRead(ushort addr)
|
||||||
|
{
|
||||||
|
byte data = 0;
|
||||||
|
|
||||||
|
if ((exsound_select & 0x10) != 0)
|
||||||
|
{
|
||||||
|
if (addr == 0x4800)
|
||||||
|
{
|
||||||
|
SetExQueue(nes.cpu.GetTotalCycles(), 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((exsound_select & 0x04) != 0)
|
||||||
|
{
|
||||||
|
if (addr >= 0x4040 && addr < 0x4100)
|
||||||
|
{
|
||||||
|
data = fds.SyncRead(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((exsound_select & 0x08) != 0)
|
||||||
|
{
|
||||||
|
if (addr >= 0x5000 && addr <= 0x5015)
|
||||||
|
{
|
||||||
|
data = mmc5.SyncRead(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct QUEUEDATA
|
public struct QUEUEDATA
|
||||||
|
@ -38,9 +38,62 @@ namespace VirtualNes.Core
|
|||||||
//todo : 实现
|
//todo : 实现
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal byte SyncRead(ushort addr)
|
||||||
|
{
|
||||||
|
byte data = (byte)(addr >> 8);
|
||||||
|
|
||||||
|
if (addr >= 0x4040 && addr <= 0x407F)
|
||||||
|
{
|
||||||
|
data = (byte)(fds_sync.main_wavetable[addr & 0x3F] | 0x40);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (addr == 0x4090)
|
||||||
|
{
|
||||||
|
data = (byte)((fds_sync.volenv_gain & 0x3F) | 0x40);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (addr == 0x4092)
|
||||||
|
{
|
||||||
|
data = (byte)((fds_sync.swpenv_gain & 0x3F) | 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
private class FDSSOUND
|
private class FDSSOUND
|
||||||
{
|
{
|
||||||
//todo : 实现
|
public byte[] reg = new byte[0x80];
|
||||||
|
public byte volenv_mode; // Volume Envelope
|
||||||
|
public byte volenv_gain;
|
||||||
|
public byte volenv_decay;
|
||||||
|
public double volenv_phaseacc;
|
||||||
|
public byte swpenv_mode; // Sweep Envelope
|
||||||
|
public byte swpenv_gain;
|
||||||
|
public byte swpenv_decay;
|
||||||
|
public double swpenv_phaseacc;
|
||||||
|
// For envelope unit
|
||||||
|
public byte envelope_enable; // $4083 bit6
|
||||||
|
public byte envelope_speed; // $408A
|
||||||
|
// For $4089
|
||||||
|
public byte wave_setup; // bit7
|
||||||
|
public int master_volume; // bit1-0
|
||||||
|
// For Main unit
|
||||||
|
public int[] main_wavetable = new int[64];
|
||||||
|
public byte main_enable;
|
||||||
|
public int main_frequency;
|
||||||
|
public int main_addr;
|
||||||
|
// For Effector(LFO) unit
|
||||||
|
public byte[] lfo_wavetable = new byte[64];
|
||||||
|
public byte lfo_enable; // 0:Enable 1:Wavetable setup
|
||||||
|
public int lfo_frequency;
|
||||||
|
public int lfo_addr;
|
||||||
|
public double lfo_phaseacc;
|
||||||
|
// For Sweep unit
|
||||||
|
public int sweep_bias;
|
||||||
|
// Misc
|
||||||
|
public int now_volume;
|
||||||
|
public int now_freq;
|
||||||
|
public int output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
public class APU_MMC5 : APU_INTERFACE
|
public class APU_MMC5 : APU_INTERFACE
|
||||||
{
|
{
|
||||||
|
SYNCRECTANGLE sch0 = new SYNCRECTANGLE();
|
||||||
|
SYNCRECTANGLE sch1 = new SYNCRECTANGLE();
|
||||||
|
|
||||||
public override void Reset(float fClock, int nRate)
|
public override void Reset(float fClock, int nRate)
|
||||||
{
|
{
|
||||||
//todo : 实现
|
//todo : 实现
|
||||||
@ -29,5 +32,28 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
//todo : 实现
|
//todo : 实现
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal byte SyncRead(ushort addr)
|
||||||
|
{
|
||||||
|
byte data = 0;
|
||||||
|
|
||||||
|
if (addr == 0x5015)
|
||||||
|
{
|
||||||
|
if ((sch0.enable != 0) && sch0.vbl_length > 0) data |= (1 << 0);
|
||||||
|
if ((sch1.enable != 0) && sch1.vbl_length > 0) data |= (1 << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SYNCRECTANGLE
|
||||||
|
{
|
||||||
|
// For sync
|
||||||
|
public byte[] reg = new byte[4];
|
||||||
|
public byte enable;
|
||||||
|
public byte holdnote;
|
||||||
|
public byte[] dummy = new byte[2];
|
||||||
|
public int vbl_length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace VirtualNes.Core
|
using System;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class ByteArrayRef
|
public class ByteArrayRef
|
||||||
{
|
{
|
||||||
@ -22,6 +24,9 @@
|
|||||||
SetArray(array, offset, length);
|
SetArray(array, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteArrayRef(byte[] array) : this(array, 0, array.Length) { }
|
||||||
|
public ByteArrayRef(byte[] array, int offset) : this(array, offset, array.Length - offset) { }
|
||||||
|
|
||||||
public void SetArray(byte[] array, int offset, int length)
|
public void SetArray(byte[] array, int offset, int length)
|
||||||
{
|
{
|
||||||
m_rawArray = array;
|
m_rawArray = array;
|
||||||
@ -40,5 +45,15 @@
|
|||||||
m_rawArray[(m_offset + index)] = value;
|
m_rawArray[(m_offset + index)] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator ByteArrayRef(byte[] array)
|
||||||
|
{
|
||||||
|
return new ByteArrayRef(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Span<byte>(ByteArrayRef array)
|
||||||
|
{
|
||||||
|
return new Span<byte>(array.m_rawArray, array.Offset, array.m_length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
455
AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/EEPROM.cs
Normal file
455
AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/EEPROM.cs
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public class X24C01
|
||||||
|
{
|
||||||
|
public const int X24C01_IDLE = 0; // Idle
|
||||||
|
public const int X24C01_ADDRESS = 1; // Address set
|
||||||
|
public const int X24C01_READ = 2; // Read
|
||||||
|
public const int X24C01_WRITE = 3; // Write
|
||||||
|
public const int X24C01_ACK = 4; // Acknowledge
|
||||||
|
public const int X24C01_ACK_WAIT = 5; // Acknowledge wait
|
||||||
|
|
||||||
|
int now_state, next_state;
|
||||||
|
int bitcnt;
|
||||||
|
byte addr, data;
|
||||||
|
byte sda;
|
||||||
|
byte scl_old, sda_old;
|
||||||
|
|
||||||
|
ByteArrayRef pEEPDATA;
|
||||||
|
|
||||||
|
public X24C01()
|
||||||
|
{
|
||||||
|
now_state = X24C01_IDLE;
|
||||||
|
next_state = X24C01_IDLE;
|
||||||
|
addr = 0;
|
||||||
|
data = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
scl_old = 0;
|
||||||
|
sda_old = 0;
|
||||||
|
|
||||||
|
pEEPDATA = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset(ByteArrayRef ptr)
|
||||||
|
{
|
||||||
|
now_state = X24C01_IDLE;
|
||||||
|
next_state = X24C01_IDLE;
|
||||||
|
addr = 0;
|
||||||
|
data = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
scl_old = 0;
|
||||||
|
sda_old = 0;
|
||||||
|
|
||||||
|
pEEPDATA = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(byte scl_in, byte sda_in)
|
||||||
|
{
|
||||||
|
// Clock line
|
||||||
|
byte scl_rise = (byte)(~scl_old & scl_in);
|
||||||
|
byte scl_fall = (byte)(scl_old & ~scl_in);
|
||||||
|
// Data line
|
||||||
|
byte sda_rise = (byte)(~sda_old & sda_in);
|
||||||
|
byte sda_fall = (byte)(sda_old & ~sda_in);
|
||||||
|
|
||||||
|
byte scl_old_temp = scl_old;
|
||||||
|
byte sda_old_temp = sda_old;
|
||||||
|
|
||||||
|
scl_old = scl_in;
|
||||||
|
sda_old = sda_in;
|
||||||
|
|
||||||
|
// Start condition?
|
||||||
|
if (scl_old_temp != 0 && sda_fall != 0)
|
||||||
|
{
|
||||||
|
now_state = X24C01_ADDRESS;
|
||||||
|
bitcnt = 0;
|
||||||
|
addr = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop condition?
|
||||||
|
if (scl_old_temp != 0 && sda_rise != 0)
|
||||||
|
{
|
||||||
|
now_state = X24C01_IDLE;
|
||||||
|
sda = 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCL ____---- RISE
|
||||||
|
if (scl_rise != 0)
|
||||||
|
{
|
||||||
|
switch (now_state)
|
||||||
|
{
|
||||||
|
case X24C01_ADDRESS:
|
||||||
|
if (bitcnt < 7)
|
||||||
|
{
|
||||||
|
// 本来はMSB->LSB
|
||||||
|
addr = (byte)(addr & (~(1 << bitcnt)));
|
||||||
|
addr = (byte)(addr | ((sda_in != 0 ? 1 : 0) << bitcnt));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sda_in != 0)
|
||||||
|
{
|
||||||
|
next_state = X24C01_READ;
|
||||||
|
data = pEEPDATA[addr & 0x7F];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_state = X24C01_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C01_ACK:
|
||||||
|
sda = 0; // ACK
|
||||||
|
break;
|
||||||
|
case X24C01_READ:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
// 本来はMSB->LSB
|
||||||
|
sda = (byte)((data & (1 << bitcnt)) != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C01_WRITE:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
// 本来はMSB->LSB
|
||||||
|
data = (byte)(data & (~(1 << bitcnt)));
|
||||||
|
data = (byte)(data | ((sda_in != 0 ? 1 : 0) << bitcnt));
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case X24C01_ACK_WAIT:
|
||||||
|
if (sda_in == 0)
|
||||||
|
{
|
||||||
|
next_state = X24C01_IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCL ----____ FALL
|
||||||
|
if (scl_fall != 0)
|
||||||
|
{
|
||||||
|
switch (now_state)
|
||||||
|
{
|
||||||
|
case X24C01_ADDRESS:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
now_state = X24C01_ACK;
|
||||||
|
sda = 0xFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C01_ACK:
|
||||||
|
now_state = next_state;
|
||||||
|
bitcnt = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
break;
|
||||||
|
case X24C01_READ:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
now_state = X24C01_ACK_WAIT;
|
||||||
|
addr = (byte)((addr + 1) & 0x7F);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C01_WRITE:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
now_state = X24C01_ACK;
|
||||||
|
next_state = X24C01_IDLE;
|
||||||
|
pEEPDATA[addr & 0x7F] = data;
|
||||||
|
addr = (byte)((addr + 1) & 0x7F);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte Read()
|
||||||
|
{
|
||||||
|
return sda;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(byte[] p)
|
||||||
|
{
|
||||||
|
//now_state = *((INT*)&p[0]);
|
||||||
|
//next_state = *((INT*)&p[4]);
|
||||||
|
//bitcnt = *((INT*)&p[8]);
|
||||||
|
//addr = p[12];
|
||||||
|
//data = p[13];
|
||||||
|
//sda = p[14];
|
||||||
|
//scl_old = p[15];
|
||||||
|
//sda_old = p[16];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(byte[] p)
|
||||||
|
{
|
||||||
|
//*((INT*)&p[0]) = now_state;
|
||||||
|
//*((INT*)&p[4]) = next_state;
|
||||||
|
//*((INT*)&p[8]) = bitcnt;
|
||||||
|
//p[12] = addr;
|
||||||
|
//p[13] = data;
|
||||||
|
//p[14] = sda;
|
||||||
|
//p[15] = scl_old;
|
||||||
|
//p[16] = sda_old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class X24C02
|
||||||
|
{
|
||||||
|
public const int X24C02_IDLE = 0; // Idle
|
||||||
|
public const int X24C02_DEVADDR = 1; // Device address set
|
||||||
|
public const int X24C02_ADDRESS = 2; // Address set
|
||||||
|
public const int X24C02_READ = 3; // Read
|
||||||
|
public const int X24C02_WRITE = 4; // Write
|
||||||
|
public const int X24C02_ACK = 5; // Acknowledge
|
||||||
|
public const int X24C02_NAK = 6; // Not Acknowledge
|
||||||
|
public const int X24C02_ACK_WAIT = 7; // Acknowledge wait
|
||||||
|
|
||||||
|
int now_state, next_state;
|
||||||
|
int bitcnt;
|
||||||
|
byte addr, data, rw;
|
||||||
|
byte sda;
|
||||||
|
byte scl_old, sda_old;
|
||||||
|
|
||||||
|
ByteArrayRef pEEPDATA;
|
||||||
|
|
||||||
|
public X24C02()
|
||||||
|
{
|
||||||
|
now_state = X24C02_IDLE;
|
||||||
|
next_state = X24C02_IDLE;
|
||||||
|
addr = 0;
|
||||||
|
data = 0;
|
||||||
|
rw = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
scl_old = 0;
|
||||||
|
sda_old = 0;
|
||||||
|
|
||||||
|
pEEPDATA = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset(ByteArrayRef ptr)
|
||||||
|
{
|
||||||
|
now_state = X24C02_IDLE;
|
||||||
|
next_state = X24C02_IDLE;
|
||||||
|
addr = 0;
|
||||||
|
data = 0;
|
||||||
|
rw = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
scl_old = 0;
|
||||||
|
sda_old = 0;
|
||||||
|
|
||||||
|
pEEPDATA = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(byte scl_in, byte sda_in)
|
||||||
|
{
|
||||||
|
// Clock line
|
||||||
|
byte scl_rise = (byte)(~scl_old & scl_in);
|
||||||
|
byte scl_fall = (byte)(scl_old & ~scl_in);
|
||||||
|
// Data line
|
||||||
|
byte sda_rise = (byte)(~sda_old & sda_in);
|
||||||
|
byte sda_fall = (byte)(sda_old & ~sda_in);
|
||||||
|
|
||||||
|
byte scl_old_temp = scl_old;
|
||||||
|
byte sda_old_temp = sda_old;
|
||||||
|
|
||||||
|
scl_old = scl_in;
|
||||||
|
sda_old = sda_in;
|
||||||
|
|
||||||
|
// Start condition?
|
||||||
|
if (scl_old_temp != 0 && sda_fall != 0)
|
||||||
|
{
|
||||||
|
now_state = X24C02_DEVADDR;
|
||||||
|
bitcnt = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop condition?
|
||||||
|
if (scl_old_temp != 0 && sda_rise != 0)
|
||||||
|
{
|
||||||
|
now_state = X24C02_IDLE;
|
||||||
|
sda = 0xFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCL ____---- RISE
|
||||||
|
if (scl_rise != 0)
|
||||||
|
{
|
||||||
|
switch (now_state)
|
||||||
|
{
|
||||||
|
case X24C02_DEVADDR:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
data = (byte)(data & (~(1 << (7 - bitcnt))));
|
||||||
|
data = (byte)(data | ((sda_in != 0 ? 1 : 0) << (7 - bitcnt)));
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C02_ADDRESS:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
addr = (byte)(addr & (~(1 << (7 - bitcnt))));
|
||||||
|
addr = (byte)(addr | ((sda_in != 0 ? 1 : 0) << (7 - bitcnt)));
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C02_READ:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
sda = (byte)((data & (1 << (7 - bitcnt))) != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C02_WRITE:
|
||||||
|
if (bitcnt < 8)
|
||||||
|
{
|
||||||
|
data = (byte)(data & (~(1 << (7 - bitcnt))));
|
||||||
|
data = (byte)(data | ((sda_in != 0 ? 1 : 0) << (7 - bitcnt)));
|
||||||
|
}
|
||||||
|
bitcnt++;
|
||||||
|
break;
|
||||||
|
case X24C02_NAK:
|
||||||
|
sda = 0xFF; // NAK
|
||||||
|
break;
|
||||||
|
case X24C02_ACK:
|
||||||
|
sda = 0; // ACK
|
||||||
|
break;
|
||||||
|
case X24C02_ACK_WAIT:
|
||||||
|
if (sda_in == 0)
|
||||||
|
{
|
||||||
|
next_state = X24C02_READ;
|
||||||
|
data = pEEPDATA[addr];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCL ----____ FALL
|
||||||
|
if (scl_fall != 0)
|
||||||
|
{
|
||||||
|
switch (now_state)
|
||||||
|
{
|
||||||
|
case X24C02_DEVADDR:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
if ((data & 0xA0) == 0xA0)
|
||||||
|
{
|
||||||
|
now_state = X24C02_ACK;
|
||||||
|
rw = (byte)(data & 0x01);
|
||||||
|
sda = 0xFF;
|
||||||
|
if (rw != 0)
|
||||||
|
{
|
||||||
|
// Now address read
|
||||||
|
next_state = X24C02_READ;
|
||||||
|
data = pEEPDATA[addr];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_state = X24C02_ADDRESS;
|
||||||
|
}
|
||||||
|
bitcnt = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
now_state = X24C02_NAK;
|
||||||
|
next_state = X24C02_IDLE;
|
||||||
|
sda = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C02_ADDRESS:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
now_state = X24C02_ACK;
|
||||||
|
sda = 0xFF;
|
||||||
|
if (rw != 0)
|
||||||
|
{
|
||||||
|
// Readでは絶対来ないが念の為
|
||||||
|
next_state = X24C02_IDLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// to Data Write
|
||||||
|
next_state = X24C02_WRITE;
|
||||||
|
}
|
||||||
|
bitcnt = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C02_READ:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
now_state = X24C02_ACK_WAIT;
|
||||||
|
addr = (byte)((addr + 1) & 0xFF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C02_WRITE:
|
||||||
|
if (bitcnt >= 8)
|
||||||
|
{
|
||||||
|
pEEPDATA[addr] = data;
|
||||||
|
now_state = X24C02_ACK;
|
||||||
|
next_state = X24C02_WRITE;
|
||||||
|
addr = (byte)((addr + 1) & 0xFF);
|
||||||
|
bitcnt = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X24C02_NAK:
|
||||||
|
now_state = X24C02_IDLE;
|
||||||
|
bitcnt = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
break;
|
||||||
|
case X24C02_ACK:
|
||||||
|
now_state = next_state;
|
||||||
|
bitcnt = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
break;
|
||||||
|
case X24C02_ACK_WAIT:
|
||||||
|
now_state = next_state;
|
||||||
|
bitcnt = 0;
|
||||||
|
sda = 0xFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte Read()
|
||||||
|
{
|
||||||
|
return sda;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(byte[] p)
|
||||||
|
{
|
||||||
|
//now_state = *((INT*)&p[0]);
|
||||||
|
//next_state = *((INT*)&p[4]);
|
||||||
|
//bitcnt = *((INT*)&p[8]);
|
||||||
|
//addr = p[12];
|
||||||
|
//data = p[13];
|
||||||
|
//rw = p[14];
|
||||||
|
//sda = p[15];
|
||||||
|
//scl_old = p[16];
|
||||||
|
//sda_old = p[17];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(byte[] p)
|
||||||
|
{
|
||||||
|
//*((INT*)&p[0]) = now_state;
|
||||||
|
//*((INT*)&p[4]) = next_state;
|
||||||
|
//*((INT*)&p[8]) = bitcnt;
|
||||||
|
//p[12] = addr;
|
||||||
|
//p[13] = data;
|
||||||
|
//p[14] = rw;
|
||||||
|
//p[15] = sda;
|
||||||
|
//p[16] = scl_old;
|
||||||
|
//p[17] = sda_old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be5901dc72f4b6045a7c33edba28145f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,11 +1,10 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Mapper016 Bandai Standard //
|
// Mapper016 Bandai Standard //
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
using static VirtualNes.MMU;
|
|
||||||
using static VirtualNes.Core.CPU;
|
using static VirtualNes.Core.CPU;
|
||||||
using INT = System.Int32;
|
using static VirtualNes.MMU;
|
||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using Codice.CM.Client.Differences;
|
using INT = System.Int32;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -38,7 +37,7 @@ namespace VirtualNes.Core
|
|||||||
irq_latch = 0;
|
irq_latch = 0;
|
||||||
|
|
||||||
irq_type = 0;
|
irq_type = 0;
|
||||||
nes.SetIrqType( NES.IRQMETHOD.IRQ_CLOCK);
|
nes.SetIrqType(NES.IRQMETHOD.IRQ_CLOCK);
|
||||||
|
|
||||||
eeprom_type = 0;
|
eeprom_type = 0;
|
||||||
|
|
||||||
@ -57,12 +56,12 @@ namespace VirtualNes.Core
|
|||||||
|
|
||||||
if (crc == 0x1d6f27f7)
|
if (crc == 0x1d6f27f7)
|
||||||
{ // Dragon Ball Z 2(Korean Hack)
|
{ // Dragon Ball Z 2(Korean Hack)
|
||||||
nes.SetIrqType( NES.IRQMETHOD.IRQ_HSYNC);
|
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||||
eeprom_type = 1;
|
eeprom_type = 1;
|
||||||
}
|
}
|
||||||
if (crc == 0x6f7247c8)
|
if (crc == 0x6f7247c8)
|
||||||
{ // Dragon Ball Z 3(Korean Hack)
|
{ // Dragon Ball Z 3(Korean Hack)
|
||||||
nes.SetIrqType( NES.IRQMETHOD.IRQ_CLOCK);
|
nes.SetIrqType(NES.IRQMETHOD.IRQ_CLOCK);
|
||||||
eeprom_type = 1;
|
eeprom_type = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
if (crc == 0x170250de)
|
if (crc == 0x170250de)
|
||||||
{ // Rokudenashi Blues(J)
|
{ // Rokudenashi Blues(J)
|
||||||
nes.SetRenderMethod( EnumRenderMethod.POST_ALL_RENDER);
|
nes.SetRenderMethod(EnumRenderMethod.POST_ALL_RENDER);
|
||||||
eeprom_type = 1;
|
eeprom_type = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,14 +139,14 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
nes.SetSAVERAM_SIZE(384);
|
nes.SetSAVERAM_SIZE(384);
|
||||||
x24c02.Reset(WRAM);
|
x24c02.Reset(WRAM);
|
||||||
x24c01.Reset(WRAM + 256);
|
x24c01.Reset(new ByteArrayRef(WRAM, 256));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//BYTE Mapper016::ReadLow(WORD addr)
|
//BYTE Mapper016::ReadLow(WORD addr)
|
||||||
public override byte ReadLow(ushort addr)
|
public override byte ReadLow(ushort addr)
|
||||||
{
|
{
|
||||||
if (patch!=0)
|
if (patch != 0)
|
||||||
{
|
{
|
||||||
return base.ReadLow(addr);
|
return base.ReadLow(addr);
|
||||||
}
|
}
|
||||||
@ -168,9 +167,9 @@ namespace VirtualNes.Core
|
|||||||
else
|
else
|
||||||
if (eeprom_type == 2)
|
if (eeprom_type == 2)
|
||||||
{
|
{
|
||||||
ret = x24c02.Read() & x24c01.Read();
|
ret = (byte)(x24c02.Read() & x24c01.Read());
|
||||||
}
|
}
|
||||||
return (ret ? 0x10 : 0) | (nes.GetBarcodeStatus());
|
return (byte)((ret != 0 ? 0x10 : 0) | (nes.GetBarcodeStatus()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0x00;
|
return 0x00;
|
||||||
@ -185,13 +184,13 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Mapper::WriteLow(addr, data);
|
base.WriteLow(addr, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper016::Write(WORD addr, BYTE data)
|
public override void Write(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
if (!patch)
|
if (patch == 0)
|
||||||
{
|
{
|
||||||
WriteSubA(addr, data);
|
WriteSubA(addr, data);
|
||||||
}
|
}
|
||||||
@ -204,7 +203,7 @@ namespace VirtualNes.Core
|
|||||||
static BYTE eeprom_addinc;
|
static BYTE eeprom_addinc;
|
||||||
|
|
||||||
// Normal mapper #16
|
// Normal mapper #16
|
||||||
void Mapper016::WriteSubA(WORD addr, BYTE data)
|
void WriteSubA(ushort addr, BYTE data)
|
||||||
{
|
{
|
||||||
switch (addr & 0x000F)
|
switch (addr & 0x000F)
|
||||||
{
|
{
|
||||||
@ -216,14 +215,14 @@ namespace VirtualNes.Core
|
|||||||
case 0x0005:
|
case 0x0005:
|
||||||
case 0x0006:
|
case 0x0006:
|
||||||
case 0x0007:
|
case 0x0007:
|
||||||
if (VROM_1K_SIZE)
|
if (VROM_1K_SIZE != 0)
|
||||||
{
|
{
|
||||||
SetVROM_1K_Bank(addr & 0x0007, data);
|
SetVROM_1K_Bank((byte)(addr & 0x0007), data);
|
||||||
}
|
}
|
||||||
if (eeprom_type == 2)
|
if (eeprom_type == 2)
|
||||||
{
|
{
|
||||||
reg[0] = data;
|
reg[0] = data;
|
||||||
x24c01.Write((data & 0x08) ? 0xFF : 0, (reg[1] & 0x40) ? 0xFF : 0);
|
x24c01.Write((byte)((data & 0x08) != 0 ? 0xFF : 0), (byte)((reg[1] & 0x40) != 0 ? 0xFF : 0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -240,7 +239,7 @@ namespace VirtualNes.Core
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x000A:
|
case 0x000A:
|
||||||
irq_enable = data & 0x01;
|
irq_enable = (byte)(data & 0x01);
|
||||||
irq_counter = irq_latch;
|
irq_counter = irq_latch;
|
||||||
nes.cpu.ClrIRQ(IRQ_MAPPER);
|
nes.cpu.ClrIRQ(IRQ_MAPPER);
|
||||||
break;
|
break;
|
||||||
@ -249,34 +248,34 @@ namespace VirtualNes.Core
|
|||||||
irq_counter = (irq_counter & 0xFF00) | data;
|
irq_counter = (irq_counter & 0xFF00) | data;
|
||||||
break;
|
break;
|
||||||
case 0x000C:
|
case 0x000C:
|
||||||
irq_latch = ((INT)data << 8) | (irq_latch & 0x00FF);
|
irq_latch = (data << 8) | (irq_latch & 0x00FF);
|
||||||
irq_counter = ((INT)data << 8) | (irq_counter & 0x00FF);
|
irq_counter = (data << 8) | (irq_counter & 0x00FF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x000D:
|
case 0x000D:
|
||||||
// EEPTYPE0(DragonBallZ)
|
// EEPTYPE0(DragonBallZ)
|
||||||
if (eeprom_type == 0)
|
if (eeprom_type == 0)
|
||||||
{
|
{
|
||||||
x24c01.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0);
|
x24c01.Write((byte)((data & 0x20) != 0 ? 0xFF : 0), (byte)((data & 0x40) != 0 ? 0xFF : 0));
|
||||||
}
|
}
|
||||||
// EEPTYPE1(DragonBallZ2,Z3,Z Gaiden)
|
// EEPTYPE1(DragonBallZ2,Z3,Z Gaiden)
|
||||||
if (eeprom_type == 1)
|
if (eeprom_type == 1)
|
||||||
{
|
{
|
||||||
x24c02.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0);
|
x24c02.Write((byte)((data & 0x20) != 0 ? 0xFF : 0), (byte)((data & 0x40) != 0 ? 0xFF : 0));
|
||||||
}
|
}
|
||||||
// EEPTYPE2(DATACH)
|
// EEPTYPE2(DATACH)
|
||||||
if (eeprom_type == 2)
|
if (eeprom_type == 2)
|
||||||
{
|
{
|
||||||
reg[1] = data;
|
reg[1] = data;
|
||||||
x24c02.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0);
|
x24c02.Write((byte)((data & 0x20) != 0 ? 0xFF : 0), (byte)((data & 0x40) != 0 ? 0xFF : 0));
|
||||||
x24c01.Write((reg[0] & 0x08) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0);
|
x24c01.Write((byte)((reg[0] & 0x08) != 0 ? 0xFF : 0), (byte)((data & 0x40) != 0 ? 0xFF : 0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Famicom Jump 2
|
// Famicom Jump 2
|
||||||
void Mapper016::WriteSubB(WORD addr, BYTE data)
|
void WriteSubB(ushort addr, BYTE data)
|
||||||
{
|
{
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
@ -284,7 +283,7 @@ namespace VirtualNes.Core
|
|||||||
case 0x8001:
|
case 0x8001:
|
||||||
case 0x8002:
|
case 0x8002:
|
||||||
case 0x8003:
|
case 0x8003:
|
||||||
reg[0] = data & 0x01;
|
reg[0] = (byte)(data & 0x01);
|
||||||
SetPROM_8K_Bank(4, reg[0] * 0x20 + reg[2] * 2 + 0);
|
SetPROM_8K_Bank(4, reg[0] * 0x20 + reg[2] * 2 + 0);
|
||||||
SetPROM_8K_Bank(5, reg[0] * 0x20 + reg[2] * 2 + 1);
|
SetPROM_8K_Bank(5, reg[0] * 0x20 + reg[2] * 2 + 1);
|
||||||
break;
|
break;
|
||||||
@ -292,7 +291,7 @@ namespace VirtualNes.Core
|
|||||||
case 0x8005:
|
case 0x8005:
|
||||||
case 0x8006:
|
case 0x8006:
|
||||||
case 0x8007:
|
case 0x8007:
|
||||||
reg[1] = data & 0x01;
|
reg[1] = (byte)(data & 0x01);
|
||||||
SetPROM_8K_Bank(6, reg[1] * 0x20 + 0x1E);
|
SetPROM_8K_Bank(6, reg[1] * 0x20 + 0x1E);
|
||||||
SetPROM_8K_Bank(7, reg[1] * 0x20 + 0x1F);
|
SetPROM_8K_Bank(7, reg[1] * 0x20 + 0x1F);
|
||||||
break;
|
break;
|
||||||
@ -313,7 +312,7 @@ namespace VirtualNes.Core
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x800A:
|
case 0x800A:
|
||||||
irq_enable = data & 0x01;
|
irq_enable = (byte)(data & 0x01);
|
||||||
irq_counter = irq_latch;
|
irq_counter = irq_latch;
|
||||||
|
|
||||||
// if( !irq_enable ) {
|
// if( !irq_enable ) {
|
||||||
@ -325,7 +324,7 @@ namespace VirtualNes.Core
|
|||||||
irq_latch = (irq_latch & 0xFF00) | data;
|
irq_latch = (irq_latch & 0xFF00) | data;
|
||||||
break;
|
break;
|
||||||
case 0x800C:
|
case 0x800C:
|
||||||
irq_latch = ((INT)data << 8) | (irq_latch & 0x00FF);
|
irq_latch = (data << 8) | (irq_latch & 0x00FF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x800D:
|
case 0x800D:
|
||||||
@ -333,9 +332,9 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper016::HSync(INT scanline)
|
public override void HSync(int scanline)
|
||||||
{
|
{
|
||||||
if (irq_enable && (nes.GetIrqType() == NES.IRQMETHOD.IRQ_HSYNC))
|
if (irq_enable != 0 && (nes.GetIrqType() == (int)NES.IRQMETHOD.IRQ_HSYNC))
|
||||||
{
|
{
|
||||||
if (irq_counter <= 113)
|
if (irq_counter <= 113)
|
||||||
{
|
{
|
||||||
@ -353,9 +352,9 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper016::Clock(INT cycles)
|
public override void Clock(int cycles)
|
||||||
{
|
{
|
||||||
if (irq_enable && (nes.GetIrqType() == NES::IRQ_CLOCK))
|
if (irq_enable != 0 && (nes.GetIrqType() == (int)NES.IRQMETHOD.IRQ_CLOCK))
|
||||||
{
|
{
|
||||||
if ((irq_counter -= cycles) <= 0)
|
if ((irq_counter -= cycles) <= 0)
|
||||||
{
|
{
|
||||||
@ -369,55 +368,55 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper016::SaveState(LPBYTE p)
|
public override void SaveState(byte[] p)
|
||||||
{
|
{
|
||||||
p[0] = reg[0];
|
//p[0] = reg[0];
|
||||||
p[1] = reg[1];
|
//p[1] = reg[1];
|
||||||
p[2] = reg[2];
|
//p[2] = reg[2];
|
||||||
p[3] = irq_enable;
|
//p[3] = irq_enable;
|
||||||
*(INT*)&p[4] = irq_counter;
|
//*(INT*)&p[4] = irq_counter;
|
||||||
*(INT*)&p[8] = irq_latch;
|
//*(INT*)&p[8] = irq_latch;
|
||||||
|
|
||||||
if (eeprom_type == 0)
|
//if (eeprom_type == 0)
|
||||||
{
|
//{
|
||||||
x24c01.Save(&p[16]);
|
// x24c01.Save(&p[16]);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
if (eeprom_type == 1)
|
//if (eeprom_type == 1)
|
||||||
{
|
//{
|
||||||
x24c02.Save(&p[16]);
|
// x24c02.Save(&p[16]);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
if (eeprom_type == 2)
|
//if (eeprom_type == 2)
|
||||||
{
|
//{
|
||||||
x24c02.Save(&p[16]);
|
// x24c02.Save(&p[16]);
|
||||||
x24c01.Save(&p[48]);
|
// x24c01.Save(&p[48]);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper016::LoadState(LPBYTE p)
|
public override void LoadState(byte[] p)
|
||||||
{
|
{
|
||||||
reg[0] = p[0];
|
//reg[0] = p[0];
|
||||||
reg[1] = p[1];
|
//reg[1] = p[1];
|
||||||
reg[2] = p[2];
|
//reg[2] = p[2];
|
||||||
irq_enable = p[3];
|
//irq_enable = p[3];
|
||||||
irq_counter = *(INT*)&p[4];
|
//irq_counter = *(INT*)&p[4];
|
||||||
irq_latch = *(INT*)&p[8];
|
//irq_latch = *(INT*)&p[8];
|
||||||
if (eeprom_type == 0)
|
//if (eeprom_type == 0)
|
||||||
{
|
//{
|
||||||
x24c01.Load(&p[16]);
|
// x24c01.Load(&p[16]);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
if (eeprom_type == 1)
|
//if (eeprom_type == 1)
|
||||||
{
|
//{
|
||||||
x24c02.Load(&p[16]);
|
// x24c02.Load(&p[16]);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
if (eeprom_type == 2)
|
//if (eeprom_type == 2)
|
||||||
{
|
//{
|
||||||
x24c02.Load(&p[16]);
|
// x24c02.Load(&p[16]);
|
||||||
x24c01.Load(&p[48]);
|
// x24c01.Load(&p[48]);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace VirtualNes.Core
|
|||||||
|
|
||||||
reg[0] = reg[1] = reg[2] = 0;
|
reg[0] = reg[1] = reg[2] = 0;
|
||||||
|
|
||||||
::memset(exram, 0, sizeof(exram));
|
MemoryUtility.ZEROMEMORY(exram, exram.Length);
|
||||||
|
|
||||||
irq_enable = 0;
|
irq_enable = 0;
|
||||||
irq_counter = 0;
|
irq_counter = 0;
|
||||||
@ -370,7 +370,8 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
if (irq_enable != 0)
|
if (irq_enable != 0)
|
||||||
{
|
{
|
||||||
if ((irq_counter += cycles) >= 0x7FFF)
|
irq_counter = (ushort)(irq_counter + cycles);
|
||||||
|
if (irq_counter >= 0x7FFF)
|
||||||
{
|
{
|
||||||
// irq_counter = 0x7FFF;
|
// irq_counter = 0x7FFF;
|
||||||
// nes.cpu.IRQ_NotPending();
|
// nes.cpu.IRQ_NotPending();
|
||||||
|
@ -28,7 +28,7 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
addrmask = 0xFFFF;
|
addrmask = 0xFFFF;
|
||||||
|
|
||||||
for (INT i = 0; i < 8; i++)
|
for (byte i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
reg[i] = i;
|
reg[i] = i;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -29,11 +30,11 @@ namespace VirtualNes.Core
|
|||||||
//void Mapper072::Write(WORD addr, BYTE data)
|
//void Mapper072::Write(WORD addr, BYTE data)
|
||||||
public override void Write(ushort addr, byte data)
|
public override void Write(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
if (data & 0x80)
|
if ((data & 0x80) != 0)
|
||||||
{
|
{
|
||||||
SetPROM_16K_Bank(4, data & 0x0F);
|
SetPROM_16K_Bank(4, data & 0x0F);
|
||||||
}
|
}
|
||||||
else if (data & 0x40)
|
else if ((data & 0x40) != 0)
|
||||||
{
|
{
|
||||||
SetVROM_8K_Bank(data & 0x0F);
|
SetVROM_8K_Bank(data & 0x0F);
|
||||||
}
|
}
|
||||||
@ -41,14 +42,14 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
if (addr >= 0xC100 && addr <= 0xC11F && data == 0x20)
|
if (addr >= 0xC100 && addr <= 0xC11F && data == 0x20)
|
||||||
{
|
{
|
||||||
//DEBUGOUT( "ADDR:%04X DATA:%02X\n", addr, data );
|
Debuger.Log($"SOUND CODE:{addr & 0x1F:X2}");
|
||||||
DEBUGOUT("SOUND CODE:%02X\n", addr & 0x1F);
|
|
||||||
|
|
||||||
// OSDにするべきか…
|
// OSDにするべきか…
|
||||||
if (Config.sound.bExtraSoundEnable)
|
if (Supporter.Config.sound.bExtraSoundEnable)
|
||||||
{
|
{
|
||||||
DirectSound.EsfAllStop();
|
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
|
||||||
DirectSound.EsfPlay(ESF_MOETENNIS_00 + (addr & 0x1F));
|
//DirectSound.EsfAllStop();
|
||||||
|
//DirectSound.EsfPlay(ESF_MOETENNIS_00 + (addr & 0x1F));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
if (addr == 0x7000)
|
if (addr == 0x7000)
|
||||||
{
|
{
|
||||||
if ((reg & 0x10) == 0 && ((data & 0x10) != 0) && cnt==0)
|
if ((reg & 0x10) == 0 && ((data & 0x10) != 0) && cnt == 0)
|
||||||
{
|
{
|
||||||
//DEBUGOUT( "WR:$%02X\n", data );
|
//DEBUGOUT( "WR:$%02X\n", data );
|
||||||
if ((data & 0x0F) == 0 // Strike
|
if ((data & 0x0F) == 0 // Strike
|
||||||
@ -46,10 +46,11 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OSDにするべきか…
|
// OSDにするべきか…
|
||||||
if (Config.sound.bExtraSoundEnable)
|
if (Supporter.Config.sound.bExtraSoundEnable)
|
||||||
{
|
{
|
||||||
DirectSound.EsfAllStop();
|
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
|
||||||
DirectSound.EsfPlay(ESF_MOEPRO_STRIKE + (data & 0x0F));
|
//DirectSound.EsfAllStop();
|
||||||
|
//DirectSound.EsfPlay(ESF_MOEPRO_STRIKE + (data & 0x0F));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reg = data;
|
reg = data;
|
||||||
@ -59,7 +60,7 @@ namespace VirtualNes.Core
|
|||||||
//void Mapper086::VSync()
|
//void Mapper086::VSync()
|
||||||
public override void VSync()
|
public override void VSync()
|
||||||
{
|
{
|
||||||
if (cnt!=0)
|
if (cnt != 0)
|
||||||
{
|
{
|
||||||
cnt--;
|
cnt--;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -72,7 +73,7 @@ namespace VirtualNes.Core
|
|||||||
key_val = 0;
|
key_val = 0;
|
||||||
mul_val1 = mul_val2 = 0;
|
mul_val1 = mul_val2 = 0;
|
||||||
|
|
||||||
for (INT i = 0; i < 4; i++)
|
for (byte i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
prg_reg[i] = (byte)(PROM_8K_SIZE - 4 + i);
|
prg_reg[i] = (byte)(PROM_8K_SIZE - 4 + i);
|
||||||
ntl_reg[i] = 0;
|
ntl_reg[i] = 0;
|
||||||
@ -94,7 +95,7 @@ namespace VirtualNes.Core
|
|||||||
//BYTE Mapper090::ReadLow(WORD addr)
|
//BYTE Mapper090::ReadLow(WORD addr)
|
||||||
public override byte ReadLow(ushort addr)
|
public override byte ReadLow(ushort addr)
|
||||||
{
|
{
|
||||||
DEBUGOUT("RD:%04X\n", addr);
|
Debuger.Log($"RD:{addr:X4}");
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
@ -120,7 +121,7 @@ namespace VirtualNes.Core
|
|||||||
//void Mapper090::WriteLow(WORD addr, BYTE data)
|
//void Mapper090::WriteLow(WORD addr, BYTE data)
|
||||||
public override void WriteLow(ushort addr, byte data)
|
public override void WriteLow(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
DEBUGOUT("WR:%04X %02X\n", addr, data);
|
Debuger.Log($"WR:{addr:X4} {data:X2}");
|
||||||
|
|
||||||
if (addr == 0x5800)
|
if (addr == 0x5800)
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -60,11 +61,12 @@ namespace VirtualNes.Core
|
|||||||
9,10, 8,11,13,12,14,15 };
|
9,10, 8,11,13,12,14,15 };
|
||||||
|
|
||||||
// OSDにするべきか…
|
// OSDにするべきか…
|
||||||
if (Config.sound.bExtraSoundEnable)
|
if (Supporter.Config.sound.bExtraSoundEnable)
|
||||||
{
|
{
|
||||||
DEBUGOUT("CODE %02X\n", data);
|
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
|
||||||
DirectSound.EsfAllStop();
|
Debuger.Log($"CODE {data:X2}");
|
||||||
DirectSound.EsfPlay(ESF_MOEPRO_STRIKE + tbl[data & 0x0F]);
|
//DirectSound.EsfAllStop();
|
||||||
|
//DirectSound.EsfPlay(ESF_MOEPRO_STRIKE + tbl[data & 0x0F]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@ using System;
|
|||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class _MapName : Mapper
|
public class Mapper107 : Mapper
|
||||||
{
|
{
|
||||||
public _MapName(NES parent) : base(parent)
|
public Mapper107(NES parent) : base(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -73,7 +74,7 @@ namespace VirtualNes.Core
|
|||||||
//void Mapper116::WriteLow(WORD addr, BYTE data)
|
//void Mapper116::WriteLow(WORD addr, BYTE data)
|
||||||
public override void WriteLow(ushort addr, byte data)
|
public override void WriteLow(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
DEBUGOUT("MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr & 0xFFFF, data & 0xFF, nes.GetScanline(), nes.cpu.GetTotalCycles());
|
Debuger.Log($"MPRWR A={addr & 0xFFFF:X4} D={data & 0xFF:X2} L={nes.GetScanline(),3} CYC={nes.cpu.GetTotalCycles()}");
|
||||||
if ((addr & 0x4100) == 0x4100)
|
if ((addr & 0x4100) == 0x4100)
|
||||||
{
|
{
|
||||||
ExChrSwitch = data;
|
ExChrSwitch = data;
|
||||||
@ -84,7 +85,7 @@ namespace VirtualNes.Core
|
|||||||
//void Mapper116::Write(WORD addr, BYTE data)
|
//void Mapper116::Write(WORD addr, BYTE data)
|
||||||
public override void Write(ushort addr, byte data)
|
public override void Write(ushort addr, byte data)
|
||||||
{
|
{
|
||||||
DEBUGOUT("MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr & 0xFFFF, data & 0xFF, nes.GetScanline(), nes.cpu.GetTotalCycles());
|
Debuger.Log($"MPRWR A={addr & 0xFFFF:X4} D={data & 0xFF:X2} L={nes.GetScanline(),3} CYC={nes.cpu.GetTotalCycles()}");
|
||||||
|
|
||||||
switch (addr & 0xE001)
|
switch (addr & 0xE001)
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -61,7 +62,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUGOUT("write to %04x:%02x\n", addr, data);
|
Debuger.Log($"write to {addr:X4}:{data:X2}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,8 @@ namespace VirtualNes.Core
|
|||||||
rom_type = 1;
|
rom_type = 1;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
memset(reg, 0, 8);
|
|
||||||
|
MemoryUtility.ZEROMEMORY(reg, reg.Length);
|
||||||
laststrobe = 1;
|
laststrobe = 1;
|
||||||
SetPROM_32K_Bank((reg[0] << 4) | (reg[1] & 0xF));
|
SetPROM_32K_Bank((reg[0] << 4) | (reg[1] & 0xF));
|
||||||
//SetPROM_32K_Bank(0);
|
//SetPROM_32K_Bank(0);
|
||||||
|
@ -7,6 +7,7 @@ using INT = System.Int32;
|
|||||||
using BYTE = System.Byte;
|
using BYTE = System.Byte;
|
||||||
using System;
|
using System;
|
||||||
using Codice.CM.Client.Differences;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace VirtualNes.Core
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
@ -20,13 +21,12 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
|
|
||||||
{
|
{
|
||||||
reg5000 = 0;
|
reg5000 = 0;
|
||||||
reg5100 = 0;
|
reg5100 = 0;
|
||||||
SetBank_CPU();
|
SetBank_CPU();
|
||||||
SetBank_PPU();
|
SetBank_PPU();
|
||||||
nes.ppu.SetExtLatchMode(TRUE);
|
nes.ppu.SetExtLatchMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void Mapper164::WriteLow(WORD addr, BYTE data)
|
//void Mapper164::WriteLow(WORD addr, BYTE data)
|
||||||
@ -51,7 +51,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUGOUT("write to %04x:%02x\n", addr, data);
|
Debuger.Log($"write to {addr:X4}:{data:X2}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -74,11 +74,11 @@ namespace VirtualNes.Core
|
|||||||
bank += (reg5000 & 0x20) >> 1;
|
bank += (reg5000 & 0x20) >> 1;
|
||||||
SetPROM_16K_Bank(4, bank + @base);
|
SetPROM_16K_Bank(4, bank + @base);
|
||||||
SetPROM_16K_Bank(6, @base + 0x1f);
|
SetPROM_16K_Bank(6, @base + 0x1f);
|
||||||
DEBUGOUT("-- normal mode: mode=%d, bank=%d --\n", mode, bank);
|
Debuger.Log($"-- normal mode: mode={mode}, bank={bank} --");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 3: /* REG MODE */
|
case 3: /* REG MODE */
|
||||||
DEBUGOUT("-- reg mode --\n");
|
Debuger.Log("-- reg mode --");
|
||||||
break;
|
break;
|
||||||
case 5: /* 32K MODE */
|
case 5: /* 32K MODE */
|
||||||
bank = (reg5000 & 0x0f);
|
bank = (reg5000 & 0x0f);
|
||||||
@ -91,7 +91,7 @@ namespace VirtualNes.Core
|
|||||||
SetPROM_16K_Bank(4, bank + @base);
|
SetPROM_16K_Bank(4, bank + @base);
|
||||||
bank = (bank & 0x10) + 0x0f;
|
bank = (bank & 0x10) + 0x0f;
|
||||||
SetPROM_16K_Bank(6, @base + 0x1f);
|
SetPROM_16K_Bank(6, @base + 0x1f);
|
||||||
DEBUGOUT("-- half mode --\n");
|
Debuger.Log("-- half mode --");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -116,18 +116,19 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
INT loopy_v = nes.ppu.GetPPUADDR();
|
INT loopy_v = nes.ppu.GetPPUADDR();
|
||||||
INT loopy_y = nes.ppu.GetTILEY();
|
INT loopy_y = nes.ppu.GetTILEY();
|
||||||
INT tileofs = (PPUREG[0] & PPU_BGTBL_BIT) << 8;
|
INT tileofs = (PPUREG[0] & PPU.PPU_BGTBL_BIT) << 8;
|
||||||
INT attradr = 0x23C0 + (loopy_v & 0x0C00) + ((loopy_v & 0x0380) >> 4);
|
INT attradr = 0x23C0 + (loopy_v & 0x0C00) + ((loopy_v & 0x0380) >> 4);
|
||||||
INT attrsft = (ntbladr & 0x0040) >> 4;
|
INT attrsft = (ntbladr & 0x0040) >> 4;
|
||||||
LPBYTE pNTBL = PPU_MEM_BANK[ntbladr >> 10];
|
Span<byte> pNTBL = PPU_MEM_BANK[ntbladr >> 10];
|
||||||
|
|
||||||
INT ntbl_x = ntbladr & 0x001F;
|
INT ntbl_x = ntbladr & 0x001F;
|
||||||
INT tileadr;
|
INT tileadr;
|
||||||
|
|
||||||
attradr &= 0x3FF;
|
attradr &= 0x3FF;
|
||||||
attr = ((pNTBL[attradr + (ntbl_x >> 2)] >> ((ntbl_x & 2) + attrsft)) & 3) << 2;
|
attr = (byte)(((pNTBL[attradr + (ntbl_x >> 2)] >> ((ntbl_x & 2) + attrsft)) & 3) << 2);
|
||||||
tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
|
tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
|
||||||
|
|
||||||
if (p_mode)
|
if (p_mode != 0)
|
||||||
{
|
{
|
||||||
tileadr = (tileadr & 0xfff7) | a3;
|
tileadr = (tileadr & 0xfff7) | a3;
|
||||||
chr_l = chr_h = PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
chr_l = chr_h = PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
||||||
|
@ -41,7 +41,7 @@ namespace VirtualNes.Core
|
|||||||
|
|
||||||
we_sram = 0; // Disable
|
we_sram = 0; // Disable
|
||||||
|
|
||||||
nes->ppu->SetChrLatchMode(TRUE);
|
nes.ppu.SetChrLatchMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void Mapper165::Write(WORD addr, BYTE data)
|
//void Mapper165::Write(WORD addr, BYTE data)
|
||||||
|
@ -18,7 +18,7 @@ namespace VirtualNes.Core
|
|||||||
public override void Reset()
|
public override void Reset()
|
||||||
{
|
{
|
||||||
//prg = ~0;
|
//prg = ~0;
|
||||||
prg = (~0);
|
prg = unchecked((byte)(~0));
|
||||||
chr = 0;
|
chr = 0;
|
||||||
Sync();
|
Sync();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ namespace VirtualNes.Core
|
|||||||
|
|
||||||
if ((crcP == 0xE80D8741) || (crcV == 0x3846520D))
|
if ((crcP == 0xE80D8741) || (crcV == 0x3846520D))
|
||||||
{//ÍâÐÇ°ÔÍõµÄ´ó½
|
{//ÍâÐÇ°ÔÍõµÄ´ó½
|
||||||
nes.SetRenderMethod( EnumRenderMethod.POST_ALL_RENDER);
|
nes.SetRenderMethod(EnumRenderMethod.POST_ALL_RENDER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
SetPROM_32K_Bank(0, 1, 2, 3);
|
SetPROM_32K_Bank(0, 1, 2, 3);
|
||||||
|
|
||||||
if (VROM_1K_SIZE)
|
if (VROM_1K_SIZE != 0)
|
||||||
{
|
{
|
||||||
SetVROM_8K_Bank(0);
|
SetVROM_8K_Bank(0);
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetIrqType()
|
internal int GetIrqType()
|
||||||
{
|
{
|
||||||
return nIRQtype;
|
return nIRQtype;
|
||||||
}
|
}
|
||||||
@ -1668,6 +1668,16 @@ namespace VirtualNes.Core
|
|||||||
return NES_scanline;
|
return NES_scanline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SetSAVERAM_SIZE(int size)
|
||||||
|
{
|
||||||
|
SAVERAM_SIZE = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal byte GetBarcodeStatus()
|
||||||
|
{
|
||||||
|
return m_BarcodeOut;
|
||||||
|
}
|
||||||
|
|
||||||
public enum IRQMETHOD
|
public enum IRQMETHOD
|
||||||
{
|
{
|
||||||
IRQ_HSYNC = 0, IRQ_CLOCK = 1
|
IRQ_HSYNC = 0, IRQ_CLOCK = 1
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace VirtualNes.Core
|
using System;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class PPU
|
public class PPU
|
||||||
{
|
{
|
||||||
@ -1125,6 +1127,26 @@
|
|||||||
return (MMU.PPUREG[1] & (PPU_BGDISP_BIT | PPU_SPDISP_BIT)) != 0;
|
return (MMU.PPUREG[1] & (PPU_BGDISP_BIT | PPU_SPDISP_BIT)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SetExtLatchMode(bool bMode)
|
||||||
|
{
|
||||||
|
bExtLatch = bMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ushort GetPPUADDR()
|
||||||
|
{
|
||||||
|
return MMU.loopy_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ushort GetTILEY()
|
||||||
|
{
|
||||||
|
return loopy_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetChrLatchMode(bool bMode)
|
||||||
|
{
|
||||||
|
bChrLatch = bMode;
|
||||||
|
}
|
||||||
|
|
||||||
public struct Sprite
|
public struct Sprite
|
||||||
{
|
{
|
||||||
public byte y
|
public byte y
|
||||||
|
@ -401,6 +401,11 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal uint GetVROM_CRC()
|
||||||
|
{
|
||||||
|
return crcvrom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user