NEShawk - break up into separate files
This commit is contained in:
parent
bd74041cde
commit
95dcae132f
|
@ -259,19 +259,19 @@
|
|||
<Compile Include="Consoles\Atari\lynx\LibLynx.cs" />
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.cs" />
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.IInputPollable.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.IMemoryDomains.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.ISaveRam.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.IStatable.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.IVideoProvider.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Coleco\ColecoVision.cs" />
|
||||
<Compile Include="Consoles\Coleco\ColecoVision.IDebuggable.cs">
|
||||
|
@ -517,7 +517,30 @@
|
|||
<Compile Include="Consoles\Nintendo\NES\iNES.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\INESPPUViewable.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.INESPPUViewable.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.IDebuggable.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.IDriveLight.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.IInputPollable.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.IMemoryDomains.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.INESPPUViewable.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.ISaveRam.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.ISettable.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.IStatable.cs">
|
||||
<DependentUpon>NES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\NES\NESControllers.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Palettes.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\PPU.cs" />
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : IDebuggable
|
||||
{
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new Dictionary<string, RegisterValue>
|
||||
{
|
||||
{ "A", cpu.A },
|
||||
{ "X", cpu.X },
|
||||
{ "Y", cpu.Y },
|
||||
{ "S", cpu.S },
|
||||
{ "PC", cpu.PC },
|
||||
{ "Flag C", cpu.FlagC },
|
||||
{ "Flag Z", cpu.FlagZ },
|
||||
{ "Flag I", cpu.FlagI },
|
||||
{ "Flag D", cpu.FlagD },
|
||||
{ "Flag B", cpu.FlagB },
|
||||
{ "Flag V", cpu.FlagV },
|
||||
{ "Flag N", cpu.FlagN },
|
||||
{ "Flag T", cpu.FlagT }
|
||||
};
|
||||
}
|
||||
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
switch (register)
|
||||
{
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
case "A":
|
||||
cpu.A = (byte)value;
|
||||
break;
|
||||
case "X":
|
||||
cpu.X = (byte)value;
|
||||
break;
|
||||
case "Y":
|
||||
cpu.Y = (byte)value;
|
||||
break;
|
||||
case "S":
|
||||
cpu.S = (byte)value;
|
||||
break;
|
||||
case "PC":
|
||||
cpu.PC = (ushort)value;
|
||||
break;
|
||||
case "Flag I":
|
||||
cpu.FlagI = value > 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanStep(StepType type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type) { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : IDriveLight
|
||||
{
|
||||
public bool DriveLightEnabled { get; private set; }
|
||||
|
||||
public bool DriveLightOn { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : IInputPollable
|
||||
{
|
||||
public int LagCount
|
||||
{
|
||||
get { return _lagcount; }
|
||||
set { _lagcount = value; }
|
||||
}
|
||||
|
||||
public bool IsLagFrame
|
||||
{
|
||||
get { return islag; }
|
||||
}
|
||||
|
||||
public IInputCallbackSystem InputCallbacks
|
||||
{
|
||||
get { return _inputCallbacks; }
|
||||
}
|
||||
|
||||
private int _lagcount;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
|
||||
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES
|
||||
{
|
||||
private MemoryDomainList _memoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>();
|
||||
var RAM = new MemoryDomain("RAM", 0x800, MemoryDomain.Endian.Little,
|
||||
addr => ram[addr], (addr, value) => ram[addr] = value);
|
||||
var SystemBus = new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little,
|
||||
addr => PeekMemory((ushort)addr), (addr, value) => ApplySystemBusPoke(addr, value));
|
||||
var PPUBus = new MemoryDomain("PPU Bus", 0x4000, MemoryDomain.Endian.Little,
|
||||
addr => ppu.ppubus_peek(addr), (addr, value) => ppu.ppubus_write(addr, value));
|
||||
var CIRAMdomain = new MemoryDomain("CIRAM (nametables)", 0x800, MemoryDomain.Endian.Little,
|
||||
addr => CIRAM[addr], (addr, value) => CIRAM[addr] = value);
|
||||
var OAMdoman = new MemoryDomain("OAM", 64 * 4, MemoryDomain.Endian.Unknown,
|
||||
addr => ppu.OAM[addr], (addr, value) => ppu.OAM[addr] = value);
|
||||
|
||||
domains.Add(RAM);
|
||||
domains.Add(SystemBus);
|
||||
domains.Add(PPUBus);
|
||||
domains.Add(CIRAMdomain);
|
||||
domains.Add(OAMdoman);
|
||||
|
||||
if (!(board is FDS) && board.SaveRam != null)
|
||||
{
|
||||
var BatteryRam = new MemoryDomain("Battery RAM", board.SaveRam.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.SaveRam[addr], (addr, value) => board.SaveRam[addr] = value);
|
||||
domains.Add(BatteryRam);
|
||||
}
|
||||
|
||||
var PRGROM = new MemoryDomain("PRG ROM", cart.prg_size * 1024, MemoryDomain.Endian.Little,
|
||||
addr => board.ROM[addr], (addr, value) => board.ROM[addr] = value);
|
||||
domains.Add(PRGROM);
|
||||
|
||||
if (board.VROM != null)
|
||||
{
|
||||
var CHRROM = new MemoryDomain("CHR VROM", cart.chr_size * 1024, MemoryDomain.Endian.Little,
|
||||
addr => board.VROM[addr], (addr, value) => board.VROM[addr] = value);
|
||||
domains.Add(CHRROM);
|
||||
}
|
||||
|
||||
if (board.VRAM != null)
|
||||
{
|
||||
var VRAM = new MemoryDomain("VRAM", board.VRAM.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.VRAM[addr], (addr, value) => board.VRAM[addr] = value);
|
||||
domains.Add(VRAM);
|
||||
}
|
||||
|
||||
if (board.WRAM != null)
|
||||
{
|
||||
var WRAM = new MemoryDomain("WRAM", board.WRAM.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.WRAM[addr], (addr, value) => board.WRAM[addr] = value);
|
||||
domains.Add(WRAM);
|
||||
}
|
||||
|
||||
// if there were more boards with special ram sets, we'd want to do something more general
|
||||
if (board is FDS)
|
||||
{
|
||||
domains.Add((board as FDS).GetDiskPeeker());
|
||||
}
|
||||
else if (board is ExROM)
|
||||
{
|
||||
domains.Add((board as ExROM).GetExRAM());
|
||||
}
|
||||
|
||||
_memoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(_memoryDomains);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,7 +84,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
|
||||
public MemoryDomain GetCHRROM()
|
||||
{
|
||||
return memoryDomains["CHR VROM"];
|
||||
return _memoryDomains["CHR VROM"];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : ISaveRam
|
||||
{
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get
|
||||
{
|
||||
if (board == null) return false;
|
||||
if (board is FDS) return true;
|
||||
if (board.SaveRam == null) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] CloneSaveRam()
|
||||
{
|
||||
if (board is FDS)
|
||||
return (board as FDS).ReadSaveRam();
|
||||
|
||||
if (board == null || board.SaveRam == null)
|
||||
return null;
|
||||
return (byte[])board.SaveRam.Clone();
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (board is FDS)
|
||||
{
|
||||
(board as FDS).StoreSaveRam(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (board == null || board.SaveRam == null)
|
||||
return;
|
||||
Array.Copy(data, board.SaveRam, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : IStatable
|
||||
{
|
||||
public NESSettings GetSettings()
|
||||
{
|
||||
return Settings.Clone();
|
||||
}
|
||||
|
||||
public NESSyncSettings GetSyncSettings()
|
||||
{
|
||||
return SyncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(NESSettings o)
|
||||
{
|
||||
Settings = o;
|
||||
if (Settings.ClipLeftAndRight)
|
||||
{
|
||||
videoProvider.left = 8;
|
||||
videoProvider.right = 247;
|
||||
}
|
||||
else
|
||||
{
|
||||
videoProvider.left = 0;
|
||||
videoProvider.right = 255;
|
||||
}
|
||||
|
||||
CoreComm.ScreenLogicalOffsetX = videoProvider.left;
|
||||
CoreComm.ScreenLogicalOffsetY = DisplayType == DisplayType.NTSC ? Settings.NTSC_TopLine : Settings.PAL_TopLine;
|
||||
|
||||
SetPalette(Settings.Palette);
|
||||
|
||||
apu.Square1V = Settings.Square1;
|
||||
apu.Square2V = Settings.Square2;
|
||||
apu.TriangleV = Settings.Triangle;
|
||||
apu.NoiseV = Settings.Noise;
|
||||
apu.DMCV = Settings.DMC;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(NESSyncSettings o)
|
||||
{
|
||||
bool ret = NESSyncSettings.NeedsReboot(SyncSettings, o);
|
||||
SyncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private NESSettings Settings = new NESSettings();
|
||||
private NESSyncSettings SyncSettings = new NESSyncSettings();
|
||||
|
||||
public class NESSyncSettings
|
||||
{
|
||||
public Dictionary<string, string> BoardProperties = new Dictionary<string, string>();
|
||||
|
||||
public enum Region
|
||||
{
|
||||
Default,
|
||||
NTSC,
|
||||
PAL,
|
||||
Dendy
|
||||
};
|
||||
|
||||
public Region RegionOverride = Region.Default;
|
||||
|
||||
public NESControlSettings Controls = new NESControlSettings();
|
||||
|
||||
public NESSyncSettings Clone()
|
||||
{
|
||||
var ret = (NESSyncSettings)MemberwiseClone();
|
||||
ret.BoardProperties = new Dictionary<string, string>(BoardProperties);
|
||||
ret.Controls = Controls.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(NESSyncSettings x, NESSyncSettings y)
|
||||
{
|
||||
return !(Util.DictionaryEqual(x.BoardProperties, y.BoardProperties) &&
|
||||
x.RegionOverride == y.RegionOverride &&
|
||||
!NESControlSettings.NeedsReboot(x.Controls, y.Controls));
|
||||
}
|
||||
}
|
||||
|
||||
public class NESSettings
|
||||
{
|
||||
public bool AllowMoreThanEightSprites = false;
|
||||
public bool ClipLeftAndRight = false;
|
||||
public bool DispBackground = true;
|
||||
public bool DispSprites = true;
|
||||
public int BackgroundColor = 0;
|
||||
|
||||
public int NTSC_TopLine = 8;
|
||||
public int NTSC_BottomLine = 231;
|
||||
public int PAL_TopLine = 0;
|
||||
public int PAL_BottomLine = 239;
|
||||
|
||||
public int[,] Palette;
|
||||
|
||||
public int Square1 = 376;
|
||||
public int Square2 = 376;
|
||||
public int Triangle = 426;
|
||||
public int Noise = 247;
|
||||
public int DMC = 167;
|
||||
|
||||
public NESSettings Clone()
|
||||
{
|
||||
var ret = (NESSettings)MemberwiseClone();
|
||||
ret.Palette = (int[,])ret.Palette.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public NESSettings()
|
||||
{
|
||||
Palette = (int[,])Palettes.QuickNESPalette.Clone();
|
||||
}
|
||||
|
||||
[Newtonsoft.Json.JsonConstructor]
|
||||
public NESSettings(int[,] Palette)
|
||||
{
|
||||
if (Palette == null)
|
||||
// only needed for SVN purposes
|
||||
this.Palette = (int[,])Palettes.QuickNESPalette.Clone();
|
||||
else
|
||||
this.Palette = Palette;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public partial class NES : IStatable
|
||||
{
|
||||
public bool BinarySaveStatesPreferred
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
SyncState(Serializer.CreateTextWriter(writer));
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
SyncState(Serializer.CreateTextReader(reader));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
SyncState(Serializer.CreateBinaryWriter(bw));
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
{
|
||||
SyncState(Serializer.CreateBinaryReader(br));
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
int version = 4;
|
||||
ser.BeginSection("NES");
|
||||
ser.Sync("version", ref version);
|
||||
ser.Sync("Frame", ref _frame);
|
||||
ser.Sync("Lag", ref _lagcount);
|
||||
ser.Sync("IsLag", ref islag);
|
||||
cpu.SyncState(ser);
|
||||
ser.Sync("ram", ref ram, false);
|
||||
ser.Sync("CIRAM", ref CIRAM, false);
|
||||
ser.Sync("cpu_accumulate", ref cpu_accumulate);
|
||||
ser.Sync("_irq_apu", ref _irq_apu);
|
||||
ser.Sync("sprdma_countdown", ref sprdma_countdown);
|
||||
ser.Sync("cpu_step", ref cpu_step);
|
||||
ser.Sync("cpu_stepcounter", ref cpu_stepcounter);
|
||||
ser.Sync("cpu_deadcounter", ref cpu_deadcounter);
|
||||
ser.BeginSection("Board");
|
||||
board.SyncState(ser);
|
||||
if (board is NESBoardBase && !((NESBoardBase)board).SyncStateFlag)
|
||||
throw new InvalidOperationException("the current NES mapper didnt call base.SyncState");
|
||||
ser.EndSection();
|
||||
ppu.SyncState(ser);
|
||||
apu.SyncState(ser);
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
ser.Sync("DB", ref DB);
|
||||
}
|
||||
if (version >= 3)
|
||||
{
|
||||
ser.Sync("latched4016", ref latched4016);
|
||||
ser.BeginSection("ControllerDeck");
|
||||
ControllerDeck.SyncState(ser);
|
||||
ser.EndSection();
|
||||
}
|
||||
if (version >= 4)
|
||||
{
|
||||
ser.Sync("resetSignal", ref resetSignal);
|
||||
ser.Sync("hardResetSignal", ref hardResetSignal);
|
||||
}
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,9 +76,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
BootGodDB.Initialize();
|
||||
}
|
||||
|
||||
public bool DriveLightEnabled { get; private set; }
|
||||
public bool DriveLightOn { get; private set; }
|
||||
|
||||
public void WriteLogTimestamp()
|
||||
{
|
||||
if (ppu != null)
|
||||
|
@ -329,9 +326,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
|
||||
int _frame;
|
||||
int _lagcount;
|
||||
bool lagged = true;
|
||||
bool islag = false;
|
||||
|
||||
public int Frame { get { return _frame; } set { _frame = value; } }
|
||||
|
||||
public void ResetCounters()
|
||||
|
@ -342,111 +337,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
|
||||
public long Timestamp { get; private set; }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
|
||||
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
|
||||
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
|
||||
|
||||
public bool DeterministicEmulation { get { return true; } }
|
||||
|
||||
public byte[] CloneSaveRam()
|
||||
{
|
||||
if (board is FDS)
|
||||
return (board as FDS).ReadSaveRam();
|
||||
|
||||
if (board == null || board.SaveRam == null)
|
||||
return null;
|
||||
return (byte[])board.SaveRam.Clone();
|
||||
}
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if (board is FDS)
|
||||
{
|
||||
(board as FDS).StoreSaveRam(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (board == null || board.SaveRam == null)
|
||||
return;
|
||||
Array.Copy(data, board.SaveRam, data.Length);
|
||||
}
|
||||
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get
|
||||
{
|
||||
if (board == null) return false;
|
||||
if (board is FDS) return true;
|
||||
if (board.SaveRam == null) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private MemoryDomainList memoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>();
|
||||
var RAM = new MemoryDomain("RAM", 0x800, MemoryDomain.Endian.Little,
|
||||
addr => ram[addr], (addr, value) => ram[addr] = value);
|
||||
var SystemBus = new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little,
|
||||
addr => PeekMemory((ushort)addr), (addr, value) => ApplySystemBusPoke(addr, value));
|
||||
var PPUBus = new MemoryDomain("PPU Bus", 0x4000, MemoryDomain.Endian.Little,
|
||||
addr => ppu.ppubus_peek(addr), (addr, value) => ppu.ppubus_write(addr, value));
|
||||
var CIRAMdomain = new MemoryDomain("CIRAM (nametables)", 0x800, MemoryDomain.Endian.Little,
|
||||
addr => CIRAM[addr], (addr, value) => CIRAM[addr] = value);
|
||||
var OAMdoman = new MemoryDomain("OAM", 64 * 4, MemoryDomain.Endian.Unknown,
|
||||
addr => ppu.OAM[addr], (addr, value) => ppu.OAM[addr] = value);
|
||||
|
||||
domains.Add(RAM);
|
||||
domains.Add(SystemBus);
|
||||
domains.Add(PPUBus);
|
||||
domains.Add(CIRAMdomain);
|
||||
domains.Add(OAMdoman);
|
||||
|
||||
if (!(board is FDS) && board.SaveRam != null)
|
||||
{
|
||||
var BatteryRam = new MemoryDomain("Battery RAM", board.SaveRam.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.SaveRam[addr], (addr, value) => board.SaveRam[addr] = value);
|
||||
domains.Add(BatteryRam);
|
||||
}
|
||||
|
||||
var PRGROM = new MemoryDomain("PRG ROM", cart.prg_size * 1024, MemoryDomain.Endian.Little,
|
||||
addr => board.ROM[addr], (addr, value) => board.ROM[addr] = value);
|
||||
domains.Add(PRGROM);
|
||||
|
||||
if (board.VROM != null)
|
||||
{
|
||||
var CHRROM = new MemoryDomain("CHR VROM", cart.chr_size * 1024, MemoryDomain.Endian.Little,
|
||||
addr => board.VROM[addr], (addr, value) => board.VROM[addr] = value);
|
||||
domains.Add(CHRROM);
|
||||
}
|
||||
|
||||
if (board.VRAM != null)
|
||||
{
|
||||
var VRAM = new MemoryDomain("VRAM", board.VRAM.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.VRAM[addr], (addr, value) => board.VRAM[addr] = value);
|
||||
domains.Add(VRAM);
|
||||
}
|
||||
|
||||
if (board.WRAM != null)
|
||||
{
|
||||
var WRAM = new MemoryDomain("WRAM", board.WRAM.Length, MemoryDomain.Endian.Little,
|
||||
addr => board.WRAM[addr], (addr, value) => board.WRAM[addr] = value);
|
||||
domains.Add(WRAM);
|
||||
}
|
||||
|
||||
// if there were more boards with special ram sets, we'd want to do something more general
|
||||
if (board is FDS)
|
||||
domains.Add((board as FDS).GetDiskPeeker());
|
||||
else if (board is ExROM)
|
||||
domains.Add((board as ExROM).GetExRAM());
|
||||
|
||||
memoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(memoryDomains);
|
||||
}
|
||||
|
||||
public string SystemId { get { return "NES"; } }
|
||||
|
||||
public string GameName { get { return game_name; } }
|
||||
|
@ -842,235 +735,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
}
|
||||
|
||||
void SyncState(Serializer ser)
|
||||
{
|
||||
int version = 4;
|
||||
ser.BeginSection("NES");
|
||||
ser.Sync("version", ref version);
|
||||
ser.Sync("Frame", ref _frame);
|
||||
ser.Sync("Lag", ref _lagcount);
|
||||
ser.Sync("IsLag", ref islag);
|
||||
cpu.SyncState(ser);
|
||||
ser.Sync("ram", ref ram, false);
|
||||
ser.Sync("CIRAM", ref CIRAM, false);
|
||||
ser.Sync("cpu_accumulate", ref cpu_accumulate);
|
||||
ser.Sync("_irq_apu", ref _irq_apu);
|
||||
ser.Sync("sprdma_countdown", ref sprdma_countdown);
|
||||
ser.Sync("cpu_step", ref cpu_step);
|
||||
ser.Sync("cpu_stepcounter", ref cpu_stepcounter);
|
||||
ser.Sync("cpu_deadcounter", ref cpu_deadcounter);
|
||||
ser.BeginSection("Board");
|
||||
board.SyncState(ser);
|
||||
if (board is NESBoardBase && !((NESBoardBase)board).SyncStateFlag)
|
||||
throw new InvalidOperationException("the current NES mapper didnt call base.SyncState");
|
||||
ser.EndSection();
|
||||
ppu.SyncState(ser);
|
||||
apu.SyncState(ser);
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
ser.Sync("DB", ref DB);
|
||||
}
|
||||
if (version >= 3)
|
||||
{
|
||||
ser.Sync("latched4016", ref latched4016);
|
||||
ser.BeginSection("ControllerDeck");
|
||||
ControllerDeck.SyncState(ser);
|
||||
ser.EndSection();
|
||||
}
|
||||
if (version >= 4)
|
||||
{
|
||||
ser.Sync("resetSignal", ref resetSignal);
|
||||
ser.Sync("hardResetSignal", ref hardResetSignal);
|
||||
}
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); }
|
||||
public void LoadStateText(TextReader reader) { SyncState(Serializer.CreateTextReader(reader)); }
|
||||
public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); }
|
||||
public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); }
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public bool BinarySaveStatesPreferred { get { return false; } }
|
||||
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new Dictionary<string, RegisterValue>
|
||||
{
|
||||
{ "A", cpu.A },
|
||||
{ "X", cpu.X },
|
||||
{ "Y", cpu.Y },
|
||||
{ "S", cpu.S },
|
||||
{ "PC", cpu.PC },
|
||||
{ "Flag C", cpu.FlagC },
|
||||
{ "Flag Z", cpu.FlagZ },
|
||||
{ "Flag I", cpu.FlagI },
|
||||
{ "Flag D", cpu.FlagD },
|
||||
{ "Flag B", cpu.FlagB },
|
||||
{ "Flag V", cpu.FlagV },
|
||||
{ "Flag N", cpu.FlagN },
|
||||
{ "Flag T", cpu.FlagT }
|
||||
};
|
||||
}
|
||||
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
switch (register)
|
||||
{
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
case "A":
|
||||
cpu.A = (byte)value;
|
||||
break;
|
||||
case "X":
|
||||
cpu.X = (byte)value;
|
||||
break;
|
||||
case "Y":
|
||||
cpu.Y = (byte)value;
|
||||
break;
|
||||
case "S":
|
||||
cpu.S = (byte)value;
|
||||
break;
|
||||
case "PC":
|
||||
cpu.PC = (ushort)value;
|
||||
break;
|
||||
case "Flag I":
|
||||
cpu.FlagI = value > 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanStep(StepType type) { return false; }
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type) { throw new NotImplementedException(); }
|
||||
|
||||
private ITraceable Tracer { get; set; }
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
|
||||
|
||||
NESSettings Settings = new NESSettings();
|
||||
NESSyncSettings SyncSettings = new NESSyncSettings();
|
||||
|
||||
public NESSettings GetSettings() { return Settings.Clone(); }
|
||||
public NESSyncSettings GetSyncSettings() { return SyncSettings.Clone(); }
|
||||
public bool PutSettings(NESSettings o)
|
||||
{
|
||||
Settings = o;
|
||||
if (Settings.ClipLeftAndRight)
|
||||
{
|
||||
videoProvider.left = 8;
|
||||
videoProvider.right = 247;
|
||||
}
|
||||
else
|
||||
{
|
||||
videoProvider.left = 0;
|
||||
videoProvider.right = 255;
|
||||
}
|
||||
CoreComm.ScreenLogicalOffsetX = videoProvider.left;
|
||||
CoreComm.ScreenLogicalOffsetY = DisplayType == DisplayType.NTSC ? Settings.NTSC_TopLine : Settings.PAL_TopLine;
|
||||
|
||||
SetPalette(Settings.Palette);
|
||||
|
||||
apu.Square1V = Settings.Square1;
|
||||
apu.Square2V = Settings.Square2;
|
||||
apu.TriangleV = Settings.Triangle;
|
||||
apu.NoiseV = Settings.Noise;
|
||||
apu.DMCV = Settings.DMC;
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool PutSyncSettings(NESSyncSettings o)
|
||||
{
|
||||
bool ret = NESSyncSettings.NeedsReboot(SyncSettings, o);
|
||||
SyncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public class NESSettings
|
||||
{
|
||||
public bool AllowMoreThanEightSprites = false;
|
||||
public bool ClipLeftAndRight = false;
|
||||
public bool DispBackground = true;
|
||||
public bool DispSprites = true;
|
||||
public int BackgroundColor = 0;
|
||||
|
||||
public int NTSC_TopLine = 8;
|
||||
public int NTSC_BottomLine = 231;
|
||||
public int PAL_TopLine = 0;
|
||||
public int PAL_BottomLine = 239;
|
||||
|
||||
public int[,] Palette;
|
||||
|
||||
public int Square1 = 376;
|
||||
public int Square2 = 376;
|
||||
public int Triangle = 426;
|
||||
public int Noise = 247;
|
||||
public int DMC = 167;
|
||||
|
||||
public NESSettings Clone()
|
||||
{
|
||||
var ret = (NESSettings)MemberwiseClone();
|
||||
ret.Palette = (int[,])ret.Palette.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public NESSettings()
|
||||
{
|
||||
Palette = (int[,])Palettes.QuickNESPalette.Clone();
|
||||
}
|
||||
|
||||
[Newtonsoft.Json.JsonConstructor]
|
||||
public NESSettings(int[,] Palette)
|
||||
{
|
||||
if (Palette == null)
|
||||
// only needed for SVN purposes
|
||||
this.Palette = (int[,])Palettes.QuickNESPalette.Clone();
|
||||
else
|
||||
this.Palette = Palette;
|
||||
}
|
||||
}
|
||||
|
||||
public class NESSyncSettings
|
||||
{
|
||||
public Dictionary<string, string> BoardProperties = new Dictionary<string, string>();
|
||||
|
||||
public enum Region
|
||||
{
|
||||
Default,
|
||||
NTSC,
|
||||
PAL,
|
||||
Dendy
|
||||
};
|
||||
|
||||
public Region RegionOverride = Region.Default;
|
||||
|
||||
public NESControlSettings Controls = new NESControlSettings();
|
||||
|
||||
public NESSyncSettings Clone()
|
||||
{
|
||||
var ret = (NESSyncSettings)MemberwiseClone();
|
||||
ret.BoardProperties = new Dictionary<string, string>(BoardProperties);
|
||||
ret.Controls = Controls.Clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(NESSyncSettings x, NESSyncSettings y)
|
||||
{
|
||||
return !(Util.DictionaryEqual(x.BoardProperties, y.BoardProperties) &&
|
||||
x.RegionOverride == y.RegionOverride &&
|
||||
!NESControlSettings.NeedsReboot(x.Controls, y.Controls));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue