190 ImGui::SameLine(ImGui::GetWindowWidth() - 100);
192 float pulse = 0.7f + 0.3f * std::sin(ImGui::GetTime() * 2.0f);
193 ImVec4 connected_color = ImVec4(0.1f, pulse, 0.3f, 1.0f);
196 ImGui::TextColored(theme.status_error,
"%s Disconnected",
ICON_MD_ERROR);
203 ImGui::TextDisabled(
"Socket");
204 const char* preview =
206 selected_socket_index_ < static_cast<int>(
socket_paths_.size()))
208 :
"No sockets found";
209 ImGui::SetNextItemWidth(-40);
210 if (ImGui::BeginCombo(
"##mesen_socket_combo", preview)) {
211 for (
int i = 0; i < static_cast<int>(
socket_paths_.size()); ++i) {
219 ImGui::SetItemDefaultFocus();
229 ImGui::TextDisabled(
"Path");
230 ImGui::SetNextItemWidth(-1);
231 ImGui::InputTextWithHint(
"##mesen_socket_path",
232 "tcp://127.0.0.1:27015 or /tmp/mesen2-*.sock",
263 ImGui::SetNextItemWidth(60);
271 ImGui::TextColored(theme.text_secondary_color,
"%s",
279 if (ImGui::CollapsingHeader(
288 ImGui::Text(
"Position:");
290 ImGui::TextColored(theme.text_secondary_color,
"X=%d, Y=%d Layer: %d",
291 link.x, link.y, link.layer);
294 ImGui::Text(
"Direction:");
296 ImGui::TextColored(theme.text_secondary_color,
"%s (0x%02X)",
297 DirectionToString(link.direction), link.direction);
299 ImGui::Text(
" State:");
301 ImGui::TextColored(theme.text_secondary_color,
"0x%02X", link.state);
304 float health_ratio = items.max_health > 0
305 ?
static_cast<float>(items.current_health) /
306 static_cast<float>(items.max_health)
308 ImVec4 health_color = HealthColor(health_ratio);
310 ImGui::Text(
"Health:");
314 int full_hearts = items.current_health / 8;
315 int max_hearts = items.max_health / 8;
318 for (
int i = 0; i < full_hearts; ++i) {
319 ImGui::SameLine(0, 0);
325 ImVec4(0.3f, 0.3f, 0.3f, 1.0f));
326 for (
int i = full_hearts; i < max_hearts; ++i) {
327 ImGui::SameLine(0, 0);
333 ImGui::TextColored(theme.text_secondary_color,
" (%d/%d)",
334 items.current_health, items.max_health);
337 ImGui::Text(
"Items:");
339 ImGui::TextColored(theme.text_secondary_color,
340 "Magic: %d Rupees: %d Bombs: %d Arrows: %d",
341 items.magic, items.rupees, items.bombs, items.arrows);
350 std::string header = absl::StrFormat(
"%s Active Sprites (%zu/16)",
353 if (ImGui::CollapsingHeader(
361 ImGui::TextDisabled(
" No active sprites");
364 if (ImGui::BeginChild(
"SpriteList", ImVec2(0, 120),
true)) {
365 for (
const auto& sprite :
sprites_) {
366 ImGui::PushID(sprite.slot);
369 ImGui::TextColored(theme.text_secondary_color,
"[%d]", sprite.slot);
373 ImVec4 sprite_color = sprite.state > 0
374 ? ImVec4(0.4f, 0.8f, 0.4f, 1.0f)
375 : ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
376 ImGui::TextColored(sprite_color,
"Type: 0x%02X", sprite.type);
379 ImGui::Text(
"@ %d,%d", sprite.x, sprite.y);
382 if (sprite.health > 0) {
383 ImGui::TextColored(ImVec4(0.8f, 0.3f, 0.3f, 1.0f),
"HP:%d",
388 ImGui::TextColored(theme.text_secondary_color,
"State:%d",
405 if (ImGui::CollapsingHeader(
410 ImGui::Text(
"Mode:");
412 ImGui::TextColored(theme.text_secondary_color,
"%d (Submode: %d)",
413 game.mode, game.submode);
415 ImGui::Text(
"Location:");
418 ImGui::TextColored(ImVec4(0.6f, 0.4f, 0.2f, 1.0f),
"Dungeon Room: 0x%04X",
421 ImGui::TextColored(ImVec4(0.2f, 0.6f, 0.2f, 1.0f),
422 "Overworld Area: 0x%02X", game.overworld_area);
426 ImGui::Text(
"Frame:");
428 ImGui::TextColored(theme.text_secondary_color,
"%llu",
emu_state_.
frame);
431 ImGui::Text(
" FPS:");
433 ImGui::TextColored(theme.text_secondary_color,
"%.1f",
emu_state_.
fps);
439 ImGui::TextColored(theme.text_secondary_color,
440 "PC=$%02X:%04X A=$%04X X=$%04X Y=$%04X",
443 ImGui::TextColored(theme.text_secondary_color,