subneshawk - delete a bunch of code by using the underlying core for services, cleanup, and implement some services that were missing

This commit is contained in:
adelikat 2020-02-18 13:16:29 -06:00
parent 4d4496af0d
commit dedd618db4
10 changed files with 85 additions and 476 deletions

View File

@ -31,7 +31,7 @@ namespace BizHawk.Client.EmuHawk
else if (core is SubNESHawk subNesHawk)
{
ss = subNesHawk.GetSyncSettings();
isFds = subNesHawk.IsFDS;
isFds = subNesHawk.IsFds;
fdsButtonCount = subNesHawk.ControllerDefinition.BoolButtons.Count(b => b.StartsWith("FDS Insert "));
}

View File

@ -293,7 +293,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
_controller = controller;
if (Tracer.Enabled)
cpu.TraceCallback = (s) => Tracer.Put(s);
cpu.TraceCallback = s => Tracer.Put(s);
else
cpu.TraceCallback = null;

View File

@ -8,15 +8,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
public partial class NES : ISettable<NES.NESSettings, NES.NESSyncSettings>
{
public NESSettings GetSettings()
{
return Settings.Clone();
}
public NESSettings GetSettings() => Settings.Clone();
public NESSyncSettings GetSyncSettings()
{
return SyncSettings.Clone();
}
public NESSyncSettings GetSyncSettings() => SyncSettings.Clone();
public bool PutSettings(NESSettings o)
{

View File

@ -67,12 +67,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
LoadStateCallback = SetupMemoryDomains
});
if (Board is BANDAI_FCG_1)
if (Board is BANDAI_FCG_1 bandai)
{
var reader = (Board as BANDAI_FCG_1).reader;
var reader = bandai.reader;
// not all BANDAI FCG 1 boards have a barcode reader
if (reader != null)
ser.Register<DatachBarcode>(reader);
{
ser.Register(reader);
}
}
}

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IDebuggable
{
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters() => subnes.GetCpuFlagsAndRegisters();
public void SetCpuRegister(string register, int value) => subnes.SetCpuRegister(register, value);
public bool CanStep(StepType type) => false;
public IMemoryCallbackSystem MemoryCallbacks => subnes.MemoryCallbacks;
[FeatureNotImplemented]
public void Step(StepType type) => throw new NotImplementedException();
public long TotalExecutedCycles => subnes.cpu.TotalExecutedCycles;
}
}

View File

@ -7,18 +7,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition => subnes.ControllerDefinition;
public ControllerDefinition ControllerDefinition => _nesCore.ControllerDefinition;
public bool FrameAdvance(IController controller, bool render, bool renderSound)
{
//Console.WriteLine("-----------------------FRAME-----------------------");
if (_tracer.Enabled)
{
subnes.cpu.TraceCallback = s => _tracer.Put(s);
_nesCore.cpu.TraceCallback = s => _tracer.Put(s);
}
else
{
subnes.cpu.TraceCallback = null;
_nesCore.cpu.TraceCallback = null;
}
_frame++;
@ -38,22 +38,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
reset_cycle_int = (int)Math.Floor(reset_cycle);
_isLag = true;
subnes.alt_lag = true;
_nesCore.alt_lag = true;
InputCallbacks.Call();
do_frame(controller);
DoFrame(controller);
bool ret = pass_a_frame;
if (pass_a_frame)
{
subnes.videoProvider.FillFrameBuffer();
_nesCore.videoProvider.FillFrameBuffer();
current_cycle = 0;
subnes.cpu.ext_ppu_cycle = current_cycle;
_nesCore.cpu.ext_ppu_cycle = current_cycle;
}
_isLag = subnes.alt_lag;
_isLag = _nesCore.alt_lag;
if (_isLag)
{
@ -65,15 +65,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
return ret;
}
public bool stop_cur_frame;
public bool pass_new_input;
public bool pass_a_frame;
public bool reset_frame;
public int current_cycle;
public float reset_cycle;
public int reset_cycle_int;
private bool stop_cur_frame;
private bool pass_new_input;
private bool pass_a_frame;
private bool reset_frame;
private int current_cycle;
private float reset_cycle;
private int reset_cycle_int;
public void do_frame(IController controller)
private void DoFrame(IController controller)
{
stop_cur_frame = false;
while (!stop_cur_frame)
@ -83,9 +83,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
SoftReset();
reset_frame = false;
}
subnes.do_single_step(controller, out pass_new_input, out pass_a_frame);
_nesCore.do_single_step(controller, out pass_new_input, out pass_a_frame);
current_cycle++;
subnes.cpu.ext_ppu_cycle = current_cycle;
_nesCore.cpu.ext_ppu_cycle = current_cycle;
stop_cur_frame |= pass_a_frame;
stop_cur_frame |= pass_new_input;
}
@ -95,7 +95,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
public string SystemId => "NES";
public bool DeterministicEmulation { get; set; }
public bool DeterministicEmulation => _nesCore.DeterministicEmulation;
public void ResetCounters()
{
@ -104,116 +104,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
_isLag = false;
}
public CoreComm CoreComm { get; }
public CoreComm CoreComm => _nesCore.CoreComm;
public void Dispose()
{
subnes.Dispose();
}
/*
#region Video provider
public int _frameHz = 60;
public int[] _vidbuffer = new int[160 * 2 * 144];
public int[] buff_L = new int[160 * 144];
public int[] buff_R = new int[160 * 144];
public int[] GetVideoBuffer()
{
// combine the 2 video buffers from the instances
for (int i = 0; i < 144; i++)
{
for (int j = 0; j < 160; j++)
{
_vidbuffer[i * 320 + j] = buff_L[i * 160 + j];
_vidbuffer[i * 320 + j + 160] = buff_R[i * 160 + j];
}
}
return _vidbuffer;
}
public int VirtualWidth => 160 * 2;
public int VirtualHeight => 144;
public int BufferWidth => 160 * 2;
public int BufferHeight => 144;
public int BackgroundColor => unchecked((int)0xFF000000);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;
public static readonly uint[] color_palette_BW = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 };
public static readonly uint[] color_palette_Gr = { 0xFFA4C505, 0xFF88A905, 0xFF1D551D, 0xFF052505 };
public uint[] color_palette = new uint[4];
#endregion
#region audio
public bool CanProvideAsync => false;
public void SetSyncMode(SyncSoundMode mode)
{
if (mode != SyncSoundMode.Sync)
{
throw new InvalidOperationException("Only Sync mode is supported_");
}
}
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
public void GetSamplesSync(out short[] samples, out int nsamp)
{
short[] temp_samp_L;
short[] temp_samp_R;
int nsamp_L;
int nsamp_R;
L.audio.GetSamplesSync(out temp_samp_L, out nsamp_L);
R.audio.GetSamplesSync(out temp_samp_R, out nsamp_R);
if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Left)
{
samples = temp_samp_L;
nsamp = nsamp_L;
}
else if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Right)
{
samples = temp_samp_R;
nsamp = nsamp_R;
}
else
{
samples = new short[0];
nsamp = 0;
}
}
public void GetSamplesAsync(short[] samples)
{
throw new NotSupportedException("Async is not available");
}
public void DiscardSamples()
{
L.audio.DiscardSamples();
R.audio.DiscardSamples();
}
private void GetSamples(short[] samples)
{
}
public void DisposeSound()
{
L.audio.DisposeSound();
R.audio.DisposeSound();
}
#endregion
*/
public void Dispose() => _nesCore.Dispose();
}
}

View File

@ -1,81 +0,0 @@
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk
{
private MemoryDomainList _memoryDomains;
private bool _memoryDomainsSetup = false;
private void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>();
var RAM = new MemoryDomainByteArray("RAM", MemoryDomain.Endian.Little, subnes.ram, true, 1);
var SystemBus = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
addr => subnes.PeekMemory((ushort)addr), (addr, value) => subnes.ApplySystemBusPoke((int)addr, value), 1);
var PPUBus = new MemoryDomainDelegate("PPU Bus", 0x4000, MemoryDomain.Endian.Little,
addr => subnes.ppu.ppubus_peek((int)addr), (addr, value) => subnes.ppu.ppubus_write((int)addr, value), 1);
var CIRAMdomain = new MemoryDomainByteArray("CIRAM (nametables)", MemoryDomain.Endian.Little, subnes.CIRAM, true, 1);
var OAMdoman = new MemoryDomainByteArray("OAM", MemoryDomain.Endian.Unknown, subnes.ppu.OAM, true, 1);
domains.Add(RAM);
domains.Add(SystemBus);
domains.Add(PPUBus);
domains.Add(CIRAMdomain);
domains.Add(OAMdoman);
if (!(subnes.Board is NES.FDS) && subnes.Board.SaveRam != null)
{
var BatteryRam = new MemoryDomainByteArray("Battery RAM", MemoryDomain.Endian.Little, subnes.Board.SaveRam, true, 1);
domains.Add(BatteryRam);
}
if (subnes.Board.ROM != null)
{
var PRGROM = new MemoryDomainByteArray("PRG ROM", MemoryDomain.Endian.Little, subnes.Board.ROM, true, 1);
domains.Add(PRGROM);
}
if (subnes.Board.VROM != null)
{
var CHRROM = new MemoryDomainByteArray("CHR VROM", MemoryDomain.Endian.Little, subnes.Board.VROM, true, 1);
domains.Add(CHRROM);
}
if (subnes.Board.VRAM != null)
{
var VRAM = new MemoryDomainByteArray("VRAM", MemoryDomain.Endian.Little, subnes.Board.VRAM, true, 1);
domains.Add(VRAM);
}
if (subnes.Board.WRAM != null)
{
var WRAM = new MemoryDomainByteArray("WRAM", MemoryDomain.Endian.Little, subnes.Board.WRAM, true, 1);
domains.Add(WRAM);
}
// if there were more boards with special ram sets, we'd want to do something more general
if (subnes.Board is NES.FDS)
{
domains.Add((subnes.Board as NES.FDS).GetDiskPeeker());
}
else if (subnes.Board is NES.ExROM)
{
domains.Add((subnes.Board as NES.ExROM).GetExRAM());
}
if (!_memoryDomainsSetup)
{
_memoryDomains = new MemoryDomainList(domains);
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(_memoryDomains);
_memoryDomainsSetup = true;
}
else
{
var src = new MemoryDomainList(domains);
_memoryDomains.MergeList(src);
}
}
}
}

View File

@ -1,45 +0,0 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : ISaveRam
{
public bool SaveRamModified
{
get
{
if (subnes.Board == null) return false;
if (subnes.Board is NES.FDS) return true;
if (subnes.Board.SaveRam == null) return false;
return true;
}
}
public byte[] CloneSaveRam()
{
if (subnes.Board is NES.FDS fds)
{
return fds.ReadSaveRam();
}
return (byte[]) subnes.Board?.SaveRam?.Clone();
}
public void StoreSaveRam(byte[] data)
{
if (subnes.Board is NES.FDS fds)
{
fds.StoreSaveRam(data);
return;
}
if (subnes.Board?.SaveRam == null)
{
return;
}
Array.Copy(data, subnes.Board.SaveRam, data.Length);
}
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Linq;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
@ -11,214 +8,85 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
"",
isPorted: false,
isReleased: true)]
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
public partial class SubNESHawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable,
IBoardInfo, ISettable<NES.NES.NESSettings, NES.NES.NESSyncSettings>, INESPPUViewable
[ServiceNotApplicable(new [] { typeof(IDriveLight) })]
public partial class SubNESHawk : IEmulator, IStatable, IInputPollable,
ISettable<NES.NES.NESSettings, NES.NES.NESSyncSettings>
{
public NES.NES subnes;
// needed for movies to accurately calculate timing
public int VBL_CNT;
[CoreConstructor("NES")]
public SubNESHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings)
{
var ser = new BasicServiceProvider(this);
subnesSettings = (NES.NES.NESSettings)settings ?? new NES.NES.NESSettings();
subnesSyncSettings = (NES.NES.NESSyncSettings)syncSettings ?? new NES.NES.NESSyncSettings();
var subNesSettings = (NES.NES.NESSettings)settings ?? new NES.NES.NESSettings();
var subNesSyncSettings = (NES.NES.NESSyncSettings)syncSettings ?? new NES.NES.NESSyncSettings();
CoreComm = comm;
_nesCore = new NES.NES(new CoreComm(comm.ShowMessage, comm.Notify) {CoreFileProvider = comm.CoreFileProvider},
game, rom, subNesSettings, subNesSyncSettings)
{
using_reset_timing = true
};
subnes = new NES.NES(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider },
game, rom, subnesSettings, subnesSyncSettings);
ser.Register<IVideoProvider>(subnes.videoProvider);
ser.Register<ISoundProvider>(subnes);
_tracer = new TraceBuffer { Header = "6502: PC, machine code, mnemonic, operands, registers (A, X, Y, P, SP), flags (NVTBDIZCR), CPU Cycle, PPU Cycle" };
ser.Register<ITraceable>(_tracer);
ser.Register<IDisassemblable>(subnes.cpu);
ServiceProvider = ser;
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(subnes._memoryDomains);
subnes.using_reset_timing = true;
HardReset();
current_cycle = 0;
subnes.cpu.ext_ppu_cycle = current_cycle;
_nesCore.cpu.ext_ppu_cycle = current_cycle;
VBL_CNT = 0;
_nesStatable = subnes.ServiceProvider.GetService<IStatable>();
_nesStatable = _nesCore.ServiceProvider.GetService<IStatable>();
var barCodeService = subnes.ServiceProvider.GetService<DatachBarcode>();
var ser = new BasicServiceProvider(this);
ServiceProvider = ser;
ser.Register(_nesCore.ServiceProvider.GetService<IVideoProvider>());
ser.Register(_nesCore.ServiceProvider.GetService<ISoundProvider>());
ser.Register(_nesCore.ServiceProvider.GetService<ITraceable>());
ser.Register(_nesCore.ServiceProvider.GetService<IDisassemblable>());
ser.Register(_nesCore.ServiceProvider.GetService<IMemoryDomains>());
ser.Register(_nesCore.ServiceProvider.GetService<INESPPUViewable>());
ser.Register(_nesCore.ServiceProvider.GetService<IBoardInfo>());
ser.Register(_nesCore.ServiceProvider.GetService<ISaveRam>());
ser.Register(_nesCore.ServiceProvider.GetService<IDebuggable>());
ser.Register(_nesCore.ServiceProvider.GetService<IRegionable>());
ser.Register(_nesCore.ServiceProvider.GetService<ICodeDataLogger>());
_tracer = new TraceBuffer { Header = "6502: PC, machine code, mnemonic, operands, registers (A, X, Y, P, SP), flags (NVTBDIZCR), CPU Cycle, PPU Cycle" };
ser.Register(_tracer);
var barCodeService = _nesCore.ServiceProvider.GetService<DatachBarcode>();
if (barCodeService != null)
{
ser.Register(barCodeService);
}
}
public void HardReset() => subnes.HardReset();
private readonly NES.NES _nesCore;
public void SoftReset()
// needed for movies to accurately calculate timing
public int VBL_CNT;
public void HardReset() => _nesCore.HardReset();
private void SoftReset()
{
subnes.Board.NESSoftReset();
subnes.cpu.NESSoftReset();
subnes.apu.NESSoftReset();
subnes.ppu.NESSoftReset();
_nesCore.Board.NESSoftReset();
_nesCore.cpu.NESSoftReset();
_nesCore.apu.NESSoftReset();
_nesCore.ppu.NESSoftReset();
current_cycle = 0;
subnes.cpu.ext_ppu_cycle = current_cycle;
_nesCore.cpu.ext_ppu_cycle = current_cycle;
}
public DisplayType Region => DisplayType.NTSC;
private int _frame;
public int _frame = 0;
public bool IsFds => _nesCore.IsFDS;
public bool IsFDS => subnes.IsFDS;
public bool IsVs => subnes.IsVS;
public bool HasMapperProperties
{
get
{
var fields = subnes.Board.GetType().GetFields();
foreach (var field in fields)
{
var attrib = field.GetCustomAttributes(typeof(MapperPropAttribute), false).OfType<MapperPropAttribute>().SingleOrDefault();
if (attrib != null)
{
return true;
}
}
return false;
}
}
public bool IsVs => _nesCore.IsVS;
private readonly ITraceable _tracer;
public bool HasMapperProperties => _nesCore.HasMapperProperties;
public string BoardName => subnes.Board.GetType().Name;
#region ISettable
private NES.NES.NESSettings subnesSettings = new NES.NES.NESSettings();
public NES.NES.NESSyncSettings subnesSyncSettings = new NES.NES.NESSyncSettings();
public NES.NES.NESSettings GetSettings()
{
return subnesSettings.Clone();
}
public NES.NES.NESSyncSettings GetSyncSettings()
{
return subnesSyncSettings.Clone();
}
public bool PutSettings(NES.NES.NESSettings o)
{
subnesSettings = o;
if (subnesSettings.ClipLeftAndRight)
{
subnes.videoProvider.left = 8;
subnes.videoProvider.right = 247;
}
else
{
subnes.videoProvider.left = 0;
subnes.videoProvider.right = 255;
}
CoreComm.ScreenLogicalOffsetX = subnes.videoProvider.left;
CoreComm.ScreenLogicalOffsetY = Region == DisplayType.NTSC ? subnesSettings.NTSC_TopLine : subnesSettings.PAL_TopLine;
subnes.SetPalette(subnesSettings.Palette);
subnes.apu.m_vol = subnesSettings.APU_vol;
return false;
}
public bool PutSyncSettings(NES.NES.NESSyncSettings o)
{
bool ret = NES.NES.NESSyncSettings.NeedsReboot(subnesSyncSettings, o);
subnesSyncSettings = o;
return ret;
}
#endregion
#region PPU Viewable
public int[] GetPalette()
{
return subnes.palette_compiled;
}
public bool BGBaseHigh => subnes.ppu.reg_2000.bg_pattern_hi;
public bool SPBaseHigh => subnes.ppu.reg_2000.obj_pattern_hi;
public bool SPTall => subnes.ppu.reg_2000.obj_size_16;
public byte[] GetPPUBus()
{
byte[] ret = new byte[0x3000];
for (int i = 0; i < 0x3000; i++)
{
ret[i] = subnes.ppu.ppubus_peek(i);
}
return ret;
}
public byte[] GetPalRam() => subnes.ppu.PALRAM;
public byte[] GetOam() => subnes.ppu.OAM;
public byte PeekPPU(int addr) => subnes.Board.PeekPPU(addr);
public byte[] GetExTiles()
{
if (subnes.Board is ExROM)
{
return subnes.Board.VROM ?? subnes.Board.VRAM;
}
throw new InvalidOperationException();
}
public bool ExActive => subnes.Board is ExROM && (subnes.Board as ExROM).ExAttrActive;
public byte[] GetExRam()
{
if (subnes.Board is ExROM)
{
return (subnes.Board as ExROM).GetExRAMArray();
}
throw new InvalidOperationException();
}
public MemoryDomain GetCHRROM() => _memoryDomains["CHR VROM"];
public void InstallCallback1(Action cb, int sl)
{
subnes.ppu.NTViewCallback = new PPU.DebugCallback { Callback = cb, Scanline = sl };
}
public void InstallCallback2(Action cb, int sl)
{
subnes.ppu.PPUViewCallback = new PPU.DebugCallback { Callback = cb, Scanline = sl };
}
public void RemoveCallback1()
{
subnes.ppu.NTViewCallback = null;
}
public void RemoveCallback2()
{
subnes.ppu.PPUViewCallback = null;
}
#endregion
public NES.NES.NESSettings GetSettings() => _nesCore.GetSettings();
public NES.NES.NESSyncSettings GetSyncSettings() => _nesCore.GetSyncSettings();
public bool PutSettings(NES.NES.NESSettings o) => _nesCore.PutSettings(o);
public bool PutSyncSettings(NES.NES.NESSyncSettings o) => _nesCore.PutSyncSettings(o);
}
}

View File

@ -202,6 +202,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=avisynth/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=backbuffer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=backcolor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bandai/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bankswitched/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bankswitching/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bezier/@EntryIndexedValue">True</s:Boolean>