list-registers.c: also list input/output pins, and emulator settings
This commit is contained in:
parent
23c94a1068
commit
6e4cfcf940
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue