#include "shell.h" #include "parser.h" #include "commands.h" #include "errors.h" #include "theme.h" #include #include //--- // io //--- static char const *info_str = "OS: type %s version %02d.%02d.%04d\n" "\n" "Header information:\n" " Bootcode timestamp (DateA) (0x%000008x) : %s\n" " Bootcode checksum (0x%000008x) : 0x%08x\n" " Serial number (0x%000008x) : %s\n" " OS version (0x%000008x) : %s\n"; static char const *footer_str = "\nFooter information:\n" " Detected footer address : 0x%08x\n" " Langdata entries found : %d\n" " OS date (DateO) (0x%000008x) : %s\n" " OS checksum (0x%000008x) : 0x%08x\n" " Computed OS checksum : 0x%08x\n"; static char const *syscall_str = "\nSyscall information:\n" " Syscall table address (0x%000008x) : 0x%08x\n" " Entries that point to valid memory : 0x%x\n" " First seemingly invalid entry : 0x%08x\n" " Syscall entries outside ROM:\n"; static char const *syscall_nonrom_str = " %%%03x -> %08x (%s memory)\n"; static std::string parse_io(Session &, Parser &parser) { std::string name = parser.at_end() ? "" : parser.symbol("vspace_name"); parser.end(); return name; } void _io(Session &session, std::string name) { VirtualSpace *space = session.current_space; if(name != "") space = session.get_space(name); if(!space) return; OS *os = space->os_analysis(); if(!os) throw CommandError("os analysis on '{}' failed", name); printf(info_str, (os->type == OS::FX ? "FX" : "CG"), os->version_major, os->version_minor, os->version_patch, &os->bootcode_timestamp, os->bootcode_timestamp.value.c_str(), &os->bootcode_checksum, os->bootcode_checksum, &os->serial_number, os->serial_number.value.c_str(), &os->version, os->version.value.c_str()); if(os->footer == (uint32_t)-1) { printf("\nFooter could not be found.\n"); } else { printf(footer_str, os->footer, os->langdata, &os->timestamp, os->timestamp.value.c_str(), &os->checksum, os->checksum, os->computed_checksum); } uint32_t syscall_table = os->syscall_table_address(); uint32_t first_noncall = space->read_u32(syscall_table + 4 * os->syscall_count()); printf(syscall_str, (os->type == OS::FX ? 0x8001007c : 0x8002007c), syscall_table, os->syscall_count(), first_noncall); int total = 0; for(int i = 0; i < os->syscall_count(); i++) { uint32_t e = os->syscall(i); MemoryRegion const *r = MemoryRegion::region_for(e); if(!r || r->name == "ROM" || r->name == "ROM_P2") continue; printf(syscall_nonrom_str, i, e, r->name.c_str()); total++; } if(!total) printf(" (none)\n"); } //--- // is //--- struct _is_args { std::string vspace_name; bool sort; }; static struct _is_args parse_is(Session &, Parser &parser) { struct _is_args args {}; parser.option("sort", [&args](std::string const &value){ args.sort = (value == "true"); }); parser.accept_options(); args.vspace_name = parser.at_end() ? "" : parser.symbol("vspace_name"); parser.accept_options(); parser.end(); return args; } struct SyscallInfo { uint32_t address; int id; }; bool operator < (const SyscallInfo &left, const SyscallInfo &right) { return (left.address < right.address) || (left.id < right.id); } void _is(Session &session, std::string vspace_name, bool sort) { VirtualSpace *space = session.current_space; if(vspace_name != "") space = session.get_space(vspace_name); if(!space) return; // TODO: is doesn't work OS *os = space->os_analysis(); if(!os) throw CommandError("os analysis on '{}' failed", vspace_name); int total = os->syscall_count(); auto info = std::make_unique(total); for(int i = 0; i < total; i++) { info[i] = (SyscallInfo){ .address = os->syscall(i), .id = i }; } if(sort) std::sort(&info[0], &info[total]); for(int i = 0; i < total; i++) { fmt::print(theme(3), " 0x{:08x}", info[i].address); fmt::print(theme(10), (total >= 0x1000 ? " %{:04x}":" %{:03x}"), info[i].id); fmt::print("\n"); } } //--- // Command registration //--- static ShellCommand _io_cmd("io", [](Session &s, Parser &p){ _io(s, parse_io(s, p)); }, [](Session &s, Parser &p){ parse_io(s, p); }, "Info OS", R"( io [] Prints information about the OS mapped in the named virtual space (defaults to the current one). This usually requires an OS binary to be mapped to ROM. )"); static ShellCommand _is_cmd("is", [](Session &s, Parser &p){ auto args = parse_is(s, p); _is(s, args.vspace_name, args.sort); }, [](Session &s, Parser &p){ parse_is(s, p); }, "Info Syscalls", R"( is [sort=true] [] Prints the syscall table for the specified virtual space (defaults to the current one). By default, syscalls are enumerated by syscall number. If sort=true is specified, they are instead sorted by address. )");