@@ -47,8 +47,19 @@ struct DisassemblerBookmark
4747 char name[32 ];
4848};
4949
50+ struct SymbolEntry
51+ {
52+ DebugSymbol* symbol;
53+ bool is_manual;
54+ int bank;
55+ };
56+
57+ static bool symbols_dirty = true ;
58+ static bool show_auto_symbols = false ;
5059static DebugSymbol*** fixed_symbols = NULL ;
5160static DebugSymbol*** dynamic_symbols = NULL ;
61+ static std::vector<SymbolEntry> fixed_symbol_list;
62+ static std::vector<SymbolEntry> dynamic_symbol_list;
5263static std::vector<DisassemblerLine> disassembler_lines (0x10000 );
5364static std::vector<DisassemblerBookmark> bookmarks;
5465static int selected_address = -1 ;
@@ -88,6 +99,12 @@ static void add_bookmark_popup(void);
8899static void add_symbol_popup (void );
89100static void save_full_disassembler (FILE* file);
90101static void save_current_disassembler (FILE* file);
102+ static bool symbol_sort_address_asc (const SymbolEntry& a, const SymbolEntry& b);
103+ static bool symbol_sort_address_desc (const SymbolEntry& a, const SymbolEntry& b);
104+ static bool symbol_sort_addr_only_asc (const SymbolEntry& a, const SymbolEntry& b);
105+ static bool symbol_sort_addr_only_desc (const SymbolEntry& a, const SymbolEntry& b);
106+ static bool symbol_sort_name_asc (const SymbolEntry& a, const SymbolEntry& b);
107+ static bool symbol_sort_name_desc (const SymbolEntry& a, const SymbolEntry& b);
91108
92109void gui_debug_disassembler_init (void )
93110{
@@ -145,6 +162,10 @@ void gui_debug_reset_symbols(void)
145162 }
146163 }
147164
165+ fixed_symbol_list.clear ();
166+ dynamic_symbol_list.clear ();
167+ symbols_dirty = true ;
168+
148169 if (emu_get_core ()->GetMedia ()->IsCDROM ())
149170 {
150171 add_cdrom_symbols ();
@@ -932,6 +953,13 @@ static void add_symbol(const char* line)
932953 snprintf (new_symbol->text , 64 , " %s" , s.text );
933954
934955 fixed_symbols[s.bank ][s.address ] = new_symbol;
956+
957+ SymbolEntry entry;
958+ entry.symbol = new_symbol;
959+ entry.is_manual = true ;
960+ entry.bank = s.bank ;
961+ fixed_symbol_list.push_back (entry);
962+ symbols_dirty = true ;
935963 }
936964 }
937965 }
@@ -977,6 +1005,8 @@ static void add_auto_symbol(GG_Disassembler_Record* record, u16 address)
9771005 {
9781006 if (record->subroutine )
9791007 snprintf (dynamic_symbols[s.bank ][s.address ]->text , 64 , " SUB_%02X_%04X" , record->jump_bank , record->jump_address );
1008+ if (show_auto_symbols)
1009+ symbols_dirty = true ;
9801010 }
9811011 else
9821012 {
@@ -986,6 +1016,15 @@ static void add_auto_symbol(GG_Disassembler_Record* record, u16 address)
9861016 snprintf (new_symbol->text , 64 , " %s" , s.text );
9871017
9881018 dynamic_symbols[s.bank ][s.address ] = new_symbol;
1019+
1020+ SymbolEntry entry;
1021+ entry.symbol = new_symbol;
1022+ entry.is_manual = false ;
1023+ entry.bank = s.bank ;
1024+ dynamic_symbol_list.push_back (entry);
1025+
1026+ if (show_auto_symbols)
1027+ symbols_dirty = true ;
9891028 }
9901029 }
9911030}
@@ -1621,61 +1660,163 @@ void gui_debug_window_symbols(void)
16211660{
16221661 ImGui::PushStyleVar (ImGuiStyleVar_WindowRounding, 8 .0f );
16231662 ImGui::SetNextWindowPos (ImVec2 (340 , 400 ), ImGuiCond_FirstUseEver);
1624- ImGui::SetNextWindowSize (ImVec2 (356 , 300 ), ImGuiCond_FirstUseEver);
1663+ ImGui::SetNextWindowSize (ImVec2 (356 , 370 ), ImGuiCond_FirstUseEver);
16251664
16261665 ImGui::Begin (" Symbols" , &config_debug.show_symbols );
16271666
1628- static bool show_auto_symbols = false ;
1629- ImGui::Checkbox (" Show Automatic Symbols" , &show_auto_symbols);
1667+ static char symbol_filter[64 ] = " " ;
1668+ static std::vector<SymbolEntry> sorted_symbols;
1669+ static int last_sort_column = -1 ;
1670+ static int last_sort_direction = -1 ;
1671+
1672+ bool prev_auto = show_auto_symbols;
1673+ ImGui::Checkbox (" Automatic Symbols" , &show_auto_symbols);
1674+ if (show_auto_symbols != prev_auto)
1675+ symbols_dirty = true ;
1676+ ImGui::SameLine ();
1677+ ImGui::PushItemWidth (-1 );
1678+ if (ImGui::InputTextWithHint (" ##symbol_filter" , " Filter..." , symbol_filter, IM_ARRAYSIZE (symbol_filter)))
1679+ symbols_dirty = true ;
1680+ ImGui::PopItemWidth ();
16301681
16311682 ImGui::Separator ();
16321683
1633- ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable;
1684+ ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable ;
16341685
16351686 if (ImGui::BeginTable (" symbols_table" , 4 , flags))
16361687 {
16371688 ImGui::TableSetupScrollFreeze (0 , 1 );
1638- ImGui::TableSetupColumn (" Bank" , ImGuiTableColumnFlags_WidthFixed, 36 .0f );
1689+ ImGui::TableSetupColumn (" Bank" , ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultSort , 36 .0f );
16391690 ImGui::TableSetupColumn (" Address" , ImGuiTableColumnFlags_WidthFixed, 58 .0f );
16401691 ImGui::TableSetupColumn (" Symbol" , ImGuiTableColumnFlags_WidthStretch, 2 .0f );
1641- ImGui::TableSetupColumn (" Type" , ImGuiTableColumnFlags_WidthFixed, 44 .0f );
1692+ ImGui::TableSetupColumn (" Type" , ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoSort , 44 .0f );
16421693 ImGui::TableHeadersRow ();
16431694
1644- ImGui::PushFont (gui_default_font);
1695+ if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs ())
1696+ {
1697+ if (sort_specs->SpecsDirty || symbols_dirty)
1698+ {
1699+ sort_specs->SpecsDirty = false ;
1700+ symbols_dirty = true ;
1701+ }
1702+
1703+ if (sort_specs->SpecsCount > 0 )
1704+ {
1705+ last_sort_column = sort_specs->Specs [0 ].ColumnIndex ;
1706+ last_sort_direction = sort_specs->Specs [0 ].SortDirection ;
1707+ }
1708+ }
16451709
1646- for ( int b = 0 ; b < 0x100 ; b++ )
1710+ if (symbols_dirty )
16471711 {
1648- for (int i = 0 ; i < 0x10000 ; i++)
1712+ symbols_dirty = false ;
1713+ sorted_symbols.clear ();
1714+
1715+ for (size_t i = 0 ; i < fixed_symbol_list.size (); i++)
16491716 {
1650- DebugSymbol* fixed = fixed_symbols[b][i];
1651- DebugSymbol* dynamic_sym = (!IsValidPointer (fixed) && show_auto_symbols) ? dynamic_symbols[b][i] : NULL ;
1717+ SymbolEntry& e = fixed_symbol_list[i];
16521718
1653- DebugSymbol* symbol = IsValidPointer (fixed) ? fixed : dynamic_sym;
1719+ if (symbol_filter[0 ] != 0 )
1720+ {
1721+ char addr_str[8 ];
1722+ snprintf (addr_str, sizeof (addr_str), " %04X" , e.symbol ->address );
16541723
1655- if (IsValidPointer (symbol))
1724+ char filter_upper[64 ];
1725+ char text_upper[64 ];
1726+ for (int j = 0 ; j < 63 && symbol_filter[j]; j++) { filter_upper[j] = toupper (symbol_filter[j]); filter_upper[j + 1 ] = 0 ; }
1727+ for (int j = 0 ; j < 63 && e.symbol ->text [j]; j++) { text_upper[j] = toupper (e.symbol ->text [j]); text_upper[j + 1 ] = 0 ; }
1728+
1729+ if (strstr (text_upper, filter_upper) == NULL && strstr (addr_str, filter_upper) == NULL )
1730+ continue ;
1731+ }
1732+
1733+ sorted_symbols.push_back (e);
1734+ }
1735+
1736+ if (show_auto_symbols)
1737+ {
1738+ for (size_t i = 0 ; i < dynamic_symbol_list.size (); i++)
16561739 {
1657- bool is_manual = IsValidPointer (fixed) ;
1740+ SymbolEntry& e = dynamic_symbol_list[i] ;
16581741
1659- ImGui::TableNextRow ();
1742+ if (IsValidPointer (fixed_symbols[e.bank ][e.symbol ->address ]))
1743+ continue ;
16601744
1661- ImGui::TableNextColumn ();
1662- ImGui::TextColored (cyan, " $%02X" , b);
1745+ if (symbol_filter[0 ] != 0 )
1746+ {
1747+ char addr_str[8 ];
1748+ snprintf (addr_str, sizeof (addr_str), " %04X" , e.symbol ->address );
16631749
1664- ImGui::TableNextColumn ();
1665- ImGui::TextColored (cyan, " $%04X" , symbol->address );
1750+ char filter_upper[64 ];
1751+ char text_upper[64 ];
1752+ for (int j = 0 ; j < 63 && symbol_filter[j]; j++) { filter_upper[j] = toupper (symbol_filter[j]); filter_upper[j + 1 ] = 0 ; }
1753+ for (int j = 0 ; j < 63 && e.symbol ->text [j]; j++) { text_upper[j] = toupper (e.symbol ->text [j]); text_upper[j + 1 ] = 0 ; }
16661754
1667- ImGui::TableNextColumn ();
1668- ImGui::TextColored (is_manual ? green : yellow, " %s" , symbol->text );
1755+ if (strstr (text_upper, filter_upper) == NULL && strstr (addr_str, filter_upper) == NULL )
1756+ continue ;
1757+ }
16691758
1670- ImGui::TableNextColumn ();
1671- if (is_manual)
1672- ImGui::TextColored (orange, " Manual" );
1673- else
1674- ImGui::TextColored (brown, " Auto" );
1759+ sorted_symbols.push_back (e);
1760+ }
1761+ }
1762+
1763+ if (last_sort_column >= 0 )
1764+ {
1765+ bool ascending = (last_sort_direction == ImGuiSortDirection_Ascending);
1766+
1767+ if (last_sort_column == 0 )
1768+ {
1769+ std::sort (sorted_symbols.begin (), sorted_symbols.end (), ascending ? symbol_sort_address_asc : symbol_sort_address_desc);
1770+ }
1771+ else if (last_sort_column == 1 )
1772+ {
1773+ std::sort (sorted_symbols.begin (), sorted_symbols.end (), ascending ? symbol_sort_addr_only_asc : symbol_sort_addr_only_desc);
1774+ }
1775+ else if (last_sort_column == 2 )
1776+ {
1777+ std::sort (sorted_symbols.begin (), sorted_symbols.end (), ascending ? symbol_sort_name_asc : symbol_sort_name_desc);
16751778 }
16761779 }
16771780 }
16781781
1782+ ImGui::PushFont (gui_default_font);
1783+
1784+ ImGuiListClipper clipper;
1785+ clipper.Begin ((int )sorted_symbols.size ());
1786+ while (clipper.Step ())
1787+ {
1788+ for (int idx = clipper.DisplayStart ; idx < clipper.DisplayEnd ; idx++)
1789+ {
1790+ DebugSymbol* symbol = sorted_symbols[idx].symbol ;
1791+ bool is_manual = sorted_symbols[idx].is_manual ;
1792+ int b = sorted_symbols[idx].bank ;
1793+
1794+ ImGui::TableNextRow ();
1795+
1796+ ImGui::TableNextColumn ();
1797+ char selectable_id[16 ];
1798+ snprintf (selectable_id, sizeof (selectable_id), " ##sym%d" , (int )idx);
1799+ if (ImGui::Selectable (selectable_id, false , ImGuiSelectableFlags_SpanAllColumns))
1800+ {
1801+ request_goto_address (symbol->address );
1802+ }
1803+ ImGui::SameLine ();
1804+ ImGui::TextColored (cyan, " $%02X" , b);
1805+
1806+ ImGui::TableNextColumn ();
1807+ ImGui::TextColored (cyan, " $%04X" , symbol->address );
1808+
1809+ ImGui::TableNextColumn ();
1810+ ImGui::TextColored (is_manual ? green : yellow, " %s" , symbol->text );
1811+
1812+ ImGui::TableNextColumn ();
1813+ if (is_manual)
1814+ ImGui::TextColored (orange, " Manual" );
1815+ else
1816+ ImGui::TextColored (brown, " Auto" );
1817+ }
1818+ }
1819+
16791820 ImGui::PopFont ();
16801821
16811822 ImGui::EndTable ();
@@ -1700,8 +1841,17 @@ void gui_debug_remove_symbol(u8 bank, u16 address)
17001841 DebugSymbol* symbol = fixed_symbols[bank][address];
17011842 if (IsValidPointer (symbol))
17021843 {
1844+ for (size_t i = 0 ; i < fixed_symbol_list.size (); i++)
1845+ {
1846+ if (fixed_symbol_list[i].symbol == symbol)
1847+ {
1848+ fixed_symbol_list.erase (fixed_symbol_list.begin () + i);
1849+ break ;
1850+ }
1851+ }
17031852 delete symbol;
17041853 fixed_symbols[bank][address] = NULL ;
1854+ symbols_dirty = true ;
17051855 }
17061856 }
17071857}
@@ -1859,3 +2009,41 @@ static void save_current_disassembler(FILE* file)
18592009 }
18602010 }
18612011}
2012+
2013+ static bool symbol_sort_address_asc (const SymbolEntry& a, const SymbolEntry& b)
2014+ {
2015+ if (a.bank != b.bank )
2016+ return a.bank < b.bank ;
2017+ return a.symbol ->address < b.symbol ->address ;
2018+ }
2019+
2020+ static bool symbol_sort_address_desc (const SymbolEntry& a, const SymbolEntry& b)
2021+ {
2022+ if (a.bank != b.bank )
2023+ return a.bank > b.bank ;
2024+ return a.symbol ->address > b.symbol ->address ;
2025+ }
2026+
2027+ static bool symbol_sort_addr_only_asc (const SymbolEntry& a, const SymbolEntry& b)
2028+ {
2029+ if (a.symbol ->address != b.symbol ->address )
2030+ return a.symbol ->address < b.symbol ->address ;
2031+ return a.bank < b.bank ;
2032+ }
2033+
2034+ static bool symbol_sort_addr_only_desc (const SymbolEntry& a, const SymbolEntry& b)
2035+ {
2036+ if (a.symbol ->address != b.symbol ->address )
2037+ return a.symbol ->address > b.symbol ->address ;
2038+ return a.bank > b.bank ;
2039+ }
2040+
2041+ static bool symbol_sort_name_asc (const SymbolEntry& a, const SymbolEntry& b)
2042+ {
2043+ return strcmp (a.symbol ->text , b.symbol ->text ) < 0 ;
2044+ }
2045+
2046+ static bool symbol_sort_name_desc (const SymbolEntry& a, const SymbolEntry& b)
2047+ {
2048+ return strcmp (a.symbol ->text , b.symbol ->text ) > 0 ;
2049+ }
0 commit comments