Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions frontend/iris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ void update_window(iris::instance* iris) {
if (iris->show_settings) show_settings(iris);
if (iris->show_pad_debugger) show_pad_debugger(iris);
if (iris->show_symbols) show_symbols(iris);
if (iris->show_threads) show_threads(iris);
if (iris->show_ee_threads) show_ee_threads(iris);
if (iris->show_iop_threads) show_iop_threads(iris);
if (iris->show_timers) show_timers(iris);
if (iris->show_sysmem_logs) show_sysmem_logs(iris);
if (iris->show_memory_card_tool) show_memory_card_tool(iris);
Expand Down Expand Up @@ -780,7 +781,8 @@ void destroy(iris::instance* iris) {
iris->show_memory_search = false;
iris->show_vu_disassembler = false;
iris->show_breakpoints = false;
iris->show_threads = false;
iris->show_ee_threads = false;
iris->show_iop_threads = false;
iris->show_timers = false;
iris->show_sysmem_logs = false;
iris->show_imgui_demo = false;
Expand Down
6 changes: 4 additions & 2 deletions frontend/iris.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,8 @@ struct instance {
bool show_settings = false;
bool show_pad_debugger = false;
bool show_symbols = false;
bool show_threads = false;
bool show_ee_threads = false;
bool show_iop_threads = false;
bool show_memory_card_tool = false;
bool show_hdd_tool = false;
bool show_imgui_demo = false;
Expand Down Expand Up @@ -828,7 +829,8 @@ void show_about_window(iris::instance* iris);
void show_settings(iris::instance* iris);
void show_pad_debugger(iris::instance* iris);
void show_symbols(iris::instance* iris);
void show_threads(iris::instance* iris);
void show_ee_threads(iris::instance* iris);
void show_iop_threads(iris::instance* iris);
void show_overlay(iris::instance* iris);
void show_memory_card_tool(iris::instance* iris);
void show_hdd_tool(iris::instance* iris);
Expand Down
6 changes: 4 additions & 2 deletions frontend/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ bool parse_toml_settings(iris::instance* iris) {
iris->show_vu_disassembler = debugger["show_vu_disassembler"].value_or(false);
iris->show_status_bar = debugger["show_status_bar"].value_or(true);
iris->show_pad_debugger = debugger["show_pad_debugger"].value_or(false);
iris->show_threads = debugger["show_threads"].value_or(false);
iris->show_ee_threads = debugger["show_ee_threads"].value_or(false);
iris->show_iop_threads = debugger["show_iop_threads"].value_or(false);
iris->show_timers = debugger["show_timers"].value_or(false);
iris->show_sysmem_logs = debugger["show_sysmem_logs"].value_or(false);
iris->show_overlay = debugger["show_overlay"].value_or(false);
Expand Down Expand Up @@ -543,7 +544,8 @@ void close(iris::instance* iris) {
{ "show_status_bar", iris->show_status_bar },
{ "show_pad_debugger", iris->show_pad_debugger },
{ "show_breakpoints", iris->show_breakpoints },
{ "show_threads", iris->show_threads },
{ "show_ee_threads", iris->show_ee_threads },
{ "show_iop_threads", iris->show_iop_threads },
{ "show_timers", iris->show_timers },
{ "show_sysmem_logs", iris->show_sysmem_logs },
{ "show_imgui_demo", iris->show_imgui_demo },
Expand Down
6 changes: 4 additions & 2 deletions frontend/ui/menubar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ void show_main_menubar(iris::instance* iris) {
if (MenuItem(ICON_MS_CODE " Symbols##ee", NULL, &iris->show_symbols));
EndDisabled();

if (MenuItem(ICON_MS_ACCOUNT_TREE " Threads##ee", NULL, &iris->show_threads));
if (MenuItem(ICON_MS_ACCOUNT_TREE " Threads##ee", NULL, &iris->show_ee_threads));

// ImGui::EndMenu();
// }
Expand All @@ -519,6 +519,7 @@ void show_main_menubar(iris::instance* iris) {
if (MenuItem(ICON_MS_TERMINAL " Logs##iop", NULL, &iris->show_iop_logs));
if (MenuItem(ICON_MS_BOLT " Interrupts##iop", NULL, &iris->show_iop_interrupts));
if (MenuItem(ICON_MS_EXTENSION " Modules##iop", NULL, &iris->show_iop_modules));
if (MenuItem(ICON_MS_ACCOUNT_TREE " Threads##iop", NULL, &iris->show_iop_threads));

// ImGui::EndMenu();
// }
Expand Down Expand Up @@ -575,7 +576,8 @@ void show_main_menubar(iris::instance* iris) {
iris->show_vu_disassembler = false;
iris->show_status_bar = false;
iris->show_breakpoints = false;
iris->show_threads = false;
iris->show_ee_threads = false;
iris->show_iop_threads = false;
iris->show_sysmem_logs = false;
iris->show_imgui_demo = false;
iris->show_overlay = false;
Expand Down
144 changes: 128 additions & 16 deletions frontend/ui/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "iris.hpp"
#include "ee/ee_def.hpp"
#include "iop/iop_def.hpp"

#include "res/IconsMaterialSymbols.h"

Expand All @@ -24,6 +25,16 @@ static inline const char* get_status_string(int status) {
return "<unknown>";
}

static inline const char* get_ee_wait_string(int wait) {
switch (wait) {
case TSW_EE_NONE: return "NONE";
case TSW_EE_SLEEP: return "SLEEP";
case TSW_EE_SEMA: return "SEMA";
}

return "<unknown>";
}

static const char* get_entry_symbol(iris::instance* iris, uint32_t addr) {
// Look up the address in the symbol table
if (addr == 0x81fc0) return "EE Idle Thread";
Expand All @@ -37,20 +48,22 @@ static const char* get_entry_symbol(iris::instance* iris, uint32_t addr) {
return nullptr;
}

void show_thread_list(iris::instance* iris) {
void show_ee_thread_list(iris::instance* iris) {
using namespace ImGui;

struct ee_state* ee = iris->ps2->ee;

ImGuiTableFlags table_flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY;
ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY;

if (BeginTable("##threadlist", 5, table_flags)) {
if (BeginTable("##threadlist_ee", 7, table_flags)) {
TableSetupScrollFreeze(0, 1);
TableSetupColumn("ID");
TableSetupColumn("Priority");
TableSetupColumn("Entry");
TableSetupColumn("PC");
TableSetupColumn("Argv");
TableSetupColumn("Status");
TableSetupColumn("WaitType");
PushFont(iris->font_small_code);
TableHeadersRow();
PopFont();
Expand All @@ -67,37 +80,136 @@ void show_thread_list(iris::instance* iris) {
Text("%d", thr->current_priority);
TableSetColumnIndex(2);

const char* symbol = get_entry_symbol(iris, thr->func);
const char* symbol = get_entry_symbol(iris, thr->entry_point);

if (symbol) {
Text("%s", symbol);
Text("%s (0x%08x)", symbol, thr->entry_point);
} else {
Text("0x%08X", thr->func);
Text("0x%08X", thr->entry_point);
}

TableSetColumnIndex(3);
if (thr->status == THS_RUN) {
Text("0x%08x", ee->pc);
} else {
Text("0x%08x", thr->resume_addr);
}

uint32_t argv = *(uint32_t*)&iris->ps2->ee_ram->buf[(thr->argv + 4) & 0x1fffffff];
TableSetColumnIndex(4);
Text("%s", thr->argc ? (char*)&iris->ps2->ee_ram->buf[argv & 0x1fffffff] : "NULL");
TableSetColumnIndex(5);
Text("%s", get_status_string(thr->status));
TableSetColumnIndex(6);
Text("%s", get_ee_wait_string(thr->wait_type));

// if (thr->argc) {
// printf("argv=%08x *argv=%08x\n", thr->argv, argv);
// }
thr++;
}

EndTable();
}
}

void show_ee_threads(iris::instance* iris) {
using namespace ImGui;

if (imgui::BeginEx("EE Threads", &iris->show_ee_threads)) {
if (!iris->ps2->ee->thread_list_base) {
ImVec2 size = CalcTextSize(ICON_MS_WARNING " Thread list hasn't been initialized yet");
ImVec2 pos = ImVec2(GetContentRegionAvail().x / 2 - size.x / 2, GetContentRegionAvail().y / 2 - size.y / 2);
ImVec4 col = GetStyle().Colors[ImGuiCol_Text];

SetCursorPos(pos);
TextDisabled(ICON_MS_WARNING " Thread list hasn't been initialized yet");

End();

return;
}

show_ee_thread_list(iris);
} End();
}

static inline const char* get_iop_wait_string(int wait) {
switch (wait) {
case TSW_IOP_NONE: return "NONE";
case TSW_IOP_SLEEP: return "SLEEP";
case TSW_IOP_DELAY: return "DELAY";
case TSW_IOP_SEMA: return "SEMA";
case TSW_IOP_EVENTFLAG: return "EVENTFLAG";
case TSW_IOP_MBX: return "MBX";
case TSW_IOP_VPL: return "VPL";
case TSW_IOP_FPL: return "FPL";
}

return "<unknown>";
}

void show_iop_thread_list(iris::instance* iris) {
using namespace ImGui;

struct iop_state* iop = iris->ps2->iop;

ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY;

if (BeginTable("##threadlist_iop", 6, table_flags)) {
TableSetupScrollFreeze(0, 1);
TableSetupColumn("ID");
TableSetupColumn("Priority");
TableSetupColumn("Entry");
TableSetupColumn("PC");
TableSetupColumn("Status");
TableSetupColumn("WaitType");
PushFont(iris->font_small_code);
TableHeadersRow();
PopFont();

uint32_t addr = iop_read32(iop, iop->thread_list_addr);

while (addr) {
struct iop_thread* thr = (struct iop_thread*)&iris->ps2->iop_ram->buf[addr & 0x1fffffff];
struct iop_thread_ctx* ctx = (struct iop_thread_ctx*)&iris->ps2->iop_ram->buf[thr->reg_storage & 0x1fffffff];

if (thr->tag != 0x7f01) {
break;
}

TableNextRow();
TableSetColumnIndex(0);
Text("%d", thr->id);

TableSetColumnIndex(1);
Text("%d", thr->priority);

TableSetColumnIndex(2);
Text("0x%08X", thr->entry_point);

TableSetColumnIndex(3);
Text("%s", thr->argc ? (char*)&iris->ps2->ee_ram->buf[argv & 0x1fffffff] : "NULL");
if (thr->status == THS_RUN) {
Text("0x%08x", iop->pc);
} else {
Text("0x%08x", ctx->pc);
}

TableSetColumnIndex(4);
Text("%s", get_status_string(thr->status));

thr++;
TableSetColumnIndex(5);
Text("%s", get_iop_wait_string(thr->wait_type));

addr = thr->next_thread;
}

EndTable();
}
}

void show_threads(iris::instance* iris) {
void show_iop_threads(iris::instance* iris) {
using namespace ImGui;

if (imgui::BeginEx("Threads", &iris->show_threads)) {
if (!iris->ps2->ee->thread_list_base) {
if (imgui::BeginEx("IOP Threads", &iris->show_iop_threads)) {
if (!iris->ps2->iop->thread_list_addr) {
ImVec2 size = CalcTextSize(ICON_MS_WARNING " Thread list hasn't been initialized yet");
ImVec2 pos = ImVec2(GetContentRegionAvail().x / 2 - size.x / 2, GetContentRegionAvail().y / 2 - size.y / 2);
ImVec4 col = GetStyle().Colors[ImGuiCol_Text];
Expand All @@ -110,8 +222,8 @@ void show_threads(iris::instance* iris) {
return;
}

show_thread_list(iris);
show_iop_thread_list(iris);
} End();
}

}
}
31 changes: 23 additions & 8 deletions src/ee/ee_def.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,25 +611,40 @@ struct ee_state {
#define THS_WAITSUSPEND 0x0C // THS_WAIT | THS_SUSPEND
#define THS_DORMANT 0x10

#define TSW_EE_NONE 0x0
#define TSW_EE_SLEEP 0x1
#define TSW_EE_SEMA 0x2

struct ee_thread_ctx {
uint32_t sa;
uint32_t fcsr;
uint32_t float_thing;
uint32_t unk;
// gpr excluding $zero
// k0/k1 contains hi, hi1, lo, lo1
uint128_t gpr[31];
float fpr[32];
};

struct ee_thread {
uint32_t prev; // TCB*
uint32_t next; // TCB*
int status;
uint32_t func; // void*
uint32_t current_stack; // void*
uint32_t resume_addr; // void*
uint32_t register_storage; // ee_thread_ctx*
uint32_t gp_reg; // void*
short current_priority;
short init_priority;
int wait_type; //0=not waiting, 1=sleeping, 2=waiting on semaphore
short current_priority;
int wait_type; // 0=not waiting, 1=sleeping, 2=waiting on semaphore
int sema_id;
int wakeup_count;
int attr;
int option;
uint32_t func_; // void* ???
uint32_t entry_point; // void* ???
int argc;
uint32_t argv; // char**
uint32_t initial_stack; // void*
uint32_t stack_memory; // void*
int stack_size;
uint32_t root; // int* function to return to when exiting thread?
uint32_t root; // int* function to return to when exiting thread?
uint32_t heap_base; // void*
};
};
32 changes: 29 additions & 3 deletions src/iop/hle/loadcore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ static unsigned get_module_list(struct iop_state* iop)
return lc_struct + 0x10;
}

static unsigned get_thread_list(struct iop_state* iop)
{
unsigned module_version = iop_read32(iop, iop->r[4] + 8);

/* Read address of ordinal 3 */
unsigned func = iop_read32(iop, iop->r[4] + 0x20);

/* Read lui+ori of address to the thread manager global */
unsigned th_struct = iop_read32(iop, func) << 16;
th_struct |= iop_read32(iop, func + 4) & 0xffff;

unsigned th_list = th_struct + 0x42c;
if (module_version > 0x101) {
th_list = th_struct + 0x430;
}

return th_list;
}

static void iop_strncpy(struct iop_state* iop, char* dest, unsigned src, int n)
{
char c;
Expand Down Expand Up @@ -96,11 +115,18 @@ void refresh_module_list(struct iop_state* iop)

int loadcore_reg_lib_ent(struct iop_state* iop)
{
unsigned list = get_module_list(iop);
unsigned module_list = get_module_list(iop);
iop->module_list_addr = module_list;
refresh_module_list(iop);

iop->module_list_addr = list;
char name[8] = {};

refresh_module_list(iop);
iop_strncpy(iop, name, iop->r[4] + 0xc, sizeof(name));
if (strncmp(name, "thbase", 6) == 0) {
unsigned thread_list = get_thread_list(iop);
iop->thread_list_addr = thread_list;
printf("iop: found thread list at %x\n", thread_list);
}

return 0;
}
Loading
Loading