m64p: Use built-in debugger to avoid major slowdowns when breakpoints are set.
This commit is contained in:
parent
2cc4e6bf58
commit
86b16a80d6
|
@ -1,6 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Common
|
namespace BizHawk.Emulation.Common
|
||||||
{
|
{
|
||||||
|
@ -9,11 +12,15 @@ namespace BizHawk.Emulation.Common
|
||||||
public MemoryCallbackSystem()
|
public MemoryCallbackSystem()
|
||||||
{
|
{
|
||||||
ExecuteCallbacksAvailable = true;
|
ExecuteCallbacksAvailable = true;
|
||||||
|
|
||||||
|
Reads.CollectionChanged += OnCollectionChanged;
|
||||||
|
Writes.CollectionChanged += OnCollectionChanged;
|
||||||
|
Execs.CollectionChanged += OnCollectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<IMemoryCallback> Reads = new List<IMemoryCallback>();
|
private readonly ObservableCollection<IMemoryCallback> Reads = new ObservableCollection<IMemoryCallback>();
|
||||||
private readonly List<IMemoryCallback> Writes = new List<IMemoryCallback>();
|
private readonly ObservableCollection<IMemoryCallback> Writes = new ObservableCollection<IMemoryCallback>();
|
||||||
private readonly List<IMemoryCallback> Execs = new List<IMemoryCallback>();
|
private readonly ObservableCollection<IMemoryCallback> Execs = new ObservableCollection<IMemoryCallback>();
|
||||||
|
|
||||||
private bool _empty = true;
|
private bool _empty = true;
|
||||||
|
|
||||||
|
@ -49,7 +56,7 @@ namespace BizHawk.Emulation.Common
|
||||||
_empty = false;
|
_empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Call(List<IMemoryCallback> cbs, uint addr)
|
private static void Call(ObservableCollection<IMemoryCallback> cbs, uint addr)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < cbs.Count; i++)
|
for (int i = 0; i < cbs.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -100,20 +107,28 @@ namespace BizHawk.Emulation.Common
|
||||||
private void UpdateHasVariables()
|
private void UpdateHasVariables()
|
||||||
{
|
{
|
||||||
_hasReads = Reads.Count > 0;
|
_hasReads = Reads.Count > 0;
|
||||||
_hasWrites = Reads.Count > 0;
|
_hasWrites = Writes.Count > 0;
|
||||||
_hasExecutes = Reads.Count > 0;
|
_hasExecutes = Execs.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int RemoveInternal(Action action)
|
private int RemoveInternal(Action action)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
var readsToRemove = Reads.Where(imc => imc.Callback == action).ToList();
|
||||||
ret += Reads.RemoveAll(imc => imc.Callback == action);
|
var writesToRemove = Writes.Where(imc => imc.Callback == action).ToList();
|
||||||
ret += Writes.RemoveAll(imc => imc.Callback == action);
|
var execsToRemove = Execs.Where(imc => imc.Callback == action).ToList();
|
||||||
ret += Execs.RemoveAll(imc => imc.Callback == action);
|
|
||||||
|
foreach(var read in readsToRemove)
|
||||||
|
Reads.Remove(read);
|
||||||
|
|
||||||
|
foreach(var write in writesToRemove)
|
||||||
|
Writes.Remove(write);
|
||||||
|
|
||||||
|
foreach(var exec in execsToRemove)
|
||||||
|
Execs.Remove(exec);
|
||||||
|
|
||||||
UpdateHasVariables();
|
UpdateHasVariables();
|
||||||
|
|
||||||
return ret;
|
return readsToRemove.Count + writesToRemove.Count + execsToRemove.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(Action action)
|
public void Remove(Action action)
|
||||||
|
@ -147,9 +162,16 @@ namespace BizHawk.Emulation.Common
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
Reads.Clear();
|
// Remove one-by-one to avoid NotifyCollectionChangedAction.Reset events.
|
||||||
Writes.Clear();
|
for(int i = (Reads.Count - 1); i >= 0; i--)
|
||||||
Execs.Clear();
|
Reads.RemoveAt(i);
|
||||||
|
|
||||||
|
for(int i = (Reads.Count - 1); i >= 0; i--)
|
||||||
|
Writes.RemoveAt(i);
|
||||||
|
|
||||||
|
for(int i = (Reads.Count - 1); i >= 0; i--)
|
||||||
|
Execs.RemoveAt(i);
|
||||||
|
|
||||||
if (!_empty)
|
if (!_empty)
|
||||||
Changes();
|
Changes();
|
||||||
_empty = true;
|
_empty = true;
|
||||||
|
@ -160,6 +182,12 @@ namespace BizHawk.Emulation.Common
|
||||||
public delegate void ActiveChangedEventHandler();
|
public delegate void ActiveChangedEventHandler();
|
||||||
public event ActiveChangedEventHandler ActiveChanged;
|
public event ActiveChangedEventHandler ActiveChanged;
|
||||||
|
|
||||||
|
public delegate void CallbackAddedEventHandler(IMemoryCallback callback);
|
||||||
|
public event CallbackAddedEventHandler CallbackAdded;
|
||||||
|
|
||||||
|
public delegate void CallbackRemovedEventHandler(IMemoryCallback callback);
|
||||||
|
public event CallbackRemovedEventHandler CallbackRemoved;
|
||||||
|
|
||||||
private void Changes()
|
private void Changes()
|
||||||
{
|
{
|
||||||
if (ActiveChanged != null)
|
if (ActiveChanged != null)
|
||||||
|
@ -168,6 +196,31 @@ namespace BizHawk.Emulation.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||||
|
{
|
||||||
|
switch(args.Action)
|
||||||
|
{
|
||||||
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
foreach(IMemoryCallback callback in args.NewItems)
|
||||||
|
{
|
||||||
|
if(CallbackAdded != null)
|
||||||
|
{
|
||||||
|
CallbackAdded(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
foreach(IMemoryCallback callback in args.OldItems)
|
||||||
|
{
|
||||||
|
if(CallbackRemoved != null)
|
||||||
|
{
|
||||||
|
CallbackRemoved(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerator<IMemoryCallback> GetEnumerator()
|
public IEnumerator<IMemoryCallback> GetEnumerator()
|
||||||
{
|
{
|
||||||
foreach (var imc in Reads)
|
foreach (var imc in Reads)
|
||||||
|
|
|
@ -84,74 +84,80 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
|
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem();
|
||||||
|
|
||||||
public bool CanStep(StepType type) { return false; }
|
public bool CanStep(StepType type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case StepType.Into:
|
||||||
|
return false; // Implemented but disabled for now. Should be re-enabled once BizHawk supports mid-frame pausing.
|
||||||
|
case StepType.Out:
|
||||||
|
return false;
|
||||||
|
case StepType.Over:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[FeatureNotImplemented]
|
return false;
|
||||||
public void Step(StepType type) { throw new NotImplementedException(); }
|
}
|
||||||
|
|
||||||
private mupen64plusApi.MemoryCallback _readcb;
|
public void Step(StepType type)
|
||||||
private mupen64plusApi.MemoryCallback _writecb;
|
{
|
||||||
private mupen64plusApi.MemoryCallback _executecb;
|
switch(type)
|
||||||
|
{
|
||||||
|
case StepType.Into:
|
||||||
|
api.Step();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RefreshMemoryCallbacks()
|
private void SetBreakpointHandler()
|
||||||
{
|
{
|
||||||
var mcs = MemoryCallbacks;
|
var mcs = MemoryCallbacks;
|
||||||
|
|
||||||
// we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
|
api.BreakpointHit += delegate(uint address, mupen64plusApi.BreakType type)
|
||||||
if (mcs.HasReads)
|
|
||||||
{
|
{
|
||||||
_readcb = delegate(uint addr)
|
api.OnBreakpoint(new mupen64plusApi.BreakParams
|
||||||
{
|
{
|
||||||
api.OnBreakpoint(new mupen64plusApi.BreakParams
|
_type = type,
|
||||||
{
|
_addr = address,
|
||||||
_type = mupen64plusApi.BreakType.Read,
|
_mcs = mcs
|
||||||
_addr = addr,
|
});
|
||||||
_mcs = mcs
|
};
|
||||||
});
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_readcb = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mcs.HasWrites)
|
private void AddBreakpoint(IMemoryCallback callback)
|
||||||
|
{
|
||||||
|
switch(callback.Type)
|
||||||
{
|
{
|
||||||
_writecb = delegate(uint addr)
|
case MemoryCallbackType.Read:
|
||||||
{
|
api.SetBreakpoint(mupen64plusApi.BreakType.Read, callback.Address);
|
||||||
api.OnBreakpoint(new mupen64plusApi.BreakParams
|
break;
|
||||||
{
|
|
||||||
_type = mupen64plusApi.BreakType.Write,
|
|
||||||
_addr = addr,
|
|
||||||
_mcs = mcs
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_writecb = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mcs.HasExecutes)
|
case MemoryCallbackType.Write:
|
||||||
{
|
api.SetBreakpoint(mupen64plusApi.BreakType.Write, callback.Address);
|
||||||
_executecb = delegate(uint addr)
|
break;
|
||||||
{
|
|
||||||
api.OnBreakpoint(new mupen64plusApi.BreakParams
|
|
||||||
{
|
|
||||||
_type = mupen64plusApi.BreakType.Execute,
|
|
||||||
_addr = addr,
|
|
||||||
_mcs = mcs
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_executecb = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
api.setReadCallback(_readcb);
|
case MemoryCallbackType.Execute:
|
||||||
api.setWriteCallback(_writecb);
|
api.SetBreakpoint(mupen64plusApi.BreakType.Execute, callback.Address);
|
||||||
api.setExecuteCallback(_executecb);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveBreakpoint(IMemoryCallback callback)
|
||||||
|
{
|
||||||
|
switch(callback.Type)
|
||||||
|
{
|
||||||
|
case MemoryCallbackType.Read:
|
||||||
|
api.RemoveBreakpoint(mupen64plusApi.BreakType.Read, callback.Address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MemoryCallbackType.Write:
|
||||||
|
api.RemoveBreakpoint(mupen64plusApi.BreakType.Write, callback.Address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MemoryCallbackType.Execute:
|
||||||
|
api.RemoveBreakpoint(mupen64plusApi.BreakType.Execute, callback.Address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
{
|
{
|
||||||
ServiceProvider = new BasicServiceProvider(this);
|
ServiceProvider = new BasicServiceProvider(this);
|
||||||
InputCallbacks = new InputCallbackSystem();
|
InputCallbacks = new InputCallbackSystem();
|
||||||
_memorycallbacks.ActiveChanged += RefreshMemoryCallbacks;
|
|
||||||
|
_memorycallbacks.CallbackAdded += AddBreakpoint;
|
||||||
|
_memorycallbacks.CallbackRemoved += RemoveBreakpoint;
|
||||||
|
|
||||||
int SaveType = 0;
|
int SaveType = 0;
|
||||||
if (game.OptionValue("SaveType") == "EEPROM_16K")
|
if (game.OptionValue("SaveType") == "EEPROM_16K")
|
||||||
|
@ -149,9 +151,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
api.AttachPlugin(mupen64plusApi.m64p_plugin_type.M64PLUGIN_RSP, rsp);
|
api.AttachPlugin(mupen64plusApi.m64p_plugin_type.M64PLUGIN_RSP, rsp);
|
||||||
|
|
||||||
InitMemoryDomains();
|
InitMemoryDomains();
|
||||||
RefreshMemoryCallbacks();
|
|
||||||
if (_syncSettings.Core != N64SyncSettings.CoreType.Dynarec)
|
if (_syncSettings.Core != N64SyncSettings.CoreType.Dynarec)
|
||||||
|
{
|
||||||
ConnectTracer();
|
ConnectTracer();
|
||||||
|
SetBreakpointHandler();
|
||||||
|
}
|
||||||
|
|
||||||
api.AsyncExecuteEmulator();
|
api.AsyncExecuteEmulator();
|
||||||
|
|
||||||
|
@ -226,8 +230,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
{
|
{
|
||||||
IsVIFrame = false;
|
IsVIFrame = false;
|
||||||
|
|
||||||
RefreshMemoryCallbacks();
|
|
||||||
|
|
||||||
if (Tracer != null && Tracer.Enabled)
|
if (Tracer != null && Tracer.Enabled)
|
||||||
{
|
{
|
||||||
api.setTraceCallback(_tracecb);
|
api.setTraceCallback(_tracecb);
|
||||||
|
|
|
@ -94,6 +94,47 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
M64CMD_SET_RENDER_CALLBACK
|
M64CMD_SET_RENDER_CALLBACK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private enum m64p_dbg_bkp_command
|
||||||
|
{
|
||||||
|
M64P_BKP_CMD_ADD_ADDR = 1,
|
||||||
|
M64P_BKP_CMD_ADD_STRUCT,
|
||||||
|
M64P_BKP_CMD_GET_STRUCT,
|
||||||
|
M64P_BKP_CMD_REPLACE,
|
||||||
|
M64P_BKP_CMD_REMOVE_ADDR,
|
||||||
|
M64P_BKP_CMD_REMOVE_IDX,
|
||||||
|
M64P_BKP_CMD_ENABLE,
|
||||||
|
M64P_BKP_CMD_DISABLE,
|
||||||
|
M64P_BKP_CMD_CHECK
|
||||||
|
};
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum m64p_dbg_bkp_flags
|
||||||
|
{
|
||||||
|
M64P_BPT_FLAG_ENABLED = 0x01,
|
||||||
|
M64P_BPT_FLAG_CONDITIONAL = 0x02,
|
||||||
|
M64P_BPT_FLAG_COUNTER = 0x04,
|
||||||
|
M64P_BPT_FLAG_READ = 0x08,
|
||||||
|
M64P_BPT_FLAG_WRITE = 0x10,
|
||||||
|
M64P_BPT_FLAG_EXEC = 0x20,
|
||||||
|
M64P_BPT_FLAG_LOG = 0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
private enum m64p_dbg_state
|
||||||
|
{
|
||||||
|
M64P_DBG_RUN_STATE = 1,
|
||||||
|
M64P_DBG_PREVIOUS_PC,
|
||||||
|
M64P_DBG_NUM_BREAKPOINTS,
|
||||||
|
M64P_DBG_CPU_DYNACORE,
|
||||||
|
M64P_DBG_CPU_NEXT_INTERRUPT
|
||||||
|
};
|
||||||
|
|
||||||
|
private enum m64p_dbg_runstate
|
||||||
|
{
|
||||||
|
M64P_DBG_RUNSTATE_PAUSED = 0,
|
||||||
|
M64P_DBG_RUNSTATE_STEPPING,
|
||||||
|
M64P_DBG_RUNSTATE_RUNNING
|
||||||
|
};
|
||||||
|
|
||||||
public enum m64p_emu_state
|
public enum m64p_emu_state
|
||||||
{
|
{
|
||||||
M64EMU_STOPPED = 1,
|
M64EMU_STOPPED = 1,
|
||||||
|
@ -127,6 +168,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
THE_ROM
|
THE_ROM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct m64p_breakpoint
|
||||||
|
{
|
||||||
|
public uint address;
|
||||||
|
public uint endaddr;
|
||||||
|
public uint flags;
|
||||||
|
}
|
||||||
|
|
||||||
// Core Specifc functions
|
// Core Specifc functions
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -362,34 +411,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void StartupCallback();
|
public delegate void StartupCallback();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type of the read/write memory callbacks
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">The address which the cpu is read/writing</param>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void MemoryCallback(uint address);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the memory read callback
|
|
||||||
/// </summary>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void SetReadCallback(MemoryCallback callback);
|
|
||||||
SetReadCallback m64pSetReadCallback;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the memory write callback
|
|
||||||
/// </summary>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void SetWriteCallback(MemoryCallback callback);
|
|
||||||
SetWriteCallback m64pSetWriteCallback;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the memory execute callback
|
|
||||||
/// </summary>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void SetExecuteCallback(MemoryCallback callback);
|
|
||||||
SetExecuteCallback m64pSetExecuteCallback;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of the trace callback
|
/// Type of the trace callback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -410,6 +431,68 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
public delegate void GetRegisters(byte[] dest);
|
public delegate void GetRegisters(byte[] dest);
|
||||||
GetRegisters m64pGetRegisters;
|
GetRegisters m64pGetRegisters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will be called when the debugger is initialized
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void DebugInitCallback();
|
||||||
|
DebugInitCallback m64pDebugInitCallback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will be called when the debugger hits a breakpoint or executes one instruction in stepping mode
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void DebugUpdateCallback(int bpt);
|
||||||
|
DebugUpdateCallback m64pDebugUpdateCallback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will be called during each vertical interrupt
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void DebugVICallback();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the debug callbacks
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate m64p_error DebugSetCallbacks(DebugInitCallback initCallback, DebugUpdateCallback updateCallback, DebugVICallback viCallback);
|
||||||
|
DebugSetCallbacks m64pDebugSetCallbacks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function searches through all current breakpoints in the debugger to find one that matches the given input parameters.
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate int DebugBreakpointLookup(uint address, uint size, uint flags);
|
||||||
|
DebugBreakpointLookup m64pDebugBreakpointLookup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This function is used to process common breakpoint commands, such as adding, removing, or searching the breakpoints
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate int DebugBreakpointCommand(m64p_dbg_bkp_command command, uint index, ref m64p_breakpoint bkp);
|
||||||
|
DebugBreakpointCommand m64pDebugBreakpointCommand;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a debugger state variable
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate int DebugGetState(m64p_dbg_state statenum);
|
||||||
|
DebugGetState m64pDebugGetState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the runstate of the emulator
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate m64p_error DebugSetRunState(m64p_dbg_runstate runstate);
|
||||||
|
DebugSetRunState m64pDebugSetRunState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Continues execution
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
delegate m64p_error DebugStep();
|
||||||
|
DebugStep m64pDebugStep;
|
||||||
|
|
||||||
// DLL handles
|
// DLL handles
|
||||||
public IntPtr CoreDll { get; private set; }
|
public IntPtr CoreDll { get; private set; }
|
||||||
|
|
||||||
|
@ -450,7 +533,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
m64pConfigSetParameter(core_section, "SaveType", m64p_type.M64TYPE_INT, ref SaveType);
|
m64pConfigSetParameter(core_section, "SaveType", m64p_type.M64TYPE_INT, ref SaveType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int enableDebugger = 1;
|
||||||
|
|
||||||
m64pConfigSetParameter(core_section, "R4300Emulator", m64p_type.M64TYPE_INT, ref CoreType);
|
m64pConfigSetParameter(core_section, "R4300Emulator", m64p_type.M64TYPE_INT, ref CoreType);
|
||||||
|
m64pConfigSetParameter(core_section, "EnableDebugger", m64p_type.M64TYPE_INT, ref enableDebugger);
|
||||||
|
|
||||||
// Pass the rom to the core
|
// Pass the rom to the core
|
||||||
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
|
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
|
||||||
|
@ -474,6 +560,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback);
|
result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback);
|
||||||
m64pRenderCallback = new RenderCallback(FireRenderEvent);
|
m64pRenderCallback = new RenderCallback(FireRenderEvent);
|
||||||
result = m64pCoreDoCommandRenderCallback(m64p_command.M64CMD_SET_RENDER_CALLBACK, 0, m64pRenderCallback);
|
result = m64pCoreDoCommandRenderCallback(m64p_command.M64CMD_SET_RENDER_CALLBACK, 0, m64pRenderCallback);
|
||||||
|
m64pDebugInitCallback = new DebugInitCallback(OnDebuggerInitialized);
|
||||||
|
m64pDebugUpdateCallback = new DebugUpdateCallback(FireBreakpointEvent);
|
||||||
|
result = m64pDebugSetCallbacks(m64pDebugInitCallback, m64pDebugUpdateCallback, null);
|
||||||
|
|
||||||
// Prepare to start the emulator in a different thread
|
// Prepare to start the emulator in a different thread
|
||||||
m64pEmulator = new Thread(ExecuteEmulator);
|
m64pEmulator = new Thread(ExecuteEmulator);
|
||||||
|
@ -530,14 +619,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
m64pCoreSaveState = (savestates_save_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_save_bkm"), typeof(savestates_save_bkm));
|
m64pCoreSaveState = (savestates_save_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_save_bkm"), typeof(savestates_save_bkm));
|
||||||
m64pCoreLoadState = (savestates_load_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_load_bkm"), typeof(savestates_load_bkm));
|
m64pCoreLoadState = (savestates_load_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_load_bkm"), typeof(savestates_load_bkm));
|
||||||
m64pDebugMemGetPointer = (DebugMemGetPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugMemGetPointer"), typeof(DebugMemGetPointer));
|
m64pDebugMemGetPointer = (DebugMemGetPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugMemGetPointer"), typeof(DebugMemGetPointer));
|
||||||
|
m64pDebugSetCallbacks = (DebugSetCallbacks)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugSetCallbacks"), typeof(DebugSetCallbacks));
|
||||||
|
m64pDebugBreakpointLookup = (DebugBreakpointLookup)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugBreakpointLookup"), typeof(DebugBreakpointLookup));
|
||||||
|
m64pDebugBreakpointCommand = ( DebugBreakpointCommand )Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugBreakpointCommand"), typeof(DebugBreakpointCommand));
|
||||||
|
m64pDebugGetState = (DebugGetState)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugGetState"), typeof(DebugGetState));
|
||||||
|
m64pDebugSetRunState = (DebugSetRunState)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugSetRunState"), typeof(DebugSetRunState));
|
||||||
|
m64pDebugStep = (DebugStep)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "DebugStep"), typeof(DebugStep));
|
||||||
m64pMemGetSize = (MemGetSize)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "MemGetSize"), typeof(MemGetSize));
|
m64pMemGetSize = (MemGetSize)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "MemGetSize"), typeof(MemGetSize));
|
||||||
m64pinit_saveram = (init_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "init_saveram"), typeof(init_saveram));
|
m64pinit_saveram = (init_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "init_saveram"), typeof(init_saveram));
|
||||||
m64psave_saveram = (save_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "save_saveram"), typeof(save_saveram));
|
m64psave_saveram = (save_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "save_saveram"), typeof(save_saveram));
|
||||||
m64pload_saveram = (load_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "load_saveram"), typeof(load_saveram));
|
m64pload_saveram = (load_saveram)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "load_saveram"), typeof(load_saveram));
|
||||||
|
|
||||||
m64pSetReadCallback = (SetReadCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetReadCallback"), typeof(SetReadCallback));
|
|
||||||
m64pSetWriteCallback = (SetWriteCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetWriteCallback"), typeof(SetWriteCallback));
|
|
||||||
m64pSetExecuteCallback = (SetExecuteCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetExecuteCallback"), typeof(SetExecuteCallback));
|
|
||||||
m64pSetTraceCallback = (SetTraceCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetTraceCallback"), typeof(SetTraceCallback));
|
m64pSetTraceCallback = (SetTraceCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetTraceCallback"), typeof(SetTraceCallback));
|
||||||
|
|
||||||
m64pGetRegisters = (GetRegisters)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "GetRegisters"), typeof(GetRegisters));
|
m64pGetRegisters = (GetRegisters)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "GetRegisters"), typeof(GetRegisters));
|
||||||
|
@ -680,9 +772,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
_breakparams._mcs.CallExecutes(_breakparams._addr);
|
_breakparams._mcs.CallExecutes(_breakparams._addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_breakpoint = false;
|
||||||
|
Resume();
|
||||||
}
|
}
|
||||||
event_breakpoint = false;
|
|
||||||
m64pContinueEvent.Set();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +784,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
_breakparams = breakparams;
|
_breakparams = breakparams;
|
||||||
event_breakpoint = true; //order important
|
event_breakpoint = true; //order important
|
||||||
m64pEvent.Set(); //order important
|
m64pEvent.Set(); //order important
|
||||||
BizHawk.Common.Win32ThreadHacks.HackyPinvokeWaitOne(m64pContinueEvent); //wait for emuhawk to finish event
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int SaveState(byte[] buffer)
|
public int SaveState(byte[] buffer)
|
||||||
|
@ -740,19 +832,56 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
m64pload_saveram(src);
|
m64pload_saveram(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReadCallback(MemoryCallback callback)
|
/* TODO: Support address masks and null address */
|
||||||
|
public void SetBreakpoint(BreakType type, uint? address)
|
||||||
{
|
{
|
||||||
m64pSetReadCallback(callback);
|
m64p_breakpoint breakpoint = new m64p_breakpoint
|
||||||
}
|
{
|
||||||
|
address = address.Value,
|
||||||
public void setWriteCallback(MemoryCallback callback)
|
endaddr = address.Value + 0x03,
|
||||||
{
|
flags = (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_ENABLED
|
||||||
m64pSetWriteCallback(callback);
|
};
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case BreakType.Read:
|
||||||
|
breakpoint.flags |= (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_READ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BreakType.Write:
|
||||||
|
breakpoint.flags |= (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_WRITE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BreakType.Execute:
|
||||||
|
breakpoint.flags |= (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_EXEC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m64pDebugBreakpointCommand(m64p_dbg_bkp_command.M64P_BKP_CMD_ADD_STRUCT, 0, ref breakpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExecuteCallback(MemoryCallback callback)
|
public void RemoveBreakpoint(BreakType type, uint? address)
|
||||||
{
|
{
|
||||||
m64pSetExecuteCallback(callback);
|
int index = 0;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case BreakType.Read:
|
||||||
|
index = m64pDebugBreakpointLookup(address.Value, 4, (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_READ);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BreakType.Write:
|
||||||
|
index = m64pDebugBreakpointLookup(address.Value, 4, (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_WRITE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BreakType.Execute:
|
||||||
|
index = m64pDebugBreakpointLookup(address.Value, 4, (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_EXEC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m64p_breakpoint unused = new m64p_breakpoint();
|
||||||
|
|
||||||
|
m64pDebugBreakpointCommand(m64p_dbg_bkp_command.M64P_BKP_CMD_REMOVE_IDX, (uint)index, ref unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTraceCallback(TraceCallback callback)
|
public void setTraceCallback(TraceCallback callback)
|
||||||
|
@ -765,6 +894,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
m64pGetRegisters(dest);
|
m64pGetRegisters(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Step()
|
||||||
|
{
|
||||||
|
m64pDebugStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
m64pDebugSetRunState(m64p_dbg_runstate.M64P_DBG_RUNSTATE_RUNNING);
|
||||||
|
m64pDebugStep();
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
|
@ -841,6 +981,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
public event Action VInterrupt;
|
public event Action VInterrupt;
|
||||||
public event Action BeforeRender;
|
public event Action BeforeRender;
|
||||||
|
|
||||||
|
public delegate void BreakpointHitCallback(uint address, BreakType type);
|
||||||
|
public event BreakpointHitCallback BreakpointHit;
|
||||||
|
|
||||||
private void FireFrameFinishedEvent()
|
private void FireFrameFinishedEvent()
|
||||||
{
|
{
|
||||||
// Execute Frame Callback functions
|
// Execute Frame Callback functions
|
||||||
|
@ -863,6 +1006,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
||||||
BeforeRender();
|
BeforeRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckBreakpointFlag(ref m64p_breakpoint bkp, m64p_dbg_bkp_flags flag)
|
||||||
|
{
|
||||||
|
return ((bkp.flags & (uint)flag) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireBreakpointEvent(int bpt)
|
||||||
|
{
|
||||||
|
// bpt equal to -1 means we're stepping
|
||||||
|
if((bpt == -1) || (BreakpointHit == null))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m64p_breakpoint breakpoint = new m64p_breakpoint();
|
||||||
|
|
||||||
|
m64pDebugBreakpointCommand(m64p_dbg_bkp_command.M64P_BKP_CMD_GET_STRUCT, (uint)bpt, ref breakpoint);
|
||||||
|
|
||||||
|
BreakType type = BreakType.Execute;
|
||||||
|
|
||||||
|
if(CheckBreakpointFlag(ref breakpoint, m64p_dbg_bkp_flags.M64P_BPT_FLAG_READ))
|
||||||
|
{
|
||||||
|
type = BreakType.Read;
|
||||||
|
}
|
||||||
|
else if(CheckBreakpointFlag(ref breakpoint, m64p_dbg_bkp_flags.M64P_BPT_FLAG_WRITE))
|
||||||
|
{
|
||||||
|
type = BreakType.Write;
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakpointHit(breakpoint.address, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDebuggerInitialized()
|
||||||
|
{
|
||||||
|
// Default value is M64P_DBG_RUNSTATE_PAUSED
|
||||||
|
m64pDebugSetRunState(m64p_dbg_runstate.M64P_DBG_RUNSTATE_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
private void CompletedFrameCallback()
|
private void CompletedFrameCallback()
|
||||||
{
|
{
|
||||||
m64pEvent.Set();
|
m64pEvent.Set();
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>DBG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>DBG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
|
|
@ -44,7 +44,7 @@ extern unsigned int op; /* this is in r4300/pure_interp.c */
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
static void (*callback_ui_init)(void) = NULL;
|
static void (*callback_ui_init)(void) = NULL;
|
||||||
static void (*callback_ui_update)(unsigned int) = NULL;
|
static void (*callback_ui_update)(int) = NULL;
|
||||||
static void (*callback_ui_vi)(void) = NULL;
|
static void (*callback_ui_vi)(void) = NULL;
|
||||||
|
|
||||||
static void (*callback_core_compare)(unsigned int) = NULL;
|
static void (*callback_core_compare)(unsigned int) = NULL;
|
||||||
|
@ -52,7 +52,7 @@ static void (*callback_core_data_sync)(int, void *) = NULL;
|
||||||
|
|
||||||
/* global Functions for use by the Core */
|
/* global Functions for use by the Core */
|
||||||
|
|
||||||
void DebuggerCallback(eDbgCallbackType type, unsigned int param)
|
void DebuggerCallback(eDbgCallbackType type, int param)
|
||||||
{
|
{
|
||||||
if (type == DEBUG_UI_INIT)
|
if (type == DEBUG_UI_INIT)
|
||||||
{
|
{
|
||||||
|
@ -92,7 +92,7 @@ EXPORT m64p_error CALL DebugSetCoreCompare(void (*dbg_core_compare)(unsigned int
|
||||||
return M64ERR_SUCCESS;
|
return M64ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT m64p_error CALL DebugSetCallbacks(void (*dbg_frontend_init)(void), void (*dbg_frontend_update)(unsigned int pc), void (*dbg_frontend_vi)(void))
|
EXPORT m64p_error CALL DebugSetCallbacks(void (*dbg_frontend_init)(void), void (*dbg_frontend_update)(int bpt), void (*dbg_frontend_vi)(void))
|
||||||
{
|
{
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
callback_ui_init = dbg_frontend_init;
|
callback_ui_init = dbg_frontend_init;
|
||||||
|
@ -273,7 +273,7 @@ EXPORT int CALL MemGetSize(m64p_dbg_memptr_type mem_ptr_type)
|
||||||
return rom_size;
|
return rom_size;
|
||||||
default:
|
default:
|
||||||
DebugMessage(M64MSG_ERROR, "Bug: MemGetSize() called with invalid m64p_dbg_memptr_type");
|
DebugMessage(M64MSG_ERROR, "Bug: MemGetSize() called with invalid m64p_dbg_memptr_type");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,9 @@ EXPORT int CALL DebugBreakpointCommand(m64p_dbg_bkp_command command, unsigned in
|
||||||
case M64P_BKP_CMD_ADD_ADDR:
|
case M64P_BKP_CMD_ADD_ADDR:
|
||||||
return add_breakpoint(index);
|
return add_breakpoint(index);
|
||||||
case M64P_BKP_CMD_ADD_STRUCT:
|
case M64P_BKP_CMD_ADD_STRUCT:
|
||||||
return add_breakpoint_struct((breakpoint *) ptr);
|
return add_breakpoint_struct((breakpoint *) ptr);
|
||||||
|
case M64P_BKP_CMD_GET_STRUCT:
|
||||||
|
return get_breakpoint_struct(index, (breakpoint *)ptr);
|
||||||
case M64P_BKP_CMD_REPLACE:
|
case M64P_BKP_CMD_REPLACE:
|
||||||
replace_breakpoint_num(index, (breakpoint *) ptr);
|
replace_breakpoint_num(index, (breakpoint *) ptr);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -38,7 +38,7 @@ typedef enum {
|
||||||
} eDbgCallbackType;
|
} eDbgCallbackType;
|
||||||
|
|
||||||
/* Functions for use by the Core, to send information back to the front-end app */
|
/* Functions for use by the Core, to send information back to the front-end app */
|
||||||
extern void DebuggerCallback(eDbgCallbackType type, unsigned int param);
|
extern void DebuggerCallback(eDbgCallbackType type, int param);
|
||||||
extern void CoreCompareCallback(void);
|
extern void CoreCompareCallback(void);
|
||||||
extern void CoreCompareDataSync(int length, void *ptr);
|
extern void CoreCompareDataSync(int length, void *ptr);
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ extern "C" {
|
||||||
* UI, this function may be called with NULL pointers in order to disable the
|
* UI, this function may be called with NULL pointers in order to disable the
|
||||||
* callbacks.
|
* callbacks.
|
||||||
*/
|
*/
|
||||||
typedef m64p_error (*ptr_DebugSetCallbacks)(void (*)(void), void (*)(unsigned int), void (*)(void));
|
typedef m64p_error (*ptr_DebugSetCallbacks)(void (*)(void), void (*)(int), void (*)(void));
|
||||||
#if defined(M64P_CORE_PROTOTYPES)
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(unsigned int), void (*)(void));
|
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(int), void (*)(void));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DebugSetCoreCompare()
|
/* DebugSetCoreCompare()
|
||||||
|
|
|
@ -289,6 +289,7 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
M64P_BKP_CMD_ADD_ADDR = 1,
|
M64P_BKP_CMD_ADD_ADDR = 1,
|
||||||
M64P_BKP_CMD_ADD_STRUCT,
|
M64P_BKP_CMD_ADD_STRUCT,
|
||||||
|
M64P_BKP_CMD_GET_STRUCT,
|
||||||
M64P_BKP_CMD_REPLACE,
|
M64P_BKP_CMD_REPLACE,
|
||||||
M64P_BKP_CMD_REMOVE_ADDR,
|
M64P_BKP_CMD_REMOVE_ADDR,
|
||||||
M64P_BKP_CMD_REMOVE_IDX,
|
M64P_BKP_CMD_REMOVE_IDX,
|
||||||
|
|
|
@ -67,6 +67,19 @@ int add_breakpoint_struct(breakpoint* newbp)
|
||||||
return g_NumBreakpoints++;
|
return g_NumBreakpoints++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_breakpoint_struct(int bpt, breakpoint* copy)
|
||||||
|
{
|
||||||
|
if (bpt >= g_NumBreakpoints)
|
||||||
|
{
|
||||||
|
DebugMessage(M64MSG_ERROR, "Invalid breakpoint index.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(copy, &g_Breakpoints[bpt], sizeof(breakpoint));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void enable_breakpoint( int bpt)
|
void enable_breakpoint( int bpt)
|
||||||
{
|
{
|
||||||
breakpoint *curBpt = g_Breakpoints + bpt;
|
breakpoint *curBpt = g_Breakpoints + bpt;
|
||||||
|
@ -196,7 +209,7 @@ int check_breakpoints_on_mem_access( uint32 pc, uint32 address, uint32 size, uin
|
||||||
log_breakpoint(pc, flags, address);
|
log_breakpoint(pc, flags, address);
|
||||||
|
|
||||||
run = 0;
|
run = 0;
|
||||||
update_debugger(pc);
|
update_debugger(pc, bpt);
|
||||||
|
|
||||||
return bpt;
|
return bpt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern breakpoint g_Breakpoints[];
|
||||||
|
|
||||||
int add_breakpoint( uint32 address );
|
int add_breakpoint( uint32 address );
|
||||||
int add_breakpoint_struct(breakpoint* newbp);
|
int add_breakpoint_struct(breakpoint* newbp);
|
||||||
|
int get_breakpoint_struct(int bpt, breakpoint* copy);
|
||||||
void remove_breakpoint_by_address( uint32 address );
|
void remove_breakpoint_by_address( uint32 address );
|
||||||
void remove_breakpoint_by_num( int bpt );
|
void remove_breakpoint_by_num( int bpt );
|
||||||
void enable_breakpoint( int breakpoint );
|
void enable_breakpoint( int breakpoint );
|
||||||
|
|
|
@ -31,13 +31,17 @@
|
||||||
|
|
||||||
#define MEMBREAKREAD(name,size) \
|
#define MEMBREAKREAD(name,size) \
|
||||||
void name##_break(void) { \
|
void name##_break(void) { \
|
||||||
check_breakpoints_on_mem_access((PC->addr)-0x4, address, size, BPT_FLAG_ENABLED | BPT_FLAG_READ); \
|
PC->addr-=0x4; \
|
||||||
|
check_breakpoints_on_mem_access(PC->addr, address, size, BPT_FLAG_ENABLED | BPT_FLAG_READ); \
|
||||||
|
PC->addr+=0x4; \
|
||||||
name (); \
|
name (); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MEMBREAKWRITE(name,size) \
|
#define MEMBREAKWRITE(name,size) \
|
||||||
void name##_break(void) { \
|
void name##_break(void) { \
|
||||||
check_breakpoints_on_mem_access((PC->addr)-0x4, address, size, BPT_FLAG_ENABLED | BPT_FLAG_WRITE); \
|
PC->addr-=0x4; \
|
||||||
|
check_breakpoints_on_mem_access(PC->addr, address, size, BPT_FLAG_ENABLED | BPT_FLAG_WRITE); \
|
||||||
|
PC->addr+=0x4; \
|
||||||
name (); \
|
name (); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,13 +66,11 @@ void destroy_debugger()
|
||||||
|
|
||||||
//]=-=-=-=-=-=-=-=-=-=-=-=-=[ Mise-a-Jour Debugger ]=-=-=-=-=-=-=-=-=-=-=-=-=[
|
//]=-=-=-=-=-=-=-=-=-=-=-=-=[ Mise-a-Jour Debugger ]=-=-=-=-=-=-=-=-=-=-=-=-=[
|
||||||
|
|
||||||
void update_debugger(uint32 pc)
|
void update_debugger(uint32 pc, int bpt)
|
||||||
// Update debugger state and display.
|
// Update debugger state and display.
|
||||||
// Should be called after each R4300 instruction
|
// Should be called after each R4300 instruction
|
||||||
// Checks for breakpoint hits on PC
|
// Checks for breakpoint hits on PC
|
||||||
{
|
{
|
||||||
int bpt;
|
|
||||||
|
|
||||||
if(run!=0) {//check if we hit a breakpoint
|
if(run!=0) {//check if we hit a breakpoint
|
||||||
bpt = check_breakpoints(pc);
|
bpt = check_breakpoints(pc);
|
||||||
if( bpt!=-1 ) {
|
if( bpt!=-1 ) {
|
||||||
|
@ -84,7 +82,7 @@ void update_debugger(uint32 pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(run!=2) {
|
if(run!=2) {
|
||||||
DebuggerCallback(DEBUG_UI_UPDATE, pc); /* call front-end to notify user interface to update */
|
DebuggerCallback(DEBUG_UI_UPDATE, bpt); /* call front-end to notify user interface to update */
|
||||||
}
|
}
|
||||||
if(run==0) {
|
if(run==0) {
|
||||||
// Emulation thread is blocked until a button is clicked.
|
// Emulation thread is blocked until a button is clicked.
|
||||||
|
|
|
@ -32,7 +32,7 @@ extern int run;
|
||||||
extern uint32 previousPC;
|
extern uint32 previousPC;
|
||||||
|
|
||||||
void init_debugger(void);
|
void init_debugger(void);
|
||||||
void update_debugger(uint32 pc);
|
void update_debugger(uint32 pc, int bpt);
|
||||||
void destroy_debugger(void);
|
void destroy_debugger(void);
|
||||||
void debugger_step(void);
|
void debugger_step(void);
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,6 @@ void dma_pi_read(void)
|
||||||
{
|
{
|
||||||
for (i=0; i < (pi_register.pi_rd_len_reg & 0xFFFFFF)+1; i++)
|
for (i=0; i < (pi_register.pi_rd_len_reg & 0xFFFFFF)+1; i++)
|
||||||
{
|
{
|
||||||
READCBADDR(0x80000000 | ((pi_register.pi_dram_addr_reg+i)^S8));
|
|
||||||
|
|
||||||
sram[((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8] =
|
sram[((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8] =
|
||||||
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8];
|
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8];
|
||||||
}
|
}
|
||||||
|
@ -147,8 +145,6 @@ void dma_pi_write(void)
|
||||||
|
|
||||||
for (i=0; i<(int)(pi_register.pi_wr_len_reg & 0xFFFFFF)+1; i++)
|
for (i=0; i<(int)(pi_register.pi_wr_len_reg & 0xFFFFFF)+1; i++)
|
||||||
{
|
{
|
||||||
WRITECBADDR(0x80000000 | ((pi_register.pi_dram_addr_reg+i)^S8));
|
|
||||||
|
|
||||||
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
||||||
sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8];
|
sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8];
|
||||||
}
|
}
|
||||||
|
@ -208,8 +204,6 @@ void dma_pi_write(void)
|
||||||
unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000;
|
unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000;
|
||||||
unsigned long rdram_address2 = pi_register.pi_dram_addr_reg+i+0xa0000000;
|
unsigned long rdram_address2 = pi_register.pi_dram_addr_reg+i+0xa0000000;
|
||||||
|
|
||||||
WRITECBADDR(0x80000000 | ((pi_register.pi_dram_addr_reg+i)^S8));
|
|
||||||
|
|
||||||
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
||||||
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
|
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
|
||||||
|
|
||||||
|
@ -240,8 +234,6 @@ void dma_pi_write(void)
|
||||||
{
|
{
|
||||||
for (i=0; i<(int)longueur; i++)
|
for (i=0; i<(int)longueur; i++)
|
||||||
{
|
{
|
||||||
WRITECBADDR(0x80000000 | ((pi_register.pi_dram_addr_reg+i)^S8));
|
|
||||||
|
|
||||||
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
||||||
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
|
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
|
||||||
}
|
}
|
||||||
|
@ -258,8 +250,6 @@ void dma_pi_write(void)
|
||||||
case 3:
|
case 3:
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
WRITECBADDR(0x80000000 | (0x318/4));
|
|
||||||
|
|
||||||
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
|
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
|
||||||
{
|
{
|
||||||
rdram[0x318/4] = 0x400000;
|
rdram[0x318/4] = 0x400000;
|
||||||
|
@ -272,8 +262,6 @@ void dma_pi_write(void)
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
{
|
{
|
||||||
WRITECBADDR(0x80000000 | (0x3F0/4));
|
|
||||||
|
|
||||||
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
|
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
|
||||||
{
|
{
|
||||||
rdram[0x3F0/4] = 0x400000;
|
rdram[0x3F0/4] = 0x400000;
|
||||||
|
@ -312,8 +300,6 @@ void dma_sp_write(void)
|
||||||
|
|
||||||
for(j=0; j<count; j++) {
|
for(j=0; j<count; j++) {
|
||||||
for(i=0; i<length; i++) {
|
for(i=0; i<length; i++) {
|
||||||
READCBADDR(0x80000000 | (dramaddr^S8));
|
|
||||||
|
|
||||||
spmem[memaddr^S8] = dram[dramaddr^S8];
|
spmem[memaddr^S8] = dram[dramaddr^S8];
|
||||||
memaddr++;
|
memaddr++;
|
||||||
dramaddr++;
|
dramaddr++;
|
||||||
|
@ -340,8 +326,6 @@ void dma_sp_read(void)
|
||||||
|
|
||||||
for(j=0; j<count; j++) {
|
for(j=0; j<count; j++) {
|
||||||
for(i=0; i<length; i++) {
|
for(i=0; i<length; i++) {
|
||||||
WRITECBADDR(0x80000000 | (dramaddr^S8));
|
|
||||||
|
|
||||||
dram[dramaddr^S8] = spmem[memaddr^S8];
|
dram[dramaddr^S8] = spmem[memaddr^S8];
|
||||||
memaddr++;
|
memaddr++;
|
||||||
dramaddr++;
|
dramaddr++;
|
||||||
|
@ -362,8 +346,6 @@ void dma_si_write(void)
|
||||||
|
|
||||||
for (i=0; i<(64/4); i++)
|
for (i=0; i<(64/4); i++)
|
||||||
{
|
{
|
||||||
READCBADDR(0x80000000 | (si_register.si_dram_addr/4+i));
|
|
||||||
|
|
||||||
PIF_RAM[i] = sl(rdram[si_register.si_dram_addr/4+i]);
|
PIF_RAM[i] = sl(rdram[si_register.si_dram_addr/4+i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +368,6 @@ void dma_si_read(void)
|
||||||
|
|
||||||
for (i=0; i<(64/4); i++)
|
for (i=0; i<(64/4); i++)
|
||||||
{
|
{
|
||||||
WRITECBADDR(0x80000000 | (si_register.si_dram_addr/4+i));
|
|
||||||
|
|
||||||
rdram[si_register.si_dram_addr/4+i] = sl(PIF_RAM[i]);
|
rdram[si_register.si_dram_addr/4+i] = sl(PIF_RAM[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,5 @@ void dma_sp_read(void);
|
||||||
|
|
||||||
void sram_format(void);
|
void sram_format(void);
|
||||||
|
|
||||||
extern void (*readCB)(unsigned int);
|
|
||||||
extern void (*writeCB)(unsigned int);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -181,17 +181,12 @@ void dma_read_flashram(void)
|
||||||
switch (flashram_info.mode)
|
switch (flashram_info.mode)
|
||||||
{
|
{
|
||||||
case STATUS_MODE:
|
case STATUS_MODE:
|
||||||
WRITECBADDR(0x80000000 | (pi_register.pi_dram_addr_reg/4));
|
|
||||||
WRITECBADDR(0x80000000 | (pi_register.pi_dram_addr_reg/4+1));
|
|
||||||
|
|
||||||
rdram[pi_register.pi_dram_addr_reg/4] = (unsigned int)(flashram_info.status >> 32);
|
rdram[pi_register.pi_dram_addr_reg/4] = (unsigned int)(flashram_info.status >> 32);
|
||||||
rdram[pi_register.pi_dram_addr_reg/4+1] = (unsigned int)(flashram_info.status);
|
rdram[pi_register.pi_dram_addr_reg/4+1] = (unsigned int)(flashram_info.status);
|
||||||
break;
|
break;
|
||||||
case READ_MODE:
|
case READ_MODE:
|
||||||
for (i=0; i<(pi_register.pi_wr_len_reg & 0x0FFFFFF)+1; i++)
|
for (i=0; i<(pi_register.pi_wr_len_reg & 0x0FFFFFF)+1; i++)
|
||||||
{
|
{
|
||||||
READCBADDR(0x80000000 | ((pi_register.pi_dram_addr_reg+i)^S8));
|
|
||||||
|
|
||||||
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
|
||||||
flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8];
|
flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8];
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,3 @@ unsigned int flashram_status(void);
|
||||||
void dma_read_flashram(void);
|
void dma_read_flashram(void);
|
||||||
void dma_write_flashram(void);
|
void dma_write_flashram(void);
|
||||||
void flashram_format(void);
|
void flashram_format(void);
|
||||||
|
|
||||||
extern void (*readCB)(unsigned int);
|
|
||||||
extern void (*writeCB)(unsigned int);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,14 +24,8 @@
|
||||||
|
|
||||||
#include "osal/preproc.h"
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
#define READCB() if (readCB) readCB(address)
|
|
||||||
#define WRITECB() if (writeCB) writeCB(address)
|
|
||||||
#define EXECUTECB() if (executeCB) executeCB(PC->addr)
|
|
||||||
#define TRACECB() if (traceCB) traceCB()
|
#define TRACECB() if (traceCB) traceCB()
|
||||||
|
|
||||||
#define READCBADDR(addr) if (readCB) readCB(addr)
|
|
||||||
#define WRITECBADDR(addr) if (writeCB) writeCB(addr)
|
|
||||||
|
|
||||||
int init_memory(int DoByteSwap);
|
int init_memory(int DoByteSwap);
|
||||||
void free_memory(void);
|
void free_memory(void);
|
||||||
#define read_word_in_memory() readmem[address>>16]()
|
#define read_word_in_memory() readmem[address>>16]()
|
||||||
|
@ -56,7 +50,6 @@ extern unsigned char cpu_byte;
|
||||||
extern unsigned short hword;
|
extern unsigned short hword;
|
||||||
extern unsigned long long dword, *rdword;
|
extern unsigned long long dword, *rdword;
|
||||||
|
|
||||||
extern void (*executeCB)(unsigned int);
|
|
||||||
extern void (*traceCB)(void);
|
extern void (*traceCB)(void);
|
||||||
|
|
||||||
extern void (*readmem[0x10000])(void);
|
extern void (*readmem[0x10000])(void);
|
||||||
|
|
|
@ -417,9 +417,8 @@ void pure_interpreter(void)
|
||||||
CoreCompareCallback();
|
CoreCompareCallback();
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
if (g_DebuggerActive) update_debugger(PC->addr);
|
if (g_DebuggerActive) update_debugger(PC->addr, -1);
|
||||||
#endif
|
#endif
|
||||||
EXECUTECB();
|
|
||||||
TRACECB();
|
TRACECB();
|
||||||
PC->ops();
|
PC->ops();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
|
||||||
// Cached interpreter functions (and fallback for dynarec).
|
// Cached interpreter functions (and fallback for dynarec).
|
||||||
// -----------------------------------------------------------
|
// -----------------------------------------------------------
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr)
|
#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr, -1)
|
||||||
#else
|
#else
|
||||||
#define UPDATE_DEBUGGER() do { } while(0)
|
#define UPDATE_DEBUGGER() do { } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1066,9 +1066,8 @@ void r4300_execute(void (*startcb)(void))
|
||||||
CoreCompareCallback();
|
CoreCompareCallback();
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
if (g_DebuggerActive) update_debugger(PC->addr);
|
if (g_DebuggerActive) update_debugger(PC->addr, -1);
|
||||||
#endif
|
#endif
|
||||||
EXECUTECB();
|
|
||||||
TRACECB();
|
TRACECB();
|
||||||
PC->ops();
|
PC->ops();
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue