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

View File

@ -107,7 +107,7 @@
<Compile Include="BinaryQuickSerializer.cs" />
<Compile Include="BizInvoke\BizInvoker.cs" />
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
<Compile Include="CodeDataLog.cs" />
<Compile Include="Base Implementations\CodeDataLog.cs" />
<Compile Include="CoreAttributes.cs" />
<Compile Include="CoreComms.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
{
@ -11,17 +13,64 @@ namespace BizHawk.Emulation.Common
/// <summary>
/// Sets the CodeDataLog as current (and logging) on the core
/// </summary>
void SetCDL(CodeDataLog cdl);
void SetCDL(ICodeDataLog cdl);
/// <summary>
/// Fills a new CodeDataLog with memory domain information suitable for the core
/// </summary>
void NewCDL(CodeDataLog cdl);
void NewCDL(ICodeDataLog cdl);
/// <summary>
/// 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
/// </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 void DisassembleCDL(Stream s, CodeDataLog cdl, IMemoryDomains mem)
public void DisassembleCDL(Stream s, ICodeDataLog cdl, IMemoryDomains mem)
{
var w = new StreamWriter(s);
w.WriteLine("; Bizhawk CDL Disassembly");
@ -78,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
public MemMapping[] Mappings; // = new MemMapping[256];
public CodeDataLog CDL = null;
public ICodeDataLog CDL = null;
[Flags]
public enum CDLUsage : byte

View File

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

View File

@ -1,24 +1,24 @@
using System;
using System.IO;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
using System;
using System.IO;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
partial class GambatteLink
{
void ICodeDataLogger.SetCDL(CodeDataLog cdl)
partial class GambatteLink
{
void ICodeDataLogger.SetCDL(ICodeDataLog cdl)
{
((ICodeDataLogger)L).SetCDL(cdl);
}
void ICodeDataLogger.NewCDL(CodeDataLog cdl)
{
((ICodeDataLogger)L).NewCDL(cdl);
((ICodeDataLogger)L).SetCDL(cdl);
}
void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl) { ((ICodeDataLogger)L).DisassembleCDL(s, cdl); }
}
void ICodeDataLogger.NewCDL(ICodeDataLog cdl)
{
((ICodeDataLogger)L).NewCDL(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);
}
public void QUERY_set_cdl(CodeDataLog cdl)
public void QUERY_set_cdl(ICodeDataLog cdl)
{
WritePipeMessage(eMessage.eMessage_QUERY_set_cdl);
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();
currCdl = cdl;
@ -186,7 +186,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
api.QUERY_set_cdl(currCdl);
}
public void NewCDL(CodeDataLog cdl)
public void NewCDL(ICodeDataLog cdl)
{
cdl["CARTROM"] = new byte[MemoryDomains["CARTROM"].Size];
@ -200,7 +200,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
cdl.SubVer = 0;
}
public void DisassembleCDL(Stream s, CodeDataLog cdl)
public void DisassembleCDL(Stream s, ICodeDataLog cdl)
{
//not supported yet
}

View File

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

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{
public sealed partial class SMS : ICodeDataLogger
{
public void SetCDL(CodeDataLog cdl)
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
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["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size];
@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
}
[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 MapMemoryDelegate MapMemory;
private CodeDataLog CDL;
private ICodeDataLog CDL;
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 void SetCDL(CodeDataLog cdl)
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null) LibGPGX.gpgx_set_cd_callback(null);
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["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size];
@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
// TODO: we have Disassembling now
// 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)
{
//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 void SetCDL(CodeDataLog cdl)
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null) Core.gpgx_set_cd_callback(null);
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["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size];
@ -29,9 +29,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
// TODO: we have Disassembling now
// 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)
{
//TODO - hard reset makes CDL go nuts.