From 618f5de54ffbc436dd36d8d773d93b7a42a5a790 Mon Sep 17 00:00:00 2001 From: adelikat Date: Mon, 12 Dec 2016 10:23:07 -0600 Subject: [PATCH] PC Engine - break off services into their separate files --- .../BizHawk.Emulation.Common.csproj | 1 + .../BizHawk.Emulation.Cores.csproj | 30 +- ...Mapping.cs => PCEngine.ICodeDataLogger.cs} | 54 +- .../PC Engine/PCEngine.IDebuggable.cs | 43 ++ .../PC Engine/PCEngine.IDriveLight.cs | 11 + .../Consoles/PC Engine/PCEngine.IEmulator.cs | 84 +++ .../PC Engine/PCEngine.IInputPollable.cs | 29 + .../PC Engine/PCEngine.IMemoryDomains.cs | 103 ++++ .../Consoles/PC Engine/PCEngine.ISaveRam.cs | 30 ++ .../Consoles/PC Engine/PCEngine.ISettable.cs | 100 ++++ .../Consoles/PC Engine/PCEngine.IStatable.cs | 123 +++++ .../Consoles/PC Engine/PCEngine.Input.cs | 5 +- .../Consoles/PC Engine/PCEngine.cs | 510 +++--------------- .../Consoles/PC Engine/VDC.Render.cs | 4 +- .../Consoles/PC Engine/VPC.cs | 16 +- 15 files changed, 671 insertions(+), 472 deletions(-) rename BizHawk.Emulation.Cores/Consoles/PC Engine/{PCEngine.CDLMapping.cs => PCEngine.ICodeDataLogger.cs} (69%) create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDriveLight.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IInputPollable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IStatable.cs diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj index 761265bec4..519f52259c 100644 --- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj +++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj @@ -140,6 +140,7 @@ + diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 3e039f2b53..f6c9f2d3d7 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -910,8 +910,34 @@ - + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + + + PCEngine.cs + @@ -921,7 +947,7 @@ - GPGX.cs + GPGX.cs diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.CDLMapping.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs similarity index 69% rename from BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.CDLMapping.cs rename to BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs index 558745beee..e46911343a 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.CDLMapping.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs @@ -1,15 +1,37 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.IO; +using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.H6280; namespace BizHawk.Emulation.Cores.PCEngine { - partial class PCEngine + public sealed partial class PCEngine : ICodeDataLogger { - static void CDLMappingApplyRange(HuC6280.MemMapping[] mm, string name, int block, int len, int initialoffs = 0) + public void SetCDL(CodeDataLog cdl) + { + Cpu.CDL = cdl; + } + + public void NewCDL(CodeDataLog cdl) + { + InitCDLMappings(); + var mm = this.Cpu.Mappings; + foreach (var kvp in SizesFromHuMap(mm)) + { + cdl[kvp.Key] = new byte[kvp.Value]; + } + + cdl.SubType = "PCE"; + cdl.SubVer = 0; + } + + public void DisassembleCDL(Stream s, CodeDataLog cdl) + { + Cpu.DisassembleCDL(s, cdl, _memoryDomains); + } + + private static void CDLMappingApplyRange(HuC6280.MemMapping[] mm, string name, int block, int len, int initialoffs = 0) { for (int i = block, offs = initialoffs; i < 256 && len > (offs - initialoffs); i++, offs += 8192) { @@ -21,10 +43,12 @@ namespace BizHawk.Emulation.Cores.PCEngine /// /// informs the CPU of the general memory layout, so it can do CDL /// - public void InitCDLMappings() + private void InitCDLMappings() { if (Cpu.Mappings != null) + { return; + } SF2UpdateCDLMappings = true; @@ -32,7 +56,9 @@ namespace BizHawk.Emulation.Cores.PCEngine CDLMappingApplyRange(mm, "ROM", 0x00, Math.Min(RomLength, 1024 * 1024)); if (PopulousRAM != null) + { CDLMappingApplyRange(mm, "Cart Battery RAM", 0x40, PopulousRAM.Length); + } // actual games came in 128K, 256K, 384K, 512K, 768K, 1024K, and Street Fighter sizes // except street fighter, games were on 1 or 2 mask roms @@ -49,6 +75,7 @@ namespace BizHawk.Emulation.Cores.PCEngine mm[i].Name = null; mm[i].Offs = 0; } + for (int i = 0x40; i < 0x50; i++) { // rebase @@ -62,18 +89,23 @@ namespace BizHawk.Emulation.Cores.PCEngine } if (SuperRam != null) + { CDLMappingApplyRange(mm, "Super System Card RAM", 0x68, SuperRam.Length); + } if (CDRam != null) + { CDLMappingApplyRange(mm, "TurboCD RAM", 0x80, CDRam.Length); + } if (BRAM != null) - CDLMappingApplyRange(mm, "Battery RAM", 0xf7, BRAM.Length); - { - var rammirrors = new HuC6280.MemMapping { Name = "Main Memory", Offs = 0 }; - mm[0xf9] = mm[0xfa] = mm[0xfb] = rammirrors; + CDLMappingApplyRange(mm, "Battery RAM", 0xf7, BRAM.Length); } + + var rammirrors = new HuC6280.MemMapping { Name = "Main Memory", Offs = 0 }; + mm[0xf9] = mm[0xfa] = mm[0xfb] = rammirrors; + CDLMappingApplyRange(mm, "Main Memory", 0xf8, Ram.Length); mm[0xff] = new HuC6280.MemMapping { Name = "MMIO", Offs = 0 }; @@ -81,7 +113,9 @@ namespace BizHawk.Emulation.Cores.PCEngine for (int i = 0; i < 256; i++) { if (mm[i].Name == null) + { mm[i].Name = "UNKNOWN"; + } } Cpu.Mappings = mm; diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs new file mode 100644 index 0000000000..8ab9091000 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : IDebuggable + { + public IDictionary GetCpuFlagsAndRegisters() + { + return new Dictionary + { + { "A", Cpu.A }, + { "X", Cpu.X }, + { "Y", Cpu.Y }, + { "PC", Cpu.PC }, + { "S", Cpu.S }, + { "MPR-0", Cpu.MPR[0] }, + { "MPR-1", Cpu.MPR[1] }, + { "MPR-2", Cpu.MPR[2] }, + { "MPR-3", Cpu.MPR[3] }, + { "MPR-4", Cpu.MPR[4] }, + { "MPR-5", Cpu.MPR[5] }, + { "MPR-6", Cpu.MPR[6] }, + { "MPR-7", Cpu.MPR[7] } + }; + } + + [FeatureNotImplemented] + public void SetCpuRegister(string register, int value) + { + throw new NotImplementedException(); + } + + public IMemoryCallbackSystem MemoryCallbacks { get; private set; } + + public bool CanStep(StepType type) { return false; } + + [FeatureNotImplemented] + public void Step(StepType type) { throw new NotImplementedException(); } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDriveLight.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDriveLight.cs new file mode 100644 index 0000000000..845cf1c135 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDriveLight.cs @@ -0,0 +1,11 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : IDriveLight + { + public bool DriveLightEnabled { get; private set; } + + public bool DriveLightOn { get; internal set; } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs new file mode 100644 index 0000000000..a6a7d673e3 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs @@ -0,0 +1,84 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; private set; } + + public ControllerDefinition ControllerDefinition + { + get { return PCEngineController; } + } + + public IController Controller { get; set; } + + public void FrameAdvance(bool render, bool rendersound) + { + _lagged = true; + DriveLightOn = false; + Frame++; + CheckSpriteLimit(); + PSG.BeginFrame(Cpu.TotalExecutedCycles); + + Cpu.Debug = Tracer.Enabled; + + if (SuperGrafx) + { + VPC.ExecFrame(render); + } + else + { + VDC1.ExecFrame(render); + } + + PSG.EndFrame(Cpu.TotalExecutedCycles); + + if (_lagged) + { + _lagCount++; + _isLag = true; + } + else + { + _isLag = false; + } + } + + public int Frame + { + get { return frame; } + set { frame = value; } + } + + public string SystemId { get; private set; } + + public bool DeterministicEmulation + { + get { return true; } + } + + public string BoardName + { + get { return null; } + } + + public void ResetCounters() + { + // this should just be a public setter instead of a new method. + Frame = 0; + _lagCount = 0; + _isLag = false; + } + + public CoreComm CoreComm { get; private set; } + + public void Dispose() + { + if (disc != null) + { + disc.Dispose(); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IInputPollable.cs new file mode 100644 index 0000000000..2f61e011b8 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IInputPollable.cs @@ -0,0 +1,29 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : IInputPollable + { + public int LagCount + { + get { return _lagCount; } + set { _lagCount = value; } + } + + public bool IsLagFrame + { + get { return _isLag; } + set { _isLag = value; } + } + + public IInputCallbackSystem InputCallbacks + { + get { return _inputCallbacks; } + } + + private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + private int _lagCount; + private bool _lagged = true; + private bool _isLag = false; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs new file mode 100644 index 0000000000..00247ab409 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine + { + private Dictionary _byteArrayDomains = new Dictionary(); + private bool _memoryDomainsInit = false; + private MemoryDomainList _memoryDomains; + + private void SetupMemoryDomains() + { + var domains = new List(2); + + var SystemBusDomain = new MemoryDomainDelegate("System Bus (21 bit)", 0x200000, MemoryDomain.Endian.Little, + (addr) => + { + if (addr < 0 || addr >= 0x200000) + throw new ArgumentOutOfRangeException(); + return Cpu.ReadMemory21((int)addr); + }, + (addr, value) => + { + if (addr < 0 || addr >= 0x200000) + throw new ArgumentOutOfRangeException(); + Cpu.WriteMemory21((int)addr, value); + }, + wordSize: 2); + domains.Add(SystemBusDomain); + + var CpuBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little, + (addr) => + { + if (addr < 0 || addr >= 0x10000) + throw new ArgumentOutOfRangeException(); + return Cpu.ReadMemory((ushort)addr); + }, + (addr, value) => + { + if (addr < 0 || addr >= 0x10000) + throw new ArgumentOutOfRangeException(); + Cpu.WriteMemory((ushort)addr, value); + }, + wordSize: 2); + domains.Add(CpuBusDomain); + + SyncAllByteArrayDomains(); + + _memoryDomains = new MemoryDomainList(domains.Concat(_byteArrayDomains.Values).ToList()); + _memoryDomains.SystemBus = CpuBusDomain; + _memoryDomains.MainMemory = _byteArrayDomains["Main Memory"]; + (ServiceProvider as BasicServiceProvider).Register(_memoryDomains); + _memoryDomainsInit = true; + } + + private void SyncAllByteArrayDomains() + { + SyncByteArrayDomain("Main Memory", Ram); + SyncByteArrayDomain("ROM", RomData); + + if (BRAM != null) + SyncByteArrayDomain("Battery RAM", BRAM); + + if (TurboCD) + { + SyncByteArrayDomain("TurboCD RAM", CDRam); + SyncByteArrayDomain("ADPCM RAM", ADPCM.RAM); + if (SuperRam != null) + { + SyncByteArrayDomain("Super System Card RAM", SuperRam); + } + } + + if (ArcadeCard) + { + SyncByteArrayDomain("Arcade Card RAM", ArcadeRam); + } + + if (PopulousRAM != null) + { + SyncByteArrayDomain("Cart Battery RAM", PopulousRAM); + } + } + + private void SyncByteArrayDomain(string name, byte[] data) + { + if (_memoryDomainsInit) + { + var m = _byteArrayDomains[name]; + m.Data = data; + } + else + { + var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1); + _byteArrayDomains.Add(name, m); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs new file mode 100644 index 0000000000..e6ac027c1f --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs @@ -0,0 +1,30 @@ +using System; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : ISaveRam + { + public bool SaveRamModified { get; private set; } + + public byte[] CloneSaveRam() + { + if (BRAM != null) + { + return (byte[])BRAM.Clone(); + } + else + { + return null; + } + } + + public void StoreSaveRam(byte[] data) + { + if (BRAM != null) + { + Array.Copy(data, BRAM, data.Length); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs new file mode 100644 index 0000000000..c789df29d9 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs @@ -0,0 +1,100 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : ISettable + { + public PCESettings GetSettings() + { + return Settings.Clone(); + } + + public PCESyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(PCESettings o) + { + bool ret; + if (o.ArcadeCardRewindHack != Settings.ArcadeCardRewindHack + || o.EqualizeVolume != Settings.EqualizeVolume) + { + ret = true; + } + else + { + ret = false; + } + + Settings = o; + return ret; + } + + public bool PutSyncSettings(PCESyncSettings o) + { + bool ret = PCESyncSettings.NeedsReboot(o, _syncSettings); + _syncSettings = o; + // SetControllerButtons(); // not safe to change the controller during emulation, so instead make it a reboot event + return ret; + } + + internal PCESettings Settings; + private PCESyncSettings _syncSettings; + + public class PCESettings + { + public bool ShowBG1 = true; + public bool ShowOBJ1 = true; + public bool ShowBG2 = true; + public bool ShowOBJ2 = true; + + // these three require core reboot to use + public bool SpriteLimit = false; + public bool EqualizeVolume = false; + public bool ArcadeCardRewindHack = true; + + public PCESettings Clone() + { + return (PCESettings)MemberwiseClone(); + } + } + + public class PCESyncSettings + { + public ControllerSetting[] Controllers = + { + new ControllerSetting { IsConnected = true }, + new ControllerSetting { IsConnected = false }, + new ControllerSetting { IsConnected = false }, + new ControllerSetting { IsConnected = false }, + new ControllerSetting { IsConnected = false } + }; + + public PCESyncSettings Clone() + { + var ret = new PCESyncSettings(); + for (int i = 0; i < Controllers.Length; i++) + { + ret.Controllers[i].IsConnected = Controllers[i].IsConnected; + } + return ret; + } + + public class ControllerSetting + { + public bool IsConnected { get; set; } + } + + public static bool NeedsReboot(PCESyncSettings x, PCESyncSettings y) + { + for (int i = 0; i < x.Controllers.Length; i++) + { + if (x.Controllers[i].IsConnected != y.Controllers[i].IsConnected) + return true; + } + return false; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IStatable.cs new file mode 100644 index 0000000000..e0cc70ff50 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IStatable.cs @@ -0,0 +1,123 @@ +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public sealed partial class PCEngine : IStatable + { + public bool BinarySaveStatesPreferred + { + get { return false; } + } + + public void SaveStateBinary(BinaryWriter bw) + { + SyncState(Serializer.CreateBinaryWriter(bw)); + } + + public void LoadStateBinary(BinaryReader br) + { + SyncState(Serializer.CreateBinaryReader(br)); + } + + public void SaveStateText(TextWriter tw) + { + SyncState(Serializer.CreateTextWriter(tw)); + } + + public void LoadStateText(TextReader tr) + { + SyncState(Serializer.CreateTextReader(tr)); + } + + public byte[] SaveStateBinary() + { + if (_stateBuffer == null) + { + var stream = new MemoryStream(); + var writer = new BinaryWriter(stream); + SaveStateBinary(writer); + writer.Flush(); + _stateBuffer = stream.ToArray(); + writer.Close(); + return _stateBuffer; + } + else + { + var stream = new MemoryStream(_stateBuffer); + var writer = new BinaryWriter(stream); + SaveStateBinary(writer); + writer.Flush(); + writer.Close(); + return _stateBuffer; + } + } + + private byte[] _stateBuffer; + + private void SyncState(Serializer ser) + { + ser.BeginSection("PCEngine"); + Cpu.SyncState(ser); + VCE.SyncState(ser); + VDC1.SyncState(ser, 1); + PSG.SyncState(ser); + + if (SuperGrafx) + { + VPC.SyncState(ser); + VDC2.SyncState(ser, 2); + } + + if (TurboCD) + { + ADPCM.SyncState(ser); + CDAudio.SyncState(ser); + SCSI.SyncState(ser); + + ser.Sync("CDRAM", ref CDRam, false); + if (SuperRam != null) + { + ser.Sync("SuperRAM", ref SuperRam, false); + } + + if (ArcadeCard) + { + ArcadeCardSyncState(ser); + } + } + + ser.Sync("RAM", ref Ram, false); + ser.Sync("IOBuffer", ref IOBuffer); + ser.Sync("CdIoPorts", ref CdIoPorts, false); + ser.Sync("BramLocked", ref BramLocked); + + ser.Sync("Frame", ref frame); + ser.Sync("Lag", ref _lagCount); + ser.Sync("IsLag", ref _isLag); + if (Cpu.ReadMemory21 == ReadMemorySF2) + { + ser.Sync("SF2MapperLatch", ref SF2MapperLatch); + } + + if (PopulousRAM != null) + { + ser.Sync("PopulousRAM", ref PopulousRAM, false); + } + + if (BRAM != null) + { + ser.Sync("BRAM", ref BRAM, false); + } + + ser.EndSection(); + + if (ser.IsReader) + { + SyncAllByteArrayDomains(); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs index f50ed0a41f..ad1d36b019 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs @@ -41,9 +41,6 @@ namespace BizHawk.Emulation.Cores.PCEngine } } - public ControllerDefinition ControllerDefinition { get { return PCEngineController; } } - public IController Controller { get; set; } - int SelectedController; byte InputByte; @@ -70,7 +67,7 @@ namespace BizHawk.Emulation.Cores.PCEngine int player = SelectedController + 1; if (player < 6) { - lagged = false; + _lagged = false; if (SEL == false) // return buttons { if (Controller["P" + player + " B1"]) value &= 0xFE; diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs index d37f151e25..7aeb5dce22 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs @@ -1,14 +1,8 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using BizHawk.Common; using BizHawk.Common.BufferExtensions; - using BizHawk.Emulation.Common; -using BizHawk.Emulation.Common.Components; - using BizHawk.Emulation.Cores.Components; using BizHawk.Emulation.Cores.Components.H6280; using BizHawk.Emulation.DiscSystem; @@ -26,46 +20,6 @@ namespace BizHawk.Emulation.Cores.PCEngine public sealed partial class PCEngine : IEmulator, ISaveRam, IStatable, IInputPollable, IDebuggable, ISettable, IDriveLight, ICodeDataLogger { - // ROM - public byte[] RomData; - public int RomLength; - Disc disc; - - // Machine - public NecSystemType Type; - public HuC6280 Cpu; - public VDC VDC1, VDC2; - public VCE VCE; - public VPC VPC; - public ScsiCDBus SCSI; - public ADPCM ADPCM; - - public HuC6280PSG PSG; - public CDAudio CDAudio; - public SoundMixer SoundMixer; - //public MetaspuSoundProvider SoundSynchronizer; - - bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } } - bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } } - bool TurboCD { get { return Type == NecSystemType.TurboCD; } } - - // BRAM - bool BramEnabled = false; - bool BramLocked = true; - byte[] BRAM; - - // Memory system - public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram - public byte[] CDRam; // TurboCD extra 64k of ram - public byte[] SuperRam; // Super System Card 192K of additional RAM - public byte[] ArcadeRam; // Arcade Card 2048K of additional RAM - - string systemid = "PCE"; - bool ForceSpriteLimit; - - // 21,477,270 Machine clocks / sec - // 7,159,090 Cpu cycles / sec - [CoreConstructor("PCE", "SGX")] public PCEngine(CoreComm comm, GameInfo game, byte[] rom, object Settings, object syncSettings) { @@ -75,37 +29,31 @@ namespace BizHawk.Emulation.Cores.PCEngine switch (game.System) { + default: case "PCE": - systemid = "PCE"; + SystemId = "PCE"; Type = NecSystemType.TurboGrafx; break; case "SGX": - systemid = "SGX"; + SystemId = "SGX"; Type = NecSystemType.SuperGrafx; break; } - this._settings = (PCESettings)Settings ?? new PCESettings(); + this.Settings = (PCESettings)Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings(); Init(game, rom); SetControllerButtons(); } - public IEmulatorServiceProvider ServiceProvider { get; private set; } - - public string BoardName { get { return null; } } - - private ITraceable Tracer { get; set; } - public IMemoryCallbackSystem MemoryCallbacks { get; private set; } - public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings) { CoreComm = comm; MemoryCallbacks = new MemoryCallbackSystem(); DriveLightEnabled = true; - systemid = "PCECD"; + SystemId = "PCECD"; Type = NecSystemType.TurboCD; this.disc = disc; - this._settings = (PCESettings)Settings ?? new PCESettings(); + this.Settings = (PCESettings)Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings(); GameInfo biosInfo; @@ -151,10 +99,48 @@ namespace BizHawk.Emulation.Cores.PCEngine SetControllerButtons(); } - public bool DriveLightEnabled { get; private set; } - public bool DriveLightOn { get; internal set; } + // ROM + public byte[] RomData; + public int RomLength; + Disc disc; - void Init(GameInfo game, byte[] rom) + // Machine + public NecSystemType Type; + public HuC6280 Cpu; + public VDC VDC1, VDC2; + public VCE VCE; + public VPC VPC; + public ScsiCDBus SCSI; + public ADPCM ADPCM; + + public HuC6280PSG PSG; + public CDAudio CDAudio; + public SoundMixer SoundMixer; + //public MetaspuSoundProvider SoundSynchronizer; + + bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } } + bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } } + bool TurboCD { get { return Type == NecSystemType.TurboCD; } } + + // BRAM + bool BramEnabled = false; + bool BramLocked = true; + byte[] BRAM; + + // Memory system + public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram + public byte[] CDRam; // TurboCD extra 64k of ram + public byte[] SuperRam; // Super System Card 192K of additional RAM + public byte[] ArcadeRam; // Arcade Card 2048K of additional RAM + + bool ForceSpriteLimit; + + // 21,477,270 Machine clocks / sec + // 7,159,090 Cpu cycles / sec + + private ITraceable Tracer { get; set; } + + private void Init(GameInfo game, byte[] rom) { Controller = NullController.GetNullController(); Cpu = new HuC6280(MemoryCallbacks); @@ -253,7 +239,7 @@ namespace BizHawk.Emulation.Cores.PCEngine { ArcadeRam = new byte[0x200000]; ArcadeCard = true; - ArcadeCardRewindHack = _settings.ArcadeCardRewindHack; + ArcadeCardRewindHack = Settings.ArcadeCardRewindHack; for (int i = 0; i < 4; i++) ArcadePage[i] = new ArcadeCardPage(); } @@ -276,7 +262,7 @@ namespace BizHawk.Emulation.Cores.PCEngine if (game["AdpcmVol"]) ADPCM.MaxVolume = int.Parse(game.OptionValue("AdpcmVol")); // the gamedb can also force equalizevolumes on - if (TurboCD && (_settings.EqualizeVolume || game["EqualizeVolumes"] || game.NotInDatabase)) + if (TurboCD && (Settings.EqualizeVolume || game["EqualizeVolumes"] || game.NotInDatabase)) SoundMixer.EqualizeVolumes(); // Ok, yes, HBlankPeriod's only purpose is game-specific hax. @@ -308,404 +294,36 @@ namespace BizHawk.Emulation.Cores.PCEngine SetupMemoryDomains(); } - int lagCount; - int frame; - bool lagged = true; - bool isLag = false; - public int Frame { get { return frame; } set { frame = value; } } - public int LagCount { get { return lagCount; } set { lagCount = value; } } - public bool IsLagFrame { get { return isLag; } set { isLag = value; } } - - private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); - public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } - - void ICodeDataLogger.SetCDL(CodeDataLog cdl) - { - Cpu.CDL = cdl; - } - - void ICodeDataLogger.NewCDL(CodeDataLog cdl) - { - InitCDLMappings(); - var mm = this.Cpu.Mappings; - foreach (var kvp in SizesFromHuMap(mm)) - { - cdl[kvp.Key] = new byte[kvp.Value]; - } - - cdl.SubType = "PCE"; - cdl.SubVer = 0; - } - - void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) - { - Cpu.DisassembleCDL(s, cdl, _memoryDomains); - } + private int frame; private static Dictionary SizesFromHuMap(IEnumerable mm) { - Dictionary sizes = new Dictionary(); - foreach (var m in mm) - { - if (!sizes.ContainsKey(m.Name) || m.MaxOffs >= sizes[m.Name]) - sizes[m.Name] = m.MaxOffs; - } - - List keys = new List(sizes.Keys); - foreach (var key in keys) - { - // becase we were looking at offsets, and each bank is 8192 big, we need to add that size - sizes[key] += 8192; - } - return sizes; - } - - public void ResetCounters() - { - // this should just be a public setter instead of a new method. - Frame = 0; - lagCount = 0; - isLag = false; - } - - public void FrameAdvance(bool render, bool rendersound) - { - lagged = true; - DriveLightOn = false; - Frame++; - CheckSpriteLimit(); - PSG.BeginFrame(Cpu.TotalExecutedCycles); - - Cpu.Debug = Tracer.Enabled; - - if (SuperGrafx) - VPC.ExecFrame(render); - else - VDC1.ExecFrame(render); - - PSG.EndFrame(Cpu.TotalExecutedCycles); - - if (lagged) + Dictionary sizes = new Dictionary(); + foreach (var m in mm) { - lagCount++; - isLag = true; + if (!sizes.ContainsKey(m.Name) || m.MaxOffs >= sizes[m.Name]) + sizes[m.Name] = m.MaxOffs; } - else - isLag = false; + + var keys = new List(sizes.Keys); + foreach (var key in keys) + { + // becase we were looking at offsets, and each bank is 8192 big, we need to add that size + sizes[key] += 8192; + } + return sizes; } - void CheckSpriteLimit() + private void CheckSpriteLimit() { - bool spriteLimit = ForceSpriteLimit | _settings.SpriteLimit; + bool spriteLimit = ForceSpriteLimit | Settings.SpriteLimit; VDC1.PerformSpriteLimit = spriteLimit; if (VDC2 != null) VDC2.PerformSpriteLimit = spriteLimit; } - public CoreComm CoreComm { get; private set; } - private ISoundProvider soundProvider; - public string SystemId { get { return systemid; } } public string Region { get; set; } - public bool DeterministicEmulation { get { return true; } } - - public byte[] CloneSaveRam() - { - if (BRAM != null) - return (byte[])BRAM.Clone(); - else - return null; - } - - public void StoreSaveRam(byte[] data) - { - if (BRAM != null) - Array.Copy(data, BRAM, data.Length); - } - - public bool SaveRamModified { get; private set; } - - public bool BinarySaveStatesPreferred { get { return false; } } - public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); } - public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); } - public void SaveStateText(TextWriter tw) { SyncState(Serializer.CreateTextWriter(tw)); } - public void LoadStateText(TextReader tr) { SyncState(Serializer.CreateTextReader(tr)); } - - void SyncState(Serializer ser) - { - ser.BeginSection("PCEngine"); - Cpu.SyncState(ser); - VCE.SyncState(ser); - VDC1.SyncState(ser, 1); - PSG.SyncState(ser); - - if (SuperGrafx) - { - VPC.SyncState(ser); - VDC2.SyncState(ser, 2); - } - - if (TurboCD) - { - ADPCM.SyncState(ser); - CDAudio.SyncState(ser); - SCSI.SyncState(ser); - - ser.Sync("CDRAM", ref CDRam, false); - if (SuperRam != null) - ser.Sync("SuperRAM", ref SuperRam, false); - if (ArcadeCard) - ArcadeCardSyncState(ser); - } - - ser.Sync("RAM", ref Ram, false); - ser.Sync("IOBuffer", ref IOBuffer); - ser.Sync("CdIoPorts", ref CdIoPorts, false); - ser.Sync("BramLocked", ref BramLocked); - - ser.Sync("Frame", ref frame); - ser.Sync("Lag", ref lagCount); - ser.Sync("IsLag", ref isLag); - if (Cpu.ReadMemory21 == ReadMemorySF2) - ser.Sync("SF2MapperLatch", ref SF2MapperLatch); - if (PopulousRAM != null) - ser.Sync("PopulousRAM", ref PopulousRAM, false); - if (BRAM != null) - ser.Sync("BRAM", ref BRAM, false); - - ser.EndSection(); - - if (ser.IsReader) - SyncAllByteArrayDomains(); - } - - byte[] stateBuffer; - public byte[] SaveStateBinary() - { - if (stateBuffer == null) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Flush(); - stateBuffer = stream.ToArray(); - writer.Close(); - return stateBuffer; - } - else - { - var stream = new MemoryStream(stateBuffer); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Flush(); - writer.Close(); - return stateBuffer; - } - } - - void SetupMemoryDomains() - { - var domains = new List(2); - - var SystemBusDomain = new MemoryDomainDelegate("System Bus (21 bit)", 0x200000, MemoryDomain.Endian.Little, - (addr) => - { - if (addr < 0 || addr >= 0x200000) - throw new ArgumentOutOfRangeException(); - return Cpu.ReadMemory21((int)addr); - }, - (addr, value) => - { - if (addr < 0 || addr >= 0x200000) - throw new ArgumentOutOfRangeException(); - Cpu.WriteMemory21((int)addr, value); - }, - wordSize: 2); - domains.Add(SystemBusDomain); - - var CpuBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little, - (addr) => - { - if (addr < 0 || addr >= 0x10000) - throw new ArgumentOutOfRangeException(); - return Cpu.ReadMemory((ushort)addr); - }, - (addr, value) => - { - if (addr < 0 || addr >= 0x10000) - throw new ArgumentOutOfRangeException(); - Cpu.WriteMemory((ushort)addr, value); - }, - wordSize: 2); - domains.Add(CpuBusDomain); - - SyncAllByteArrayDomains(); - - _memoryDomains = new MemoryDomainList(domains.Concat(_byteArrayDomains.Values).ToList()); - _memoryDomains.SystemBus = CpuBusDomain; - _memoryDomains.MainMemory = _byteArrayDomains["Main Memory"]; - (ServiceProvider as BasicServiceProvider).Register(_memoryDomains); - _memoryDomainsInit = true; - } - - private void SyncAllByteArrayDomains() - { - SyncByteArrayDomain("Main Memory", Ram); - SyncByteArrayDomain("ROM", RomData); - - if (BRAM != null) - SyncByteArrayDomain("Battery RAM", BRAM); - - if (TurboCD) - { - SyncByteArrayDomain("TurboCD RAM", CDRam); - SyncByteArrayDomain("ADPCM RAM", ADPCM.RAM); - if (SuperRam != null) - SyncByteArrayDomain("Super System Card RAM", SuperRam); - } - - if (ArcadeCard) - SyncByteArrayDomain("Arcade Card RAM", ArcadeRam); - - if (PopulousRAM != null) - SyncByteArrayDomain("Cart Battery RAM", PopulousRAM); - } - - private void SyncByteArrayDomain(string name, byte[] data) - { - if (_memoryDomainsInit) - { - var m = _byteArrayDomains[name]; - m.Data = data; - } - else - { - var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1); - _byteArrayDomains.Add(name, m); - } - } - - private Dictionary _byteArrayDomains = new Dictionary(); - private bool _memoryDomainsInit = false; - private MemoryDomainList _memoryDomains; - - public IDictionary GetCpuFlagsAndRegisters() - { - return new Dictionary - { - { "A", Cpu.A }, - { "X", Cpu.X }, - { "Y", Cpu.Y }, - { "PC", Cpu.PC }, - { "S", Cpu.S }, - { "MPR-0", Cpu.MPR[0] }, - { "MPR-1", Cpu.MPR[1] }, - { "MPR-2", Cpu.MPR[2] }, - { "MPR-3", Cpu.MPR[3] }, - { "MPR-4", Cpu.MPR[4] }, - { "MPR-5", Cpu.MPR[5] }, - { "MPR-6", Cpu.MPR[6] }, - { "MPR-7", Cpu.MPR[7] } - }; - } - - public bool CanStep(StepType type) { return false; } - - [FeatureNotImplemented] - public void Step(StepType type) { throw new NotImplementedException(); } - - [FeatureNotImplemented] - public void SetCpuRegister(string register, int value) - { - throw new NotImplementedException(); - } - - public void Dispose() - { - if (disc != null) - disc.Dispose(); - } - - public PCESettings _settings; - private PCESyncSettings _syncSettings; - - public PCESettings GetSettings() { return _settings.Clone(); } - public PCESyncSettings GetSyncSettings() { return _syncSettings.Clone(); } - public bool PutSettings(PCESettings o) - { - bool ret; - if (o.ArcadeCardRewindHack != _settings.ArcadeCardRewindHack || - o.EqualizeVolume != _settings.EqualizeVolume) - ret = true; - else - ret = false; - - _settings = o; - return ret; - } - - public bool PutSyncSettings(PCESyncSettings o) - { - bool ret = PCESyncSettings.NeedsReboot(o, _syncSettings); - _syncSettings = o; - // SetControllerButtons(); // not safe to change the controller during emulation, so instead make it a reboot event - return ret; - } - - public class PCESettings - { - public bool ShowBG1 = true; - public bool ShowOBJ1 = true; - public bool ShowBG2 = true; - public bool ShowOBJ2 = true; - - // these three require core reboot to use - public bool SpriteLimit = false; - public bool EqualizeVolume = false; - public bool ArcadeCardRewindHack = true; - - public PCESettings Clone() - { - return (PCESettings)MemberwiseClone(); - } - } - - public class PCESyncSettings - { - public ControllerSetting[] Controllers = - { - new ControllerSetting { IsConnected = true }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false } - }; - - public PCESyncSettings Clone() - { - var ret = new PCESyncSettings(); - for (int i = 0; i < Controllers.Length; i++) - { - ret.Controllers[i].IsConnected = Controllers[i].IsConnected; - } - return ret; - } - - public class ControllerSetting - { - public bool IsConnected { get; set; } - } - - public static bool NeedsReboot(PCESyncSettings x, PCESyncSettings y) - { - for (int i = 0; i < x.Controllers.Length; i++) - { - if (x.Controllers[i].IsConnected != y.Controllers[i].IsConnected) - return true; - } - return false; - } - } } } diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs index 9f64ae29a7..e85c7b78f1 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs @@ -108,8 +108,8 @@ namespace BizHawk.Emulation.Cores.PCEngine if (ActiveLine >= FrameHeight) return; - RenderBackgroundScanline(pce._settings.ShowBG1); - RenderSpritesScanline(pce._settings.ShowOBJ1); + RenderBackgroundScanline(pce.Settings.ShowBG1); + RenderSpritesScanline(pce.Settings.ShowOBJ1); } Action RenderBackgroundScanline; diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs index 6930b4c23d..74836981b6 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs @@ -246,16 +246,16 @@ namespace BizHawk.Emulation.Cores.PCEngine switch (EffectivePriorityMode) { case 0: - RenderBackgroundScanline(VDC1, 12, PCE._settings.ShowBG1); - RenderBackgroundScanline(VDC2, 2, PCE._settings.ShowBG2); - RenderSpritesScanline(VDC1, 11, 14, PCE._settings.ShowOBJ1); - RenderSpritesScanline(VDC2, 1, 3, PCE._settings.ShowOBJ2); + RenderBackgroundScanline(VDC1, 12, PCE.Settings.ShowBG1); + RenderBackgroundScanline(VDC2, 2, PCE.Settings.ShowBG2); + RenderSpritesScanline(VDC1, 11, 14, PCE.Settings.ShowOBJ1); + RenderSpritesScanline(VDC2, 1, 3, PCE.Settings.ShowOBJ2); break; case 1: - RenderBackgroundScanline(VDC1, 12, PCE._settings.ShowBG1); - RenderBackgroundScanline(VDC2, 2, PCE._settings.ShowBG2); - RenderSpritesScanline(VDC1, 11, 14, PCE._settings.ShowOBJ1); - RenderSpritesScanline(VDC2, 1, 13, PCE._settings.ShowOBJ2); + RenderBackgroundScanline(VDC1, 12, PCE.Settings.ShowBG1); + RenderBackgroundScanline(VDC2, 2, PCE.Settings.ShowBG2); + RenderSpritesScanline(VDC1, 11, 14, PCE.Settings.ShowOBJ1); + RenderSpritesScanline(VDC2, 1, 13, PCE.Settings.ShowOBJ2); break; } }