2017-08-18 05:08:22 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
|
|
|
* Project64 - A Nintendo 64 emulator. *
|
|
|
|
* http://www.pj64-emu.com/ *
|
|
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
|
|
* *
|
|
|
|
* License: *
|
|
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Breakpoints.h"
|
|
|
|
|
|
|
|
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
|
|
|
#include <Project64-core/N64System/Mips/OpcodeName.h>
|
|
|
|
#include <Project64-core/N64System/N64Class.h>
|
|
|
|
|
|
|
|
CBreakpoints::CBreakpoints()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_Debugging = FALSE;
|
|
|
|
m_Skipping = FALSE;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::Pause()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
KeepDebugging();
|
|
|
|
g_System->Pause();
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::Resume()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
g_System->ExternalEvent(SysEvent_ResumeCPU_FromMenu);
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:15:06 +00:00
|
|
|
bool CBreakpoints::isDebugging()
|
2017-08-18 05:08:22 +00:00
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
return m_Debugging;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::KeepDebugging()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_Debugging = true;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::StopDebugging()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_Debugging = false;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:15:06 +00:00
|
|
|
bool CBreakpoints::isSkipping()
|
|
|
|
{
|
|
|
|
bool ret = m_Skipping;
|
|
|
|
m_Skipping = FALSE;
|
|
|
|
return ret;
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
void CBreakpoints::Skip()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_Skipping = true;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CBreakpoints::RBPAdd(uint32_t address, bool bTemporary)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
if (!ReadBPExists(address))
|
|
|
|
{
|
|
|
|
m_ReadMem.insert(breakpoints_t::value_type(address, bTemporary));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CBreakpoints::WBPAdd(uint32_t address, bool bTemporary)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
if (!WriteBPExists(address))
|
|
|
|
{
|
|
|
|
m_WriteMem.insert(breakpoints_t::value_type(address, bTemporary));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
2017-12-04 06:41:27 +00:00
|
|
|
bool CBreakpoints::AddExecution(uint32_t address, bool bTemporary)
|
2017-08-18 05:08:22 +00:00
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
if (!ExecutionBPExists(address))
|
|
|
|
{
|
|
|
|
m_Execution.insert(breakpoints_t::value_type(address, bTemporary));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::RBPRemove(uint32_t address)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
breakpoints_t::iterator itr = m_ReadMem.find(address);
|
|
|
|
if (itr != m_ReadMem.end())
|
|
|
|
{
|
|
|
|
m_ReadMem.erase(itr);
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::WBPRemove(uint32_t address)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
breakpoints_t::iterator itr = m_WriteMem.find(address);
|
|
|
|
if (itr != m_WriteMem.end())
|
|
|
|
{
|
|
|
|
m_WriteMem.erase(itr);
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
2017-12-04 06:41:27 +00:00
|
|
|
void CBreakpoints::RemoveExecution(uint32_t address)
|
2017-08-18 05:08:22 +00:00
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
breakpoints_t::iterator itr = m_Execution.find(address);
|
|
|
|
if (itr != m_Execution.end())
|
|
|
|
{
|
|
|
|
m_Execution.erase(itr);
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::RBPToggle(uint32_t address, bool bTemporary)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
if (RBPAdd(address, bTemporary) == false)
|
|
|
|
{
|
|
|
|
RBPRemove(address);
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::WBPToggle(uint32_t address, bool bTemporary)
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
if (WBPAdd(address, bTemporary) == false)
|
|
|
|
{
|
|
|
|
WBPRemove(address);
|
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::EBPToggle(uint32_t address, bool bTemporary)
|
|
|
|
{
|
2017-12-04 06:41:27 +00:00
|
|
|
if (AddExecution(address, bTemporary) == false)
|
2017-11-23 21:15:06 +00:00
|
|
|
{
|
2017-12-04 06:41:27 +00:00
|
|
|
RemoveExecution(address);
|
2017-11-23 21:15:06 +00:00
|
|
|
}
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::RBPClear()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_ReadMem.clear();
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::WBPClear()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_WriteMem.clear();
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::EBPClear()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
m_Execution.clear();
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CBreakpoints::BPClear()
|
|
|
|
{
|
2017-11-23 21:15:06 +00:00
|
|
|
RBPClear();
|
|
|
|
WBPClear();
|
|
|
|
EBPClear();
|
|
|
|
}
|
|
|
|
|
|
|
|
CBreakpoints::BPSTATE CBreakpoints::ReadBPExists(uint32_t address, bool bRemoveTemp)
|
|
|
|
{
|
|
|
|
breakpoints_t::const_iterator itr = m_ReadMem.find(address);
|
|
|
|
if (itr != m_ReadMem.end())
|
|
|
|
{
|
|
|
|
if (itr->second)
|
|
|
|
{
|
|
|
|
if (bRemoveTemp)
|
|
|
|
{
|
|
|
|
m_ReadMem.erase(itr);
|
|
|
|
}
|
|
|
|
return BP_SET_TEMP;
|
|
|
|
}
|
|
|
|
return BP_SET;
|
|
|
|
}
|
|
|
|
return BP_NOT_SET;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBreakpoints::BPSTATE CBreakpoints::WriteBPExists(uint32_t address, bool bRemoveTemp)
|
|
|
|
{
|
|
|
|
breakpoints_t::const_iterator itr = m_WriteMem.find(address);
|
|
|
|
if (itr != m_WriteMem.end())
|
|
|
|
{
|
|
|
|
if (itr->second)
|
|
|
|
{
|
|
|
|
if (bRemoveTemp)
|
|
|
|
{
|
|
|
|
m_ReadMem.erase(itr);
|
|
|
|
}
|
|
|
|
return BP_SET_TEMP;
|
|
|
|
}
|
|
|
|
return BP_SET;
|
|
|
|
}
|
|
|
|
return BP_NOT_SET;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp)
|
|
|
|
{
|
|
|
|
breakpoints_t::const_iterator itr = m_Execution.find(address);
|
|
|
|
if (itr != m_Execution.end())
|
|
|
|
{
|
|
|
|
if (itr->second)
|
|
|
|
{
|
|
|
|
if (bRemoveTemp)
|
|
|
|
{
|
2017-12-04 06:41:27 +00:00
|
|
|
m_Execution.erase(itr);
|
2017-11-23 21:15:06 +00:00
|
|
|
}
|
|
|
|
return BP_SET_TEMP;
|
|
|
|
}
|
|
|
|
return BP_SET;
|
|
|
|
}
|
|
|
|
return BP_NOT_SET;
|
|
|
|
}
|