2022-08-22 22:21:23 +02:00
# include "gui/wxgui.h"
# include "gui/debugger/DebuggerWindow2.h"
# include <filesystem>
# include "config/ActiveSettings.h"
# include "Cafe/OS/RPL/rpl_structs.h"
# include "Cafe/OS/RPL/rpl_debug_symbols.h"
# include "gui/debugger/RegisterWindow.h"
# include "gui/debugger/DumpWindow.h"
# include "Cafe/HW/Espresso/Debugger/Debugger.h"
# include "Cafe/OS/RPL/rpl.h"
# include "gui/debugger/DisasmCtrl.h"
# include "gui/debugger/SymbolWindow.h"
# include "gui/debugger/BreakpointWindow.h"
# include "gui/debugger/ModuleWindow.h"
# include "util/helpers/helpers.h"
# if BOOST_OS_LINUX
2022-08-26 04:03:26 +02:00
# include "resource/embedded/resources.h"
2022-08-22 22:21:23 +02:00
# endif
enum
{
// file
MENU_ID_FILE_EXIT = wxID_HIGHEST + 8000 ,
// settings
MENU_ID_OPTIONS_PIN_TO_MAINWINDOW ,
MENU_ID_OPTIONS_BREAK_ON_START ,
// window
MENU_ID_WINDOW_REGISTERS ,
MENU_ID_WINDOW_DUMP ,
MENU_ID_WINDOW_STACK ,
MENU_ID_WINDOW_BREAKPOINTS ,
MENU_ID_WINDOW_MODULE ,
MENU_ID_WINDOW_SYMBOL ,
// tool
TOOL_ID_GOTO ,
TOOL_ID_BP ,
TOOL_ID_PAUSE ,
TOOL_ID_STEP_OVER ,
TOOL_ID_STEP_INTO ,
} ;
wxDEFINE_EVENT ( wxEVT_DEBUGGER_CLOSE , wxCloseEvent ) ;
wxDEFINE_EVENT ( wxEVT_UPDATE_VIEW , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_BREAKPOINT_CHANGE , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_BREAKPOINT_HIT , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_MOVE_IP , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_RUN , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_NOTIFY_MODULE_LOADED , wxCommandEvent ) ;
wxDEFINE_EVENT ( wxEVT_NOTIFY_MODULE_UNLOADED , wxCommandEvent ) ;
wxBEGIN_EVENT_TABLE ( DebuggerWindow2 , wxFrame )
EVT_SHOW ( DebuggerWindow2 : : OnShow )
EVT_CLOSE ( DebuggerWindow2 : : OnClose )
EVT_COMMAND ( wxID_ANY , wxEVT_UPDATE_VIEW , DebuggerWindow2 : : OnUpdateView )
EVT_COMMAND ( wxID_ANY , wxEVT_BREAKPOINT_CHANGE , DebuggerWindow2 : : OnBreakpointChange )
EVT_COMMAND ( wxID_ANY , wxEVT_MOVE_IP , DebuggerWindow2 : : OnMoveIP )
EVT_COMMAND ( wxID_ANY , wxEVT_COMMAND_TOOL_CLICKED , DebuggerWindow2 : : OnToolClicked )
EVT_COMMAND ( wxID_ANY , wxEVT_BREAKPOINT_HIT , DebuggerWindow2 : : OnBreakpointHit )
EVT_COMMAND ( wxID_ANY , wxEVT_RUN , DebuggerWindow2 : : OnRunProgram )
EVT_COMMAND ( wxID_ANY , wxEVT_NOTIFY_MODULE_LOADED , DebuggerWindow2 : : OnNotifyModuleLoaded )
EVT_COMMAND ( wxID_ANY , wxEVT_NOTIFY_MODULE_UNLOADED , DebuggerWindow2 : : OnNotifyModuleUnloaded )
// file menu
EVT_MENU ( MENU_ID_FILE_EXIT , DebuggerWindow2 : : OnExit )
// setting
EVT_MENU ( MENU_ID_OPTIONS_PIN_TO_MAINWINDOW , DebuggerWindow2 : : OnOptionsInput )
// window
EVT_MENU_RANGE ( MENU_ID_WINDOW_REGISTERS , MENU_ID_WINDOW_MODULE , DebuggerWindow2 : : OnWindowMenu )
wxEND_EVENT_TABLE ( )
DebuggerWindow2 * g_debugger_window ;
void DebuggerConfig : : Load ( XMLConfigParser & parser )
{
pin_to_main = parser . get ( " PinToMainWindow " , true ) ;
break_on_start = parser . get ( " break_on_start " , true ) ;
auto window_parser = parser . get ( " Windows " ) ;
show_register = window_parser . get ( " Registers " , true ) ;
show_dump = window_parser . get ( " MemoryDump " , true ) ;
show_stack = window_parser . get ( " Stack " , true ) ;
show_breakpoints = window_parser . get ( " Breakpoints " , true ) ;
show_modules = window_parser . get ( " Modules " , true ) ;
show_symbols = window_parser . get ( " Symbols " , true ) ;
}
void DebuggerConfig : : Save ( XMLConfigParser & parser )
{
parser . set ( " PinToMainWindow " , pin_to_main ) ;
parser . set ( " break_on_start " , break_on_start ) ;
auto window_parser = parser . set ( " Windows " ) ;
window_parser . set ( " Registers " , show_register ) ;
window_parser . set ( " MemoryDump " , show_dump ) ;
window_parser . set ( " Stack " , show_stack ) ;
window_parser . set ( " Breakpoints " , show_breakpoints ) ;
window_parser . set ( " Modules " , show_modules ) ;
window_parser . set ( " Symbols " , show_symbols ) ;
}
void DebuggerModuleStorage : : Load ( XMLConfigParser & parser )
{
auto breakpoints_parser = parser . get ( " Breakpoints " ) ;
for ( auto element = breakpoints_parser . get ( " Entry " ) ; element . valid ( ) ; element = breakpoints_parser . get ( " Entry " , element ) )
{
const auto address_string = element . get ( " Address " , " " ) ;
if ( * address_string = = ' \0 ' )
continue ;
uint32 relative_address = std : : stoul ( address_string , nullptr , 16 ) ;
if ( relative_address = = 0 )
continue ;
auto type = element . get ( " Type " , 0 ) ;
auto enabled = element . get ( " Enabled " , true ) ;
const auto comment = element . get ( " Comment " , " " ) ;
// calculate absolute address
uint32 module_base_address = ( type = = DEBUGGER_BP_T_NORMAL ? this - > rpl_module - > regionMappingBase_text . GetMPTR ( ) : this - > rpl_module - > regionMappingBase_data ) ;
uint32 address = module_base_address + relative_address ;
// don't change anything if there's already a breakpoint
if ( debugger_getFirstBP ( address ) ! = nullptr )
continue ;
// register breakpoints in debugger
if ( type = = DEBUGGER_BP_T_NORMAL )
debugger_createExecuteBreakpoint ( address ) ;
else if ( type = = DEBUGGER_BP_T_MEMORY_READ )
debugger_createMemoryBreakpoint ( address , true , false ) ;
else if ( type = = DEBUGGER_BP_T_MEMORY_WRITE )
debugger_createMemoryBreakpoint ( address , false , true ) ;
else
continue ;
DebuggerBreakpoint * debugBreakpoint = debugger_getFirstBP ( address ) ;
if ( ! enabled )
debugger_toggleBreakpoint ( address , false , debugBreakpoint ) ;
debugBreakpoint - > comment = boost : : nowide : : widen ( comment ) ;
}
auto comments_parser = parser . get ( " Comments " ) ;
for ( XMLConfigParser element = comments_parser . get ( " Entry " ) ; element . valid ( ) ; element = comments_parser . get ( " Entry " , element ) )
{
const auto address_string = element . get ( " Address " , " " ) ;
if ( * address_string = = ' \0 ' )
continue ;
uint32 address = std : : stoul ( address_string , nullptr , 16 ) ;
if ( address = = 0 )
continue ;
const auto comment = element . get ( " Comment " , " " ) ;
if ( * comment = = ' \0 ' )
continue ;
rplDebugSymbol_createComment ( address , boost : : nowide : : widen ( comment ) . c_str ( ) ) ;
}
}
void DebuggerModuleStorage : : Save ( XMLConfigParser & parser )
{
auto breakpoints_parser = parser . set ( " Breakpoints " ) ;
for ( const auto & bp : debuggerState . breakpoints )
{
// check breakpoint type
if ( bp - > dbType ! = DEBUGGER_BP_T_DEBUGGER )
continue ;
// check whether the breakpoint is part of the current module being saved
RPLModule * address_module ;
if ( bp - > bpType = = DEBUGGER_BP_T_NORMAL ) address_module = RPLLoader_FindModuleByCodeAddr ( bp - > address ) ;
else if ( bp - > isMemBP ( ) ) address_module = RPLLoader_FindModuleByDataAddr ( bp - > address ) ;
else continue ;
if ( ! address_module | | ! ( address_module - > moduleName2 = = this - > module_name & & address_module - > patchCRC = = this - > crc_hash ) )
continue ;
uint32_t relative_address = bp - > address - ( bp - > isMemBP ( ) ? address_module - > regionMappingBase_data : address_module - > regionMappingBase_text . GetMPTR ( ) ) ;
auto entry = breakpoints_parser . set ( " Entry " ) ;
entry . set ( " Address " , fmt : : format ( " {:#10x} " , relative_address ) ) ;
entry . set ( " Comment " , boost : : nowide : : narrow ( bp - > comment ) . c_str ( ) ) ;
entry . set ( " Type " , bp - > bpType ) ;
entry . set ( " Enabled " , bp - > enabled ) ;
if ( this - > delete_breakpoints_after_saving ) debugger_deleteBreakpoint ( bp ) ;
this - > delete_breakpoints_after_saving = false ;
}
auto comments_parser = parser . set ( " Comments " ) ;
for ( const auto & comment_entry : rplDebugSymbol_getSymbols ( ) )
{
// check comment type
const auto comment_address = comment_entry . first ;
const auto comment = static_cast < rplDebugSymbolComment * > ( comment_entry . second ) ;
if ( ! comment | | comment - > type ! = RplDebugSymbolComment )
continue ;
// check whether it's part of the current module being saved
RPLModule * address_module = RPLLoader_FindModuleByCodeAddr ( comment_entry . first ) ;
if ( ! address_module | | ! ( address_module - > moduleName2 = = module_name & & address_module - > patchCRC = = this - > crc_hash ) )
continue ;
uint32_t relative_address = comment_address - address_module - > regionMappingBase_text . GetMPTR ( ) ;
auto entry = comments_parser . set ( " Entry " ) ;
entry . set ( " Address " , fmt : : format ( " {:#10x} " , relative_address ) ) ;
entry . set ( " Comment " , boost : : nowide : : narrow ( comment - > comment ) . c_str ( ) ) ;
}
}
void DebuggerWindow2 : : CreateToolBar ( )
{
m_toolbar = wxFrame : : CreateToolBar ( wxTB_HORIZONTAL , wxID_ANY ) ;
m_toolbar - > SetToolBitmapSize ( wxSize ( 1 , 1 ) ) ;
m_toolbar - > AddTool ( TOOL_ID_GOTO , wxEmptyString , wxBITMAP_PNG ( DEBUGGER_GOTO ) , wxNullBitmap , wxITEM_NORMAL , _ ( " GoTo (CTRL + G) " ) , " test " , NULL ) ;
m_toolbar - > AddSeparator ( ) ;
m_toolbar - > AddTool ( TOOL_ID_BP , wxEmptyString , wxBITMAP_PNG ( DEBUGGER_BP_RED ) , wxNullBitmap , wxITEM_NORMAL , _ ( " Toggle Breakpoint (F9) " ) , wxEmptyString , NULL ) ;
m_toolbar - > AddSeparator ( ) ;
m_pause = wxBITMAP_PNG ( DEBUGGER_PAUSE ) ;
m_run = wxBITMAP_PNG ( DEBUGGER_PLAY ) ;
m_toolbar - > AddTool ( TOOL_ID_PAUSE , wxEmptyString , m_pause , wxNullBitmap , wxITEM_NORMAL , _ ( " Break (F5) " ) , wxEmptyString , NULL ) ;
m_toolbar - > AddTool ( TOOL_ID_STEP_INTO , wxEmptyString , wxBITMAP_PNG ( DEBUGGER_STEP_INTO ) , wxNullBitmap , wxITEM_NORMAL , _ ( " Step Into (F11) " ) , wxEmptyString , NULL ) ;
m_toolbar - > AddTool ( TOOL_ID_STEP_OVER , wxEmptyString , wxBITMAP_PNG ( DEBUGGER_STEP_OVER ) , wxNullBitmap , wxITEM_NORMAL , _ ( " Step Over (F10) " ) , wxEmptyString , NULL ) ;
m_toolbar - > AddSeparator ( ) ;
m_toolbar - > Realize ( ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_INTO , false ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_OVER , false ) ;
}
void DebuggerWindow2 : : SaveModuleStorage ( const RPLModule * module , bool delete_breakpoints )
{
auto path = GetModuleStoragePath ( module - > moduleName2 , module - > patchCRC ) ;
for ( auto & module_storage : m_modules_storage )
{
if ( module_storage - > data ( ) . module_name = = module - > moduleName2 & & module_storage - > data ( ) . crc_hash = = module - > patchCRC )
{
module_storage - > data ( ) . delete_breakpoints_after_saving = delete_breakpoints ;
module_storage - > Save ( path ) ;
if ( delete_breakpoints ) m_modules_storage . erase ( std : : find ( m_modules_storage . begin ( ) , m_modules_storage . end ( ) , module_storage ) ) ;
}
}
}
void DebuggerWindow2 : : LoadModuleStorage ( const RPLModule * module )
{
auto path = GetModuleStoragePath ( module - > moduleName2 , module - > patchCRC ) ;
bool already_loaded = std : : any_of ( m_modules_storage . begin ( ) , m_modules_storage . end ( ) , [ path ] ( const std : : unique_ptr < XMLDebuggerModuleConfig > & debug ) { return debug - > GetFilename ( ) = = path ; } ) ;
if ( ! path . empty ( ) & & ! already_loaded )
{
m_modules_storage . emplace_back ( std : : move ( new XMLDebuggerModuleConfig ( path , { module - > moduleName2 , module - > patchCRC , module , false } ) ) ) ;
}
}
DebuggerWindow2 : : DebuggerWindow2 ( wxFrame & parent , const wxRect & display_size )
2022-09-03 22:55:58 +02:00
: wxFrame ( & parent , wxID_ANY , _ ( " PPC Debugger " ) , wxDefaultPosition , wxSize ( 1280 , 300 ) , wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT ) ,
2022-08-22 22:21:23 +02:00
m_module_address ( 0 )
{
this - > wxWindowBase : : SetBackgroundColour ( * wxWHITE ) ;
const auto file = ActiveSettings : : GetPath ( " debugger/config.xml " ) ;
m_config . SetFilename ( file . generic_wstring ( ) ) ;
m_config . Load ( ) ;
debuggerState . breakOnEntry = m_config . data ( ) . break_on_start ;
m_main_position = parent . GetPosition ( ) ;
m_main_size = parent . GetSize ( ) ;
auto y = std : : max < uint32 > ( 300 , ( display_size . GetHeight ( ) - 500 - 300 ) * 0.8 ) ;
this - > SetSize ( 1280 , y ) ;
CreateMenuBar ( ) ;
CreateToolBar ( ) ;
wxBoxSizer * main_sizer = new wxBoxSizer ( wxVERTICAL ) ;
// load configs for already loaded modules
const auto module_count = RPLLoader_GetModuleCount ( ) ;
const auto module_list = RPLLoader_GetModuleList ( ) ;
for ( sint32 i = 0 ; i < module_count ; i + + )
{
const auto module = module_list [ i ] ;
LoadModuleStorage ( module ) ;
}
wxString label_text = _ ( " > no modules loaded " ) ;
if ( module_count ! = 0 )
{
RPLModule * current_rpl_module = RPLLoader_FindModuleByCodeAddr ( MEMORY_CODEAREA_ADDR ) ;
if ( current_rpl_module )
label_text = wxString : : Format ( " > %s " , current_rpl_module - > moduleName2 . c_str ( ) ) ;
else
label_text = _ ( " > unknown module " ) ;
}
m_module_label = new wxStaticText ( this , wxID_ANY , label_text ) ;
m_module_label - > SetBackgroundColour ( * wxWHITE ) ;
m_module_label - > SetForegroundColour ( wxColour ( 0xFFbf52fe ) ) ;
main_sizer - > Add ( m_module_label , 0 , wxEXPAND | wxALL , 5 ) ;
m_disasm_ctrl = new DisasmCtrl ( this , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxScrolledWindowStyle ) ;
main_sizer - > Add ( m_disasm_ctrl , 1 , wxEXPAND ) ;
this - > SetSizer ( main_sizer ) ;
this - > wxWindowBase : : Layout ( ) ;
m_register_window = new RegisterWindow ( * this , m_main_position , m_main_size ) ;
m_dump_window = new DumpWindow ( * this , m_main_position , m_main_size ) ;
m_breakpoint_window = new BreakpointWindow ( * this , m_main_position , m_main_size ) ;
m_module_window = new ModuleWindow ( * this , m_main_position , m_main_size ) ;
m_symbol_window = new SymbolWindow ( * this , m_main_position , m_main_size ) ;
const bool value = m_config . data ( ) . pin_to_main ;
m_config . data ( ) . pin_to_main = true ;
OnParentMove ( m_main_position , m_main_size ) ;
m_config . data ( ) . pin_to_main = value ;
g_debugger_window = this ;
}
DebuggerWindow2 : : ~ DebuggerWindow2 ( )
{
debuggerState . breakOnEntry = false ;
g_debugger_window = nullptr ;
// save configs for all modules that are still loaded
// doesn't delete breakpoints since that should (in the future) be done by unloading the rpl modules when exiting the current game
const auto module_count = RPLLoader_GetModuleCount ( ) ;
const auto module_list = RPLLoader_GetModuleList ( ) ;
for ( sint32 i = 0 ; i < module_count ; i + + )
{
const auto module = module_list [ i ] ;
if ( module )
SaveModuleStorage ( module , false ) ;
}
if ( m_register_window & & m_register_window - > IsShown ( ) )
m_register_window - > Close ( true ) ;
if ( m_dump_window & & m_dump_window - > IsShown ( ) )
m_dump_window - > Close ( true ) ;
if ( m_breakpoint_window & & m_breakpoint_window - > IsShown ( ) )
m_breakpoint_window - > Close ( true ) ;
if ( m_module_window & & m_module_window - > IsShown ( ) )
m_module_window - > Close ( true ) ;
if ( m_symbol_window & & m_symbol_window - > IsShown ( ) )
m_symbol_window - > Close ( true ) ;
m_config . Save ( ) ;
}
void DebuggerWindow2 : : OnClose ( wxCloseEvent & event )
{
debuggerState . breakOnEntry = false ;
const wxCloseEvent parentEvent ( wxEVT_DEBUGGER_CLOSE ) ;
wxPostEvent ( m_parent , parentEvent ) ;
event . Skip ( ) ;
}
void DebuggerWindow2 : : OnMoveIP ( wxCommandEvent & event )
{
const auto ip = debuggerState . debugSession . instructionPointer ;
UpdateModuleLabel ( ip ) ;
m_disasm_ctrl - > CenterOffset ( ip ) ;
}
void DebuggerWindow2 : : OnParentMove ( const wxPoint & main_position , const wxSize & main_size )
{
m_main_position = main_position ;
m_main_size = main_size ;
if ( ! m_config . data ( ) . pin_to_main )
return ;
wxSize size ( m_main_size . x , GetSize ( ) . GetHeight ( ) ) ;
SetSize ( size ) ;
wxPoint position = m_main_position ;
position . y - = size . y ;
SetPosition ( position ) ;
m_register_window - > OnMainMove ( main_position , main_size ) ;
m_dump_window - > OnMainMove ( main_position , main_size ) ;
m_breakpoint_window - > OnMainMove ( main_position , main_size ) ;
m_module_window - > OnMainMove ( main_position , main_size ) ;
m_symbol_window - > OnMainMove ( main_position , main_size ) ;
}
void DebuggerWindow2 : : OnNotifyModuleLoaded ( wxCommandEvent & event )
{
RPLModule * module = ( RPLModule * ) event . GetClientData ( ) ;
LoadModuleStorage ( module ) ;
m_module_window - > OnGameLoaded ( ) ;
m_symbol_window - > OnGameLoaded ( ) ;
m_disasm_ctrl - > Init ( ) ;
}
void DebuggerWindow2 : : OnNotifyModuleUnloaded ( wxCommandEvent & event )
{
RPLModule * module = ( RPLModule * ) event . GetClientData ( ) ;
SaveModuleStorage ( module , true ) ;
m_module_window - > OnGameLoaded ( ) ;
m_symbol_window - > OnGameLoaded ( ) ;
m_disasm_ctrl - > Init ( ) ;
}
void DebuggerWindow2 : : OnGameLoaded ( )
{
m_disasm_ctrl - > Init ( ) ;
m_dump_window - > OnGameLoaded ( ) ;
m_module_window - > OnGameLoaded ( ) ;
m_breakpoint_window - > OnGameLoaded ( ) ;
m_symbol_window - > OnGameLoaded ( ) ;
RPLModule * current_rpl_module = RPLLoader_FindModuleByCodeAddr ( MEMORY_CODEAREA_ADDR ) ;
if ( current_rpl_module )
m_module_label - > SetLabel ( wxString : : Format ( " > %s " , current_rpl_module - > moduleName2 . c_str ( ) ) ) ;
this - > SendSizeEvent ( ) ;
}
XMLDebuggerConfig & DebuggerWindow2 : : GetConfig ( )
{
return m_config ;
}
bool DebuggerWindow2 : : Show ( bool show )
{
const bool result = wxFrame : : Show ( show ) ;
if ( show )
{
m_register_window - > Show ( m_config . data ( ) . show_register ) ;
m_dump_window - > Show ( m_config . data ( ) . show_dump ) ;
m_breakpoint_window - > Show ( m_config . data ( ) . show_breakpoints ) ;
m_module_window - > Show ( m_config . data ( ) . show_modules ) ;
m_symbol_window - > Show ( m_config . data ( ) . show_symbols ) ;
}
else
{
m_register_window - > Show ( false ) ;
m_dump_window - > Show ( false ) ;
m_breakpoint_window - > Show ( false ) ;
m_module_window - > Show ( false ) ;
m_symbol_window - > Show ( false ) ;
}
return result ;
}
std : : wstring DebuggerWindow2 : : GetModuleStoragePath ( std : : string module_name , uint32_t crc_hash ) const
{
if ( module_name . empty ( ) | | crc_hash = = 0 ) return std : : wstring ( ) ;
return ActiveSettings : : GetPath ( " debugger/{}_{:#10x}.xml " , module_name , crc_hash ) . generic_wstring ( ) ;
}
void DebuggerWindow2 : : OnBreakpointHit ( wxCommandEvent & event )
{
const auto ip = debuggerState . debugSession . instructionPointer ;
UpdateModuleLabel ( ip ) ;
m_toolbar - > SetToolShortHelp ( TOOL_ID_PAUSE , _ ( " Run (F5) " ) ) ;
m_toolbar - > SetToolNormalBitmap ( TOOL_ID_PAUSE , m_run ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_INTO , true ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_OVER , true ) ;
m_disasm_ctrl - > CenterOffset ( ip ) ;
}
void DebuggerWindow2 : : OnRunProgram ( wxCommandEvent & event )
{
m_toolbar - > SetToolShortHelp ( TOOL_ID_PAUSE , _ ( " Break (F5) " ) ) ;
m_toolbar - > SetToolNormalBitmap ( TOOL_ID_PAUSE , m_pause ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_INTO , false ) ;
m_toolbar - > EnableTool ( TOOL_ID_STEP_OVER , false ) ;
}
void DebuggerWindow2 : : OnToolClicked ( wxCommandEvent & event )
{
switch ( event . GetId ( ) )
{
case TOOL_ID_GOTO :
m_disasm_ctrl - > GoToAddressDialog ( ) ;
break ;
case TOOL_ID_PAUSE :
if ( debugger_isTrapped ( ) )
debugger_resume ( ) ;
else
debugger_forceBreak ( ) ;
break ;
case TOOL_ID_STEP_INTO :
if ( debugger_isTrapped ( ) )
debuggerState . debugSession . stepInto = true ;
break ;
case TOOL_ID_STEP_OVER :
if ( debugger_isTrapped ( ) )
debuggerState . debugSession . stepOver = true ;
break ;
}
}
void DebuggerWindow2 : : OnBreakpointChange ( wxCommandEvent & event )
{
m_breakpoint_window - > OnUpdateView ( ) ;
UpdateModuleLabel ( ) ;
}
void DebuggerWindow2 : : OnOptionsInput ( wxCommandEvent & event )
{
switch ( event . GetId ( ) )
{
case MENU_ID_OPTIONS_PIN_TO_MAINWINDOW :
{
const bool value = ! m_config . data ( ) . pin_to_main ;
m_config . data ( ) . pin_to_main = value ;
if ( value )
OnParentMove ( m_main_position , m_main_size ) ;
break ;
}
case MENU_ID_OPTIONS_BREAK_ON_START :
{
const bool value = ! m_config . data ( ) . break_on_start ;
m_config . data ( ) . break_on_start = value ;
debuggerState . breakOnEntry = value ;
break ;
}
default :
return ;
}
m_config . Save ( ) ;
}
void DebuggerWindow2 : : OnWindowMenu ( wxCommandEvent & event )
{
switch ( event . GetId ( ) )
{
case MENU_ID_WINDOW_REGISTERS :
{
const bool value = ! m_config . data ( ) . show_register ;
m_config . data ( ) . show_register = value ;
m_register_window - > Show ( value ) ;
break ;
}
case MENU_ID_WINDOW_DUMP :
{
const bool value = ! m_config . data ( ) . show_dump ;
m_config . data ( ) . show_dump = value ;
m_dump_window - > Show ( value ) ;
break ;
}
case MENU_ID_WINDOW_BREAKPOINTS :
{
const bool value = ! m_config . data ( ) . show_breakpoints ;
m_config . data ( ) . show_breakpoints = value ;
m_breakpoint_window - > Show ( value ) ;
break ;
}
case MENU_ID_WINDOW_MODULE :
{
const bool value = ! m_config . data ( ) . show_modules ;
m_config . data ( ) . show_modules = value ;
m_module_window - > Show ( value ) ;
break ;
}
case MENU_ID_WINDOW_SYMBOL :
{
const bool value = ! m_config . data ( ) . show_symbols ;
m_config . data ( ) . show_symbols = value ;
m_symbol_window - > Show ( value ) ;
break ;
}
default :
return ;
}
m_config . Save ( ) ;
}
void DebuggerWindow2 : : OnUpdateView ( wxCommandEvent & event )
{
UpdateModuleLabel ( ) ;
m_disasm_ctrl - > OnUpdateView ( ) ;
m_register_window - > OnUpdateView ( ) ;
m_breakpoint_window - > OnUpdateView ( ) ;
}
void DebuggerWindow2 : : OnExit ( wxCommandEvent & event )
{
this - > Close ( ) ;
}
void DebuggerWindow2 : : OnShow ( wxShowEvent & event )
{
m_register_window - > Show ( ) ;
m_dump_window - > Show ( ) ;
m_breakpoint_window - > Show ( ) ;
m_module_window - > Show ( ) ;
m_symbol_window - > Show ( ) ;
event . Skip ( ) ;
}
void DebuggerWindow2 : : CreateMenuBar ( )
{
auto menu_bar = new wxMenuBar ;
// file
wxMenu * file_menu = new wxMenu ;
file_menu - > Append ( MENU_ID_FILE_EXIT , _ ( " &Exit " ) ) ;
file_menu - > Bind ( wxEVT_MENU , & DebuggerWindow2 : : OnExit , this ) ;
menu_bar - > Append ( file_menu , _ ( " &File " ) ) ;
// options
wxMenu * options_menu = new wxMenu ;
options_menu - > Append ( MENU_ID_OPTIONS_PIN_TO_MAINWINDOW , _ ( " &Pin to main window " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . pin_to_main ) ;
options_menu - > Append ( MENU_ID_OPTIONS_BREAK_ON_START , _ ( " Break on &entry point " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . break_on_start ) ;
menu_bar - > Append ( options_menu , _ ( " &Options " ) ) ;
// window
wxMenu * window_menu = new wxMenu ;
window_menu - > Append ( MENU_ID_WINDOW_REGISTERS , _ ( " &Registers " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . show_register ) ;
window_menu - > Append ( MENU_ID_WINDOW_DUMP , _ ( " &Memory Dump " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . show_dump ) ;
window_menu - > Append ( MENU_ID_WINDOW_BREAKPOINTS , _ ( " &Breakpoints " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . show_breakpoints ) ;
window_menu - > Append ( MENU_ID_WINDOW_MODULE , _ ( " Module&list " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . show_modules ) ;
window_menu - > Append ( MENU_ID_WINDOW_SYMBOL , _ ( " &Symbols " ) , wxEmptyString , wxITEM_CHECK ) - > Check ( m_config . data ( ) . show_symbols ) ;
menu_bar - > Append ( window_menu , _ ( " &Window " ) ) ;
SetMenuBar ( menu_bar ) ;
options_menu - > Bind ( wxEVT_MENU , & DebuggerWindow2 : : OnOptionsInput , this ) ;
window_menu - > Bind ( wxEVT_MENU , & DebuggerWindow2 : : OnWindowMenu , this ) ;
}
void DebuggerWindow2 : : UpdateModuleLabel ( uint32 address )
{
if ( address = = 0 )
address = m_disasm_ctrl - > GetViewBaseAddress ( ) ;
RPLModule * module = RPLLoader_FindModuleByCodeAddr ( address ) ;
if ( module & & m_module_address ! = module - > regionMappingBase_text . GetMPTR ( ) )
{
m_module_label - > SetLabel ( wxString : : Format ( " > %s " , module - > moduleName2 . c_str ( ) ) ) ;
m_module_address = module - > regionMappingBase_text . GetMPTR ( ) ;
}
else if ( address > = mmuRange_CODECAVE . getBase ( ) & & address < mmuRange_CODECAVE . getEnd ( ) )
{
m_module_label - > SetLabel ( wxString : : Format ( " > %s " , " Cemu codecave " ) ) ;
m_module_address = mmuRange_CODECAVE . getBase ( ) ;
}
}