Make an interface for CodeDataLog, and move CodeDataLog to Base Implementations

This commit is contained in:
adelikat 2016-12-16 11:33:02 -06:00
parent 691632f188
commit eda79c2212
12 changed files with 158 additions and 67 deletions

View File

@ -1,17 +1,20 @@
using System; using System;
using System.Runtime.InteropServices;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; using System.IO;
using BizHawk.Emulation.Common; using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
public class CodeDataLog : Dictionary<string, byte[]> /// <summary>
/// The base implementation of ICodeDataLog
/// </summary>
/// <seealso cref="ICodeDataLogger" />
/// <seealso cref="ICodeDataLog" />
public class CodeDataLog : Dictionary<string, byte[]>, ICodeDataLog
{ {
public CodeDataLog() public CodeDataLog()
{ {
Active = true;
} }
/// <summary> /// <summary>
@ -20,10 +23,15 @@ namespace BizHawk.Emulation.Common
public void Pin() public void Pin()
{ {
if (Pins.Count != 0) if (Pins.Count != 0)
{
throw new InvalidOperationException("incremental astrological examination"); throw new InvalidOperationException("incremental astrological examination");
}
foreach (var kvp in this) foreach (var kvp in this)
{
Pins[kvp.Key] = GCHandle.Alloc(kvp.Value, GCHandleType.Pinned); Pins[kvp.Key] = GCHandle.Alloc(kvp.Value, GCHandleType.Pinned);
} }
}
/// <summary> /// <summary>
/// Unpins the managed arrays, to be paired with calls to Pin() /// Unpins the managed arrays, to be paired with calls to Pin()
@ -31,7 +39,10 @@ namespace BizHawk.Emulation.Common
public void Unpin() public void Unpin()
{ {
foreach (var pin in Pins.Values) foreach (var pin in Pins.Values)
{
pin.Free(); pin.Free();
}
Pins.Clear(); Pins.Clear();
} }
@ -46,49 +57,67 @@ namespace BizHawk.Emulation.Common
/// <summary> /// <summary>
/// Pinned managed arrays /// Pinned managed arrays
/// </summary> /// </summary>
Dictionary<string, GCHandle> Pins = new Dictionary<string, GCHandle>(); private readonly Dictionary<string, GCHandle> Pins = new Dictionary<string, GCHandle>();
/// <summary> /// <summary>
/// Whether the CDL is tracking a block with the given name /// Whether the CDL is tracking a block with the given name
/// </summary> /// </summary>
public bool Has(string blockname) { return ContainsKey(blockname); } public bool Has(string blockname)
{
return ContainsKey(blockname);
}
/// <summary> /// <summary>
/// This is just a hook, if needed, to readily suspend logging, without having to rewire the core /// This is just a hook, if needed, to readily suspend logging, without having to rewire the core
/// </summary> /// </summary>
public bool Active = true; public bool Active { get; set; }
public string SubType; public string SubType { get; set; }
public int SubVer; public int SubVer { get; set; }
/// <summary> /// <summary>
/// Tests whether the other CodeDataLog is structurally identical /// Tests whether the other CodeDataLog is structurally identical
/// </summary> /// </summary>
public bool Check(CodeDataLog other) public bool Check(ICodeDataLog other)
{ {
if (SubType != other.SubType) if (SubType != other.SubType)
{
return false; return false;
if (SubVer != other.SubVer) }
return false;
if (this.Count != other.Count) if (SubVer != other.SubVer)
{
return false; return false;
}
if (Count != other.Count)
{
return false;
}
foreach (var kvp in this) foreach (var kvp in this)
{ {
if (!other.ContainsKey(kvp.Key)) if (!other.ContainsKey(kvp.Key))
{
return false; return false;
}
var oval = other[kvp.Key]; var oval = other[kvp.Key];
if (oval.Length != kvp.Value.Length) if (oval.Length != kvp.Value.Length)
{
return false; return false;
} }
}
return true; return true;
} }
public void LogicalOrFrom(CodeDataLog other) public void LogicalOrFrom(ICodeDataLog other)
{
if (Count != other.Count)
{ {
if (this.Count != other.Count)
throw new InvalidDataException("Dictionaries must have the same number of keys!"); throw new InvalidDataException("Dictionaries must have the same number of keys!");
}
foreach (var kvp in other) foreach (var kvp in other)
{ {
@ -96,25 +125,31 @@ namespace BizHawk.Emulation.Common
byte[] todata = this[kvp.Key]; byte[] todata = this[kvp.Key];
if (fromdata.Length != todata.Length) if (fromdata.Length != todata.Length)
{
throw new InvalidDataException("Memory regions must be the same size!"); throw new InvalidDataException("Memory regions must be the same size!");
}
for (int i = 0; i < todata.Length; i++) for (int i = 0; i < todata.Length; i++)
{
todata[i] |= fromdata[i]; todata[i] |= fromdata[i];
} }
} }
}
public void ClearData() public void ClearData()
{ {
foreach (byte[] data in Values) foreach (byte[] data in Values)
{
Array.Clear(data, 0, data.Length); Array.Clear(data, 0, data.Length);
} }
}
public void Save(Stream s) public void Save(Stream s)
{ {
_Save(s, true); _Save(s, true);
} }
Dictionary<string, long> _Save(Stream s, bool forReal) private Dictionary<string, long> _Save(Stream s, bool forReal)
{ {
var ret = new Dictionary<string, long>(); var ret = new Dictionary<string, long>();
var w = new BinaryWriter(s); var w = new BinaryWriter(s);
@ -142,6 +177,7 @@ namespace BizHawk.Emulation.Common
addr += kvp.Value.Length; addr += kvp.Value.Length;
} }
} }
w.Flush(); w.Flush();
return ret; return ret;
} }
@ -156,11 +192,17 @@ namespace BizHawk.Emulation.Common
var br = new BinaryReader(s); var br = new BinaryReader(s);
string id = br.ReadString(); string id = br.ReadString();
if (id == "BIZHAWK-CDL-1") if (id == "BIZHAWK-CDL-1")
{
SubType = "PCE"; SubType = "PCE";
}
else if (id == "BIZHAWK-CDL-2") else if (id == "BIZHAWK-CDL-2")
{
SubType = br.ReadString().TrimEnd(' '); SubType = br.ReadString().TrimEnd(' ');
}
else else
{
throw new InvalidDataException("File is not a Bizhawk CDL file!"); throw new InvalidDataException("File is not a Bizhawk CDL file!");
}
int count = br.ReadInt32(); int count = br.ReadInt32();
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)

View File

@ -107,7 +107,7 @@
<Compile Include="BinaryQuickSerializer.cs" /> <Compile Include="BinaryQuickSerializer.cs" />
<Compile Include="BizInvoke\BizInvoker.cs" /> <Compile Include="BizInvoke\BizInvoker.cs" />
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" /> <Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
<Compile Include="CodeDataLog.cs" /> <Compile Include="Base Implementations\CodeDataLog.cs" />
<Compile Include="CoreAttributes.cs" /> <Compile Include="CoreAttributes.cs" />
<Compile Include="CoreComms.cs" /> <Compile Include="CoreComms.cs" />
<Compile Include="Database\CRC32.cs" /> <Compile Include="Database\CRC32.cs" />

View File

@ -1,4 +1,6 @@
using System.IO; using System;
using System.IO;
using System.Collections.Generic;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
@ -11,17 +13,64 @@ namespace BizHawk.Emulation.Common
/// <summary> /// <summary>
/// Sets the CodeDataLog as current (and logging) on the core /// Sets the CodeDataLog as current (and logging) on the core
/// </summary> /// </summary>
void SetCDL(CodeDataLog cdl); void SetCDL(ICodeDataLog cdl);
/// <summary> /// <summary>
/// Fills a new CodeDataLog with memory domain information suitable for the core /// Fills a new CodeDataLog with memory domain information suitable for the core
/// </summary> /// </summary>
void NewCDL(CodeDataLog cdl); void NewCDL(ICodeDataLog cdl);
/// <summary> /// <summary>
/// Disassembles the CodeDataLog to an output Stream. Can't be done without a core because there's no code to disassemble otherwise! /// Disassembles the CodeDataLog to an output Stream. Can't be done without a core because there's no code to disassemble otherwise!
/// This could be extended later to produce richer multi-file disassembly /// This could be extended later to produce richer multi-file disassembly
/// </summary> /// </summary>
void DisassembleCDL(Stream s, CodeDataLog cdl); void DisassembleCDL(Stream s, ICodeDataLog cdl);
}
/// <summary>
/// Defines a code/data log to be used with the code/data logger
/// </summary>
/// <seealso cref="ICodeDataLogger" />
public interface ICodeDataLog : IDictionary<string, byte[]>
{
/// <summary>
/// Pins the managed arrays. Not that we expect them to be allocated, but in case we do, seeing thish ere will remind us to check for the pin condition and abort
/// </summary>
void Pin();
/// <summary>
/// Unpins the managed arrays, to be paired with calls to Pin()
/// </summary>
void Unpin();
/// <summary>
/// Retrieves the pointer to a managed array
/// </summary>
IntPtr GetPin(string key);
/// <summary>
/// Whether the CDL is tracking a block with the given name
/// </summary>
bool Has(string blockname);
/// <summary>
/// This is just a hook, if needed, to readily suspend logging, without having to rewire the core
/// </summary>
bool Active { get; set; }
string SubType { get; set; }
int SubVer { get; set; }
/// <summary>
/// Tests whether the other CodeDataLog is structurally identical
/// </summary>
bool Check(ICodeDataLog other);
void LogicalOrFrom(ICodeDataLog other);
void ClearData();
void Save(Stream s);
} }
} }

View File

@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
{ {
public partial class HuC6280 public partial class HuC6280
{ {
public void DisassembleCDL(Stream s, CodeDataLog cdl, IMemoryDomains mem) public void DisassembleCDL(Stream s, ICodeDataLog cdl, IMemoryDomains mem)
{ {
var w = new StreamWriter(s); var w = new StreamWriter(s);
w.WriteLine("; Bizhawk CDL Disassembly"); w.WriteLine("; Bizhawk CDL Disassembly");
@ -78,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
public MemMapping[] Mappings; // = new MemMapping[256]; public MemMapping[] Mappings; // = new MemMapping[256];
public CodeDataLog CDL = null; public ICodeDataLog CDL = null;
[Flags] [Flags]
public enum CDLUsage : byte public enum CDLUsage : byte

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
partial class Gameboy partial class Gameboy
{ {
void ICodeDataLogger.SetCDL(CodeDataLog cdl) void ICodeDataLogger.SetCDL(ICodeDataLog cdl)
{ {
CDL = cdl; CDL = cdl;
if(cdl == null) if(cdl == null)
@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
LibGambatte.gambatte_setcdcallback(GambatteState, CDCallback); LibGambatte.gambatte_setcdcallback(GambatteState, CDCallback);
} }
void ICodeDataLogger.NewCDL(CodeDataLog cdl) void ICodeDataLogger.NewCDL(ICodeDataLog cdl)
{ {
cdl["ROM"] = new byte[MemoryDomains["ROM"].Size]; cdl["ROM"] = new byte[MemoryDomains["ROM"].Size];
@ -32,9 +32,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
} }
//not supported //not supported
void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { } void ICodeDataLogger.DisassembleCDL(Stream s, ICodeDataLog cdl) { }
CodeDataLog CDL; ICodeDataLog CDL;
LibGambatte.CDCallback CDCallback; LibGambatte.CDCallback CDCallback;
void CDCallbackProc(int addr, LibGambatte.CDLog_AddrType addrtype, LibGambatte.CDLog_Flags flags) void CDCallbackProc(int addr, LibGambatte.CDLog_AddrType addrtype, LibGambatte.CDLog_Flags flags)
{ {

View File

@ -8,17 +8,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
partial class GambatteLink partial class GambatteLink
{ {
void ICodeDataLogger.SetCDL(CodeDataLog cdl) void ICodeDataLogger.SetCDL(ICodeDataLog cdl)
{ {
((ICodeDataLogger)L).SetCDL(cdl); ((ICodeDataLogger)L).SetCDL(cdl);
} }
void ICodeDataLogger.NewCDL(CodeDataLog cdl) void ICodeDataLogger.NewCDL(ICodeDataLog cdl)
{ {
((ICodeDataLogger)L).NewCDL(cdl); ((ICodeDataLogger)L).NewCDL(cdl);
} }
void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { ((ICodeDataLogger)L).DisassembleCDL(s, cdl); } void ICodeDataLogger.DisassembleCDL(Stream s, ICodeDataLog cdl) { ((ICodeDataLogger)L).DisassembleCDL(s, cdl); }
} }
} }

View File

@ -204,7 +204,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
Marshal.Copy(temp, 0, new IntPtr(ptr), CpuRegs.SIZEOF); Marshal.Copy(temp, 0, new IntPtr(ptr), CpuRegs.SIZEOF);
} }
public void QUERY_set_cdl(CodeDataLog cdl) public void QUERY_set_cdl(ICodeDataLog cdl)
{ {
WritePipeMessage(eMessage.eMessage_QUERY_set_cdl); WritePipeMessage(eMessage.eMessage_QUERY_set_cdl);
if (cdl == null) if (cdl == null)

View File

@ -174,9 +174,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
} }
} }
CodeDataLog currCdl; ICodeDataLog currCdl;
public void SetCDL(CodeDataLog cdl) public void SetCDL(ICodeDataLog cdl)
{ {
if(currCdl != null) currCdl.Unpin(); if(currCdl != null) currCdl.Unpin();
currCdl = cdl; currCdl = cdl;
@ -186,7 +186,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
api.QUERY_set_cdl(currCdl); api.QUERY_set_cdl(currCdl);
} }
public void NewCDL(CodeDataLog cdl) public void NewCDL(ICodeDataLog cdl)
{ {
cdl["CARTROM"] = new byte[MemoryDomains["CARTROM"].Size]; cdl["CARTROM"] = new byte[MemoryDomains["CARTROM"].Size];
@ -200,7 +200,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
cdl.SubVer = 0; cdl.SubVer = 0;
} }
public void DisassembleCDL(Stream s, CodeDataLog cdl) public void DisassembleCDL(Stream s, ICodeDataLog cdl)
{ {
//not supported yet //not supported yet
} }

View File

@ -8,12 +8,12 @@ namespace BizHawk.Emulation.Cores.PCEngine
{ {
public sealed partial class PCEngine : ICodeDataLogger public sealed partial class PCEngine : ICodeDataLogger
{ {
public void SetCDL(CodeDataLog cdl) public void SetCDL(ICodeDataLog cdl)
{ {
Cpu.CDL = cdl; Cpu.CDL = cdl;
} }
public void NewCDL(CodeDataLog cdl) public void NewCDL(ICodeDataLog cdl)
{ {
InitCDLMappings(); InitCDLMappings();
var mm = this.Cpu.Mappings; var mm = this.Cpu.Mappings;
@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
cdl.SubVer = 0; cdl.SubVer = 0;
} }
public void DisassembleCDL(Stream s, CodeDataLog cdl) public void DisassembleCDL(Stream s, ICodeDataLog cdl)
{ {
Cpu.DisassembleCDL(s, cdl, _memoryDomains); Cpu.DisassembleCDL(s, cdl, _memoryDomains);
} }

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{ {
public sealed partial class SMS : ICodeDataLogger public sealed partial class SMS : ICodeDataLogger
{ {
public void SetCDL(CodeDataLog cdl) public void SetCDL(ICodeDataLog cdl)
{ {
CDL = cdl; CDL = cdl;
if (cdl == null) if (cdl == null)
@ -23,7 +23,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
} }
} }
public void NewCDL(CodeDataLog cdl) public void NewCDL(ICodeDataLog cdl)
{ {
cdl["ROM"] = new byte[MemoryDomains["ROM"].Size]; cdl["ROM"] = new byte[MemoryDomains["ROM"].Size];
cdl["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size]; cdl["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size];
@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
} }
[FeatureNotImplemented] [FeatureNotImplemented]
public void DisassembleCDL(Stream s, CodeDataLog cdl) public void DisassembleCDL(Stream s, ICodeDataLog cdl)
{ {
} }
@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write); private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write);
private MapMemoryDelegate MapMemory; private MapMemoryDelegate MapMemory;
private CodeDataLog CDL; private ICodeDataLog CDL;
private void RunCDL(ushort address, CDLog_Flags flags) private void RunCDL(ushort address, CDLog_Flags flags)
{ {

View File

@ -7,14 +7,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{ {
public partial class GPGX : ICodeDataLogger public partial class GPGX : ICodeDataLogger
{ {
public void SetCDL(CodeDataLog cdl) public void SetCDL(ICodeDataLog cdl)
{ {
CDL = cdl; CDL = cdl;
if (cdl == null) LibGPGX.gpgx_set_cd_callback(null); if (cdl == null) LibGPGX.gpgx_set_cd_callback(null);
else LibGPGX.gpgx_set_cd_callback(CDCallback); else LibGPGX.gpgx_set_cd_callback(CDCallback);
} }
public void NewCDL(CodeDataLog cdl) public void NewCDL(ICodeDataLog cdl)
{ {
cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size]; cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size];
cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size]; cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size];
@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
// TODO: we have Disassembling now // TODO: we have Disassembling now
// not supported // not supported
public void DisassembleCDL(Stream s, CodeDataLog cdl) { } public void DisassembleCDL(Stream s, ICodeDataLog cdl) { }
private CodeDataLog CDL; private ICodeDataLog CDL;
private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags) private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags)
{ {
//TODO - hard reset makes CDL go nuts. //TODO - hard reset makes CDL go nuts.

View File

@ -7,14 +7,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
public partial class GPGX : ICodeDataLogger public partial class GPGX : ICodeDataLogger
{ {
public void SetCDL(CodeDataLog cdl) public void SetCDL(ICodeDataLog cdl)
{ {
CDL = cdl; CDL = cdl;
if (cdl == null) Core.gpgx_set_cd_callback(null); if (cdl == null) Core.gpgx_set_cd_callback(null);
else Core.gpgx_set_cd_callback(CDCallback); else Core.gpgx_set_cd_callback(CDCallback);
} }
public void NewCDL(CodeDataLog cdl) public void NewCDL(ICodeDataLog cdl)
{ {
cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size]; cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size];
cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size]; cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size];
@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
// TODO: we have Disassembling now // TODO: we have Disassembling now
// not supported // not supported
public void DisassembleCDL(Stream s, CodeDataLog cdl) { } public void DisassembleCDL(Stream s, ICodeDataLog cdl) { }
private CodeDataLog CDL; private ICodeDataLog CDL;
private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags) private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags)
{ {
//TODO - hard reset makes CDL go nuts. //TODO - hard reset makes CDL go nuts.