From 4460055da3c77c30187ce15ca08f719a17fbd8e9 Mon Sep 17 00:00:00 2001 From: adelikat Date: Sun, 28 Feb 2016 12:01:12 -0500 Subject: [PATCH] SMS - break up services into separate files --- .../BizHawk.Emulation.Cores.csproj | 11 +- .../{CDL_SMS.cs => SMS.ICodeDataLogger.cs} | 99 ++-- .../Consoles/Sega/SMS/SMS.IDebuggable.cs | 133 +++++ .../Consoles/Sega/SMS/SMS.IEmulator.cs | 100 ++++ .../Consoles/Sega/SMS/SMS.IInputPollable.cs | 25 + .../Consoles/Sega/SMS/SMS.IMemoryDomains.cs | 71 +++ .../Consoles/Sega/SMS/SMS.ISaveRam.cs | 34 ++ .../Consoles/Sega/SMS/SMS.ISettable.cs | 84 ++++ .../Consoles/Sega/SMS/SMS.IStatable.cs | 98 ++++ .../Consoles/Sega/SMS/SMS.Input.cs | 25 +- .../Consoles/Sega/SMS/SMS.cs | 453 ++---------------- 11 files changed, 650 insertions(+), 483 deletions(-) rename BizHawk.Emulation.Cores/Consoles/Sega/SMS/{CDL_SMS.cs => SMS.ICodeDataLogger.cs} (62%) create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IInputPollable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISettable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 41154a738b..d9265f8e8c 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -818,7 +818,7 @@ GPGX.cs - GPGX.cs + GPGX.cs GPGX.cs @@ -846,8 +846,15 @@ Yabause.cs - + + + + + + + + diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/CDL_SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs similarity index 62% rename from BizHawk.Emulation.Cores/Consoles/Sega/SMS/CDL_SMS.cs rename to BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs index c95becd9e9..1b00f989e1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/CDL_SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs @@ -4,9 +4,51 @@ using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Sega.MasterSystem { - partial class SMS + public sealed partial class SMS : ICodeDataLogger { - enum CDLog_AddrType + public void SetCDL(CodeDataLog cdl) + { + CDL = cdl; + if (cdl == null) + { + Cpu.ReadMemory = ReadMemory; + Cpu.WriteMemory = WriteMemory; + Cpu.FetchMemory = FetchMemory_StubThunk; + } + else + { + Cpu.ReadMemory = ReadMemory_CDL; + Cpu.WriteMemory = WriteMemory; + Cpu.FetchMemory = FetchMemory_CDL; + } + } + + public void NewCDL(CodeDataLog cdl) + { + cdl["ROM"] = new byte[MemoryDomains["ROM"].Size]; + cdl["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size]; + + if (MemoryDomains.Has("Save RAM")) + { + cdl["Save RAM"] = new byte[MemoryDomains["Save RAM"].Size]; + } + + if (MemoryDomains.Has("Cart (Volatile) RAM")) + { + cdl["Cart (Volatile) RAM"] = new byte[MemoryDomains["Cart (Volatile) RAM"].Size]; + } + + cdl.SubType = "SMS"; + cdl.SubVer = 0; + } + + [FeatureNotImplemented] + public void DisassembleCDL(Stream s, CodeDataLog cdl) + { + + } + + private enum CDLog_AddrType { None, ROM, @@ -16,24 +58,24 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } [Flags] - public enum CDLog_Flags + private enum CDLog_Flags { ExecFirst = 0x01, ExecOperand = 0x02, Data = 0x04 }; - struct CDLog_MapResults + private struct CDLog_MapResults { public CDLog_AddrType Type; public int Address; } - delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write); + private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write); + private MapMemoryDelegate MapMemory; + private CodeDataLog CDL; - MapMemoryDelegate MapMemory; - - void RunCDL(ushort address, CDLog_Flags flags) + private void RunCDL(ushort address, CDLog_Flags flags) { if (MapMemory != null) { @@ -52,7 +94,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem /// /// A wrapper for FetchMemory which inserts CDL logic /// - public byte FetchMemory_CDL(ushort address, bool first) + private byte FetchMemory_CDL(ushort address, bool first) { RunCDL(address, first ? CDLog_Flags.ExecFirst : CDLog_Flags.ExecOperand); return ReadMemory(address); @@ -61,47 +103,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem /// /// A wrapper for ReadMemory which inserts CDL logic /// - public byte ReadMemory_CDL(ushort address) + private byte ReadMemory_CDL(ushort address) { RunCDL(address, CDLog_Flags.Data); return ReadMemory(address); } - - void ICodeDataLogger.SetCDL(CodeDataLog cdl) - { - CDL = cdl; - if (cdl == null) - { - Cpu.ReadMemory = ReadMemory; - Cpu.WriteMemory = WriteMemory; - Cpu.FetchMemory = FetchMemory_StubThunk; - } - else - { - Cpu.ReadMemory = ReadMemory_CDL; - Cpu.WriteMemory = WriteMemory; - Cpu.FetchMemory = FetchMemory_CDL; - } - } - - void ICodeDataLogger.NewCDL(CodeDataLog cdl) - { - cdl["ROM"] = new byte[memoryDomains["ROM"].Size]; - cdl["Main RAM"] = new byte[memoryDomains["Main RAM"].Size]; - - if (memoryDomains.Has("Save RAM")) - cdl["Save RAM"] = new byte[memoryDomains["Save RAM"].Size]; - - if (memoryDomains.Has("Cart (Volatile) RAM")) - cdl["Cart (Volatile) RAM"] = new byte[memoryDomains["Cart (Volatile) RAM"].Size]; - - cdl.SubType = "SMS"; - cdl.SubVer = 0; - } - - //not supported - void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { } - - CodeDataLog CDL; } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs new file mode 100644 index 0000000000..aaf4ee4d4f --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Common.NumberExtensions; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : IDebuggable + { + public IDictionary GetCpuFlagsAndRegisters() + { + return new Dictionary + { + { "A", Cpu.RegisterA }, + { "AF", Cpu.RegisterAF }, + { "B", Cpu.RegisterB }, + { "BC", Cpu.RegisterBC }, + { "C", Cpu.RegisterC }, + { "D", Cpu.RegisterD }, + { "DE", Cpu.RegisterDE }, + { "E", Cpu.RegisterE }, + { "F", Cpu.RegisterF }, + { "H", Cpu.RegisterH }, + { "HL", Cpu.RegisterHL }, + { "I", Cpu.RegisterI }, + { "IX", Cpu.RegisterIX }, + { "IY", Cpu.RegisterIY }, + { "L", Cpu.RegisterL }, + { "PC", Cpu.RegisterPC }, + { "R", Cpu.RegisterR }, + { "Shadow AF", Cpu.RegisterShadowAF }, + { "Shadow BC", Cpu.RegisterShadowBC }, + { "Shadow DE", Cpu.RegisterShadowDE }, + { "Shadow HL", Cpu.RegisterShadowHL }, + { "SP", Cpu.RegisterSP }, + { "Flag C", Cpu.RegisterF.Bit(0) }, + { "Flag N", Cpu.RegisterF.Bit(1) }, + { "Flag P/V", Cpu.RegisterF.Bit(2) }, + { "Flag 3rd", Cpu.RegisterF.Bit(3) }, + { "Flag H", Cpu.RegisterF.Bit(4) }, + { "Flag 5th", Cpu.RegisterF.Bit(5) }, + { "Flag Z", Cpu.RegisterF.Bit(6) }, + { "Flag S", Cpu.RegisterF.Bit(7) }, + }; + } + + public void SetCpuRegister(string register, int value) + { + switch (register) + { + default: + throw new InvalidOperationException(); + case "A": + Cpu.RegisterA = (byte)value; + break; + case "AF": + Cpu.RegisterAF = (byte)value; + break; + case "B": + Cpu.RegisterB = (byte)value; + break; + case "BC": + Cpu.RegisterBC = (byte)value; + break; + case "C": + Cpu.RegisterC = (byte)value; + break; + case "D": + Cpu.RegisterD = (byte)value; + break; + case "DE": + Cpu.RegisterDE = (byte)value; + break; + case "E": + Cpu.RegisterE = (byte)value; + break; + case "F": + Cpu.RegisterF = (byte)value; + break; + case "H": + Cpu.RegisterH = (byte)value; + break; + case "HL": + Cpu.RegisterHL = (byte)value; + break; + case "I": + Cpu.RegisterI = (byte)value; + break; + case "IX": + Cpu.RegisterIX = (byte)value; + break; + case "IY": + Cpu.RegisterIY = (byte)value; + break; + case "L": + Cpu.RegisterL = (byte)value; + break; + case "PC": + Cpu.RegisterPC = (ushort)value; + break; + case "R": + Cpu.RegisterR = (byte)value; + break; + case "Shadow AF": + Cpu.RegisterShadowAF = (byte)value; + break; + case "Shadow BC": + Cpu.RegisterShadowBC = (byte)value; + break; + case "Shadow DE": + Cpu.RegisterShadowDE = (byte)value; + break; + case "Shadow HL": + Cpu.RegisterShadowHL = (byte)value; + break; + case "SP": + Cpu.RegisterSP = (byte)value; + break; + } + } + + public bool CanStep(StepType type) { return false; } + + public IMemoryCallbackSystem MemoryCallbacks { get; private set; } + + [FeatureNotImplemented] + public void Step(StepType type) + { + throw new NotImplementedException(); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs new file mode 100644 index 0000000000..3770568f83 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -0,0 +1,100 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; private set; } + + public ISoundProvider SoundProvider + { + get { return ActiveSoundProvider; } + } + + public ISyncSoundProvider SyncSoundProvider + { + get { return new FakeSyncSound(ActiveSoundProvider, 735); } + } + + public bool StartAsyncSound() + { + return true; + } + + public void EndAsyncSound() { } + + public ControllerDefinition ControllerDefinition + { + get + { + if (IsGameGear) + { + return GGController; + } + + return SmsController; + } + } + + public IController Controller { get; set; } + + public void FrameAdvance(bool render, bool rendersound) + { + _lagged = true; + Frame++; + PSG.BeginFrame(Cpu.TotalExecutedCycles); + Cpu.Debug = Tracer.Enabled; + if (!IsGameGear) + { + PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte)0xFF; + } + + if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first + { + Cpu.Logger = (s) => Tracer.Put(s); + } + + if (IsGameGear == false) + { + Cpu.NonMaskableInterrupt = Controller["Pause"]; + } + + if (IsGame3D && Settings.Fix3D) + { + Vdp.ExecFrame((Frame & 1) == 0); + } + else + { + Vdp.ExecFrame(render); + } + + PSG.EndFrame(Cpu.TotalExecutedCycles); + if (_lagged) + { + _lagCount++; + _isLag = true; + } + else + { + _isLag = false; + } + } + + public string SystemId { get { return "SMS"; } } + + public bool DeterministicEmulation { get { return true; } } + + public string BoardName { get { return null; } } + + public void ResetCounters() + { + Frame = 0; + _lagCount = 0; + _isLag = false; + } + + public CoreComm CoreComm { get; private set; } + + public void Dispose() { } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IInputPollable.cs new file mode 100644 index 0000000000..82a3e637d8 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IInputPollable.cs @@ -0,0 +1,25 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : IInputPollable + { + public int LagCount + { + get { return _lagCount; } + set { _lagCount = value; } + } + + public bool IsLagFrame + { + get { return _isLag; } + set { _isLag = value; } + } + + public IInputCallbackSystem InputCallbacks { get; private set; } + + private int _lagCount = 0; + private bool _lagged = true; + private bool _isLag = false; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs new file mode 100644 index 0000000000..db343028f1 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS + { + private MemoryDomainList MemoryDomains; + + void SetupMemoryDomains() + { + var domains = new List(3); + var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, MemoryDomain.Endian.Little, + addr => SystemRam[addr], + (addr, value) => SystemRam[addr] = value); + var VRamDomain = new MemoryDomain("Video RAM", Vdp.VRAM.Length, MemoryDomain.Endian.Little, + addr => Vdp.VRAM[addr], + (addr, value) => Vdp.VRAM[addr] = value); + + var ROMDomain = new MemoryDomain("ROM", RomData.Length, MemoryDomain.Endian.Little, + addr => RomData[addr], + (addr, value) => RomData[addr] = value); + + var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little, + (addr) => + { + if (addr < 0 || addr >= 65536) + { + throw new ArgumentOutOfRangeException(); + } + + return Cpu.ReadMemory((ushort)addr); + }, + (addr, value) => + { + if (addr < 0 || addr >= 65536) + { + throw new ArgumentOutOfRangeException(); + } + + Cpu.WriteMemory((ushort)addr, value); + }); + + domains.Add(MainMemoryDomain); + domains.Add(VRamDomain); + domains.Add(ROMDomain); + domains.Add(SystemBusDomain); + + if (SaveRAM != null) + { + var SaveRamDomain = new MemoryDomain("Save RAM", SaveRAM.Length, MemoryDomain.Endian.Little, + addr => SaveRAM[addr], + (addr, value) => { SaveRAM[addr] = value; SaveRamModified = true; }); + domains.Add(SaveRamDomain); + } + + if (ExtRam != null) + { + var ExtRamDomain = new MemoryDomain("Cart (Volatile) RAM", ExtRam.Length, MemoryDomain.Endian.Little, + addr => ExtRam[addr], + (addr, value) => { ExtRam[addr] = value; }); + domains.Add(ExtRamDomain); + } + + MemoryDomains = new MemoryDomainList(domains); + (ServiceProvider as BasicServiceProvider).Register(MemoryDomains); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs new file mode 100644 index 0000000000..9e88f186c7 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs @@ -0,0 +1,34 @@ +using System; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : ISaveRam + { + public byte[] CloneSaveRam() + { + if (SaveRAM != null) + { + return (byte[])SaveRAM.Clone(); + } + else + { + return null; + } + } + + public void StoreSaveRam(byte[] data) + { + if (SaveRAM != null) + { + Array.Copy(data, SaveRAM, data.Length); + } + } + + public bool SaveRamModified { get; private set; } + + private byte[] SaveRAM; + private byte SaveRamBank; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISettable.cs new file mode 100644 index 0000000000..0fac8cd1bb --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISettable.cs @@ -0,0 +1,84 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : ISettable + { + public SMSSettings GetSettings() + { + return Settings.Clone(); + } + + public SMSSyncSettings GetSyncSettings() + { + return SyncSettings.Clone(); + } + + public bool PutSettings(SMSSettings o) + { + bool ret = SMSSettings.RebootNeeded(Settings, o); + Settings = o; + return ret; + } + + public bool PutSyncSettings(SMSSyncSettings o) + { + bool ret = SMSSyncSettings.RebootNeeded(SyncSettings, o); + SyncSettings = o; + return ret; + } + + internal SMSSettings Settings { get; private set; } + internal SMSSyncSettings SyncSettings { get; private set; } + + public class SMSSettings + { + // Game settings + public bool ForceStereoSeparation = false; + public bool SpriteLimit = false; + public bool Fix3D = true; + + // GG settings + public bool ShowClippedRegions = false; + public bool HighlightActiveDisplayRegion = false; + + // graphics settings + public bool DispBG = true; + public bool DispOBJ = true; + + public SMSSettings Clone() + { + return (SMSSettings)MemberwiseClone(); + } + + public static bool RebootNeeded(SMSSettings x, SMSSettings y) + { + return false; + } + } + + public class SMSSyncSettings + { + public bool EnableFM = true; + public bool AllowOverlock = false; + public bool UseBIOS = false; + public string ConsoleRegion = "Export"; + public string DisplayType = "NTSC"; + + public SMSSyncSettings Clone() + { + return (SMSSyncSettings)MemberwiseClone(); + } + + public static bool RebootNeeded(SMSSyncSettings x, SMSSyncSettings y) + { + return + x.EnableFM != y.EnableFM || + x.AllowOverlock != y.AllowOverlock || + x.UseBIOS != y.UseBIOS || + x.ConsoleRegion != y.ConsoleRegion || + x.DisplayType != y.DisplayType; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs new file mode 100644 index 0000000000..f1d564ef08 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs @@ -0,0 +1,98 @@ +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : 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); + _stateBuffer = stream.ToArray(); + writer.Close(); + return _stateBuffer; + } + else + { + var stream = new MemoryStream(_stateBuffer); + var writer = new BinaryWriter(stream); + SaveStateBinary(writer); + writer.Close(); + return _stateBuffer; + } + } + + private byte[] _stateBuffer; + + private void SyncState(Serializer ser) + { + ser.BeginSection("SMS"); + Cpu.SyncState(ser); + Vdp.SyncState(ser); + PSG.SyncState(ser); + ser.Sync("RAM", ref SystemRam, false); + ser.Sync("RomBank0", ref RomBank0); + ser.Sync("RomBank1", ref RomBank1); + ser.Sync("RomBank2", ref RomBank2); + ser.Sync("RomBank3", ref RomBank3); + ser.Sync("Port01", ref Port01); + ser.Sync("Port02", ref Port02); + ser.Sync("Port3E", ref Port3E); + ser.Sync("Port3F", ref Port3F); + + if (SaveRAM != null) + { + ser.Sync("SaveRAM", ref SaveRAM, false); + ser.Sync("SaveRamBank", ref SaveRamBank); + } + + if (ExtRam != null) + { + ser.Sync("ExtRAM", ref ExtRam, true); + } + + if (HasYM2413) + { + YM2413.SyncState(ser); + } + + ser.Sync("Frame", ref frame); + ser.Sync("LagCount", ref _lagCount); + ser.Sync("IsLag", ref _isLag); + + ser.EndSection(); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs index 5c9cd5b4e6..045efb215f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs @@ -25,25 +25,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } }; - public ControllerDefinition ControllerDefinition - { - get - { - if (IsGameGear) - { - return GGController; - } - - return SmsController; - } - } - - public IController Controller { get; set; } - - byte ReadControls1() + private byte ReadControls1() { InputCallbacks.Call(); - lagged = false; + _lagged = false; byte value = 0xFF; if (Controller["P1 Up"]) value &= 0xFE; @@ -59,10 +44,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem return value; } - byte ReadControls2() + private byte ReadControls2() { InputCallbacks.Call(); - lagged = false; + _lagged = false; byte value = 0xFF; if (Controller["P2 Left"]) value &= 0xFE; @@ -74,7 +59,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem if ((Port3F & 0x0F) == 5) { - if (region == "Japan") + if (_region == "Japan") { value &= 0x3F; } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index 2e5165cc95..622fe2afb3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -1,11 +1,7 @@ using System; using System.Collections.Generic; -using System.IO; -using BizHawk.Common; -using BizHawk.Common.NumberExtensions; using BizHawk.Common.StringExtensions; - using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.Components; using BizHawk.Emulation.Cores.Components.Z80; @@ -32,68 +28,39 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem IDebuggable, ISettable, ICodeDataLogger { // Constants - public const int BankSize = 16384; + private const int BankSize = 16384; // ROM - public byte[] RomData; - public byte RomBank0, RomBank1, RomBank2, RomBank3; - public byte RomBanks; - - // SaveRAM - public byte[] SaveRAM; - public byte SaveRamBank; - - public byte[] BiosRom; - - public byte[] CloneSaveRam() - { - if (SaveRAM != null) - return (byte[])SaveRAM.Clone(); - else - return null; - } - public void StoreSaveRam(byte[] data) - { - if (SaveRAM != null) - Array.Copy(data, SaveRAM, data.Length); - } - - public bool SaveRamModified { get; private set; } + private byte[] RomData; + private byte RomBank0, RomBank1, RomBank2, RomBank3; + private byte RomBanks; + private byte[] BiosRom; // Machine resources - public Z80A Cpu; - public byte[] SystemRam; + private Z80A Cpu; + private byte[] SystemRam; public VDP Vdp; - public SN76489 PSG; - public YM2413 YM2413; - public SoundMixer SoundMixer; - public bool IsGameGear = false; - public bool IsSG1000 = false; + private SN76489 PSG; + private YM2413 YM2413; + private SoundMixer SoundMixer; + public bool IsGameGear { get; set; } + public bool IsSG1000 { get; set; } - public bool HasYM2413 = false; + private bool HasYM2413 = false; - int frame = 0; - int lagCount = 0; - bool lagged = true; - bool isLag = false; + private int frame = 0; + 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; } } - public IMemoryCallbackSystem MemoryCallbacks { get; private set; } + private byte Port01 = 0xFF; + private byte Port02 = 0xFF; + private byte Port3E = 0xAF; + private byte Port3F = 0xFF; - byte Port01 = 0xFF; - byte Port02 = 0xFF; - byte Port3E = 0xAF; - byte Port3F = 0xFF; - - byte ForceStereoByte = 0xAD; - bool IsGame3D = false; + private byte ForceStereoByte = 0xAD; + private bool IsGame3D = false; public DisplayType Region { get; set; } - public bool DeterministicEmulation { get { return true; } } [CoreConstructor("SMS", "SG", "GG")] public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) @@ -217,16 +184,15 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); + InputCallbacks = new InputCallbackSystem(); + Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register(Tracer); serviceProvider.Register(new Disassembler()); - } - public IEmulatorServiceProvider ServiceProvider { get; private set; } - private ITraceable Tracer { get; set; } string DetermineRegion(string gameRegion) @@ -246,7 +212,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem return "Japan"; } - DisplayType DetermineDisplayType(string display, string region) + private DisplayType DetermineDisplayType(string display, string region) { if (display == "NTSC") return DisplayType.NTSC; if (display == "PAL") return DisplayType.PAL; @@ -254,32 +220,25 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem return DisplayType.NTSC; } - public void ResetCounters() - { - Frame = 0; - lagCount = 0; - isLag = false; - } - /// /// The ReadMemory callback for the mapper /// - Func ReadMemory; + private Func ReadMemory; /// /// The WriteMemory callback for the wrapper /// - Action WriteMemory; + private Action WriteMemory; /// /// A dummy FetchMemory that simply reads the memory /// - public byte FetchMemory_StubThunk(ushort address, bool first) + private byte FetchMemory_StubThunk(ushort address, bool first) { return ReadMemory(address); } - public byte ReadPort(ushort port) + private byte ReadPort(ushort port) { port &= 0xFF; if (port < 0x40) // General IO ports @@ -322,7 +281,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } } - public void WritePort(ushort port, byte value) + private void WritePort(ushort port, byte value) { port &= 0xFF; if (port < 0x40) // general IO ports @@ -350,357 +309,23 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem else if (port == 0xF2 && HasYM2413) YM2413.DetectionValue = value; } - public void FrameAdvance(bool render, bool rendersound) + private ISoundProvider ActiveSoundProvider; + + private string _region; + private string RegionStr { - lagged = true; - Frame++; - PSG.BeginFrame(Cpu.TotalExecutedCycles); - Cpu.Debug = Tracer.Enabled; - if (!IsGameGear) - PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte) 0xFF; - - if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first - Cpu.Logger = (s) => Tracer.Put(s); - - if (IsGameGear == false) - Cpu.NonMaskableInterrupt = Controller["Pause"]; - - if (IsGame3D && Settings.Fix3D) - Vdp.ExecFrame((Frame & 1) == 0); - else - Vdp.ExecFrame(render); - - PSG.EndFrame(Cpu.TotalExecutedCycles); - if (lagged) - { - lagCount++; - isLag = true; - } - else - isLag = false; - } - - 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("SMS"); - Cpu.SyncState(ser); - Vdp.SyncState(ser); - PSG.SyncState(ser); - ser.Sync("RAM", ref SystemRam, false); - ser.Sync("RomBank0", ref RomBank0); - ser.Sync("RomBank1", ref RomBank1); - ser.Sync("RomBank2", ref RomBank2); - ser.Sync("RomBank3", ref RomBank3); - ser.Sync("Port01", ref Port01); - ser.Sync("Port02", ref Port02); - ser.Sync("Port3E", ref Port3E); - ser.Sync("Port3F", ref Port3F); - - if (SaveRAM != null) - { - ser.Sync("SaveRAM", ref SaveRAM, false); - ser.Sync("SaveRamBank", ref SaveRamBank); - } - if (ExtRam != null) - ser.Sync("ExtRAM", ref ExtRam, true); - if (HasYM2413) - YM2413.SyncState(ser); - - ser.Sync("Frame", ref frame); - ser.Sync("LagCount", ref lagCount); - ser.Sync("IsLag", ref isLag); - - ser.EndSection(); - } - - byte[] stateBuffer; - public byte[] SaveStateBinary() - { - if (stateBuffer == null) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - stateBuffer = stream.ToArray(); - writer.Close(); - return stateBuffer; - } - else - { - var stream = new MemoryStream(stateBuffer); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Close(); - return stateBuffer; - } - } - - public CoreComm CoreComm { get; private set; } - - ISoundProvider ActiveSoundProvider; - public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } } - public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(ActiveSoundProvider, 735); } } - public bool StartAsyncSound() { return true; } - public void EndAsyncSound() { } - - public string SystemId { get { return "SMS"; } } - - public string BoardName { get { return null; } } - - string region; - public string RegionStr - { - get { return region; } + get { return _region; } set { if (value.NotIn(validRegions)) + { throw new Exception("Passed value " + value + " is not a valid region!"); - region = value; + } + + _region = value; } } - readonly string[] validRegions = { "Export", "Japan", "Auto" }; - - MemoryDomainList memoryDomains; - - void SetupMemoryDomains() - { - var domains = new List(3); - var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, MemoryDomain.Endian.Little, - addr => SystemRam[addr], - (addr, value) => SystemRam[addr] = value); - var VRamDomain = new MemoryDomain("Video RAM", Vdp.VRAM.Length, MemoryDomain.Endian.Little, - addr => Vdp.VRAM[addr], - (addr, value) => Vdp.VRAM[addr] = value); - - var ROMDomain = new MemoryDomain("ROM", RomData.Length, MemoryDomain.Endian.Little, - addr => RomData[addr], - (addr, value) => RomData[addr] = value); - - var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, MemoryDomain.Endian.Little, - (addr) => - { - if (addr < 0 || addr >= 65536) - throw new ArgumentOutOfRangeException(); - return Cpu.ReadMemory((ushort)addr); - }, - (addr, value) => - { - if (addr < 0 || addr >= 65536) - throw new ArgumentOutOfRangeException(); - Cpu.WriteMemory((ushort)addr, value); - }); - - domains.Add(MainMemoryDomain); - domains.Add(VRamDomain); - domains.Add(ROMDomain); - domains.Add(SystemBusDomain); - - if (SaveRAM != null) - { - var SaveRamDomain = new MemoryDomain("Save RAM", SaveRAM.Length, MemoryDomain.Endian.Little, - addr => SaveRAM[addr], - (addr, value) => { SaveRAM[addr] = value; SaveRamModified = true; }); - domains.Add(SaveRamDomain); - } - if (ExtRam != null) - { - var ExtRamDomain = new MemoryDomain("Cart (Volatile) RAM", ExtRam.Length, MemoryDomain.Endian.Little, - addr => ExtRam[addr], - (addr, value) => { ExtRam[addr] = value; }); - domains.Add(ExtRamDomain); - } - memoryDomains = new MemoryDomainList(domains); - (ServiceProvider as BasicServiceProvider).Register(memoryDomains); - } - - public IDictionary GetCpuFlagsAndRegisters() - { - return new Dictionary - { - { "A", Cpu.RegisterA }, - { "AF", Cpu.RegisterAF }, - { "B", Cpu.RegisterB }, - { "BC", Cpu.RegisterBC }, - { "C", Cpu.RegisterC }, - { "D", Cpu.RegisterD }, - { "DE", Cpu.RegisterDE }, - { "E", Cpu.RegisterE }, - { "F", Cpu.RegisterF }, - { "H", Cpu.RegisterH }, - { "HL", Cpu.RegisterHL }, - { "I", Cpu.RegisterI }, - { "IX", Cpu.RegisterIX }, - { "IY", Cpu.RegisterIY }, - { "L", Cpu.RegisterL }, - { "PC", Cpu.RegisterPC }, - { "R", Cpu.RegisterR }, - { "Shadow AF", Cpu.RegisterShadowAF }, - { "Shadow BC", Cpu.RegisterShadowBC }, - { "Shadow DE", Cpu.RegisterShadowDE }, - { "Shadow HL", Cpu.RegisterShadowHL }, - { "SP", Cpu.RegisterSP }, - { "Flag C", Cpu.RegisterF.Bit(0) }, - { "Flag N", Cpu.RegisterF.Bit(1) }, - { "Flag P/V", Cpu.RegisterF.Bit(2) }, - { "Flag 3rd", Cpu.RegisterF.Bit(3) }, - { "Flag H", Cpu.RegisterF.Bit(4) }, - { "Flag 5th", Cpu.RegisterF.Bit(5) }, - { "Flag Z", Cpu.RegisterF.Bit(6) }, - { "Flag S", Cpu.RegisterF.Bit(7) }, - }; - } - - public void SetCpuRegister(string register, int value) - { - switch (register) - { - default: - throw new InvalidOperationException(); - case "A": - Cpu.RegisterA = (byte)value; - break; - case "AF": - Cpu.RegisterAF = (byte)value; - break; - case "B": - Cpu.RegisterB = (byte)value; - break; - case "BC": - Cpu.RegisterBC = (byte)value; - break; - case "C": - Cpu.RegisterC = (byte)value; - break; - case "D": - Cpu.RegisterD = (byte)value; - break; - case "DE": - Cpu.RegisterDE = (byte)value; - break; - case "E": - Cpu.RegisterE = (byte)value; - break; - case "F": - Cpu.RegisterF = (byte)value; - break; - case "H": - Cpu.RegisterH = (byte)value; - break; - case "HL": - Cpu.RegisterHL = (byte)value; - break; - case "I": - Cpu.RegisterI = (byte)value; - break; - case "IX": - Cpu.RegisterIX = (byte)value; - break; - case "IY": - Cpu.RegisterIY = (byte)value; - break; - case "L": - Cpu.RegisterL = (byte)value; - break; - case "PC": - Cpu.RegisterPC = (ushort)value; - break; - case "R": - Cpu.RegisterR = (byte)value; - break; - case "Shadow AF": - Cpu.RegisterShadowAF = (byte)value; - break; - case "Shadow BC": - Cpu.RegisterShadowBC = (byte)value; - break; - case "Shadow DE": - Cpu.RegisterShadowDE = (byte)value; - break; - case "Shadow HL": - Cpu.RegisterShadowHL = (byte)value; - break; - case "SP": - Cpu.RegisterSP = (byte)value; - break; - } - } - - public bool CanStep(StepType type) { return false; } - - [FeatureNotImplemented] - public void Step(StepType type) { throw new NotImplementedException(); } - - public void Dispose() { } - - public SMSSettings GetSettings() { return Settings.Clone(); } - public SMSSyncSettings GetSyncSettings() { return SyncSettings.Clone(); } - public bool PutSettings(SMSSettings o) - { - bool ret = SMSSettings.RebootNeeded(Settings, o); - Settings = o; - return ret; - } - public bool PutSyncSettings(SMSSyncSettings o) - { - bool ret = SMSSyncSettings.RebootNeeded(SyncSettings, o); - SyncSettings = o; - return ret; - } - - public SMSSettings Settings; - public SMSSyncSettings SyncSettings; - - public class SMSSettings - { - // Game settings - public bool ForceStereoSeparation = false; - public bool SpriteLimit = false; - public bool Fix3D = true; - // GG settings - public bool ShowClippedRegions = false; - public bool HighlightActiveDisplayRegion = false; - // graphics settings - public bool DispBG = true; - public bool DispOBJ = true; - - public SMSSettings Clone() - { - return (SMSSettings)MemberwiseClone(); - } - public static bool RebootNeeded(SMSSettings x, SMSSettings y) - { - return false; - } - } - - public class SMSSyncSettings - { - public bool EnableFM = true; - public bool AllowOverlock = false; - public bool UseBIOS = false; - public string ConsoleRegion = "Export"; - public string DisplayType = "NTSC"; - - public SMSSyncSettings Clone() - { - return (SMSSyncSettings)MemberwiseClone(); - } - public static bool RebootNeeded(SMSSyncSettings x, SMSSyncSettings y) - { - return - x.EnableFM != y.EnableFM || - x.AllowOverlock != y.AllowOverlock || - x.UseBIOS != y.UseBIOS || - x.ConsoleRegion != y.ConsoleRegion || - x.DisplayType != y.DisplayType; - } - } + private readonly string[] validRegions = { "Export", "Japan", "Auto" }; } } \ No newline at end of file