ImDebugger: sort the symbol list by name

The symbol map hands symbols over in address order, which is fine for the
disassembly but meaningless to browse - CrossCraft has 3734 functions and
scrolling for one is just a wall of text.

Sorted where you suggested, in the match list that already backs the filter:
it's rebuilt only when the filter text or the symbol map changes, so this costs
nothing per frame, and sorting the indices rather than symCache_ itself leaves
selectedSymbol_ pointing at the cache, so a selection survives filtering and the
Edit Symbol box above the list keeps working.

Case-insensitive, with ties broken by address so the order can't wobble between
rebuilds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-08-18 14:26:09 +02:00
1 parent 3463789597
commit 82dd963df6
1 file changed
+10
+10
View File
@@ -1356,6 +1356,16 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, ImConfig &cfg, ImContro
if (symFilter_[0] == '\0' || containsNoCase(symCache_[i].name, symFilter_))
symMatches_.push_back(i);
}
// By name, because that's what you're reading when you scroll this. The symbol map
// hands them over in address order, which is meaningless to browse - a game with a few
// thousand functions is just a wall. Sorting the match list rather than symCache_
// leaves selectedSymbol_ indexing the cache, so a selection survives filtering, and
// this only runs on a rebuild rather than per frame.
std::sort(symMatches_.begin(), symMatches_.end(), [this](int a, int b) {
const int cmp = strcasecmp(symCache_[a].name.c_str(), symCache_[b].name.c_str());
// Ties broken by address so the order can't wobble between rebuilds.
return cmp != 0 ? cmp < 0 : symCache_[a].address < symCache_[b].address;
});
}
if (ImGui::BeginListBox("##symbols", ImGui::GetContentRegionAvail())) {