1118 lines
32 KiB
C#
1118 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
namespace MyNes.Core
|
|
{
|
|
internal abstract class Board
|
|
{
|
|
protected byte[][] PRG_RAM;
|
|
|
|
protected bool[] PRG_RAM_ENABLED;
|
|
|
|
protected bool[] PRG_RAM_WRITABLE;
|
|
|
|
protected bool[] PRG_RAM_BATTERY;
|
|
|
|
protected byte[][] PRG_ROM;
|
|
|
|
protected int PRG_RAM_08KB_DEFAULT_BLK_Count;
|
|
|
|
internal int PRG_ROM_04KB_Count;
|
|
|
|
protected int PRG_ROM_08KB_Count;
|
|
|
|
protected int PRG_ROM_16KB_Count;
|
|
|
|
protected int PRG_ROM_32KB_Count;
|
|
|
|
protected int PRG_ROM_04KB_Mask;
|
|
|
|
protected int PRG_ROM_08KB_Mask;
|
|
|
|
protected int PRG_ROM_16KB_Mask;
|
|
|
|
protected int PRG_ROM_32KB_Mask;
|
|
|
|
internal int PRG_RAM_04KB_Count;
|
|
|
|
protected int PRG_RAM_08KB_Count;
|
|
|
|
protected int PRG_RAM_16KB_Count;
|
|
|
|
protected int PRG_RAM_32KB_Count;
|
|
|
|
protected int PRG_RAM_04KB_Mask;
|
|
|
|
protected int PRG_RAM_08KB_Mask;
|
|
|
|
protected int PRG_RAM_16KB_Mask;
|
|
|
|
protected int PRG_RAM_32KB_Mask;
|
|
|
|
protected bool[] PRG_AREA_BLK_RAM;
|
|
|
|
protected int[] PRG_AREA_BLK_INDEX;
|
|
|
|
protected int PRG_TMP_INDX;
|
|
|
|
protected int PRG_TMP_AREA;
|
|
|
|
protected byte[][] CHR_RAM;
|
|
|
|
protected bool[] CHR_RAM_ENABLED;
|
|
|
|
protected bool[] CHR_RAM_WRITABLE;
|
|
|
|
protected bool[] CHR_RAM_BATTERY;
|
|
|
|
protected byte[][] CHR_ROM;
|
|
|
|
protected bool[] CHR_AREA_BLK_RAM;
|
|
|
|
protected int[] CHR_AREA_BLK_INDEX;
|
|
|
|
protected int CHR_TMP_INDX;
|
|
|
|
protected int CHR_TMP_AREA;
|
|
|
|
protected int CHR_ROM_01KB_DEFAULT_BLK_Count;
|
|
|
|
internal int CHR_ROM_01KB_Count;
|
|
|
|
protected int CHR_ROM_02KB_Count;
|
|
|
|
protected int CHR_ROM_04KB_Count;
|
|
|
|
protected int CHR_ROM_08KB_Count;
|
|
|
|
internal int CHR_ROM_01KB_Mask;
|
|
|
|
protected int CHR_ROM_02KB_Mask;
|
|
|
|
protected int CHR_ROM_04KB_Mask;
|
|
|
|
protected int CHR_ROM_08KB_Mask;
|
|
|
|
internal int CHR_RAM_01KB_Count;
|
|
|
|
protected int CHR_RAM_02KB_Count;
|
|
|
|
protected int CHR_RAM_04KB_Count;
|
|
|
|
protected int CHR_RAM_08KB_Count;
|
|
|
|
internal int CHR_RAM_01KB_Mask;
|
|
|
|
protected int CHR_RAM_02KB_Mask;
|
|
|
|
protected int CHR_RAM_04KB_Mask;
|
|
|
|
protected int CHR_RAM_08KB_Mask;
|
|
|
|
protected byte[][] NMT_RAM;
|
|
|
|
internal int[] NMT_AREA_BLK_INDEX;
|
|
|
|
protected int NMT_TMP_INDX;
|
|
|
|
protected int NMT_TMP_AREA;
|
|
|
|
internal Mirroring NMT_DEFAULT_MIRROR;
|
|
|
|
internal string SHA1 = "";
|
|
|
|
internal string CRC = "";
|
|
|
|
internal bool IsGameFoundOnDB;
|
|
|
|
internal NesCartDatabaseGameInfo GameInfo;
|
|
|
|
internal NesCartDatabaseCartridgeInfo GameCartInfo;
|
|
|
|
internal bool SRAMSaveRequired;
|
|
|
|
protected bool enabled_ppuA12ToggleTimer;
|
|
|
|
protected bool ppuA12TogglesOnRaisingEdge;
|
|
|
|
protected int old_vram_address;
|
|
|
|
protected int new_vram_address;
|
|
|
|
protected int ppu_cycles_timer;
|
|
|
|
internal bool enable_external_sound;
|
|
|
|
internal bool IsGameGenieActive;
|
|
|
|
internal GameGenieCode[] GameGenieCodes;
|
|
|
|
internal string BoardType { get; private set; }
|
|
|
|
internal string BoardPCB { get; private set; }
|
|
|
|
internal List<string> Chips { get; private set; }
|
|
|
|
internal string Name { get; set; }
|
|
|
|
internal int MapperNumber { get; set; }
|
|
|
|
internal bool HasIssues { get; set; }
|
|
|
|
internal virtual string Issues { get; set; }
|
|
|
|
public Board()
|
|
{
|
|
MapperNumber = -1;
|
|
PRG_RAM_08KB_DEFAULT_BLK_Count = 1;
|
|
CHR_ROM_01KB_DEFAULT_BLK_Count = 8;
|
|
LoadAttrs();
|
|
}
|
|
|
|
internal virtual void Initialize(IRom rom)
|
|
{
|
|
SHA1 = rom.SHA1;
|
|
SRAMSaveRequired = false;
|
|
IsGameGenieActive = false;
|
|
BoardType = "N/A";
|
|
BoardPCB = "N/A";
|
|
Chips = new List<string>();
|
|
if (NesCartDatabase.Ready)
|
|
{
|
|
Tracer.WriteLine("Looking for rom in the database ..");
|
|
GameInfo = NesCartDatabase.Find(SHA1, out IsGameFoundOnDB);
|
|
if (GameInfo.Cartridges != null)
|
|
{
|
|
foreach (NesCartDatabaseCartridgeInfo cartridge in GameInfo.Cartridges)
|
|
{
|
|
if (cartridge.SHA1.ToLower() == SHA1.ToLower())
|
|
{
|
|
GameCartInfo = cartridge;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (IsGameFoundOnDB)
|
|
{
|
|
Tracer.WriteInformation("Game found in Database !!");
|
|
Tracer.WriteLine("> Game name: " + GameInfo.Game_Name);
|
|
Tracer.WriteLine("> Game alt name: " + GameInfo.Game_AltName);
|
|
BoardType = GameCartInfo.Board_Type;
|
|
Tracer.WriteLine("> Board Type: " + BoardType);
|
|
BoardPCB = GameCartInfo.Board_Pcb;
|
|
Tracer.WriteLine("> Board Pcb: " + BoardPCB);
|
|
if (GameCartInfo.chip_type != null)
|
|
{
|
|
for (int i = 0; i < GameCartInfo.chip_type.Count; i++)
|
|
{
|
|
Console.WriteLine($"> CHIP {(i + 1).ToString()}: {GameCartInfo.chip_type[i]}");
|
|
Chips.Add(GameCartInfo.chip_type[i]);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Tracer.WriteWarning("Game is not found in database .");
|
|
}
|
|
}
|
|
Tracer.WriteLine("Initializing the board (Mapper # " + MapperNumber + ") ....");
|
|
Tracer.WriteLine("Loading PRG ROM ...");
|
|
PRG_AREA_BLK_RAM = new bool[16];
|
|
PRG_AREA_BLK_INDEX = new int[16];
|
|
PRG_ROM = new byte[0][];
|
|
int num = 0;
|
|
for (int j = 0; j < rom.PRG.Length; j += 4096)
|
|
{
|
|
Array.Resize(ref PRG_ROM, PRG_ROM.GetLength(0) + 1);
|
|
PRG_ROM[num] = new byte[4096];
|
|
for (int k = 0; k < 4096; k++)
|
|
{
|
|
PRG_ROM[num][k] = rom.PRG[j + k];
|
|
}
|
|
num++;
|
|
}
|
|
PRG_ROM_04KB_Count = PRG_ROM.GetLength(0);
|
|
PRG_ROM_04KB_Mask = PRG_ROM_04KB_Count - 1;
|
|
PRG_ROM_08KB_Count = PRG_ROM_04KB_Count / 2;
|
|
PRG_ROM_08KB_Mask = PRG_ROM_08KB_Count - 1;
|
|
PRG_ROM_16KB_Count = PRG_ROM_04KB_Count / 4;
|
|
PRG_ROM_16KB_Mask = PRG_ROM_16KB_Count - 1;
|
|
PRG_ROM_32KB_Count = PRG_ROM_04KB_Count / 8;
|
|
PRG_ROM_32KB_Mask = PRG_ROM_32KB_Count - 1;
|
|
Tracer.WriteLine("PRG ROM loaded successfully.");
|
|
Tracer.WriteLine("PRG ROM Size = " + PRG_ROM_04KB_Count * 4 + "KB");
|
|
Tracer.WriteLine("Loading PRG RAM ...");
|
|
SRAMBankInfo[] pRGRAM8KCountFromDB = GetPRGRAM8KCountFromDB();
|
|
PRG_RAM = new byte[0][];
|
|
PRG_RAM_BATTERY = new bool[0];
|
|
PRG_RAM_ENABLED = new bool[0];
|
|
PRG_RAM_WRITABLE = new bool[0];
|
|
SRAMBankInfo[] array = pRGRAM8KCountFromDB;
|
|
for (int l = 0; l < array.Length; l++)
|
|
{
|
|
SRAMBankInfo sRAMBankInfo = array[l];
|
|
if (sRAMBankInfo.BATTERY)
|
|
{
|
|
SRAMSaveRequired = true;
|
|
}
|
|
int result = 0;
|
|
int.TryParse(sRAMBankInfo.SIZE.Replace("k", ""), out result);
|
|
if (result > 0)
|
|
{
|
|
int num2 = result / 2;
|
|
for (int m = 0; m < num2; m++)
|
|
{
|
|
Array.Resize(ref PRG_RAM_BATTERY, PRG_RAM_BATTERY.Length + 1);
|
|
Array.Resize(ref PRG_RAM_ENABLED, PRG_RAM_ENABLED.Length + 1);
|
|
Array.Resize(ref PRG_RAM_WRITABLE, PRG_RAM_WRITABLE.Length + 1);
|
|
Array.Resize(ref PRG_RAM, PRG_RAM.GetLength(0) + 1);
|
|
PRG_RAM[PRG_RAM.GetLength(0) - 1] = new byte[4096];
|
|
PRG_RAM_BATTERY[PRG_RAM_BATTERY.Length - 1] = sRAMBankInfo.BATTERY;
|
|
PRG_RAM_ENABLED[PRG_RAM_ENABLED.Length - 1] = true;
|
|
PRG_RAM_WRITABLE[PRG_RAM_WRITABLE.Length - 1] = true;
|
|
}
|
|
}
|
|
}
|
|
PRG_RAM_04KB_Count = PRG_RAM.GetLength(0);
|
|
PRG_RAM_04KB_Mask = PRG_RAM_04KB_Count - 1;
|
|
PRG_RAM_08KB_Count = PRG_RAM_04KB_Count / 2;
|
|
PRG_RAM_08KB_Mask = PRG_RAM_08KB_Count - 1;
|
|
PRG_RAM_16KB_Count = PRG_RAM_04KB_Count / 4;
|
|
PRG_RAM_16KB_Mask = PRG_RAM_16KB_Count - 1;
|
|
PRG_RAM_32KB_Count = PRG_RAM_04KB_Count / 8;
|
|
PRG_RAM_32KB_Mask = PRG_RAM_32KB_Count - 1;
|
|
Tracer.WriteLine("PRG RAM loaded successfully.");
|
|
Tracer.WriteLine("PRG RAM Size = " + PRG_RAM_04KB_Count * 4 + "KB");
|
|
if (rom.HasTrainer)
|
|
{
|
|
rom.Trainer.CopyTo(PRG_RAM[3], 0);
|
|
}
|
|
Tracer.WriteLine("Loading CHR ROM ...");
|
|
CHR_ROM = new byte[0][];
|
|
CHR_AREA_BLK_RAM = new bool[8];
|
|
CHR_AREA_BLK_INDEX = new int[8];
|
|
num = 0;
|
|
for (int n = 0; n < rom.CHR.Length; n += 1024)
|
|
{
|
|
Array.Resize(ref CHR_ROM, CHR_ROM.GetLength(0) + 1);
|
|
CHR_ROM[num] = new byte[1024];
|
|
for (int num3 = 0; num3 < 1024; num3++)
|
|
{
|
|
CHR_ROM[num][num3] = rom.CHR[n + num3];
|
|
}
|
|
num++;
|
|
}
|
|
CHR_ROM_01KB_Count = CHR_ROM.GetLength(0);
|
|
CHR_ROM_01KB_Mask = CHR_ROM_01KB_Count - 1;
|
|
CHR_ROM_02KB_Count = CHR_ROM_01KB_Count / 2;
|
|
CHR_ROM_02KB_Mask = CHR_ROM_02KB_Count - 1;
|
|
CHR_ROM_04KB_Count = CHR_ROM_01KB_Count / 4;
|
|
CHR_ROM_04KB_Mask = CHR_ROM_04KB_Count - 1;
|
|
CHR_ROM_08KB_Count = CHR_ROM_01KB_Count / 8;
|
|
CHR_ROM_08KB_Mask = CHR_ROM_08KB_Count - 1;
|
|
Tracer.WriteLine("CHR ROM loaded successfully.");
|
|
Tracer.WriteLine("CHR ROM Size = " + CHR_ROM_01KB_Count + "KB");
|
|
Tracer.WriteLine("Loading CHR RAM ...");
|
|
int cHRRAM1KCountFromDB = GetCHRRAM1KCountFromDB();
|
|
CHR_RAM = new byte[0][];
|
|
CHR_RAM_BATTERY = new bool[cHRRAM1KCountFromDB];
|
|
CHR_RAM_ENABLED = new bool[cHRRAM1KCountFromDB];
|
|
CHR_RAM_WRITABLE = new bool[cHRRAM1KCountFromDB];
|
|
for (int num4 = 0; num4 < cHRRAM1KCountFromDB; num4++)
|
|
{
|
|
Array.Resize(ref CHR_RAM, CHR_RAM.GetLength(0) + 1);
|
|
CHR_RAM[num4] = new byte[1024];
|
|
CHR_RAM_BATTERY[num4] = false;
|
|
CHR_RAM_ENABLED[num4] = true;
|
|
CHR_RAM_WRITABLE[num4] = true;
|
|
}
|
|
CHR_RAM_01KB_Count = CHR_RAM.GetLength(0);
|
|
CHR_RAM_01KB_Mask = CHR_RAM_01KB_Count - 1;
|
|
CHR_RAM_02KB_Count = CHR_RAM_01KB_Count / 2;
|
|
CHR_RAM_02KB_Mask = CHR_RAM_02KB_Count - 1;
|
|
CHR_RAM_04KB_Count = CHR_RAM_01KB_Count / 4;
|
|
CHR_RAM_04KB_Mask = CHR_RAM_04KB_Count - 1;
|
|
CHR_RAM_08KB_Count = CHR_RAM_01KB_Count / 8;
|
|
CHR_RAM_08KB_Mask = CHR_RAM_08KB_Count - 1;
|
|
Tracer.WriteLine("CHR RAM loaded successfully.");
|
|
Tracer.WriteLine("CHR RAM Size = " + CHR_RAM_01KB_Count + "KB");
|
|
Tracer.WriteLine("Loading Nametables ...");
|
|
NMT_AREA_BLK_INDEX = new int[4];
|
|
NMT_RAM = new byte[0][];
|
|
for (int num5 = 0; num5 < 4; num5++)
|
|
{
|
|
Array.Resize(ref NMT_RAM, NMT_RAM.GetLength(0) + 1);
|
|
NMT_RAM[num5] = new byte[1024];
|
|
}
|
|
NMT_DEFAULT_MIRROR = rom.Mirroring;
|
|
Tracer.WriteLine("Mirroring set to " + NMT_DEFAULT_MIRROR);
|
|
Tracer.WriteLine("Board (Mapper # " + MapperNumber + ") initialized successfully.");
|
|
}
|
|
|
|
internal virtual void HardReset()
|
|
{
|
|
Tracer.WriteLine("Hard reset board (Mapper # " + MapperNumber + ") ....");
|
|
Tracer.WriteLine("Switching 16KB PRG RAM at 0x4000 - 0x7000");
|
|
Toggle16KPRG_RAM(ram: true, PRGArea.Area4000);
|
|
Switch16KPRG(0, PRGArea.Area4000);
|
|
Tracer.WriteLine("Switching 32KB PRG ROM at 0x8000 - 0xF000");
|
|
Toggle32KPRG_RAM(ram: false, PRGArea.Area8000);
|
|
Switch32KPRG(0, PRGArea.Area8000);
|
|
Tracer.WriteLine("Switching 8KB CHR " + ((CHR_ROM_01KB_Count == 0) ? "RAM" : "ROM") + " at 0x0000 - 0x1000");
|
|
Toggle08KCHR_RAM(CHR_ROM_01KB_Count == 0);
|
|
Switch08KCHR(0);
|
|
Tracer.WriteLine("Switching to mirroring: " + NMT_DEFAULT_MIRROR);
|
|
Switch01KNMTFromMirroring(NMT_DEFAULT_MIRROR);
|
|
Tracer.WriteLine("Hard reset board (Mapper # " + MapperNumber + ") is done successfully.");
|
|
}
|
|
|
|
internal virtual void SoftReset()
|
|
{
|
|
}
|
|
|
|
protected virtual void LoadAttrs()
|
|
{
|
|
enable_external_sound = false;
|
|
Attribute[] customAttributes = Attribute.GetCustomAttributes(GetType());
|
|
foreach (Attribute attribute in customAttributes)
|
|
{
|
|
if (attribute.GetType() == typeof(BoardInfoAttribute))
|
|
{
|
|
BoardInfoAttribute boardInfoAttribute = (BoardInfoAttribute)attribute;
|
|
Name = boardInfoAttribute.Name;
|
|
MapperNumber = boardInfoAttribute.Mapper;
|
|
PRG_RAM_08KB_DEFAULT_BLK_Count = boardInfoAttribute.DefaultPRG_RAM_8KB_BanksCount;
|
|
CHR_ROM_01KB_DEFAULT_BLK_Count = boardInfoAttribute.DefaultCHR_RAM_1KB_BanksCount;
|
|
enabled_ppuA12ToggleTimer = boardInfoAttribute.Enabled_ppuA12ToggleTimer;
|
|
ppuA12TogglesOnRaisingEdge = boardInfoAttribute.PPUA12TogglesOnRaisingEdge;
|
|
}
|
|
else if (attribute.GetType() == typeof(WithExternalSoundAttribute))
|
|
{
|
|
enable_external_sound = true;
|
|
}
|
|
else if (attribute.GetType() == typeof(HassIssuesAttribute))
|
|
{
|
|
HasIssues = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected SRAMBankInfo[] GetPRGRAM8KCountFromDB()
|
|
{
|
|
Tracer.WriteLine("Retrieving PRG RAM information from database ....");
|
|
List<SRAMBankInfo> list = new List<SRAMBankInfo>();
|
|
if (IsGameFoundOnDB)
|
|
{
|
|
if (GameCartInfo.WRAMBanks.Count > 0)
|
|
{
|
|
foreach (SRAMBankInfo wRAMBank in GameCartInfo.WRAMBanks)
|
|
{
|
|
list.Add(wRAMBank);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Tracer.WriteLine("This game has no PRG RAM !");
|
|
Tracer.WriteWarning("> Adding 8K x " + PRG_RAM_08KB_DEFAULT_BLK_Count + " PRG RAM BANKS to avoid exceptions.");
|
|
SRAMBankInfo item = new SRAMBankInfo(0, PRG_RAM_08KB_DEFAULT_BLK_Count * 8 + "k", BATTERY: true);
|
|
list.Add(item);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Tracer.WriteWarning("Could't find this game in database .... Adding 8K x " + PRG_RAM_08KB_DEFAULT_BLK_Count + " PRG RAM BANKS to avoid exceptions.");
|
|
SRAMBankInfo item2 = new SRAMBankInfo(0, PRG_RAM_08KB_DEFAULT_BLK_Count * 8 + "k", BATTERY: true);
|
|
list.Add(item2);
|
|
}
|
|
return list.ToArray();
|
|
}
|
|
|
|
protected int GetCHRRAM1KCountFromDB()
|
|
{
|
|
int num = 0;
|
|
Tracer.WriteLine("Retrieving CHR RAM information from database ....");
|
|
if (IsGameFoundOnDB)
|
|
{
|
|
bool flag = false;
|
|
if (GameCartInfo.VRAM_sizes != null)
|
|
{
|
|
Tracer.WriteLine("Using database to initialize CHR RAM .....");
|
|
foreach (string vRAM_size in GameCartInfo.VRAM_sizes)
|
|
{
|
|
int result = 0;
|
|
if (int.TryParse(vRAM_size.Replace("k", ""), out result))
|
|
{
|
|
Tracer.WriteLine(">CHR RAM CHIP SIZE " + vRAM_size + " KB added");
|
|
num += result;
|
|
if (num > 0)
|
|
{
|
|
flag = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
Tracer.WriteLine("Game not found in database to initialize CHR RAM; CHR RAM size set to " + CHR_ROM_01KB_DEFAULT_BLK_Count + " KB");
|
|
num = CHR_ROM_01KB_DEFAULT_BLK_Count;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Tracer.WriteWarning("Game not found in database to initialize CHR RAM; CHR RAM size set to " + CHR_ROM_01KB_DEFAULT_BLK_Count + " KB");
|
|
num = CHR_ROM_01KB_DEFAULT_BLK_Count;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
internal virtual void WriteEX(ref ushort addr, ref byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
|
|
{
|
|
PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual void WriteSRM(ref ushort addr, ref byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
|
|
{
|
|
PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual void WritePRG(ref ushort addr, ref byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
|
|
{
|
|
PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual void ReadEX(ref ushort addr, out byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX])
|
|
{
|
|
val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
|
|
val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
}
|
|
|
|
internal virtual void ReadSRM(ref ushort addr, out byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX])
|
|
{
|
|
val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
|
|
val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
}
|
|
|
|
internal virtual void ReadPRG(ref ushort addr, out byte val)
|
|
{
|
|
PRG_TMP_AREA = (addr >> 12) & 0xF;
|
|
if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
|
|
if (PRG_RAM_ENABLED[PRG_TMP_INDX])
|
|
{
|
|
val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
|
|
val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
|
|
}
|
|
if (!IsGameGenieActive)
|
|
{
|
|
return;
|
|
}
|
|
GameGenieCode[] gameGenieCodes = GameGenieCodes;
|
|
for (int i = 0; i < gameGenieCodes.Length; i++)
|
|
{
|
|
GameGenieCode gameGenieCode = gameGenieCodes[i];
|
|
if (!gameGenieCode.Enabled || gameGenieCode.Address != addr)
|
|
{
|
|
continue;
|
|
}
|
|
if (gameGenieCode.IsCompare)
|
|
{
|
|
if (gameGenieCode.Compare == val)
|
|
{
|
|
val = gameGenieCode.Value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
val = gameGenieCode.Value;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
internal virtual void WriteCHR(ref ushort addr, ref byte val)
|
|
{
|
|
CHR_TMP_AREA = (addr >> 10) & 7;
|
|
if (CHR_AREA_BLK_RAM[CHR_TMP_AREA])
|
|
{
|
|
CHR_TMP_INDX = CHR_AREA_BLK_INDEX[CHR_TMP_AREA] & CHR_RAM_01KB_Mask;
|
|
if (CHR_RAM_ENABLED[CHR_TMP_INDX] && CHR_RAM_WRITABLE[CHR_TMP_INDX])
|
|
{
|
|
CHR_RAM[CHR_TMP_INDX][addr & 0x3FF] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual void ReadCHR(ref ushort addr, out byte val)
|
|
{
|
|
CHR_TMP_AREA = (addr >> 10) & 7;
|
|
CHR_TMP_INDX = CHR_AREA_BLK_INDEX[CHR_TMP_AREA];
|
|
if (CHR_AREA_BLK_RAM[CHR_TMP_AREA])
|
|
{
|
|
CHR_TMP_INDX &= CHR_RAM_01KB_Mask;
|
|
if (CHR_RAM_ENABLED[CHR_TMP_INDX])
|
|
{
|
|
val = CHR_RAM[CHR_TMP_INDX][addr & 0x3FF];
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CHR_TMP_INDX &= CHR_ROM_01KB_Mask;
|
|
val = CHR_ROM[CHR_TMP_INDX][addr & 0x3FF];
|
|
}
|
|
}
|
|
|
|
internal virtual void WriteNMT(ref ushort addr, ref byte val)
|
|
{
|
|
NMT_TMP_AREA = (addr >> 10) & 3;
|
|
NMT_TMP_INDX = NMT_AREA_BLK_INDEX[NMT_TMP_AREA];
|
|
NMT_RAM[NMT_TMP_INDX][addr & 0x3FF] = val;
|
|
}
|
|
|
|
internal virtual void ReadNMT(ref ushort addr, out byte val)
|
|
{
|
|
NMT_TMP_AREA = (addr >> 10) & 3;
|
|
NMT_TMP_INDX = NMT_AREA_BLK_INDEX[NMT_TMP_AREA];
|
|
val = NMT_RAM[NMT_TMP_INDX][addr & 0x3FF];
|
|
}
|
|
|
|
protected void Switch04KPRG(int index, PRGArea area)
|
|
{
|
|
PRG_AREA_BLK_INDEX[(uint)area] = index;
|
|
}
|
|
|
|
protected void Switch08KPRG(int index, PRGArea area)
|
|
{
|
|
index *= 2;
|
|
PRG_AREA_BLK_INDEX[(uint)area] = index;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
|
|
}
|
|
|
|
protected void Switch16KPRG(int index, PRGArea area)
|
|
{
|
|
index *= 4;
|
|
PRG_AREA_BLK_INDEX[(uint)area] = index;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
|
|
}
|
|
|
|
protected void Switch32KPRG(int index, PRGArea area)
|
|
{
|
|
index *= 8;
|
|
PRG_AREA_BLK_INDEX[(uint)area] = index;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 4)] = index + 4;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 5)] = index + 5;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 6)] = index + 6;
|
|
PRG_AREA_BLK_INDEX[(uint)(area + 7)] = index + 7;
|
|
}
|
|
|
|
protected void Toggle04KPRG_RAM(bool ram, PRGArea area)
|
|
{
|
|
PRG_AREA_BLK_RAM[(uint)area] = ram;
|
|
}
|
|
|
|
protected void Toggle08KPRG_RAM(bool ram, PRGArea area)
|
|
{
|
|
PRG_AREA_BLK_RAM[(uint)area] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
|
|
}
|
|
|
|
protected void Toggle16KPRG_RAM(bool ram, PRGArea area)
|
|
{
|
|
PRG_AREA_BLK_RAM[(uint)area] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 2)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 3)] = ram;
|
|
}
|
|
|
|
protected void Toggle32KPRG_RAM(bool ram, PRGArea area)
|
|
{
|
|
PRG_AREA_BLK_RAM[(uint)area] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 2)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 3)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 4)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 5)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 6)] = ram;
|
|
PRG_AREA_BLK_RAM[(uint)(area + 7)] = ram;
|
|
}
|
|
|
|
protected void TogglePRGRAMEnable(bool enable)
|
|
{
|
|
for (int i = 0; i < PRG_RAM_ENABLED.Length; i++)
|
|
{
|
|
PRG_RAM_ENABLED[i] = enable;
|
|
}
|
|
}
|
|
|
|
protected void TogglePRGRAMWritableEnable(bool enable)
|
|
{
|
|
for (int i = 0; i < PRG_RAM_WRITABLE.Length; i++)
|
|
{
|
|
PRG_RAM_WRITABLE[i] = enable;
|
|
}
|
|
}
|
|
|
|
protected void Toggle04KPRG_RAM_Enabled(bool enable, int index)
|
|
{
|
|
PRG_RAM_ENABLED[index] = enable;
|
|
}
|
|
|
|
protected void Toggle04KPRG_RAM_Writable(bool enable, int index)
|
|
{
|
|
PRG_RAM_WRITABLE[index] = enable;
|
|
}
|
|
|
|
protected void Toggle04KPRG_RAM_Battery(bool enable, int index)
|
|
{
|
|
PRG_RAM_BATTERY[index] = enable;
|
|
}
|
|
|
|
protected void Switch01KCHR(int index, CHRArea area)
|
|
{
|
|
CHR_AREA_BLK_INDEX[(uint)area] = index;
|
|
}
|
|
|
|
protected void Switch02KCHR(int index, CHRArea area)
|
|
{
|
|
index *= 2;
|
|
CHR_AREA_BLK_INDEX[(uint)area] = index;
|
|
CHR_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
|
|
}
|
|
|
|
protected void Switch04KCHR(int index, CHRArea area)
|
|
{
|
|
index *= 4;
|
|
CHR_AREA_BLK_INDEX[(uint)area] = index;
|
|
CHR_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
|
|
CHR_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
|
|
CHR_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
|
|
}
|
|
|
|
protected void Switch08KCHR(int index)
|
|
{
|
|
index *= 8;
|
|
CHR_AREA_BLK_INDEX[0] = index;
|
|
CHR_AREA_BLK_INDEX[1] = index + 1;
|
|
CHR_AREA_BLK_INDEX[2] = index + 2;
|
|
CHR_AREA_BLK_INDEX[3] = index + 3;
|
|
CHR_AREA_BLK_INDEX[4] = index + 4;
|
|
CHR_AREA_BLK_INDEX[5] = index + 5;
|
|
CHR_AREA_BLK_INDEX[6] = index + 6;
|
|
CHR_AREA_BLK_INDEX[7] = index + 7;
|
|
}
|
|
|
|
protected void Toggle01KCHR_RAM(bool ram, CHRArea area)
|
|
{
|
|
CHR_AREA_BLK_RAM[(uint)area] = ram;
|
|
}
|
|
|
|
protected void Toggle02KCHR_RAM(bool ram, CHRArea area)
|
|
{
|
|
CHR_AREA_BLK_RAM[(uint)area] = ram;
|
|
CHR_AREA_BLK_RAM[(uint)(area + 1)] = ram;
|
|
}
|
|
|
|
protected void Toggle04KCHR_RAM(bool ram, CHRArea area)
|
|
{
|
|
CHR_AREA_BLK_RAM[(uint)area] = ram;
|
|
CHR_AREA_BLK_RAM[(uint)(area + 1)] = ram;
|
|
CHR_AREA_BLK_RAM[(uint)(area + 2)] = ram;
|
|
CHR_AREA_BLK_RAM[(uint)(area + 3)] = ram;
|
|
}
|
|
|
|
protected void Toggle08KCHR_RAM(bool ram)
|
|
{
|
|
CHR_AREA_BLK_RAM[0] = ram;
|
|
CHR_AREA_BLK_RAM[1] = ram;
|
|
CHR_AREA_BLK_RAM[2] = ram;
|
|
CHR_AREA_BLK_RAM[3] = ram;
|
|
CHR_AREA_BLK_RAM[4] = ram;
|
|
CHR_AREA_BLK_RAM[5] = ram;
|
|
CHR_AREA_BLK_RAM[6] = ram;
|
|
CHR_AREA_BLK_RAM[7] = ram;
|
|
}
|
|
|
|
protected void Toggle01KCHR_RAM_Enabled(bool enable, int index)
|
|
{
|
|
CHR_RAM_ENABLED[index] = enable;
|
|
}
|
|
|
|
protected void Toggle01KCHR_RAM_Writable(bool enable, int index)
|
|
{
|
|
CHR_RAM_WRITABLE[index] = enable;
|
|
}
|
|
|
|
protected void ToggleCHRRAMWritableEnable(bool enable)
|
|
{
|
|
for (int i = 0; i < CHR_RAM_WRITABLE.Length; i++)
|
|
{
|
|
CHR_RAM_WRITABLE[i] = enable;
|
|
}
|
|
}
|
|
|
|
protected void Toggle01KCHR_RAM_Battery(bool enable, int index)
|
|
{
|
|
CHR_RAM_BATTERY[index] = enable;
|
|
}
|
|
|
|
protected void Switch01KNMT(int index, byte area)
|
|
{
|
|
NMT_AREA_BLK_INDEX[area] = index;
|
|
}
|
|
|
|
protected void Switch01KNMT(byte mirroring)
|
|
{
|
|
NMT_AREA_BLK_INDEX[0] = mirroring & 3;
|
|
NMT_AREA_BLK_INDEX[1] = (mirroring >> 2) & 3;
|
|
NMT_AREA_BLK_INDEX[2] = (mirroring >> 4) & 3;
|
|
NMT_AREA_BLK_INDEX[3] = (mirroring >> 6) & 3;
|
|
}
|
|
|
|
protected void Switch01KNMTFromMirroring(Mirroring mirroring)
|
|
{
|
|
NMT_AREA_BLK_INDEX[0] = (int)(mirroring & (Mirroring)3);
|
|
NMT_AREA_BLK_INDEX[1] = ((int)mirroring >> 2) & 3;
|
|
NMT_AREA_BLK_INDEX[2] = ((int)mirroring >> 4) & 3;
|
|
NMT_AREA_BLK_INDEX[3] = ((int)mirroring >> 6) & 3;
|
|
}
|
|
|
|
internal virtual void OnPPUAddressUpdate(ref ushort address)
|
|
{
|
|
if (!enabled_ppuA12ToggleTimer)
|
|
{
|
|
return;
|
|
}
|
|
old_vram_address = new_vram_address;
|
|
new_vram_address = address & 0x1000;
|
|
if (ppuA12TogglesOnRaisingEdge)
|
|
{
|
|
if (old_vram_address < new_vram_address)
|
|
{
|
|
if (ppu_cycles_timer > 8)
|
|
{
|
|
OnPPUA12RaisingEdge();
|
|
}
|
|
ppu_cycles_timer = 0;
|
|
}
|
|
}
|
|
else if (old_vram_address > new_vram_address)
|
|
{
|
|
if (ppu_cycles_timer > 8)
|
|
{
|
|
OnPPUA12RaisingEdge();
|
|
}
|
|
ppu_cycles_timer = 0;
|
|
}
|
|
}
|
|
|
|
internal virtual void OnCPUClock()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnPPUClock()
|
|
{
|
|
if (enabled_ppuA12ToggleTimer)
|
|
{
|
|
ppu_cycles_timer++;
|
|
}
|
|
}
|
|
|
|
internal virtual void OnPPUA12RaisingEdge()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnPPUScanlineTick()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnAPUClockDuration()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnAPUClockEnvelope()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnAPUClockSingle()
|
|
{
|
|
}
|
|
|
|
internal virtual void OnAPUClock()
|
|
{
|
|
}
|
|
|
|
internal virtual double APUGetSample()
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
internal virtual void APUApplyChannelsSettings()
|
|
{
|
|
}
|
|
|
|
internal void SetupGameGenie(bool IsGameGenieActive, GameGenieCode[] GameGenieCodes)
|
|
{
|
|
this.IsGameGenieActive = IsGameGenieActive;
|
|
this.GameGenieCodes = GameGenieCodes;
|
|
}
|
|
|
|
internal virtual void WriteStateData(ref BinaryWriter bin)
|
|
{
|
|
for (int i = 0; i < PRG_RAM.Length; i++)
|
|
{
|
|
bin.Write(PRG_RAM[i]);
|
|
}
|
|
for (int j = 0; j < PRG_RAM_ENABLED.Length; j++)
|
|
{
|
|
bin.Write(PRG_RAM_ENABLED[j]);
|
|
}
|
|
for (int k = 0; k < PRG_RAM_WRITABLE.Length; k++)
|
|
{
|
|
bin.Write(PRG_RAM_WRITABLE[k]);
|
|
}
|
|
for (int l = 0; l < PRG_RAM_BATTERY.Length; l++)
|
|
{
|
|
bin.Write(PRG_RAM_BATTERY[l]);
|
|
}
|
|
for (int m = 0; m < PRG_AREA_BLK_RAM.Length; m++)
|
|
{
|
|
bin.Write(PRG_AREA_BLK_RAM[m]);
|
|
}
|
|
for (int n = 0; n < PRG_AREA_BLK_INDEX.Length; n++)
|
|
{
|
|
bin.Write(PRG_AREA_BLK_INDEX[n]);
|
|
}
|
|
bin.Write(PRG_TMP_INDX);
|
|
bin.Write(PRG_TMP_AREA);
|
|
for (int num = 0; num < CHR_RAM.Length; num++)
|
|
{
|
|
bin.Write(CHR_RAM[num]);
|
|
}
|
|
for (int num2 = 0; num2 < CHR_RAM_ENABLED.Length; num2++)
|
|
{
|
|
bin.Write(CHR_RAM_ENABLED[num2]);
|
|
}
|
|
for (int num3 = 0; num3 < CHR_RAM_WRITABLE.Length; num3++)
|
|
{
|
|
bin.Write(CHR_RAM_WRITABLE[num3]);
|
|
}
|
|
for (int num4 = 0; num4 < CHR_RAM_BATTERY.Length; num4++)
|
|
{
|
|
bin.Write(CHR_RAM_BATTERY[num4]);
|
|
}
|
|
for (int num5 = 0; num5 < CHR_AREA_BLK_RAM.Length; num5++)
|
|
{
|
|
bin.Write(CHR_AREA_BLK_RAM[num5]);
|
|
}
|
|
for (int num6 = 0; num6 < CHR_AREA_BLK_INDEX.Length; num6++)
|
|
{
|
|
bin.Write(CHR_AREA_BLK_INDEX[num6]);
|
|
}
|
|
bin.Write(CHR_TMP_INDX);
|
|
bin.Write(CHR_TMP_AREA);
|
|
for (int num7 = 0; num7 < NMT_RAM.Length; num7++)
|
|
{
|
|
bin.Write(NMT_RAM[num7]);
|
|
}
|
|
for (int num8 = 0; num8 < NMT_AREA_BLK_INDEX.Length; num8++)
|
|
{
|
|
bin.Write(NMT_AREA_BLK_INDEX[num8]);
|
|
}
|
|
bin.Write(NMT_TMP_INDX);
|
|
bin.Write(NMT_TMP_AREA);
|
|
}
|
|
|
|
internal virtual void ReadStateData(ref BinaryReader bin)
|
|
{
|
|
for (int i = 0; i < PRG_RAM.Length; i++)
|
|
{
|
|
bin.Read(PRG_RAM[i], 0, PRG_RAM[i].Length);
|
|
}
|
|
for (int j = 0; j < PRG_RAM_ENABLED.Length; j++)
|
|
{
|
|
PRG_RAM_ENABLED[j] = bin.ReadBoolean();
|
|
}
|
|
for (int k = 0; k < PRG_RAM_WRITABLE.Length; k++)
|
|
{
|
|
PRG_RAM_WRITABLE[k] = bin.ReadBoolean();
|
|
}
|
|
for (int l = 0; l < PRG_RAM_BATTERY.Length; l++)
|
|
{
|
|
PRG_RAM_BATTERY[l] = bin.ReadBoolean();
|
|
}
|
|
for (int m = 0; m < PRG_AREA_BLK_RAM.Length; m++)
|
|
{
|
|
PRG_AREA_BLK_RAM[m] = bin.ReadBoolean();
|
|
}
|
|
for (int n = 0; n < PRG_AREA_BLK_INDEX.Length; n++)
|
|
{
|
|
PRG_AREA_BLK_INDEX[n] = bin.ReadInt32();
|
|
}
|
|
PRG_TMP_INDX = bin.ReadInt32();
|
|
PRG_TMP_AREA = bin.ReadInt32();
|
|
for (int num = 0; num < CHR_RAM.Length; num++)
|
|
{
|
|
bin.Read(CHR_RAM[num], 0, CHR_RAM[num].Length);
|
|
}
|
|
for (int num2 = 0; num2 < CHR_RAM_ENABLED.Length; num2++)
|
|
{
|
|
CHR_RAM_ENABLED[num2] = bin.ReadBoolean();
|
|
}
|
|
for (int num3 = 0; num3 < CHR_RAM_WRITABLE.Length; num3++)
|
|
{
|
|
CHR_RAM_WRITABLE[num3] = bin.ReadBoolean();
|
|
}
|
|
for (int num4 = 0; num4 < CHR_RAM_BATTERY.Length; num4++)
|
|
{
|
|
CHR_RAM_BATTERY[num4] = bin.ReadBoolean();
|
|
}
|
|
for (int num5 = 0; num5 < CHR_AREA_BLK_RAM.Length; num5++)
|
|
{
|
|
CHR_AREA_BLK_RAM[num5] = bin.ReadBoolean();
|
|
}
|
|
for (int num6 = 0; num6 < CHR_AREA_BLK_INDEX.Length; num6++)
|
|
{
|
|
CHR_AREA_BLK_INDEX[num6] = bin.ReadInt32();
|
|
}
|
|
CHR_TMP_INDX = bin.ReadInt32();
|
|
CHR_TMP_AREA = bin.ReadInt32();
|
|
for (int num7 = 0; num7 < NMT_RAM.Length; num7++)
|
|
{
|
|
bin.Read(NMT_RAM[num7], 0, NMT_RAM[num7].Length);
|
|
}
|
|
for (int num8 = 0; num8 < NMT_AREA_BLK_INDEX.Length; num8++)
|
|
{
|
|
NMT_AREA_BLK_INDEX[num8] = bin.ReadInt32();
|
|
}
|
|
NMT_TMP_INDX = bin.ReadInt32();
|
|
NMT_TMP_AREA = bin.ReadInt32();
|
|
}
|
|
|
|
internal void SaveSRAM(Stream stream)
|
|
{
|
|
for (int i = 0; i < PRG_RAM_04KB_Count; i++)
|
|
{
|
|
if (PRG_RAM_BATTERY[i])
|
|
{
|
|
stream.Write(PRG_RAM[i], 0, 4096);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal byte[] GetSRAMBuffer()
|
|
{
|
|
List<byte> list = new List<byte>();
|
|
for (int i = 0; i < PRG_RAM_04KB_Count; i++)
|
|
{
|
|
if (PRG_RAM_BATTERY[i])
|
|
{
|
|
list.AddRange(PRG_RAM[i]);
|
|
}
|
|
}
|
|
return list.ToArray();
|
|
}
|
|
|
|
internal void LoadSRAM(Stream stream)
|
|
{
|
|
for (int i = 0; i < PRG_RAM_04KB_Count; i++)
|
|
{
|
|
if (PRG_RAM_BATTERY[i])
|
|
{
|
|
stream.Read(PRG_RAM[i], 0, 4096);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void LoadSRAM(byte[] buffer)
|
|
{
|
|
int num = 0;
|
|
for (int i = 0; i < PRG_RAM_04KB_Count; i++)
|
|
{
|
|
if (PRG_RAM_BATTERY[i])
|
|
{
|
|
for (int j = 0; j < 4096; j++)
|
|
{
|
|
PRG_RAM[i][j] = buffer[j + num];
|
|
}
|
|
num += 4096;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|