261 lines
10 KiB
C#
261 lines
10 KiB
C#
|
using VirtualNes.Core;
|
|||
|
|
|||
|
namespace VirtualNes
|
|||
|
{
|
|||
|
public static class MMU
|
|||
|
{
|
|||
|
// CPU 儊儌儕僶儞僋
|
|||
|
public static ArrayRef<byte>[] CPU_MEM_BANK = new ArrayRef<byte>[8]; // 8K扨埵
|
|||
|
public static byte[] CPU_MEM_TYPE = new byte[8];
|
|||
|
public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡
|
|||
|
// PPU 儊儌儕僶儞僋
|
|||
|
public static ArrayRef<byte>[] PPU_MEM_BANK = new ArrayRef<byte>[12]; // 1K扨埵
|
|||
|
public static byte[] PPU_MEM_TYPE = new byte[12];
|
|||
|
public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡
|
|||
|
public static byte[] CRAM_USED = new byte[16]; // 僗僥乕僩僙乕僽梡
|
|||
|
|
|||
|
// NES儊儌儕
|
|||
|
public static byte[] RAM = new byte[8 * 1024]; // NES撪憻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
|
|||
|
|
|||
|
public static byte[] CRAM = new byte[32 * 1024]; // 僉儍儔僋僞僷僞乕儞RAM
|
|||
|
public static byte[] VRAM = new byte[4 * 1024]; // 僱乕儉僥乕僽儖/傾僩儕價儏乕僩RAM
|
|||
|
|
|||
|
public static byte[] SPRAM = new byte[0x100]; // 僗僾儔僀僩RAM
|
|||
|
public static byte[] BGPAL = new byte[0x10]; // BG僷儗僢僩
|
|||
|
public static byte[] SPPAL = new byte[0x10]; // SP僷儗僢僩
|
|||
|
// 儗僕僗僞
|
|||
|
public static byte[] CPUREG = new byte[0x18]; // Nes $4000-$4017
|
|||
|
public static byte[] PPUREG = new byte[0x04]; // Nes $2000-$2003
|
|||
|
|
|||
|
// PPU撪晹儗僕僗僞
|
|||
|
public static byte PPU56Toggle; // $2005-$2006 Toggle
|
|||
|
public static byte PPU7_Temp; // $2007 read buffer
|
|||
|
public static ushort loopy_t; // same as $2005/$2006
|
|||
|
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;
|
|||
|
public const byte BANKTYPE_RAM = 0xFF;
|
|||
|
public const byte BANKTYPE_DRAM = 0x01;
|
|||
|
public const byte BANKTYPE_MAPPER = 0x80;
|
|||
|
// For VROM/VRAM=/CRAM (PPU)
|
|||
|
public const byte BANKTYPE_VROM = 0x00;
|
|||
|
public const byte BANKTYPE_CRAM = 0x01;
|
|||
|
public const byte BANKTYPE_VRAM = 0x80;
|
|||
|
|
|||
|
// =ミラータイプ;
|
|||
|
public const byte VRAM_HMIRROR = 0x00; // Horizontal
|
|||
|
public const byte VRAM_VMIRROR = 0x01; // Virtical
|
|||
|
public const byte VRAM_MIRROR4 = 0x02; // All screen
|
|||
|
public const byte VRAM_MIRROR4L = 0x03; // PA10 L固定 $2000-$23FFのミラー
|
|||
|
public const byte VRAM_MIRROR4H = 0x04; // PA10 H固定 $2400-$27FFのミラー
|
|||
|
|
|||
|
// Frame-IRQ儗僕僗僞($4017)
|
|||
|
public static int FrameIRQ;
|
|||
|
|
|||
|
internal static void SetPROM_Bank(byte page, byte[] ptr, byte type)
|
|||
|
{
|
|||
|
CPU_MEM_BANK[page] = new ArrayRef<byte>(ptr, 0, ptr.Length);
|
|||
|
CPU_MEM_TYPE[page] = type;
|
|||
|
CPU_MEM_PAGE[page] = 0;
|
|||
|
}
|
|||
|
|
|||
|
internal static void SetPROM_Bank(byte page, ArrayRef<byte> ptr, byte type)
|
|||
|
{
|
|||
|
CPU_MEM_BANK[page] = ptr;
|
|||
|
CPU_MEM_TYPE[page] = type;
|
|||
|
CPU_MEM_PAGE[page] = 0;
|
|||
|
}
|
|||
|
|
|||
|
internal static void SetPROM_4K_Bank(ushort addr, int bank)
|
|||
|
{
|
|||
|
throw new System.NotImplementedException();
|
|||
|
|
|||
|
bank %= (PROM_8K_SIZE * 2);
|
|||
|
|
|||
|
//TODO
|
|||
|
//memcpy(&CPU_MEM_BANK[addr >> 13][addr & 0x1FFF], PROM + 0x1000 * bank, 0x1000);
|
|||
|
//// memcpy( &CPU_MEM_BANK[addr>>13][addr&0x1FFF], YSRAM+0x1000*bank, 0x1000);
|
|||
|
CPU_MEM_TYPE[addr >> 13] = BANKTYPE_ROM;
|
|||
|
CPU_MEM_PAGE[addr >> 13] = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
internal static void SetPROM_8K_Bank(byte page, int bank)
|
|||
|
{
|
|||
|
bank %= PROM_8K_SIZE;
|
|||
|
CPU_MEM_BANK[page] = new ArrayRef<byte>(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank);
|
|||
|
CPU_MEM_TYPE[page] = BANKTYPE_ROM;
|
|||
|
CPU_MEM_PAGE[page] = bank;
|
|||
|
}
|
|||
|
|
|||
|
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, ArrayRef<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 ArrayRef<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 ArrayRef<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 ArrayRef<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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|