m64p: Use built-in debugger to avoid major slowdowns when breakpoints are set.

This commit is contained in:
Wyst3r 2016-11-19 12:02:39 +01:00
parent 2cc4e6bf58
commit 86b16a80d6
23 changed files with 397 additions and 479 deletions

View File

@ -1,6 +1,9 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace BizHawk.Emulation.Common
{
@ -9,11 +12,15 @@ namespace BizHawk.Emulation.Common
public MemoryCallbackSystem()
{
ExecuteCallbacksAvailable = true;
Reads.CollectionChanged += OnCollectionChanged;
Writes.CollectionChanged += OnCollectionChanged;
Execs.CollectionChanged += OnCollectionChanged;
}
private readonly List<IMemoryCallback> Reads = new List<IMemoryCallback>();
private readonly List<IMemoryCallback> Writes = new List<IMemoryCallback>();
private readonly List<IMemoryCallback> Execs = new List<IMemoryCallback>();
private readonly ObservableCollection<IMemoryCallback> Reads = new ObservableCollection<IMemoryCallback>();
private readonly ObservableCollection<IMemoryCallback> Writes = new ObservableCollection<IMemoryCallback>();
private readonly ObservableCollection<IMemoryCallback> Execs = new ObservableCollection<IMemoryCallback>();
private bool _empty = true;
@ -49,7 +56,7 @@ namespace BizHawk.Emulation.Common
_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++)
{
@ -100,20 +107,28 @@ namespace BizHawk.Emulation.Common
private void UpdateHasVariables()
{
_hasReads = Reads.Count > 0;
_hasWrites = Reads.Count > 0;
_hasExecutes = Reads.Count > 0;
_hasWrites = Writes.Count > 0;
_hasExecutes = Execs.Count > 0;
}
private int RemoveInternal(Action action)
{
int ret = 0;
ret += Reads.RemoveAll(imc => imc.Callback == action);
ret += Writes.RemoveAll(imc => imc.Callback == action);
ret += Execs.RemoveAll(imc => imc.Callback == action);
var readsToRemove = Reads.Where(imc => imc.Callback == action).ToList();
var writesToRemove = Writes.Where(imc => imc.Callback == action).ToList();
var execsToRemove = Execs.Where(imc => imc.Callback == action).ToList();
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();
return ret;
return readsToRemove.Count + writesToRemove.Count + execsToRemove.Count;
}
public void Remove(Action action)
@ -147,9 +162,16 @@ namespace BizHawk.Emulation.Common
public void Clear()
{
Reads.Clear();
Writes.Clear();
Execs.Clear();
// Remove one-by-one to avoid NotifyCollectionChangedAction.Reset events.
for(int i = (Reads.Count - 1); i >= 0; i--)
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)
Changes();
_empty = true;
@ -160,6 +182,12 @@ namespace BizHawk.Emulation.Common
public delegate void ActiveChangedEventHandler();
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()
{
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()
{
foreach (var imc in Reads)

View File

@ -84,74 +84,80 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
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]
public void Step(StepType type) { throw new NotImplementedException(); }
return false;
}
private mupen64plusApi.MemoryCallback _readcb;
private mupen64plusApi.MemoryCallback _writecb;
private mupen64plusApi.MemoryCallback _executecb;
public void Step(StepType type)
{
switch(type)
{
case StepType.Into:
api.Step();
break;
}
}
private void RefreshMemoryCallbacks()
private void SetBreakpointHandler()
{
var mcs = MemoryCallbacks;
// we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
if (mcs.HasReads)
api.BreakpointHit += delegate(uint address, mupen64plusApi.BreakType type)
{
_readcb = delegate(uint addr)
api.OnBreakpoint(new mupen64plusApi.BreakParams
{
api.OnBreakpoint(new mupen64plusApi.BreakParams
{
_type = mupen64plusApi.BreakType.Read,
_addr = addr,
_mcs = mcs
});
};
}
else
{
_readcb = null;
}
_type = type,
_addr = address,
_mcs = mcs
});
};
}
if (mcs.HasWrites)
private void AddBreakpoint(IMemoryCallback callback)
{
switch(callback.Type)
{
_writecb = delegate(uint addr)
{
api.OnBreakpoint(new mupen64plusApi.BreakParams
{
_type = mupen64plusApi.BreakType.Write,
_addr = addr,
_mcs = mcs
});
};
}
else
{
_writecb = null;
}
case MemoryCallbackType.Read:
api.SetBreakpoint(mupen64plusApi.BreakType.Read, callback.Address);
break;
if (mcs.HasExecutes)
{
_executecb = delegate(uint addr)
{
api.OnBreakpoint(new mupen64plusApi.BreakParams
{
_type = mupen64plusApi.BreakType.Execute,
_addr = addr,
_mcs = mcs
});
};
}
else
{
_executecb = null;
}
case MemoryCallbackType.Write:
api.SetBreakpoint(mupen64plusApi.BreakType.Write, callback.Address);
break;
api.setReadCallback(_readcb);
api.setWriteCallback(_writecb);
api.setExecuteCallback(_executecb);
case MemoryCallbackType.Execute:
api.SetBreakpoint(mupen64plusApi.BreakType.Execute, callback.Address);
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;
}
}
}
}

View File

@ -55,7 +55,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
{
ServiceProvider = new BasicServiceProvider(this);
InputCallbacks = new InputCallbackSystem();
_memorycallbacks.ActiveChanged += RefreshMemoryCallbacks;
_memorycallbacks.CallbackAdded += AddBreakpoint;
_memorycallbacks.CallbackRemoved += RemoveBreakpoint;
int SaveType = 0;
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);
InitMemoryDomains();
RefreshMemoryCallbacks();
if (_syncSettings.Core != N64SyncSettings.CoreType.Dynarec)
{
ConnectTracer();
SetBreakpointHandler();
}
api.AsyncExecuteEmulator();
@ -226,8 +230,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
{
IsVIFrame = false;
RefreshMemoryCallbacks();
if (Tracer != null && Tracer.Enabled)
{
api.setTraceCallback(_tracecb);

View File

@ -94,6 +94,47 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
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
{
M64EMU_STOPPED = 1,
@ -127,6 +168,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
THE_ROM
}
[StructLayout(LayoutKind.Sequential)]
public struct m64p_breakpoint
{
public uint address;
public uint endaddr;
public uint flags;
}
// Core Specifc functions
/// <summary>
@ -362,34 +411,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
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>
/// Type of the trace callback
/// </summary>
@ -410,6 +431,68 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
public delegate void GetRegisters(byte[] dest);
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
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);
}
int enableDebugger = 1;
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
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);
m64pRenderCallback = new RenderCallback(FireRenderEvent);
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
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));
m64pCoreLoadState = (savestates_load_bkm)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_load_bkm"), typeof(savestates_load_bkm));
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));
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));
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));
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);
break;
}
event_breakpoint = false;
Resume();
}
event_breakpoint = false;
m64pContinueEvent.Set();
}
}
@ -691,7 +784,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
_breakparams = breakparams;
event_breakpoint = true; //order important
m64pEvent.Set(); //order important
BizHawk.Common.Win32ThreadHacks.HackyPinvokeWaitOne(m64pContinueEvent); //wait for emuhawk to finish event
}
public int SaveState(byte[] buffer)
@ -740,19 +832,56 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
m64pload_saveram(src);
}
public void setReadCallback(MemoryCallback callback)
/* TODO: Support address masks and null address */
public void SetBreakpoint(BreakType type, uint? address)
{
m64pSetReadCallback(callback);
}
public void setWriteCallback(MemoryCallback callback)
{
m64pSetWriteCallback(callback);
m64p_breakpoint breakpoint = new m64p_breakpoint
{
address = address.Value,
endaddr = address.Value + 0x03,
flags = (uint)m64p_dbg_bkp_flags.M64P_BPT_FLAG_ENABLED
};
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)
@ -765,6 +894,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
m64pGetRegisters(dest);
}
public void Step()
{
m64pDebugStep();
}
public void Resume()
{
m64pDebugSetRunState(m64p_dbg_runstate.M64P_DBG_RUNSTATE_RUNNING);
m64pDebugStep();
}
public void Dispose()
{
if (!disposed)
@ -841,6 +981,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
public event Action VInterrupt;
public event Action BeforeRender;
public delegate void BreakpointHitCallback(uint address, BreakType type);
public event BreakpointHitCallback BreakpointHit;
private void FireFrameFinishedEvent()
{
// Execute Frame Callback functions
@ -863,6 +1006,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
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()
{
m64pEvent.Set();

View File

@ -62,7 +62,7 @@
<ClCompile>
<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>
<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>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -88,7 +88,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<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>
<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>
<PrecompiledHeader>
</PrecompiledHeader>

View File

@ -44,7 +44,7 @@ extern unsigned int op; /* this is in r4300/pure_interp.c */
/* local variables */
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_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 */
void DebuggerCallback(eDbgCallbackType type, unsigned int param)
void DebuggerCallback(eDbgCallbackType type, int param)
{
if (type == DEBUG_UI_INIT)
{
@ -92,7 +92,7 @@ EXPORT m64p_error CALL DebugSetCoreCompare(void (*dbg_core_compare)(unsigned int
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
callback_ui_init = dbg_frontend_init;
@ -273,7 +273,7 @@ EXPORT int CALL MemGetSize(m64p_dbg_memptr_type mem_ptr_type)
return rom_size;
default:
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:
return add_breakpoint(index);
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:
replace_breakpoint_num(index, (breakpoint *) ptr);
return 0;

View File

@ -38,7 +38,7 @@ typedef enum {
} eDbgCallbackType;
/* 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 CoreCompareDataSync(int length, void *ptr);

View File

@ -39,9 +39,9 @@ extern "C" {
* UI, this function may be called with NULL pointers in order to disable the
* 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)
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(unsigned int), void (*)(void));
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(int), void (*)(void));
#endif
/* DebugSetCoreCompare()

View File

@ -289,6 +289,7 @@ typedef enum {
typedef enum {
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,

View File

@ -67,6 +67,19 @@ int add_breakpoint_struct(breakpoint* newbp)
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)
{
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);
run = 0;
update_debugger(pc);
update_debugger(pc, bpt);
return bpt;
}

View File

@ -29,6 +29,7 @@ extern breakpoint g_Breakpoints[];
int add_breakpoint( uint32 address );
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_num( int bpt );
void enable_breakpoint( int breakpoint );

View File

@ -31,13 +31,17 @@
#define MEMBREAKREAD(name,size) \
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 (); \
}
#define MEMBREAKWRITE(name,size) \
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 (); \
}

View File

@ -66,13 +66,11 @@ void destroy_debugger()
//]=-=-=-=-=-=-=-=-=-=-=-=-=[ Mise-a-Jour Debugger ]=-=-=-=-=-=-=-=-=-=-=-=-=[
void update_debugger(uint32 pc)
void update_debugger(uint32 pc, int bpt)
// Update debugger state and display.
// Should be called after each R4300 instruction
// Checks for breakpoint hits on PC
{
int bpt;
if(run!=0) {//check if we hit a breakpoint
bpt = check_breakpoints(pc);
if( bpt!=-1 ) {
@ -84,7 +82,7 @@ void update_debugger(uint32 pc)
}
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) {
// Emulation thread is blocked until a button is clicked.

View File

@ -32,7 +32,7 @@ extern int run;
extern uint32 previousPC;
void init_debugger(void);
void update_debugger(uint32 pc);
void update_debugger(uint32 pc, int bpt);
void destroy_debugger(void);
void debugger_step(void);

View File

@ -106,8 +106,6 @@ void dma_pi_read(void)
{
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] =
((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++)
{
WRITECBADDR(0x80000000 | ((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];
}
@ -208,8 +204,6 @@ void dma_pi_write(void)
unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000;
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]=
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++)
{
WRITECBADDR(0x80000000 | ((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];
}
@ -258,8 +250,6 @@ void dma_pi_write(void)
case 3:
case 6:
{
WRITECBADDR(0x80000000 | (0x318/4));
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
{
rdram[0x318/4] = 0x400000;
@ -272,8 +262,6 @@ void dma_pi_write(void)
}
case 5:
{
WRITECBADDR(0x80000000 | (0x3F0/4));
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
{
rdram[0x3F0/4] = 0x400000;
@ -312,8 +300,6 @@ void dma_sp_write(void)
for(j=0; j<count; j++) {
for(i=0; i<length; i++) {
READCBADDR(0x80000000 | (dramaddr^S8));
spmem[memaddr^S8] = dram[dramaddr^S8];
memaddr++;
dramaddr++;
@ -340,8 +326,6 @@ void dma_sp_read(void)
for(j=0; j<count; j++) {
for(i=0; i<length; i++) {
WRITECBADDR(0x80000000 | (dramaddr^S8));
dram[dramaddr^S8] = spmem[memaddr^S8];
memaddr++;
dramaddr++;
@ -362,8 +346,6 @@ void dma_si_write(void)
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]);
}
@ -386,8 +368,6 @@ void dma_si_read(void)
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]);
}

View File

@ -31,8 +31,5 @@ void dma_sp_read(void);
void sram_format(void);
extern void (*readCB)(unsigned int);
extern void (*writeCB)(unsigned int);
#endif

View File

@ -181,17 +181,12 @@ void dma_read_flashram(void)
switch (flashram_info.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+1] = (unsigned int)(flashram_info.status);
break;
case READ_MODE:
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]=
flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8];
}

View File

@ -35,6 +35,3 @@ unsigned int flashram_status(void);
void dma_read_flashram(void);
void dma_write_flashram(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

View File

@ -24,14 +24,8 @@
#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 READCBADDR(addr) if (readCB) readCB(addr)
#define WRITECBADDR(addr) if (writeCB) writeCB(addr)
int init_memory(int DoByteSwap);
void free_memory(void);
#define read_word_in_memory() readmem[address>>16]()
@ -56,7 +50,6 @@ extern unsigned char cpu_byte;
extern unsigned short hword;
extern unsigned long long dword, *rdword;
extern void (*executeCB)(unsigned int);
extern void (*traceCB)(void);
extern void (*readmem[0x10000])(void);

View File

@ -417,9 +417,8 @@ void pure_interpreter(void)
CoreCompareCallback();
#endif
#ifdef DBG
if (g_DebuggerActive) update_debugger(PC->addr);
if (g_DebuggerActive) update_debugger(PC->addr, -1);
#endif
EXECUTECB();
TRACECB();
PC->ops();
}

View File

@ -73,7 +73,7 @@ int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
// Cached interpreter functions (and fallback for dynarec).
// -----------------------------------------------------------
#ifdef DBG
#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr)
#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr, -1)
#else
#define UPDATE_DEBUGGER() do { } while(0)
#endif
@ -1066,9 +1066,8 @@ void r4300_execute(void (*startcb)(void))
CoreCompareCallback();
#endif
#ifdef DBG
if (g_DebuggerActive) update_debugger(PC->addr);
if (g_DebuggerActive) update_debugger(PC->addr, -1);
#endif
EXECUTECB();
TRACECB();
PC->ops();
}

Binary file not shown.