diff --git a/emulator/list-registers.c b/emulator/list-registers.c index f21cb57..777f7b3 100644 --- a/emulator/list-registers.c +++ b/emulator/list-registers.c @@ -15,21 +15,32 @@ // Structure of CPU73050.dll //--- -/* First is an address to the list of register tables - struct reg (*TABLE_LIST_ADDRESS)[][] - (second-level arrays are not stored contiguously) */ -uint32_t const TABLE_LIST_ADDRESS = 0x100903e0; -/* Just following is the list of peripheral modules - struct module MODULE_LIST[] - Unlike register tables this is not a pointer, it's the whole table */ -uint32_t const MODULE_LIST = 0x100903e4; +/* Large tabe of [struct module] objects */ +uint32_t const MODULE_TABLE = 0x100903e4; + +/* List of register tables, pin input tables, pin output tables, and setting + tables (one of each per module) */ +uint32_t const REGISTER_TABLE_LIST = 0x10090184; +uint32_t const PIN_INPUT_TABLE_LIST = 0x1009021c; +uint32_t const PIN_OUTPUT_TABLE_LIST = 0x100902b4; +uint32_t const SETTING_TABLE_LIST = 0x1009034c; + +/* These function pointers are trivial reads used at a lot of places */ +uint32_t const REGu8_fun1_generic = 0x10028982; +uint32_t const REGu16_fun1_generic = 0x10028987; +uint32_t const REGu32_fun1_generic = 0x1002898b; /* Each module has the following structure (yet to be discovered entirely) */ struct module { uint32_t pointer_to_name; uint32_t pointer_to_description; - uint32_t unknown[28]; + uint32_t unknown_1[4]; + uint32_t register_count; + uint32_t pin_input_count; + uint32_t pin_output_count; + uint32_t setting_count; + uint32_t unknown_2[20]; }; /* Each peripheral register has this structure */ struct reg @@ -55,6 +66,34 @@ struct reg uint32_t unknown_6[13]; }; +struct pin_input +{ + uint32_t pointer_to_name; + uint32_t pointer_to_description; + uint32_t unknown_1[3]; + uint32_t zero_1[6]; /* Always zero in reachable instances */ + uint32_t func; + uint32_t zero_2[6]; /* Always zero in reachable instances */ +}; +struct pin_output +{ + uint32_t pointer_to_name; + uint32_t pointer_to_description; + uint32_t unknown[3]; + uint32_t zero_1[4]; /* Always zero in reachable instances */ +}; +struct setting +{ + uint32_t pointer_to_name; + uint32_t pointer_to_description; + + uint32_t zero_1[1]; /* Always zero in reachable instances */ + uint32_t unknown; + uint32_t zero_2[3]; /* Always zero in reachable instances */ + uint32_t func1; + uint32_t func2; + uint32_t zero_3[3]; /* Always zero in reachable instances */ +}; //--- // ELF utilities @@ -144,19 +183,6 @@ int valid_looking_module(Elf32_Ehdr *elf, struct module *m) return 1; } -int valid_looking_reg(Elf32_Ehdr *elf, struct reg *r) -{ - /* Check that there is a valid name */ - if((r->pointer_to_name & 0xfff00000) != 0x10000000) return 0; - if((r->pointer_to_description & 0xfff00000) != 0x10000000) return 0; - - /* Check that the name is printable ASCII */ - uint8_t const *name = get_virtual(elf, r->pointer_to_name); - if(!valid_looking_string(name)) return 0; - - return 1; -} - //--- // Analysis of CPU73050.elf to find SH7305 register lists //--- @@ -174,7 +200,7 @@ void print_module(Elf32_Ehdr *elf, struct module *m) printf(" %-10s %s\n", name, desc); } -void print_reg_f(char str[8][9], ...) +void print_reg_f(char str[8][32], ...) { va_list args; va_start(args, str); @@ -182,8 +208,20 @@ void print_reg_f(char str[8][9], ...) for(int i = 0; i < 8; i++) { uint32_t ptr = va_arg(args, uint32_t); - if(ptr == 0) sprintf(str[i], "%-8s", ""); - else sprintf(str[i], "%08x", ptr); + if(ptr == 0) + { + sprintf(str[i], "%-8s", ""); + } + else if(ptr == REGu8_fun1_generic || + ptr == REGu16_fun1_generic || + ptr == REGu32_fun1_generic) + { + sprintf(str[i], "\x1b[32m%08x\x1b[0m", ptr); + } + else + { + sprintf(str[i], "%08x", ptr); + } } va_end(args); @@ -193,9 +231,9 @@ void print_reg(Elf32_Ehdr *elf, struct reg *r) { if(r == NULL) { - printf(" (Virtual) Name: Address: Data size: " - "Access size: f1_u8 f2_u8 f1_u16 f2_u16 " - "f1_u32 f2_u32 f1_def f2_def Description:\n"); + printf(" Name: Address: Data size: " + "Access size: read8 write8 read16 write16 " + "read32 write32 f1_def f2_def Description:\n"); return; } @@ -214,7 +252,7 @@ void print_reg(Elf32_Ehdr *elf, struct reg *r) if(r->access_size == 2) sprintf(s2, "u16"); if(r->access_size == 4) sprintf(s2, "u32"); - char fstr[8][9]; + char fstr[8][32]; print_reg_f(fstr, r->f1_u8, r->f2_u8, r->f1_u16, r->f2_u16, r->f1_u32, r->f2_u32, r->f1_other, r->f2_other); @@ -223,6 +261,55 @@ void print_reg(Elf32_Ehdr *elf, struct reg *r) printf(" %s\n", desc); } +void print_pin_input(Elf32_Ehdr *elf, struct pin_input *p) +{ + if(p == NULL) + { + printf(" Name: ?1: ?2: ?3: func: " + "Description:\n"); + return; + } + + char const *name = get_virtual(elf, p->pointer_to_name); + char const *desc = get_virtual(elf, p->pointer_to_description); + + printf(" %-8s %08x %08x %08x %08x %s\n", name, + p->unknown_1[0], p->unknown_1[1], p->unknown_1[2], + p->func, desc); +} + +void print_pin_output(Elf32_Ehdr *elf, struct pin_output *p) +{ + if(p == NULL) + { + printf(" Name: ?1: ?2: ?3: " + "Description:\n"); + return; + } + + char const *name = get_virtual(elf, p->pointer_to_name); + char const *desc = get_virtual(elf, p->pointer_to_description); + + printf(" %-8s %08x %08x %08x %s\n", name, + p->unknown[0], p->unknown[1], p->unknown[2], desc); +} + +void print_setting(Elf32_Ehdr *elf, struct setting *s) +{ + if(s == NULL) + { + printf(" Name: ?1: func1: func2: " + "Description:\n"); + return; + } + + char const *name = get_virtual(elf, s->pointer_to_name); + char const *desc = get_virtual(elf, s->pointer_to_description); + + printf(" %-8s %08x %08x %08x %s\n", name, s->unknown, + s->func1, s->func2, desc); +} + int main(int argc, char **argv) { int e; @@ -252,79 +339,95 @@ int main(int argc, char **argv) check_header(elf); print_sections(elf); + /** Reminder of extracted addresses **/ + + printf("\nAddresses extracted via reverse-engineering:\n"); + printf(" Module table: 100903e4\n"); + printf(" Register table list: 10090184\n"); + printf(" Pin input table list: 1009021c\n"); + printf(" Pin output table list: 100902b4\n"); + printf(" Setting table list: 1009034c\n"); + /** List modules **/ - struct module *modules = get_virtual(elf, MODULE_LIST); + struct module *modules = get_virtual(elf, MODULE_TABLE); printf("\nModule list:\n"); print_module(elf, NULL); - for(int i = 0; 1; i++) + int i = 0; + while(1) { struct module *m = &modules[i]; if(!valid_looking_module(elf, m)) break; - printf(" %08x ", MODULE_LIST + i*(int)sizeof(struct module)); + printf(" %08x ", MODULE_TABLE + i*(int)sizeof(struct module)); print_module(elf, m); + i++; } + int module_count = i - 1; + printf("Total: %d modules (excluding CPU73050)\n", module_count); - /** List virtual addresses of tables **/ + /** Print information for each module **/ - uint32_t TABLE_LIST = *(uint32_t *)get_virtual(elf,TABLE_LIST_ADDRESS); - uint32_t *tables = get_virtual(elf, TABLE_LIST); + uint32_t *register_tables = get_virtual(elf, REGISTER_TABLE_LIST); + uint32_t *pin_input_tables = get_virtual(elf, PIN_INPUT_TABLE_LIST); + uint32_t *pin_output_tables = get_virtual(elf, PIN_OUTPUT_TABLE_LIST); + uint32_t *setting_tables = get_virtual(elf, SETTING_TABLE_LIST); - printf("\nThe table list at %08x (HARDCODED) has these tables:\n", - TABLE_LIST); - - for(int i = 0; tables[i]; i++) + int entry_count = 0; + for(int i = 0; i < module_count; i++) { - printf(" %08x", tables[i]); - if((i % 8) == 7 || !tables[i+1]) printf("\n"); - } - - /** List contents of tables **/ - - int total = 0; - - for(int i = 0; tables[i]; i++) - { - uint32_t entry = tables[i]; - struct reg *table = get_virtual(elf, entry); - - char header[256]; - sprintf(header, "\nIn the table at %08x:\n", entry); - int header_printed = 0; - - int k = 0; - while(valid_looking_reg(elf, table + k)) - { - if(!header_printed) - { - printf("%s", header); - print_reg(elf, NULL); - header_printed = 1; - } - - struct reg *r = table + k; - printf(" %08x ", entry + k * (int)sizeof(struct reg)); - print_reg(elf, r); - - k++; - } - total += k; - - if(k == 0) - { - /* Try to view it as a string */ - uint8_t const *str = (void *)table; - if(valid_looking_string(str)) - { - printf("\nThe table at %08x is a string:\n", - entry); - printf(" %s\n", str); - } - else printf("\nNothing in the table at %08x\n", entry); - } + struct reg *regs = get_virtual(elf, register_tables[i]); + struct pin_input *pin_inputs = get_virtual(elf, pin_input_tables[i]); + struct pin_output *pin_outputs = get_virtual(elf, pin_output_tables[i]); + struct setting *settings = get_virtual(elf, setting_tables[i]); + + struct module *m = &modules[i]; + char *name = get_virtual(elf, m->pointer_to_name); + + printf("\nRegister table for %s (%d registers):\n", name, + m->register_count); + if(m->register_count) + { + print_reg(elf, NULL); + for(uint k = 0; k < m->register_count; k++) + print_reg(elf, regs + k); + } + else printf(" No registers!\n"); + + if(m->pin_input_count) + { + printf("Pin input table for %s (%d pins):\n", name, + m->pin_input_count); + print_pin_input(elf, NULL); + for(uint k = 0; k < m->pin_input_count; k++) + print_pin_input(elf, pin_inputs + k); + } + + if(m->pin_output_count) + { + printf("Pin output table for %s (%d pins):\n", name, + m->pin_output_count); + print_pin_output(elf, NULL); + for(uint k = 0; k < m->pin_output_count; k++) + print_pin_output(elf, pin_outputs + k); + } + + if(m->setting_count) + { + printf("Setting table for %s (%d settings):\n", name, + m->setting_count); + print_setting(elf, NULL); + for(uint k = 0; k < m->setting_count; k++) + print_setting(elf, settings + k); + } + + entry_count += m->register_count; + entry_count += m->pin_input_count; + entry_count += m->pin_output_count; + entry_count += m->setting_count; } + printf("\nFound a total of %d objects.\n", entry_count); free(elf); return 0; }