diff --git a/src/emu/cpuintrf.c b/src/emu/cpuintrf.c index e23e8fd0223..3570a242e34 100644 --- a/src/emu/cpuintrf.c +++ b/src/emu/cpuintrf.c @@ -1308,11 +1308,12 @@ void cpu_reset(const device_config *device) offs_t cpu_get_physical_pc_byte(const device_config *device) { + const address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM); offs_t pc; cpu_push_context(device); - pc = cpu_address_to_byte(device, ADDRESS_SPACE_PROGRAM, cpu_get_info_int(device, CPUINFO_INT_PC)); - pc = cpu_address_physical(device, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, pc); + pc = memory_address_to_byte(space, cpu_get_info_int(device, CPUINFO_INT_PC)); + memory_address_physical(space, TRANSLATE_FETCH, &pc); cpu_pop_context(); return pc; } @@ -1367,7 +1368,8 @@ offs_t cpu_dasm(const device_config *device, char *buffer, offs_t pc, const UINT assert((result & DASMFLAG_LENGTHMASK) != 0); #ifdef MAME_DEBUG { - int bytes = cpu_address_to_byte(device, ADDRESS_SPACE_PROGRAM, result & DASMFLAG_LENGTHMASK); + const address_space *space = classheader->space[ADDRESS_SPACE_PROGRAM]; + int bytes = memory_address_to_byte(space, result & DASMFLAG_LENGTHMASK); assert(bytes >= cpu_get_min_opcode_bytes(device)); assert(bytes <= cpu_get_max_opcode_bytes(device)); (void) bytes; /* appease compiler */ diff --git a/src/emu/cpuintrf.h b/src/emu/cpuintrf.h index 3f017628a1c..a8add247d67 100644 --- a/src/emu/cpuintrf.h +++ b/src/emu/cpuintrf.h @@ -554,6 +554,7 @@ typedef enum _cpu_type cpu_type; #define cputype_get_databus_width(cputype, space) cputype_get_info_int(cputype, CPUINFO_INT_DATABUS_WIDTH + (space)) #define cputype_get_addrbus_width(cputype, space) cputype_get_info_int(cputype, CPUINFO_INT_ADDRBUS_WIDTH + (space)) #define cputype_get_addrbus_shift(cputype, space) cputype_get_info_int(cputype, CPUINFO_INT_ADDRBUS_SHIFT + (space)) +#define cputype_get_logaddr_width(cputype, space) cputype_get_info_int(cputype, CPUINFO_INT_LOGADDR_WIDTH + (space)) #define cputype_get_page_shift(cputype, space) cputype_get_info_int(cputype, CPUINFO_INT_PAGE_SHIFT + (space)) #define cputype_get_debug_register_list(cputype) cputype_get_info_ptr(cputype, CPUINFO_PTR_DEBUG_REGISTER_LIST) #define cputype_get_name(cputype) cputype_get_info_string(cputype, CPUINFO_STR_NAME) @@ -798,74 +799,4 @@ INLINE const address_space *cpu_get_address_space(const device_config *cpu, int } -/*------------------------------------------------- - cpu_address_to_byte - convert an address in - the specified address space to a byte offset --------------------------------------------------*/ - -INLINE offs_t cpu_address_to_byte(const device_config *cpu, int space, offs_t address) -{ - cpu_class_header *classheader = cpu->classtoken; - int shift = classheader->address_shift[space]; - return (shift < 0) ? (address << -shift) : (address >> shift); -} - - -/*------------------------------------------------- - cpu_address_to_byte_end - convert an address - in the specified address space to a byte - offset specifying the last byte covered by - the address --------------------------------------------------*/ - -INLINE offs_t cpu_address_to_byte_end(const device_config *cpu, int space, offs_t address) -{ - cpu_class_header *classheader = cpu->classtoken; - int shift = classheader->address_shift[space]; - return (shift < 0) ? ((address << -shift) | ((1 << -shift) - 1)) : (address >> shift); -} - - -/*------------------------------------------------- - cpu_byte_to_address - convert a byte offset - to an address in the specified address space --------------------------------------------------*/ - -INLINE offs_t cpu_byte_to_address(const device_config *cpu, int space, offs_t address) -{ - cpu_class_header *classheader = cpu->classtoken; - int shift = classheader->address_shift[space]; - return (shift < 0) ? (address >> -shift) : (address << shift); -} - - -/*------------------------------------------------- - cpu_byte_to_address_end - convert a byte offset - to an address in the specified address space - specifying the last address covered by the - byte --------------------------------------------------*/ - -INLINE offs_t cpu_byte_to_address_end(const device_config *cpu, int space, offs_t address) -{ - cpu_class_header *classheader = cpu->classtoken; - int shift = classheader->address_shift[space]; - return (shift < 0) ? (address >> -shift) : ((address << shift) | ((1 << shift) - 1)); -} - - -/*------------------------------------------------- - cpu_address_physical - return the physical - address corresponding to the given logical - address --------------------------------------------------*/ - -INLINE offs_t cpu_address_physical(const device_config *cpu, int space, int intention, offs_t address) -{ - cpu_class_header *classheader = cpu->classtoken; - if (classheader->translate != NULL) - (*classheader->translate)(cpu, space, intention, &address); - return address; -} - #endif /* __CPUINTRF_H__ */ diff --git a/src/emu/debug/debugcmd.c b/src/emu/debug/debugcmd.c index 4e7de58921a..0dda12cf6c9 100644 --- a/src/emu/debug/debugcmd.c +++ b/src/emu/debug/debugcmd.c @@ -114,9 +114,7 @@ static void execute_hardreset(running_machine *machine, int ref, int params, con /*************************************************************************** - - Initialization - + INITIALIZATION ***************************************************************************/ /*------------------------------------------------- @@ -282,9 +280,7 @@ static void debug_command_exit(running_machine *machine) /*************************************************************************** - - Simple Global Functions - + GLOBAL FUNCTIONS ***************************************************************************/ /*------------------------------------------------- @@ -319,9 +315,7 @@ static UINT64 execute_if(void *globalref, void *ref, UINT32 params, const UINT64 /*************************************************************************** - - Global accessors - + GLOBAL ACCESSORS ***************************************************************************/ /*------------------------------------------------- @@ -361,9 +355,7 @@ static void global_set(void *globalref, void *ref, UINT64 value) /*************************************************************************** - - Parameter Validation Helpers - + PARAMETER VALIDATION HELPERS ***************************************************************************/ /*------------------------------------------------- @@ -373,25 +365,46 @@ static void global_set(void *globalref, void *ref, UINT64 value) int debug_command_parameter_number(running_machine *machine, const char *param, UINT64 *result) { - EXPRERR err = expression_evaluate(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result); + EXPRERR err; + + /* NULL parameter does nothing and returns no error */ + if (param == NULL) + return TRUE; + + /* evaluate the expression; success if no error */ + err = expression_evaluate(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result); if (err == EXPRERR_NONE) - return 1; + return TRUE; + + /* print an error pointing to the character that caused it */ debug_console_printf("Error in expression: %s\n", param); debug_console_printf(" %*s^", EXPRERR_ERROR_OFFSET(err), ""); debug_console_printf("%s\n", exprerr_to_string(err)); - return 0; + return FALSE; } /*------------------------------------------------- debug_command_parameter_cpu - validates a - number parameter as a cpu + parameter as a cpu -------------------------------------------------*/ int debug_command_parameter_cpu(running_machine *machine, const char *param, const device_config **result) { UINT64 cpunum; EXPRERR err; + + /* if no parameter, use the visible CPU */ + if (param == NULL) + { + *result = debug_cpu_get_visible_cpu(machine); + if (*result == NULL) + { + debug_console_printf("No valid CPU is currently selected\n"); + return FALSE; + } + return TRUE; + } /* first look for a tag match */ *result = cputag_get_cpu(machine, param); @@ -409,15 +422,39 @@ int debug_command_parameter_cpu(running_machine *machine, const char *param, con /* if out of range, complain */ if (cpunum >= ARRAY_LENGTH(machine->cpu) || machine->cpu[cpunum] == NULL) { - debug_console_printf("Invalid CPU index %d\n", (UINT32) ((FPTR)*result)); + debug_console_printf("Invalid CPU index %d\n", (UINT32)cpunum); return FALSE; } - *result = machine->cpu[cpunum]; return TRUE; } +/*------------------------------------------------- + debug_command_parameter_cpu_space - validates + a parameter as a cpu and retrieves the given + address space +-------------------------------------------------*/ + +int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, const address_space **result) +{ + const device_config *cpu; + + /* first do the standard CPU thing */ + if (!debug_command_parameter_cpu(machine, param, &cpu)) + return FALSE; + + /* fetch the space pointer */ + *result = cpu_get_address_space(cpu, spacenum); + if (*result == NULL) + { + debug_console_printf("No %s memory space found for CPU '%s'\n", address_space_names[spacenum], cpu->tag); + return FALSE; + } + return TRUE; +} + + /*------------------------------------------------- debug_command_parameter_expression - validates an expression parameter @@ -425,13 +462,25 @@ int debug_command_parameter_cpu(running_machine *machine, const char *param, con static int debug_command_parameter_expression(running_machine *machine, const char *param, parsed_expression **result) { - EXPRERR err = expression_parse(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result); + EXPRERR err; + + /* NULL parameter does nothing and returns no error */ + if (param == NULL) + { + *result = NULL; + return TRUE; + } + + /* parse the expression; success if no error */ + err = expression_parse(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result); if (err == EXPRERR_NONE) - return 1; + return TRUE; + + /* output an error */ debug_console_printf("Error in expression: %s\n", param); debug_console_printf(" %*s^", EXPRERR_ERROR_OFFSET(err), ""); debug_console_printf("%s\n", exprerr_to_string(err)); - return 0; + return FALSE; } @@ -442,9 +491,18 @@ static int debug_command_parameter_expression(running_machine *machine, const ch static int debug_command_parameter_command(running_machine *machine, const char *param) { - CMDERR err = debug_console_validate_command(machine, param); + CMDERR err; + + /* NULL parameter does nothing and returns no error */ + if (param == NULL) + return TRUE; + + /* validate the comment; success if no error */ + err = debug_console_validate_command(machine, param); if (err == CMDERR_NONE) - return 1; + return TRUE; + + /* output an error */ debug_console_printf("Error in command: %s\n", param); debug_console_printf(" %*s^", CMDERR_ERROR_OFFSET(err), ""); debug_console_printf("%s\n", debug_cmderr_to_string(err)); @@ -454,9 +512,7 @@ static int debug_command_parameter_command(running_machine *machine, const char /*************************************************************************** - - Command Helpers - + COMMAND HELPERS ***************************************************************************/ /*------------------------------------------------- @@ -691,7 +747,7 @@ static void execute_step(running_machine *machine, int ref, int params, const ch UINT64 steps = 1; /* if we have a parameter, use it instead */ - if (params > 0 && !debug_command_parameter_number(machine, param[0], &steps)) + if (!debug_command_parameter_number(machine, param[0], &steps)) return; debug_cpu_single_step(machine, steps); @@ -707,7 +763,7 @@ static void execute_over(running_machine *machine, int ref, int params, const ch UINT64 steps = 1; /* if we have a parameter, use it instead */ - if (params > 0 && !debug_command_parameter_number(machine, param[0], &steps)) + if (!debug_command_parameter_number(machine, param[0], &steps)) return; debug_cpu_single_step_over(machine, steps); @@ -733,7 +789,7 @@ static void execute_go(running_machine *machine, int ref, int params, const char UINT64 addr = ~0; /* if we have a parameter, use it instead */ - if (params > 0 && !debug_command_parameter_number(machine, param[0], &addr)) + if (!debug_command_parameter_number(machine, param[0], &addr)) return; debug_cpu_go(machine, addr); @@ -760,7 +816,7 @@ static void execute_go_interrupt(running_machine *machine, int ref, int params, UINT64 irqline = -1; /* if we have a parameter, use it instead */ - if (params > 0 && !debug_command_parameter_number(machine, param[0], &irqline)) + if (!debug_command_parameter_number(machine, param[0], &irqline)) return; debug_cpu_go_interrupt(machine, irqline); @@ -776,7 +832,7 @@ static void execute_go_time(running_machine *machine, int ref, int params, const UINT64 milliseconds = -1; /* if we have a parameter, use it instead */ - if (params > 0 && !debug_command_parameter_number(machine, param[0], &milliseconds)) + if (!debug_command_parameter_number(machine, param[0], &milliseconds)) return; debug_cpu_go_milliseconds(machine, milliseconds); @@ -835,15 +891,15 @@ static void execute_ignore(running_machine *machine, int ref, int params, const for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++) if (machine->cpu[cpunum] != NULL) { - const cpu_debug_data *info = cpu_get_debug_data(machine->cpu[cpunum]); + const cpu_debug_data *cpuinfo = cpu_get_debug_data(machine->cpu[cpunum]); /* build up a comma-separated list */ - if ((info->flags & DEBUG_FLAG_OBSERVING) == 0) + if ((cpuinfo->flags & DEBUG_FLAG_OBSERVING) == 0) { if (buflen == 0) - buflen += sprintf(&buffer[buflen], "Currently ignoring CPU %d", cpunum); + buflen += sprintf(&buffer[buflen], "Currently ignoring CPU '%s'", machine->cpu[cpunum]->tag); else - buflen += sprintf(&buffer[buflen], ",%d", cpunum); + buflen += sprintf(&buffer[buflen], ", '%s'", machine->cpu[cpunum]->tag); } } @@ -900,15 +956,15 @@ static void execute_observe(running_machine *machine, int ref, int params, const for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++) if (machine->cpu[cpunum] != NULL) { - const cpu_debug_data *info = cpu_get_debug_data(machine->cpu[cpunum]); + const cpu_debug_data *cpuinfo = cpu_get_debug_data(machine->cpu[cpunum]); /* build up a comma-separated list */ - if ((info->flags & DEBUG_FLAG_OBSERVING) != 0) + if ((cpuinfo->flags & DEBUG_FLAG_OBSERVING) != 0) { if (buflen == 0) - buflen += sprintf(&buffer[buflen], "Currently observing CPU %d", cpunum); + buflen += sprintf(&buffer[buflen], "Currently observing CPU '%s'", machine->cpu[cpunum]->tag); else - buflen += sprintf(&buffer[buflen], ",%d", cpunum); + buflen += sprintf(&buffer[buflen], ", '%s'", machine->cpu[cpunum]->tag); } } @@ -942,13 +998,17 @@ static void execute_observe(running_machine *machine, int ref, int params, const static void execute_comment(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); + const device_config *cpu; UINT64 address; /* param 1 is the address for the comment */ if (!debug_command_parameter_number(machine, param[0], &address)) return; + /* CPU parameter is implicit */ + if (!debug_command_parameter_cpu(machine, NULL, &cpu)) + return; + /* make sure param 2 exists */ if (strlen(param[1]) == 0) { @@ -968,12 +1028,16 @@ static void execute_comment(running_machine *machine, int ref, int params, const static void execute_comment_del(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); + const device_config *cpu; UINT64 address; /* param 1 can either be a command or the address for the comment */ if (!debug_command_parameter_number(machine, param[0], &address)) return; + + /* CPU parameter is implicit */ + if (!debug_command_parameter_cpu(machine, NULL, &cpu)) + return; /* If it's a number, it must be an address */ /* The bankoff and cbn will be pulled from what's currently active */ @@ -1001,6 +1065,7 @@ static void execute_comment_save(running_machine *machine, int ref, int params, static void execute_bpset(running_machine *machine, int ref, int params, const char *param[]) { parsed_expression *condition = NULL; + const device_config *cpu; const char *action = NULL; UINT64 address; int bpnum; @@ -1010,15 +1075,19 @@ static void execute_bpset(running_machine *machine, int ref, int params, const c return; /* param 2 is the condition */ - if (params > 1 && !debug_command_parameter_expression(machine, param[1], &condition)) + if (!debug_command_parameter_expression(machine, param[1], &condition)) return; /* param 3 is the action */ - if (params > 2 && !debug_command_parameter_command(machine, action = param[2])) + if (!debug_command_parameter_command(machine, action = param[2])) + return; + + /* CPU is implicit */ + if (!debug_command_parameter_cpu(machine, NULL, &cpu)) return; /* set the breakpoint */ - bpnum = debug_cpu_breakpoint_set(debug_cpu_get_visible_cpu(machine), address, condition, action); + bpnum = debug_cpu_breakpoint_set(cpu, address, condition, action); debug_console_printf("Breakpoint %X set\n", bpnum); } @@ -1154,6 +1223,7 @@ static void execute_bplist(running_machine *machine, int ref, int params, const static void execute_wpset(running_machine *machine, int ref, int params, const char *param[]) { parsed_expression *condition = NULL; + const address_space *space; const char *action = NULL; UINT64 address, length; int type = 0; @@ -1181,15 +1251,19 @@ static void execute_wpset(running_machine *machine, int ref, int params, const c } /* param 4 is the condition */ - if (params > 3 && !debug_command_parameter_expression(machine, param[3], &condition)) + if (!debug_command_parameter_expression(machine, param[3], &condition)) return; /* param 5 is the action */ - if (params > 4 && !debug_command_parameter_command(machine, action = param[4])) + if (!debug_command_parameter_command(machine, action = param[4])) + return; + + /* CPU is implicit */ + if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space)) return; /* set the watchpoint */ - wpnum = debug_cpu_watchpoint_set(cpu_get_address_space(debug_cpu_get_visible_cpu(machine), ref), type, address, length, condition, action); + wpnum = debug_cpu_watchpoint_set(space, type, address, length, condition, action); debug_console_printf("Watchpoint %X set\n", wpnum); } @@ -1217,7 +1291,7 @@ static void execute_wpclear(running_machine *machine, int ref, int params, const for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) { debug_cpu_watchpoint *wp; - while ((wp = cpuinfo->space[spacenum].wplist) != NULL) + while ((wp = cpuinfo->wplist[spacenum]) != NULL) debug_cpu_watchpoint_clear(machine, wp->index); } } @@ -1261,7 +1335,7 @@ static void execute_wpdisenable(running_machine *machine, int ref, int params, c for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) { debug_cpu_watchpoint *wp; - for (wp = cpuinfo->space[spacenum].wplist; wp != NULL; wp = wp->next) + for (wp = cpuinfo->wplist[spacenum]; wp != NULL; wp = wp->next) debug_cpu_watchpoint_enable(machine, wp->index, ref); } } @@ -1303,20 +1377,20 @@ static void execute_wplist(running_machine *machine, int ref, int params, const int spacenum; for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) - { - if (cpuinfo->space[spacenum].wplist != NULL) + if (cpuinfo->wplist[spacenum] != NULL) { static const char *const types[] = { "unkn ", "read ", "write", "r/w " }; + const address_space *space = cpu_get_address_space(machine->cpu[cpunum], spacenum); debug_cpu_watchpoint *wp; - debug_console_printf("CPU %d %s space watchpoints:\n", cpunum, address_space_names[spacenum]); + debug_console_printf("CPU '%s' %s space watchpoints:\n", space->cpu->tag, address_space_names[spacenum]); /* loop over the watchpoints */ - for (wp = cpuinfo->space[spacenum].wplist; wp != NULL; wp = wp->next) + for (wp = cpuinfo->wplist[spacenum]; wp != NULL; wp = wp->next) { int buflen; buflen = sprintf(buffer, "%c%4X @ %08X-%08X %s", wp->enabled ? ' ' : 'D', - wp->index, BYTE2ADDR(wp->address, cpuinfo, spacenum), BYTE2ADDR(wp->address + wp->length, cpuinfo, spacenum) - 1, types[wp->type & 3]); + wp->index, memory_byte_to_address(space, wp->address), memory_byte_to_address_end(space, wp->address + wp->length) - 1, types[wp->type & 3]); if (wp->condition) buflen += sprintf(&buffer[buflen], " if %s", expression_original_string(wp->condition)); if (wp->action) @@ -1325,7 +1399,6 @@ static void execute_wplist(running_machine *machine, int ref, int params, const printed++; } } - } } if (!printed) @@ -1340,7 +1413,7 @@ static void execute_wplist(running_machine *machine, int ref, int params, const static void execute_hotspot(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); + const device_config *cpu; UINT64 threshhold; UINT64 count; @@ -1359,7 +1432,7 @@ static void execute_hotspot(running_machine *machine, int ref, int params, const if (cpuinfo->hotspots != NULL) { debug_cpu_hotspot_track(cpuinfo->device, 0, 0); - debug_console_printf("Cleared hotspot tracking on CPU %d\n", (int)cpunum); + debug_console_printf("Cleared hotspot tracking on CPU '%s'\n", machine->cpu[cpunum]->tag); cleared = TRUE; } } @@ -1372,11 +1445,11 @@ static void execute_hotspot(running_machine *machine, int ref, int params, const /* extract parameters */ count = 64; threshhold = 250; - if (params > 0 && !debug_command_parameter_cpu(machine, param[0], &cpu)) + if (!debug_command_parameter_cpu(machine, (params > 0) ? param[0] : NULL, &cpu)) return; - if (params > 1 && !debug_command_parameter_number(machine, param[1], &count)) + if (!debug_command_parameter_number(machine, param[1], &count)) return; - if (params > 2 && !debug_command_parameter_number(machine, param[2], &threshhold)) + if (!debug_command_parameter_number(machine, param[2], &threshhold)) return; /* attempt to install */ @@ -1393,31 +1466,22 @@ static void execute_hotspot(running_machine *machine, int ref, int params, const static void execute_save(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const address_space *space = cpu_get_address_space(cpu, ref); UINT64 offset, endoffset, length; - const cpu_debug_data *info; - int spacenum = ref; + const address_space *space; FILE *f; UINT64 i; /* validate parameters */ - if (space == NULL) - { - debug_console_printf("Invalid or non-existant address space %s on CPU '%s'\n", address_space_names[ref], cpu->tag); - return; - } if (!debug_command_parameter_number(machine, param[1], &offset)) return; if (!debug_command_parameter_number(machine, param[2], &length)) return; - if (params > 3 && !debug_command_parameter_cpu(machine, param[3], &cpu)) + if (!debug_command_parameter_cpu_space(machine, (params > 3) ? param[3] : NULL, ref, &space)) return; /* determine the addresses to write */ - info = cpu_get_debug_data(cpu); - endoffset = ADDR2BYTE_MASKED(offset + length - 1, info, spacenum); - offset = ADDR2BYTE_MASKED(offset, info, spacenum); + endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; + offset = memory_address_to_byte(space, offset) & space->bytemask; /* open the file */ f = fopen(param[0], "wb"); @@ -1428,7 +1492,7 @@ static void execute_save(running_machine *machine, int ref, int params, const ch } /* now write the data out */ - cpu_push_context(cpu); + cpu_push_context(space->cpu); for (i = offset; i <= endoffset; i++) { UINT8 byte = debug_read_byte(space, i, TRUE); @@ -1448,44 +1512,35 @@ static void execute_save(running_machine *machine, int ref, int params, const ch static void execute_dump(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const address_space *space = cpu_get_address_space(cpu, ref); UINT64 offset, endoffset, length, width = 0, ascii = 1; - const cpu_debug_data *info; - int spacenum = ref; + const address_space *space; FILE *f = NULL; UINT64 i, j; /* validate parameters */ - if (space == NULL) - { - debug_console_printf("Invalid or non-existant address space %s on CPU '%s'\n", address_space_names[ref], cpu->tag); - return; - } if (!debug_command_parameter_number(machine, param[1], &offset)) return; if (!debug_command_parameter_number(machine, param[2], &length)) return; - if (params > 3 && !debug_command_parameter_number(machine, param[3], &width)) + if (!debug_command_parameter_number(machine, param[3], &width)) return; - if (params > 4 && !debug_command_parameter_number(machine, param[4], &ascii)) + if (!debug_command_parameter_number(machine, param[4], &ascii)) return; - if (params > 5 && !debug_command_parameter_cpu(machine, param[5], &cpu)) + if (!debug_command_parameter_cpu_space(machine, (params > 5) ? param[5] : NULL, ref, &space)) return; /* further validation */ - info = cpu_get_debug_data(cpu); if (width == 0) - width = info->space[spacenum].databytes; - if (width < ADDR2BYTE(1, info, spacenum)) - width = ADDR2BYTE(1, info, spacenum); + width = space->dbits / 8; + if (width < memory_address_to_byte(space, 1)) + width = memory_address_to_byte(space, 1); if (width != 1 && width != 2 && width != 4 && width != 8) { debug_console_printf("Invalid width! (must be 1,2,4 or 8)\n"); return; } - endoffset = ADDR2BYTE_MASKED(offset + length - 1, info, spacenum); - offset = ADDR2BYTE_MASKED(offset, info, spacenum); + endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; + offset = memory_address_to_byte(space, offset) & space->bytemask; /* open the file */ f = fopen(param[0], "w"); @@ -1496,14 +1551,14 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch } /* now write the data out */ - cpu_push_context(cpu); + cpu_push_context(space->cpu); for (i = offset; i <= endoffset; i += 16) { char output[200]; int outdex = 0; /* print the address */ - outdex += sprintf(&output[outdex], "%0*X: ", info->space[spacenum].logchars, (UINT32)BYTE2ADDR(i, info, spacenum)); + outdex += sprintf(&output[outdex], "%0*X: ", space->logaddrchars, (UINT32)memory_byte_to_address(space, i)); /* print the bytes */ switch (width) @@ -1514,7 +1569,7 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch if (i + j <= endoffset) { offs_t curaddr = i + j; - if (info->translate == NULL || (*info->translate)(cpu, spacenum, TRANSLATE_READ, &curaddr)) + if (memory_address_physical(space, TRANSLATE_READ, &curaddr)) { UINT8 byte = debug_read_byte(space, i + j, TRUE); outdex += sprintf(&output[outdex], " %02X", byte); @@ -1533,7 +1588,7 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch if (i + j <= endoffset) { offs_t curaddr = i + j; - if (info->translate == NULL || (*info->translate)(cpu, spacenum, TRANSLATE_READ_DEBUG, &curaddr)) + if (memory_address_physical(space, TRANSLATE_READ_DEBUG, &curaddr)) { UINT16 word = debug_read_word(space, i + j, TRUE); outdex += sprintf(&output[outdex], " %04X", word); @@ -1552,7 +1607,7 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch if (i + j <= endoffset) { offs_t curaddr = i + j; - if (info->translate == NULL || (*info->translate)(cpu, spacenum, TRANSLATE_READ_DEBUG, &curaddr)) + if (memory_address_physical(space, TRANSLATE_READ_DEBUG, &curaddr)) { UINT32 dword = debug_read_dword(space, i + j, TRUE); outdex += sprintf(&output[outdex], " %08X", dword); @@ -1571,7 +1626,7 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch if (i + j <= endoffset) { offs_t curaddr = i + j; - if (info->translate == NULL || (*info->translate)(cpu, spacenum, TRANSLATE_READ_DEBUG, &curaddr)) + if (memory_address_physical(space, TRANSLATE_READ_DEBUG, &curaddr)) { UINT64 qword = debug_read_qword(space, i + j, TRUE); outdex += sprintf(&output[outdex], " %08X%08X", (UINT32)(qword >> 32), (UINT32)qword); @@ -1592,7 +1647,7 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch for (j = 0; j < 16 && (i + j) <= endoffset; j++) { offs_t curaddr = i + j; - if (info->translate == NULL || (*info->translate)(cpu, spacenum, TRANSLATE_READ_DEBUG, &curaddr)) + if (memory_address_physical(space, TRANSLATE_READ_DEBUG, &curaddr)) { UINT8 byte = debug_read_byte(space, i + j, TRUE); outdex += sprintf(&output[outdex], "%c", (byte >= 32 && byte < 128) ? byte : '.'); @@ -1619,34 +1674,27 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch static void execute_find(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const address_space *space = cpu_get_address_space(cpu, ref); UINT64 offset, endoffset, length; - const cpu_debug_data *info; + const address_space *space; UINT64 data_to_find[256]; UINT8 data_size[256]; int cur_data_size; int data_count = 0; - int spacenum = ref; int found = 0; UINT64 i, j; /* validate parameters */ - if (space == NULL) - { - debug_console_printf("Invalid or non-existant address space %s on CPU '%s'\n", address_space_names[ref], cpu->tag); - return; - } if (!debug_command_parameter_number(machine, param[0], &offset)) return; if (!debug_command_parameter_number(machine, param[1], &length)) return; + if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space)) + return; /* further validation */ - info = cpu_get_debug_data(cpu); - endoffset = ADDR2BYTE_MASKED(offset + length - 1, info, spacenum); - offset = ADDR2BYTE_MASKED(offset, info, spacenum); - cur_data_size = ADDR2BYTE(1, info, spacenum); + endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; + offset = memory_address_to_byte(space, offset) & space->bytemask; + cur_data_size = memory_address_to_byte(space, 1); if (cur_data_size == 0) cur_data_size = 1; @@ -1686,7 +1734,7 @@ static void execute_find(running_machine *machine, int ref, int params, const ch } /* now search */ - cpu_push_context(cpu); + cpu_push_context(space->cpu); for (i = offset; i <= endoffset; i += data_size[0]) { int suboffset = 0; @@ -1710,7 +1758,7 @@ static void execute_find(running_machine *machine, int ref, int params, const ch if (match) { found++; - debug_console_printf("Found at %*X\n", info->space[spacenum].logchars, (UINT32)BYTE2ADDR(i, info, spacenum)); + debug_console_printf("Found at %*X\n", space->logaddrchars, (UINT32)memory_byte_to_address(space, i)); } } cpu_pop_context(); @@ -1727,11 +1775,9 @@ static void execute_find(running_machine *machine, int ref, int params, const ch static void execute_dasm(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const address_space *space = cpu_get_address_space(cpu, ADDRESS_SPACE_PROGRAM); UINT64 offset, length, bytes = 1; - const cpu_debug_data *info; int minbytes, maxbytes, byteswidth; + const address_space *space; FILE *f = NULL; int i, j; @@ -1740,17 +1786,14 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch return; if (!debug_command_parameter_number(machine, param[2], &length)) return; - if (params > 3 && !debug_command_parameter_number(machine, param[3], &bytes)) + if (!debug_command_parameter_number(machine, param[3], &bytes)) return; - if (params > 4 && !debug_command_parameter_cpu(machine, param[4], &cpu)) + if (!debug_command_parameter_cpu_space(machine, (params > 4) ? param[4] : NULL, ADDRESS_SPACE_PROGRAM, &space)) return; - /* further validation */ - info = cpu_get_debug_data(cpu); - /* determine the width of the bytes */ - minbytes = cpu_get_min_opcode_bytes(cpu); - maxbytes = cpu_get_max_opcode_bytes(cpu); + minbytes = cpu_get_min_opcode_bytes(space->cpu); + maxbytes = cpu_get_max_opcode_bytes(space->cpu); byteswidth = 0; if (bytes) { @@ -1767,10 +1810,10 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch } /* now write the data out */ - cpu_push_context(cpu); + cpu_push_context(space->cpu); for (i = 0; i < length; ) { - int pcbyte = ADDR2BYTE_MASKED(offset + i, info, ADDRESS_SPACE_PROGRAM); + int pcbyte = memory_address_to_byte(space, offset + i) & space->bytemask; char output[200+DEBUG_COMMENT_MAX_LINE_LENGTH], disasm[200]; const char *comment; offs_t tempaddr; @@ -1778,11 +1821,11 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch int numbytes = 0; /* print the address */ - outdex += sprintf(&output[outdex], "%0*X: ", info->space[ADDRESS_SPACE_PROGRAM].logchars, (UINT32)BYTE2ADDR(pcbyte, info, ADDRESS_SPACE_PROGRAM)); + outdex += sprintf(&output[outdex], "%0*X: ", space->logaddrchars, (UINT32)memory_byte_to_address(space, pcbyte)); /* make sure we can translate the address */ tempaddr = pcbyte; - if (info->translate == NULL || (*info->translate)(info->device, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH_DEBUG, &tempaddr)) + if (memory_address_physical(space, TRANSLATE_FETCH_DEBUG, &tempaddr)) { UINT8 opbuf[64], argbuf[64]; @@ -1794,14 +1837,14 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch } /* disassemble the result */ - i += numbytes = cpu_dasm(cpu, disasm, offset + i, opbuf, argbuf) & DASMFLAG_LENGTHMASK; + i += numbytes = cpu_dasm(space->cpu, disasm, offset + i, opbuf, argbuf) & DASMFLAG_LENGTHMASK; } /* print the bytes */ if (bytes) { int startdex = outdex; - numbytes = ADDR2BYTE(numbytes, info, ADDRESS_SPACE_PROGRAM); + numbytes = memory_address_to_byte(space, numbytes); switch (minbytes) { case 1: @@ -1836,7 +1879,7 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch sprintf(&output[outdex], "%s", disasm); /* attempt to add the comment */ - comment = debug_comment_get_text(cpu, tempaddr, debug_comment_get_opcode_crc32(cpu, tempaddr)); + comment = debug_comment_get_text(space->cpu, tempaddr, debug_comment_get_opcode_crc32(space->cpu, tempaddr)); if (comment != NULL) { /* somewhat arbitrary guess as to how long most disassembly lines will be [column 60] */ @@ -1871,15 +1914,15 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch static void execute_trace_internal(running_machine *machine, int ref, int params, const char *param[], int trace_over) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); const char *action = NULL, *filename = param[0]; + const device_config *cpu; FILE *f = NULL; const char *mode; /* validate parameters */ - if (params > 1 && !debug_command_parameter_cpu(machine, param[1], &cpu)) + if (!debug_command_parameter_cpu(machine, (params > 1) ? param[1] : NULL, &cpu)) return; - if (params > 2 && !debug_command_parameter_command(machine, action = param[2])) + if (!debug_command_parameter_command(machine, action = param[2])) return; /* further validation */ @@ -1951,53 +1994,52 @@ static void execute_traceflush(running_machine *machine, int ref, int params, co static void execute_history(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const address_space *space = cpu_get_address_space(cpu, ADDRESS_SPACE_PROGRAM); UINT64 count = DEBUG_HISTORY_SIZE; - const cpu_debug_data *info; + const cpu_debug_data *cpuinfo; + const address_space *space; int i; /* validate parameters */ - if (params > 0 && !debug_command_parameter_cpu(machine, param[0], &cpu)) + if (!debug_command_parameter_cpu_space(machine, (params > 0) ? param[0] : NULL, ADDRESS_SPACE_PROGRAM, &space)) return; - if (params > 1 && !debug_command_parameter_number(machine, param[1], &count)) + if (!debug_command_parameter_number(machine, param[1], &count)) return; /* further validation */ if (count > DEBUG_HISTORY_SIZE) count = DEBUG_HISTORY_SIZE; - info = cpu_get_debug_data(cpu); + cpuinfo = cpu_get_debug_data(space->cpu); /* loop over lines */ - cpu_push_context(cpu); + cpu_push_context(space->cpu); for (i = 0; i < count; i++) { - offs_t pc = info->pc_history[(info->pc_history_index + DEBUG_HISTORY_SIZE - count + i) % DEBUG_HISTORY_SIZE]; - int maxbytes = cpu_get_max_opcode_bytes(cpu); + offs_t pc = cpuinfo->pc_history[(cpuinfo->pc_history_index + DEBUG_HISTORY_SIZE - count + i) % DEBUG_HISTORY_SIZE]; + int maxbytes = cpu_get_max_opcode_bytes(space->cpu); UINT8 opbuf[64], argbuf[64]; char buffer[200]; offs_t pcbyte; int numbytes; /* fetch the bytes up to the maximum */ - pcbyte = ADDR2BYTE_MASKED(pc, info, ADDRESS_SPACE_PROGRAM); + pcbyte = memory_address_to_byte(space, pc) & space->bytemask; for (numbytes = 0; numbytes < maxbytes; numbytes++) { opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, FALSE); argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, TRUE); } - cpu_dasm(cpu, buffer, pc, opbuf, argbuf); + cpu_dasm(space->cpu, buffer, pc, opbuf, argbuf); - debug_console_printf("%0*X: %s\n", info->space[ADDRESS_SPACE_PROGRAM].logchars, pc, buffer); + debug_console_printf("%0*X: %s\n", space->logaddrchars, pc, buffer); } cpu_pop_context(); } /*------------------------------------------------- - execute_snap - execute the trace over command + execute_snap - execute the snapshot command -------------------------------------------------*/ static void execute_snap(running_machine *machine, int ref, int params, const char *param[]) @@ -2061,9 +2103,7 @@ static void execute_source(running_machine *machine, int ref, int params, const static void execute_map(running_machine *machine, int ref, int params, const char *param[]) { - const device_config *cpu = debug_cpu_get_visible_cpu(machine); - const cpu_debug_data *info; - int spacenum = ref; + const address_space *space; offs_t taddress; UINT64 address; int intention; @@ -2071,28 +2111,23 @@ static void execute_map(running_machine *machine, int ref, int params, const cha /* validate parameters */ if (!debug_command_parameter_number(machine, param[0], &address)) return; - info = cpu_get_debug_data(cpu); + + /* CPU is implicit */ + if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space)) + return; /* do the translation first */ for (intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++) { static const char *const intnames[] = { "Read", "Write", "Fetch" }; - taddress = ADDR2BYTE_MASKED(address, info, spacenum); - if (info->translate != NULL) + taddress = memory_address_to_byte(space, address) & space->bytemask; + if (memory_address_physical(space, intention, &taddress)) { - if ((*info->translate)(info->device, spacenum, intention, &taddress)) - { - const char *mapname = memory_get_handler_string(cpu_get_address_space(cpu, spacenum), intention == TRANSLATE_WRITE_DEBUG, taddress); - debug_console_printf("%7s: %08X logical == %08X physical -> %s\n", intnames[intention & 3], (UINT32)address, BYTE2ADDR(taddress, info, spacenum), mapname); - } - else - debug_console_printf("%7s: %08X logical is unmapped\n", intnames[intention & 3], (UINT32)address); + const char *mapname = memory_get_handler_string(space, intention == TRANSLATE_WRITE_DEBUG, taddress); + debug_console_printf("%7s: %08X logical == %08X physical -> %s\n", intnames[intention & 3], (UINT32)address, memory_byte_to_address(space, taddress), mapname); } else - { - const char *mapname = memory_get_handler_string(cpu_get_address_space(cpu, spacenum), intention == TRANSLATE_WRITE_DEBUG, taddress); - debug_console_printf("%7s: %08X -> %s\n", intnames[intention & 3], BYTE2ADDR(taddress, info, spacenum), mapname); - } + debug_console_printf("%7s: %08X logical is unmapped\n", intnames[intention & 3], (UINT32)address); } } @@ -2138,7 +2173,7 @@ static void execute_symlist(running_machine *machine, int ref, int params, const int symnum, count = 0; /* validate parameters */ - if (params > 0 && !debug_command_parameter_cpu(machine, param[0], &cpu)) + if (!debug_command_parameter_cpu(machine, param[0], &cpu)) return; if (cpu != NULL) diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 6d32ca346e2..4700e1804cb 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -17,11 +17,22 @@ FUNCTION PROTOTYPES ***************************************************************************/ -/* initialization */ +/* ----- initialization ----- */ + +/* initializes the command system */ void debug_command_init(running_machine *machine); -/* parameter validation */ + + +/* ----- parameter validation ----- */ + +/* validates a number parameter */ int debug_command_parameter_number(running_machine *machine, const char *param, UINT64 *result); + +/* validates a parameter as a cpu */ int debug_command_parameter_cpu(running_machine *machine, const char *param, const device_config **result); +/* validates a parameter as a cpu and retrieves the given address space */ +int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, const address_space **result); + #endif diff --git a/src/emu/debug/debugcmt.c b/src/emu/debug/debugcmt.c index 32c3269a2d3..b8f49da0a3c 100644 --- a/src/emu/debug/debugcmt.c +++ b/src/emu/debug/debugcmt.c @@ -310,7 +310,6 @@ UINT32 debug_comment_all_change_count(running_machine *machine) UINT32 debug_comment_get_opcode_crc32(const device_config *device, offs_t address) { - const cpu_debug_data *info = cpu_get_debug_data(device); const address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM); int i; UINT32 crc; @@ -318,7 +317,7 @@ UINT32 debug_comment_get_opcode_crc32(const device_config *device, offs_t addres char buff[256]; offs_t numbytes; int maxbytes = cpu_get_max_opcode_bytes(device); - UINT32 addrmask = (cpu_get_debug_data(device))->space[ADDRESS_SPACE_PROGRAM].logaddrmask; + UINT32 addrmask = space->logaddrmask; memset(opbuf, 0x00, sizeof(opbuf)); memset(argbuf, 0x00, sizeof(argbuf)); @@ -331,7 +330,7 @@ UINT32 debug_comment_get_opcode_crc32(const device_config *device, offs_t addres } numbytes = cpu_dasm(device, buff, address & addrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK; - numbytes = ADDR2BYTE(numbytes, info, ADDRESS_SPACE_PROGRAM); + numbytes = memory_address_to_byte(space, numbytes); crc = crc32(0, argbuf, numbytes); diff --git a/src/emu/debug/debugcon.c b/src/emu/debug/debugcon.c index 6b2a7d81bbe..0a323a0752a 100644 --- a/src/emu/debug/debugcon.c +++ b/src/emu/debug/debugcon.c @@ -209,7 +209,10 @@ static CMDERR internal_execute_command(running_machine *machine, int execute, in params = 0; } else + { params = 0; + param[0] = NULL; + } /* search the command list */ len = strlen(command); @@ -260,7 +263,7 @@ static CMDERR internal_execute_command(running_machine *machine, int execute, in static CMDERR internal_parse_command(running_machine *machine, const char *original_command, int execute) { char command[MAX_COMMAND_LENGTH], parens[MAX_COMMAND_LENGTH]; - char *params[MAX_COMMAND_PARAMS]; + char *params[MAX_COMMAND_PARAMS] = { 0 }; CMDERR result = CMDERR_NONE; char *command_start; char *p, c = 0; @@ -328,7 +331,7 @@ static CMDERR internal_parse_command(running_machine *machine, const char *origi if (isexpr && paramcount == 1) { UINT64 expresult; - EXPRERR exprerr = expression_evaluate(command_start, cpu_get_debug_data(machine->activecpu)->symtable, &debug_expression_callbacks, machine, &expresult); + EXPRERR exprerr = expression_evaluate(command_start, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, &expresult); if (exprerr != EXPRERR_NONE) return MAKE_CMDERR_EXPRESSION_ERROR(EXPRERR_ERROR_OFFSET(exprerr)); } diff --git a/src/emu/debug/debugcpu.c b/src/emu/debug/debugcpu.c index e52569a7ab3..71e10d37a3b 100644 --- a/src/emu/debug/debugcpu.c +++ b/src/emu/debug/debugcpu.c @@ -159,8 +159,8 @@ const express_callbacks debug_expression_callbacks = void debug_cpu_init(running_machine *machine) { const device_config *first_screen = video_screen_first(machine->config); - int cpunum, spacenum, regnum; debugcpu_private *global; + int cpunum, regnum; /* allocate and reset globals */ machine->debugcpu_data = global = auto_malloc(sizeof(*global)); @@ -204,11 +204,9 @@ void debug_cpu_init(running_machine *machine) /* reset the PC data */ info->flags = DEBUG_FLAG_OBSERVING | DEBUG_FLAG_HISTORY; info->device = machine->cpu[cpunum]; - info->endianness = cpu_get_endianness(info->device); info->opwidth = cpu_get_min_opcode_bytes(info->device); /* fetch the memory accessors */ - info->translate = (cpu_translate_func)cpu_get_info_fct(info->device, CPUINFO_PTR_TRANSLATE); info->read = (cpu_read_func)cpu_get_info_fct(info->device, CPUINFO_PTR_READ); info->write = (cpu_write_func)cpu_get_info_fct(info->device, CPUINFO_PTR_WRITE); info->readop = (cpu_readop_func)cpu_get_info_fct(info->device, CPUINFO_PTR_READOP); @@ -252,40 +250,6 @@ void debug_cpu_init(running_machine *machine) /* add the symbol to the table */ symtable_add_register(info->symtable, symname, (void *)(FPTR)regnum, get_cpu_reg, set_cpu_reg); } - - /* loop over address spaces and get info */ - for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) - { - debug_space_info *spaceinfo = &info->space[spacenum]; - int datawidth = cpu_get_databus_width(info->device, spacenum); - int logwidth = cpu_get_logaddr_width(info->device, spacenum); - int physwidth = cpu_get_addrbus_width(info->device, spacenum); - int addrshift = cpu_get_addrbus_shift(info->device, spacenum); - int pageshift = cpu_get_page_shift(info->device, spacenum); - - if (logwidth == 0) - logwidth = physwidth; - - spaceinfo->space = cpu_get_address_space(cpu, spacenum); - spaceinfo->databytes = datawidth / 8; - spaceinfo->pageshift = pageshift; - - /* left/right shifts to convert addresses to bytes */ - spaceinfo->addr2byte_lshift = (addrshift < 0) ? -addrshift : 0; - spaceinfo->addr2byte_rshift = (addrshift > 0) ? addrshift : 0; - - /* number of character used to display addresses */ - spaceinfo->physchars = (physwidth + 3) / 4; - spaceinfo->logchars = (logwidth + 3) / 4; - - /* masks to apply to addresses */ - spaceinfo->physaddrmask = (0xfffffffful >> (32 - physwidth)); - spaceinfo->logaddrmask = (0xfffffffful >> (32 - logwidth)); - - /* masks to apply to byte addresses */ - spaceinfo->physbytemask = ((spaceinfo->physaddrmask << spaceinfo->addr2byte_lshift) | ((1 << spaceinfo->addr2byte_lshift) - 1)) >> spaceinfo->addr2byte_rshift; - spaceinfo->logbytemask = ((spaceinfo->logaddrmask << spaceinfo->addr2byte_lshift) | ((1 << spaceinfo->addr2byte_lshift) - 1)) >> spaceinfo->addr2byte_rshift; - } } /* first CPU is visible by default */ @@ -614,7 +578,7 @@ void debug_cpu_instruction_hook(const device_config *device, offs_t curpc) { /* clear the memory modified flag and wait */ global->memory_modified = FALSE; - osd_wait_for_debugger(device->machine, firststop); + osd_wait_for_debugger(device, firststop); firststop = FALSE; /* if something modified memory, update the screen */ @@ -1051,8 +1015,8 @@ int debug_cpu_watchpoint_set(const address_space *space, int type, offs_t addres wp->index = global->wpindex++; wp->enabled = TRUE; wp->type = type; - wp->address = ADDR2BYTE_MASKED(address, info, space->spacenum); - wp->length = ADDR2BYTE(length, info, space->spacenum); + wp->address = memory_address_to_byte(space, address) & space->bytemask; + wp->length = memory_address_to_byte(space, length); wp->condition = condition; wp->action = NULL; if (action != NULL) @@ -1062,8 +1026,8 @@ int debug_cpu_watchpoint_set(const address_space *space, int type, offs_t addres } /* hook us in */ - wp->next = info->space[space->spacenum].wplist; - info->space[space->spacenum].wplist = wp; + wp->next = info->wplist[space->spacenum]; + info->wplist[space->spacenum] = wp; watchpoint_update_flags(space); @@ -1088,12 +1052,12 @@ int debug_cpu_watchpoint_clear(running_machine *machine, int wpnum) cpu_debug_data *info = cpu_get_debug_data(machine->cpu[cpunum]); for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) - for (pwp = NULL, wp = info->space[spacenum].wplist; wp != NULL; pwp = wp, wp = wp->next) + for (pwp = NULL, wp = info->wplist[spacenum]; wp != NULL; pwp = wp, wp = wp->next) if (wp->index == wpnum) { /* unlink us from the list */ if (pwp == NULL) - info->space[spacenum].wplist = wp->next; + info->wplist[spacenum] = wp->next; else pwp->next = wp->next; @@ -1131,7 +1095,7 @@ int debug_cpu_watchpoint_enable(running_machine *machine, int wpnum, int enable) cpu_debug_data *info = cpu_get_debug_data(machine->cpu[cpunum]); for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) - for (wp = info->space[spacenum].wplist; wp; wp = wp->next) + for (wp = info->wplist[spacenum]; wp != NULL; wp = wp->next) if (wp->index == wpnum) { wp->enabled = (enable != 0); @@ -1302,13 +1266,13 @@ UINT8 debug_read_byte(const address_space *space, offs_t address, int apply_tran UINT8 result; /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, return 0xff */ - if (apply_translation && info->translate != NULL && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_READ_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_READ_DEBUG, &address)) result = 0xff; /* if there is a custom read handler, and it returns TRUE, use that value */ @@ -1333,12 +1297,10 @@ UINT8 debug_read_byte(const address_space *space, offs_t address, int apply_tran UINT16 debug_read_word(const address_space *space, offs_t address, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); - UINT64 custom; UINT16 result; /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is misaligned read, or if there are no word readers, just read two bytes */ if ((address & 1) != 0) @@ -1347,7 +1309,7 @@ UINT16 debug_read_word(const address_space *space, offs_t address, int apply_tra UINT8 byte1 = debug_read_byte(space, address + 1, apply_translation); /* based on the endianness, the result is assembled differently */ - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) result = byte0 | (byte1 << 8); else result = byte1 | (byte0 << 8); @@ -1356,15 +1318,18 @@ UINT16 debug_read_word(const address_space *space, offs_t address, int apply_tra /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + UINT64 custom; + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, return 0xffff */ - if (apply_translation && info->translate != NULL && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_READ_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_READ_DEBUG, &address)) result = 0xffff; /* if there is a custom read handler, and it returns TRUE, use that value */ - else if (info->read && (*info->read)(space->cpu, space->spacenum, address, 2, &custom)) + else if (info->read != NULL && (*info->read)(space->cpu, space->spacenum, address, 2, &custom)) result = custom; /* otherwise, call the byte reading function for the translated address */ @@ -1387,12 +1352,10 @@ UINT16 debug_read_word(const address_space *space, offs_t address, int apply_tra UINT32 debug_read_dword(const address_space *space, offs_t address, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); - UINT64 custom; UINT32 result; /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is misaligned read, or if there are no dword readers, just read two words */ if ((address & 3) != 0) @@ -1401,7 +1364,7 @@ UINT32 debug_read_dword(const address_space *space, offs_t address, int apply_tr UINT16 word1 = debug_read_word(space, address + 2, apply_translation); /* based on the endianness, the result is assembled differently */ - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) result = word0 | (word1 << 16); else result = word1 | (word0 << 16); @@ -1410,15 +1373,18 @@ UINT32 debug_read_dword(const address_space *space, offs_t address, int apply_tr /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + UINT64 custom; + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, return 0xffffffff */ - if (apply_translation && info->translate != NULL && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_READ_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_READ_DEBUG, &address)) result = 0xffffffff; /* if there is a custom read handler, and it returns TRUE, use that value */ - else if (info->read && (*info->read)(space->cpu, space->spacenum, address, 4, &custom)) + else if (info->read != NULL && (*info->read)(space->cpu, space->spacenum, address, 4, &custom)) result = custom; /* otherwise, call the byte reading function for the translated address */ @@ -1441,12 +1407,10 @@ UINT32 debug_read_dword(const address_space *space, offs_t address, int apply_tr UINT64 debug_read_qword(const address_space *space, offs_t address, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); - UINT64 custom; UINT64 result; /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is misaligned read, or if there are no qword readers, just read two dwords */ if ((address & 7) != 0) @@ -1455,7 +1419,7 @@ UINT64 debug_read_qword(const address_space *space, offs_t address, int apply_tr UINT32 dword1 = debug_read_dword(space, address + 4, apply_translation); /* based on the endianness, the result is assembled differently */ - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) result = dword0 | ((UINT64)dword1 << 32); else result = dword1 | ((UINT64)dword0 << 32); @@ -1464,15 +1428,18 @@ UINT64 debug_read_qword(const address_space *space, offs_t address, int apply_tr /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + UINT64 custom; + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, return 0xffffffffffffffff */ - if (apply_translation && info->translate != NULL && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_READ_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_READ_DEBUG, &address)) result = ~(UINT64)0; /* if there is a custom read handler, and it returns TRUE, use that value */ - else if (info->read && (*info->read)(space->cpu, space->spacenum, address, 8, &custom)) + else if (info->read != NULL && (*info->read)(space->cpu, space->spacenum, address, 8, &custom)) result = custom; /* otherwise, call the byte reading function for the translated address */ @@ -1498,17 +1465,17 @@ void debug_write_byte(const address_space *space, offs_t address, UINT8 data, in cpu_debug_data *info = cpu_get_debug_data(space->cpu); /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, we're done */ - if (apply_translation && info->translate != NULL && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_WRITE_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_WRITE_DEBUG, &address)) ; /* if there is a custom write handler, and it returns TRUE, use that */ - else if (info->write && (*info->write)(space->cpu, space->spacenum, address, 1, data)) + else if (info->write != NULL && (*info->write)(space->cpu, space->spacenum, address, 1, data)) ; /* otherwise, call the byte reading function for the translated address */ @@ -1529,15 +1496,14 @@ void debug_write_byte(const address_space *space, offs_t address, UINT8 data, in void debug_write_word(const address_space *space, offs_t address, UINT16 data, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is a misaligned write, or if there are no word writers, just read two bytes */ if ((address & 1) != 0) { - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) { debug_write_byte(space, address + 0, data >> 0, apply_translation); debug_write_byte(space, address + 1, data >> 8, apply_translation); @@ -1552,15 +1518,17 @@ void debug_write_word(const address_space *space, offs_t address, UINT16 data, i /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, we're done */ - if (apply_translation && info->translate && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_WRITE_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_WRITE_DEBUG, &address)) ; /* if there is a custom write handler, and it returns TRUE, use that */ - else if (info->write && (*info->write)(space->cpu, space->spacenum, address, 2, data)) + else if (info->write != NULL && (*info->write)(space->cpu, space->spacenum, address, 2, data)) ; /* otherwise, call the byte reading function for the translated address */ @@ -1582,15 +1550,14 @@ void debug_write_word(const address_space *space, offs_t address, UINT16 data, i void debug_write_dword(const address_space *space, offs_t address, UINT32 data, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is a misaligned write, or if there are no dword writers, just read two words */ if ((address & 3) != 0) { - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) { debug_write_word(space, address + 0, data >> 0, apply_translation); debug_write_word(space, address + 2, data >> 16, apply_translation); @@ -1605,15 +1572,17 @@ void debug_write_dword(const address_space *space, offs_t address, UINT32 data, /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, we're done */ - if (apply_translation && info->translate && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_WRITE_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_WRITE_DEBUG, &address)) ; /* if there is a custom write handler, and it returns TRUE, use that */ - else if (info->write && (*info->write)(space->cpu, space->spacenum, address, 4, data)) + else if (info->write != NULL && (*info->write)(space->cpu, space->spacenum, address, 4, data)) ; /* otherwise, call the byte reading function for the translated address */ @@ -1635,15 +1604,14 @@ void debug_write_dword(const address_space *space, offs_t address, UINT32 data, void debug_write_qword(const address_space *space, offs_t address, UINT64 data, int apply_translation) { debugcpu_private *global = space->machine->debugcpu_data; - cpu_debug_data *info = cpu_get_debug_data(space->cpu); /* mask against the logical byte mask */ - address &= info->space[space->spacenum].logbytemask; + address &= space->logbytemask; /* if this is a misaligned write, or if there are no qword writers, just read two dwords */ if ((address & 7) != 0) { - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) { debug_write_dword(space, address + 0, data >> 0, apply_translation); debug_write_dword(space, address + 4, data >> 32, apply_translation); @@ -1654,18 +1622,21 @@ void debug_write_qword(const address_space *space, offs_t address, UINT64 data, debug_write_dword(space, address + 4, data >> 0, apply_translation); } } + /* otherwise, this proceeds like the byte case */ else { + cpu_debug_data *info = cpu_get_debug_data(space->cpu); + /* all accesses from this point on are for the debugger */ memory_set_debugger_access(space, global->debugger_access = TRUE); /* translate if necessary; if not mapped, we're done */ - if (apply_translation && info->translate && !(*info->translate)(space->cpu, space->spacenum, TRANSLATE_WRITE_DEBUG, &address)) + if (apply_translation && !memory_address_physical(space, TRANSLATE_WRITE_DEBUG, &address)) ; /* if there is a custom write handler, and it returns TRUE, use that */ - else if (info->write && (*info->write)(space->cpu, space->spacenum, address, 8, data)) + else if (info->write != NULL && (*info->write)(space->cpu, space->spacenum, address, 8, data)) ; /* otherwise, call the byte reading function for the translated address */ @@ -1691,10 +1662,10 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i const void *ptr; /* keep in logical range */ - address &= info->space[ADDRESS_SPACE_PROGRAM].logbytemask; + address &= space->logbytemask; /* shortcut if we have a custom routine */ - if (info->readop) + if (info->readop != NULL) { UINT64 result; if ((*info->readop)(space->cpu, address, size, &result)) @@ -1702,25 +1673,25 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i } /* if we're bigger than the address bus, break into smaller pieces */ - if (size > info->space[ADDRESS_SPACE_PROGRAM].databytes) + if (size > space->dbits / 8) { int halfsize = size / 2; UINT64 r0 = debug_read_opcode(space, address + 0, halfsize, arg); UINT64 r1 = debug_read_opcode(space, address + halfsize, halfsize, arg); - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) return r0 | (r1 << (8 * halfsize)); else return r1 | (r0 << (8 * halfsize)); } /* translate to physical first */ - if (info->translate && !(*info->translate)(space->cpu, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH_DEBUG, &address)) + if (!memory_address_physical(space, TRANSLATE_FETCH_DEBUG, &address)) return ~(UINT64)0 & (~(UINT64)0 >> (64 - 8*size)); /* keep in physical range */ - address &= info->space[ADDRESS_SPACE_PROGRAM].physbytemask; - switch (info->space[ADDRESS_SPACE_PROGRAM].databytes * 10 + size) + address &= space->bytemask; + switch (space->dbits / 8 * 10 + size) { /* dump opcodes in bytes from a byte-sized bus */ case 11: @@ -1728,7 +1699,7 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i /* dump opcodes in bytes from a word-sized bus */ case 21: - address ^= (info->endianness == CPU_IS_LE) ? BYTE_XOR_LE(0) : BYTE_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? BYTE_XOR_LE(0) : BYTE_XOR_BE(0); break; /* dump opcodes in words from a word-sized bus */ @@ -1737,12 +1708,12 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i /* dump opcodes in bytes from a dword-sized bus */ case 41: - address ^= (info->endianness == CPU_IS_LE) ? BYTE4_XOR_LE(0) : BYTE4_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? BYTE4_XOR_LE(0) : BYTE4_XOR_BE(0); break; /* dump opcodes in words from a dword-sized bus */ case 42: - address ^= (info->endianness == CPU_IS_LE) ? WORD_XOR_LE(0) : WORD_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? WORD_XOR_LE(0) : WORD_XOR_BE(0); break; /* dump opcodes in dwords from a dword-sized bus */ @@ -1751,17 +1722,17 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i /* dump opcodes in bytes from a qword-sized bus */ case 81: - address ^= (info->endianness == CPU_IS_LE) ? BYTE8_XOR_LE(0) : BYTE8_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? BYTE8_XOR_LE(0) : BYTE8_XOR_BE(0); break; /* dump opcodes in words from a qword-sized bus */ case 82: - address ^= (info->endianness == CPU_IS_LE) ? WORD2_XOR_LE(0) : WORD2_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? WORD2_XOR_LE(0) : WORD2_XOR_BE(0); break; /* dump opcodes in dwords from a qword-sized bus */ case 84: - address ^= (info->endianness == CPU_IS_LE) ? DWORD_XOR_LE(0) : DWORD_XOR_BE(0); + address ^= (space->endianness == CPU_IS_LE) ? DWORD_XOR_LE(0) : DWORD_XOR_BE(0); break; /* dump opcodes in qwords from a qword-sized bus */ @@ -1769,13 +1740,13 @@ UINT64 debug_read_opcode(const address_space *space, offs_t address, int size, i break; default: - fatalerror("debug_read_opcode: unknown type = %d", info->space[ADDRESS_SPACE_PROGRAM].databytes * 10 + size); + fatalerror("debug_read_opcode: unknown type = %d", space->dbits / 8 * 10 + size); break; } /* get pointer to data */ /* note that we query aligned to the bus width, and then add back the low bits */ - lowbits_mask = info->space[ADDRESS_SPACE_PROGRAM].databytes - 1; + lowbits_mask = space->dbits / 8 - 1; if (!arg) ptr = memory_decrypted_read_ptr(space, address & ~lowbits_mask); else @@ -1832,11 +1803,11 @@ static void debug_cpu_exit(running_machine *machine) debug_cpu_breakpoint_clear(machine, info->bplist->index); /* loop over all address spaces */ - for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) + for (spacenum = 0; spacenum < ARRAY_LENGTH(info->wplist); spacenum++) { /* free all watchpoints */ - while (info->space[spacenum].wplist != NULL) - debug_cpu_watchpoint_clear(machine, info->space[spacenum].wplist->index); + while (info->wplist[spacenum] != NULL) + debug_cpu_watchpoint_clear(machine, info->wplist[spacenum]->index); } } @@ -1933,6 +1904,8 @@ static void perform_trace(cpu_debug_data *info) /* if no more than 1 hit, process normally */ if (count <= 1) { + const address_space *space = cpu_get_address_space(info->device, ADDRESS_SPACE_PROGRAM); + /* if we just finished looping, indicate as much */ if (info->trace.loops != 0) fprintf(info->trace.file, "\n (loops for %d instructions)\n\n", info->trace.loops); @@ -1943,7 +1916,7 @@ static void perform_trace(cpu_debug_data *info) debug_console_execute_command(info->device->machine, info->trace.action, 0); /* print the address */ - offset = sprintf(buffer, "%0*X: ", info->space[ADDRESS_SPACE_PROGRAM].logchars, pc); + offset = sprintf(buffer, "%0*X: ", space->logaddrchars, pc); /* print the disassembly */ dasmresult = dasm_wrapped(info->device, &buffer[offset], pc); @@ -2132,7 +2105,7 @@ static void watchpoint_update_flags(const address_space *space) enableread = TRUE; /* see if there are any enabled breakpoints */ - for (wp = info->space[space->spacenum].wplist; wp != NULL; wp = wp->next) + for (wp = info->wplist[space->spacenum]; wp != NULL; wp = wp->next) if (wp->enabled) { if (wp->type & WATCHPOINT_READ) @@ -2169,7 +2142,7 @@ static void watchpoint_check(const address_space *space, int type, offs_t addres /* adjust address, size & value_to_write based on mem_mask. */ if (mem_mask != 0) { - int bus_size = info->space[space->spacenum].databytes; + int bus_size = space->dbits / 8; int address_offset = 0; while (address_offset < bus_size && (mem_mask & 0xff) == 0) @@ -2185,7 +2158,7 @@ static void watchpoint_check(const address_space *space, int type, offs_t addres mem_mask >>= 8; } - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) address += address_offset; else address += bus_size - size - address_offset; @@ -2197,7 +2170,7 @@ static void watchpoint_check(const address_space *space, int type, offs_t addres global->wpdata = value_to_write; /* see if we match */ - for (wp = info->space[space->spacenum].wplist; wp != NULL; wp = wp->next) + for (wp = info->wplist[space->spacenum]; wp != NULL; wp = wp->next) if (wp->enabled && (wp->type & type) != 0 && address + size > wp->address && address < wp->address + wp->length) /* if we do, evaluate the condition */ @@ -2221,14 +2194,14 @@ static void watchpoint_check(const address_space *space, int type, offs_t addres if (type & WATCHPOINT_WRITE) { - sprintf(buffer, "Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->index, sizes[size], cpu_byte_to_address(space->cpu, space->spacenum, address), cpu_get_pc(space->cpu)); + sprintf(buffer, "Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->index, sizes[size], memory_byte_to_address(space, address), cpu_get_pc(space->cpu)); if (value_to_write >> 32) sprintf(&buffer[strlen(buffer)], " (data=%X%08X)", (UINT32)(value_to_write >> 32), (UINT32)value_to_write); else sprintf(&buffer[strlen(buffer)], " (data=%X)", (UINT32)value_to_write); } else - sprintf(buffer, "Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->index, sizes[size], cpu_byte_to_address(space->cpu, space->spacenum, address), cpu_get_pc(space->cpu)); + sprintf(buffer, "Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->index, sizes[size], memory_byte_to_address(space, address), cpu_get_pc(space->cpu)); debug_console_printf("%s\n", buffer); compute_debug_flags(space->cpu); } @@ -2252,7 +2225,7 @@ static void check_hotspots(const address_space *space, offs_t address) /* see if we have a match in our list */ for (hotindex = 0; hotindex < info->hotspot_count; hotindex++) - if (info->hotspots[hotindex].access == address && info->hotspots[hotindex].pc == pc && info->hotspots[hotindex].spacenum == space->spacenum) + if (info->hotspots[hotindex].access == address && info->hotspots[hotindex].pc == pc && info->hotspots[hotindex].space == space) break; /* if we didn't find any, make a new entry */ @@ -2261,13 +2234,13 @@ static void check_hotspots(const address_space *space, offs_t address) /* if the bottom of the list is over the threshhold, print it */ debug_hotspot_entry *spot = &info->hotspots[info->hotspot_count - 1]; if (spot->count > info->hotspot_threshhold) - debug_console_printf("Hotspot @ %s %08X (PC=%08X) hit %d times (fell off bottom)\n", address_space_names[spot->spacenum], spot->access, spot->pc, spot->count); + debug_console_printf("Hotspot @ %s %08X (PC=%08X) hit %d times (fell off bottom)\n", space->name, spot->access, spot->pc, spot->count); /* move everything else down and insert this one at the top */ memmove(&info->hotspots[1], &info->hotspots[0], sizeof(info->hotspots[0]) * (info->hotspot_count - 1)); info->hotspots[0].access = address; info->hotspots[0].pc = pc; - info->hotspots[0].spacenum = space->spacenum; + info->hotspots[0].space = space; info->hotspots[0].count = 1; } @@ -2293,7 +2266,6 @@ static void check_hotspots(const address_space *space, offs_t address) static UINT32 dasm_wrapped(const device_config *device, char *buffer, offs_t pc) { - const cpu_debug_data *cpuinfo = cpu_get_debug_data(device); const address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM); int maxbytes = cpu_get_max_opcode_bytes(device); UINT8 opbuf[64], argbuf[64]; @@ -2301,7 +2273,7 @@ static UINT32 dasm_wrapped(const device_config *device, char *buffer, offs_t pc) int numbytes; /* fetch the bytes up to the maximum */ - pcbyte = ADDR2BYTE_MASKED(pc, cpuinfo, ADDRESS_SPACE_PROGRAM); + pcbyte = memory_address_to_byte(space, pc) & space->bytemask; for (numbytes = 0; numbytes < maxbytes; numbytes++) { opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, FALSE); @@ -2387,10 +2359,8 @@ static UINT64 expression_read_address_space(const address_space *space, offs_t a if (space != NULL) { - cpu_debug_data *info = cpu_get_debug_data(space->cpu); - /* adjust the address into a byte address */ - address = ADDR2BYTE(address, info, space->spacenum); + address = memory_address_to_byte(space, address); /* switch contexts and do the read */ cpu_push_context(space->cpu); @@ -2418,12 +2388,11 @@ static UINT64 expression_read_program_direct(const address_space *space, int opc if (space != NULL) { - cpu_debug_data *info = cpu_get_debug_data(space->cpu); UINT8 *base; /* adjust the address into a byte address, but not if being called recursively */ if ((opcode & 2) == 0) - address = ADDR2BYTE(address, info, ADDRESS_SPACE_PROGRAM); + address = memory_address_to_byte(space, address); /* call ourself recursively until we are byte-sized */ if (size > 1) @@ -2436,7 +2405,7 @@ static UINT64 expression_read_program_direct(const address_space *space, int opc r1 = expression_read_program_direct(space, opcode | 2, address + halfsize, halfsize); /* assemble based on the target endianness */ - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) result = r0 | (r1 << (8 * halfsize)); else result = r1 | (r0 << (8 * halfsize)); @@ -2446,7 +2415,7 @@ static UINT64 expression_read_program_direct(const address_space *space, int opc else { /* lowmask specified which address bits are within the databus width */ - offs_t lowmask = info->space[ADDRESS_SPACE_PROGRAM].databytes - 1; + offs_t lowmask = space->dbits / 8 - 1; /* get the base of memory, aligned to the address minus the lowbits */ if (opcode & 1) @@ -2457,7 +2426,7 @@ static UINT64 expression_read_program_direct(const address_space *space, int opc /* if we have a valid base, return the appropriate byte */ if (base != NULL) { - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) result = base[BYTE8_XOR_LE(address) & lowmask]; else result = base[BYTE8_XOR_BE(address) & lowmask]; @@ -2598,10 +2567,8 @@ static void expression_write_address_space(const address_space *space, offs_t ad { if (space != NULL) { - const cpu_debug_data *info = cpu_get_debug_data(space->cpu); - /* adjust the address into a byte address */ - address = ADDR2BYTE(address, info, space->spacenum); + address = memory_address_to_byte(space, address); /* switch contexts and do the write */ cpu_push_context(space->cpu); @@ -2626,13 +2593,12 @@ static void expression_write_program_direct(const address_space *space, int opco { if (space != NULL) { - const cpu_debug_data *info = cpu_get_debug_data(space->cpu); debugcpu_private *global = space->machine->debugcpu_data; UINT8 *base; /* adjust the address into a byte address, but not if being called recursively */ if ((opcode & 2) == 0) - address = ADDR2BYTE(address, info, ADDRESS_SPACE_PROGRAM); + address = memory_address_to_byte(space, address); /* call ourself recursively until we are byte-sized */ if (size > 1) @@ -2642,7 +2608,7 @@ static void expression_write_program_direct(const address_space *space, int opco /* break apart based on the target endianness */ halfmask = ~(UINT64)0 >> (64 - 8 * halfsize); - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) { r0 = data & halfmask; r1 = (data >> (8 * halfsize)) & halfmask; @@ -2662,7 +2628,7 @@ static void expression_write_program_direct(const address_space *space, int opco else { /* lowmask specified which address bits are within the databus width */ - offs_t lowmask = info->space[ADDRESS_SPACE_PROGRAM].databytes - 1; + offs_t lowmask = space->dbits / 8 - 1; /* get the base of memory, aligned to the address minus the lowbits */ if (opcode & 1) @@ -2673,7 +2639,7 @@ static void expression_write_program_direct(const address_space *space, int opco /* if we have a valid base, write the appropriate byte */ if (base != NULL) { - if (info->endianness == CPU_IS_LE) + if (space->endianness == CPU_IS_LE) base[BYTE8_XOR_LE(address) & lowmask] = data; else base[BYTE8_XOR_BE(address) & lowmask] = data; diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index fcd648ac7a8..2a3fecb1497 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -62,16 +62,6 @@ -/*************************************************************************** - MACROS -***************************************************************************/ - -#define ADDR2BYTE(val,info,spc) (((val) << (info)->space[spc].addr2byte_lshift) >> (info)->space[spc].addr2byte_rshift) -#define ADDR2BYTE_MASKED(val,info,spc) (ADDR2BYTE(val,info,spc) & (info)->space[spc].logbytemask) -#define BYTE2ADDR(val,info,spc) (((val) << (info)->space[spc].addr2byte_rshift) >> (info)->space[spc].addr2byte_lshift) - - - /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -97,30 +87,12 @@ struct _debug_trace_info }; -typedef struct _debug_space_info debug_space_info; -struct _debug_space_info -{ - const address_space *space; /* pointer to the CPU's address space */ - debug_cpu_watchpoint *wplist; /* list of watchpoints */ - UINT8 databytes; /* width of the data bus, in bytes */ - UINT8 pageshift; /* page shift */ - UINT8 addr2byte_lshift; /* left shift to convert CPU address to a byte value */ - UINT8 addr2byte_rshift; /* right shift to convert CPU address to a byte value */ - UINT8 physchars; /* number of characters to use for physical addresses */ - UINT8 logchars; /* number of characters to use for logical addresses */ - offs_t physaddrmask; /* physical address mask */ - offs_t logaddrmask; /* logical address mask */ - offs_t physbytemask; /* physical byte mask */ - offs_t logbytemask; /* logical byte mask */ -}; - - typedef struct _debug_hotspot_entry debug_hotspot_entry; struct _debug_hotspot_entry { offs_t access; /* access address */ offs_t pc; /* PC of the access */ - int spacenum; /* space where the access occurred */ + const address_space *space; /* space where the access occurred */ UINT32 count; /* number of hits */ }; @@ -131,7 +103,6 @@ struct _cpu_debug_data const device_config *device; /* CPU device object */ symbol_table * symtable; /* symbol table for expression evaluation */ UINT32 flags; /* debugging flags for this CPU */ - UINT8 endianness; /* little or bigendian */ UINT8 opwidth; /* width of an opcode */ offs_t stepaddr; /* step target address for DEBUG_FLAG_STEPPING_OVER */ int stepsleft; /* number of steps left until done */ @@ -147,12 +118,11 @@ struct _cpu_debug_data UINT32 pc_history_index; /* current history index */ int hotspot_count; /* number of hotspots */ int hotspot_threshhold; /* threshhold for the number of hits to print */ - cpu_translate_func translate; /* address translation routine */ cpu_read_func read; /* memory read routine */ cpu_write_func write; /* memory write routine */ cpu_readop_func readop; /* opcode read routine */ debug_instruction_hook_func instrhook; /* per-instruction callback hook */ - debug_space_info space[ADDRESS_SPACES]; /* per-address space info */ + debug_cpu_watchpoint *wplist[ADDRESS_SPACES]; /* watchpoint lists for each address space */ }; diff --git a/src/emu/debug/debugvw.c b/src/emu/debug/debugvw.c index 08cafe29015..3381aa89e7b 100644 --- a/src/emu/debug/debugvw.c +++ b/src/emu/debug/debugvw.c @@ -31,20 +31,56 @@ #define DASM_MAX_BYTES (16) #define MEM_MAX_LINE_WIDTH (1024) +enum _view_notification +{ + VIEW_NOTIFY_NONE, + VIEW_NOTIFY_VISIBLE_CHANGED, + VIEW_NOTIFY_CURSOR_CHANGED +}; +typedef enum _view_notification view_notification; + + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ -/* debug_view_callbacks contains calbacks specific to a given view */ +typedef int (*view_alloc_func)(debug_view *view); +typedef void (*view_free_func)(debug_view *view); +typedef void (*view_update_func)(debug_view *view); +typedef void (*view_notify_func)(debug_view *view, view_notification type); +typedef void (*view_char_func)(debug_view *view, int ch); + + +/* debug_view_callbacks contains internal callbacks specific to a given view */ typedef struct _debug_view_callbacks debug_view_callbacks; struct _debug_view_callbacks { - int (*alloc)(debug_view *); /* allocate memory */ - void (*free)(debug_view *); /* free memory */ - void (*update)(debug_view *); /* update contents */ - void (*getprop)(debug_view *, UINT32, debug_property_info *value); /* get property */ - void (*setprop)(debug_view *, UINT32, debug_property_info value); /* set property */ + view_alloc_func alloc; /* allocate memory */ + view_free_func free; /* free memory */ + view_update_func update; /* update contents */ + view_notify_func notify; /* notify of something changed */ + view_char_func handlechar; /* handle a typed character */ +}; + + +/* debug_view_section contains information about a section of a view */ +typedef struct _debug_view_section debug_view_section; +struct _debug_view_section +{ + INT32 pos; /* starting position */ + INT32 width; /* width of this section */ +}; + + +/* debug view expression contains information about an embedded expression */ +typedef struct _debug_view_expression debug_view_expression; +struct _debug_view_expression +{ + UINT64 result; /* last result from the expression */ + parsed_expression * parsed; /* parsed expression data */ + astring * string; /* copy of the expression string */ + UINT8 dirty; /* true if the expression needs to be re-evaluated */ }; @@ -52,31 +88,31 @@ struct _debug_view_callbacks /* typedef struct _debug_view debug_view -- defined in debugvw.h */ struct _debug_view { - running_machine *machine; /* machine associated with this view */ - debug_view * next; /* link to the next view */ - UINT8 type; /* type of view */ - void * extra_data; /* extra view-specific data */ + /* core view data */ + debug_view * next; /* link to the next view */ + running_machine * machine; /* machine associated with this view */ + UINT8 type; /* type of view */ + void * extra_data; /* extra view-specific data */ debug_view_callbacks cb; /* callback for this view */ - void * osd_private_data; /* OSD-managed private data */ + + /* OSD data */ + debug_view_osd_update_func osdupdate; /* callback for the update */ + void * osdprivate; /* OSD-managed private data */ /* visibility info */ - UINT32 visible_rows; /* number of currently visible rows */ - UINT32 visible_cols; /* number of currently visible columns */ - UINT32 total_rows; /* total number of rows */ - UINT32 total_cols; /* total number of columns */ - UINT32 top_row; /* current top row */ - UINT32 left_col; /* current left column */ - UINT32 supports_cursor; /* does this view support a cursor? */ - UINT32 cursor_visible; /* is the cursor visible? */ - UINT32 cursor_row; /* cursor row */ - UINT32 cursor_col; /* cursor column */ + debug_view_xy visible; /* visible size (in rows and columns) */ + debug_view_xy total; /* total size (in rows and columns) */ + debug_view_xy topleft; /* top-left visible position (in rows and columns) */ + debug_view_xy cursor; /* cursor position */ + UINT8 supports_cursor; /* does this view support a cursor? */ + UINT8 cursor_visible; /* is the cursor visible? */ /* update info */ - UINT8 update_level; /* update level; updates when this hits 0 */ - UINT8 update_pending; /* true if there is a pending update */ - void (*update_func)(debug_view *);/* callback for the update */ - debug_view_char *viewdata; /* current array of view data */ - int viewdata_size; /* number of elements of the viewdata array */ + UINT8 recompute; /* does this view require a recomputation? */ + UINT8 update_level; /* update level; updates when this hits 0 */ + UINT8 update_pending; /* true if there is a pending update */ + debug_view_char * viewdata; /* current array of view data */ + int viewdata_size; /* number of elements of the viewdata array */ }; @@ -84,23 +120,22 @@ struct _debug_view typedef struct _debug_view_register debug_view_register; struct _debug_view_register { - UINT64 lastval; /* last value */ - UINT64 currval; /* current value */ - UINT32 regnum; /* index */ - UINT8 tagstart; /* starting tag char */ - UINT8 taglen; /* number of tag chars */ - UINT8 valstart; /* starting value char */ - UINT8 vallen; /* number of value chars */ + UINT64 lastval; /* last value */ + UINT64 currval; /* current value */ + UINT32 regnum; /* index */ + UINT8 tagstart; /* starting tag char */ + UINT8 taglen; /* number of tag chars */ + UINT8 valstart; /* starting value char */ + UINT8 vallen; /* number of value chars */ }; typedef struct _debug_view_registers debug_view_registers; struct _debug_view_registers { - UINT8 recompute; /* do we need to recompute the layout the next change? */ - UINT8 cpunum; /* target CPU number */ - int divider; /* dividing column */ - UINT64 last_update; /* execution counter at last update */ + const device_config *device; /* CPU device whose registers we are showing */ + int divider; /* dividing column */ + UINT64 last_update; /* execution counter at last update */ debug_view_register reg[MAX_REGS]; /* register data */ }; @@ -109,27 +144,20 @@ struct _debug_view_registers typedef struct _debug_view_disasm debug_view_disasm; struct _debug_view_disasm { - UINT8 recompute; /* do we need to recompute the layout the next change? */ - UINT8 cpunum; /* target CPU number */ - UINT8 right_column; /* right column? */ - UINT32 backwards_steps; /* number of backwards steps */ - UINT32 dasm_width; /* width of the disassembly area */ - UINT8 * last_direct_raw; /* last direct raw value */ - UINT8 * last_direct_decrypted; /* last direct decrypted value */ - UINT32 last_change_count; /* last comment change count */ - offs_t last_pcbyte; /* last PC byte value */ - UINT32 active_address; /* the address cursor_row is pointing to */ - int divider1, divider2; /* left and right divider columns */ - int divider3; /* comment divider column */ - UINT8 live_tracking; /* track the value of the live expression? */ - UINT64 last_result; /* last result from the expression */ - parsed_expression *expression; /* expression to compute */ - char * expression_string; /* copy of the expression string */ - UINT8 expression_dirty; /* true if the expression needs to be re-evaluated */ - UINT32 allocated_rows; /* allocated rows */ - UINT32 allocated_cols; /* allocated columns */ - offs_t * address; /* addresses of the instructions */ - char * dasm; /* disassembled instructions */ + const address_space *space; /* address space whose data we are disassembling */ + disasm_right_column right_column; /* right column contents */ + UINT32 backwards_steps; /* number of backwards steps */ + UINT32 dasm_width; /* width of the disassembly area */ + UINT8 * last_direct_raw; /* last direct raw value */ + UINT8 * last_direct_decrypted; /* last direct decrypted value */ + UINT32 last_change_count; /* last comment change count */ + offs_t last_pcbyte; /* last PC byte value */ + int divider1, divider2; /* left and right divider columns */ + int divider3; /* comment divider column */ + debug_view_expression expression; /* expression-related information */ + debug_view_xy allocated; /* allocated rows/columns */ + offs_t * byteaddress; /* addresses of the instructions */ + char * dasm; /* disassembled instructions */ }; @@ -137,25 +165,19 @@ struct _debug_view_disasm typedef struct _debug_view_memory debug_view_memory; struct _debug_view_memory { - UINT8 recompute; /* do we need to recompute the layout the next change? */ - UINT8 cpunum; /* target CPU number */ - int divider1, divider2; /* left and right divider columns */ - UINT8 spacenum; /* target address space */ - UINT8 bytes_per_chunk; /* bytes per unit */ - UINT16 chunks_displayed; /* number of chunks displayed per line */ - UINT8 reverse_view; /* reverse-endian view? */ - UINT8 ascii_view; /* display ASCII characters? */ - UINT8 live_tracking; /* track the value of the live expression? */ - UINT8 byte_offset; /* byte offset within each row */ - UINT8 no_translation; /* don't run addresses through the cpu translation hook */ - UINT64 last_result; /* last result from the expression */ - parsed_expression *expression; /* expression to compute */ - char * expression_string; /* copy of the expression string */ - UINT8 expression_dirty; /* true if the expression needs to be re-evaluated */ - void * raw_base; /* base of raw memory view (overrides CPU/space) */ - UINT32 raw_length; /* length of raw memory view */ - UINT8 raw_offset_xor; /* xor to apply to offsets */ - UINT8 raw_little_endian; /* little endian data? */ + const address_space *space; /* address space whose data we are disassembling */ + memory_view_raw raw; /* raw memory data */ + debug_view_expression expression; /* expression describing the start address */ + UINT32 chunks_per_row; /* number of chunks displayed per line */ + UINT8 bytes_per_chunk; /* bytes per chunk */ + UINT8 reverse_view; /* reverse-endian view? */ + UINT8 ascii_view; /* display ASCII characters? */ + UINT8 no_translation; /* don't run addresses through the cpu translation hook */ + debug_view_section section[3]; /* (derived) 3 sections to manage */ + offs_t maxaddr; /* (derived) maximum address to display */ + UINT32 bytes_per_row; /* (derived) number of bytes displayed per line */ + UINT32 byte_offset; /* (derived) offset of starting visible byte */ + char addrformat[10]; /* (derived) format string to use to print addresses */ }; @@ -163,9 +185,18 @@ struct _debug_view_memory typedef struct _debug_view_textbuf debug_view_textbuf; struct _debug_view_textbuf { - text_buffer * textbuf; /* pointer to the text buffer */ - UINT8 at_bottom; /* are we tracking new stuff being added? */ - UINT32 topseq; /* sequence number of the top line */ + text_buffer * textbuf; /* pointer to the text buffer */ + UINT8 at_bottom; /* are we tracking new stuff being added? */ + UINT32 topseq; /* sequence number of the top line */ +}; + + +/* memory_view_pos contains positioning data for memory views */ +typedef struct _memory_view_pos memory_view_pos; +struct _memory_view_pos +{ + UINT8 spacing; /* spacing between each entry */ + UINT8 shift[24]; /* shift for each character */ }; @@ -176,56 +207,118 @@ struct _debug_view_textbuf static debug_view *first_view; +static const memory_view_pos memory_pos_table[9] = +{ + /* 0 bytes per chunk: */ { 0, { 0 } }, + /* 1 byte per chunk: 00 11 22 33 44 55 66 77 */ { 3, { 0x04, 0x00, 0x80 } }, + /* 2 bytes per chunk: 0011 2233 4455 6677 */ { 6, { 0x8c, 0x0c, 0x08, 0x04, 0x00, 0x80 } }, + /* 3 bytes per chunk: */ { 0, { 0 } }, + /* 4 bytes per chunk: 00112233 44556677 */ { 12, { 0x9c, 0x9c, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80 } }, + /* 5 bytes per chunk: */ { 0, { 0 } }, + /* 6 bytes per chunk: */ { 0, { 0 } }, + /* 7 bytes per chunk: */ { 0, { 0 } }, + /* 8 bytes per chunk: 0011223344556677 */ { 24, { 0xbc, 0xbc, 0xbc, 0xbc, 0x3c, 0x38, 0x34, 0x30, 0x2c, 0x28, 0x24, 0x20, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80, 0x80, 0x80 } } +}; + /*************************************************************************** FUNCTION PROTOTYPES ***************************************************************************/ -static int console_alloc(debug_view *view); +static void debug_view_exit(running_machine *machine); -static int log_alloc(debug_view *view); +static int textbuf_view_alloc(debug_view *view, text_buffer *textbuf); +static void textbuf_view_free(debug_view *view); +static void textbuf_view_notify(debug_view *view, view_notification type); +static void textbuf_view_update(debug_view *view); -static int registers_alloc(debug_view *view); -static void registers_free(debug_view *view); -static void registers_update(debug_view *view); -static void registers_getprop(debug_view *view, UINT32 property, debug_property_info *value); -static void registers_setprop(debug_view *view, UINT32 property, debug_property_info value); +static int console_view_alloc(debug_view *view); -static int disasm_alloc(debug_view *view); -static void disasm_free(debug_view *view); -static void disasm_update(debug_view *view); -static void disasm_getprop(debug_view *view, UINT32 property, debug_property_info *value); -static void disasm_setprop(debug_view *view, UINT32 property, debug_property_info value); +static int log_view_alloc(debug_view *view); -static int memory_alloc(debug_view *view); -static void memory_free(debug_view *view); -static void memory_update(debug_view *view); -static void memory_getprop(debug_view *view, UINT32 property, debug_property_info *value); -static void memory_setprop(debug_view *view, UINT32 property, debug_property_info value); +static int registers_view_alloc(debug_view *view); +static void registers_view_free(debug_view *view); +static void registers_view_update(debug_view *view); -static int textbuf_alloc(debug_view *view, text_buffer *textbuf); -static void textbuf_free(debug_view *view); -static void textbuf_update(debug_view *view); -static void textbuf_getprop(debug_view *view, UINT32 property, debug_property_info *value); -static void textbuf_setprop(debug_view *view, UINT32 property, debug_property_info value); +static int disasm_view_alloc(debug_view *view); +static void disasm_view_free(debug_view *view); +static void disasm_view_notify(debug_view *view, view_notification type); +static void disasm_view_update(debug_view *view); +static void disasm_view_char(debug_view *view, int chval); + +static int memory_view_alloc(debug_view *view); +static void memory_view_free(debug_view *view); +static void memory_view_notify(debug_view *view, view_notification type); +static void memory_view_update(debug_view *view); +static void memory_view_char(debug_view *view, int chval); +static void memory_view_recompute(debug_view *view); +static int memory_view_needs_recompute(debug_view *view); +static void memory_view_get_cursor_pos(debug_view *view, offs_t *address, UINT8 *shift); +static void memory_view_set_cursor_pos(debug_view *view, offs_t address, UINT8 shift); +static UINT64 memory_view_read(debug_view_memory *memdata, UINT8 size, offs_t offs); +static void memory_view_write(debug_view_memory *memdata, UINT8 size, offs_t offs, UINT64 data); static const debug_view_callbacks callback_table[] = { - { NULL, NULL, NULL, NULL, NULL }, - { console_alloc, textbuf_free, textbuf_update, textbuf_getprop, textbuf_setprop }, - { registers_alloc, registers_free, registers_update, registers_getprop, registers_setprop }, - { disasm_alloc, disasm_free, disasm_update, disasm_getprop, disasm_setprop }, - { memory_alloc, memory_free, memory_update, memory_getprop, memory_setprop }, - { log_alloc, textbuf_free, textbuf_update, textbuf_getprop, textbuf_setprop } + { NULL, NULL, NULL, NULL, NULL }, + { console_view_alloc, textbuf_view_free, textbuf_view_update, textbuf_view_notify, NULL }, + { registers_view_alloc, registers_view_free, registers_view_update, NULL, NULL }, + { disasm_view_alloc, disasm_view_free, disasm_view_update, disasm_view_notify, disasm_view_char }, + { memory_view_alloc, memory_view_free, memory_view_update, memory_view_notify, memory_view_char }, + { log_view_alloc, textbuf_view_free, textbuf_view_update, textbuf_view_notify, NULL } }; /*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ - Initialization and shutdown +/*------------------------------------------------- + in_section - return TRUE if the given X + coordinate is within a section +-------------------------------------------------*/ +INLINE int in_section(int x, const debug_view_section *section) +{ + return (x >= section->pos && x < section->pos + section->width); +} + + +/*------------------------------------------------- + adjust_visible_x_for_cursor - adjust a view's + visible X position to ensure the cursor is + visible +-------------------------------------------------*/ + +INLINE void adjust_visible_x_for_cursor(debug_view *view) +{ + if (view->cursor.x < view->topleft.x) + view->topleft.x = view->cursor.x; + else if (view->cursor.x >= view->topleft.x + view->visible.x - 1) + view->topleft.x = view->cursor.x - view->visible.x + 2; +} + + +/*------------------------------------------------- + adjust_visible_y_for_cursor - adjust a view's + visible Y position to ensure the cursor is + visible +-------------------------------------------------*/ + +INLINE void adjust_visible_y_for_cursor(debug_view *view) +{ + if (view->cursor.y < view->topleft.y) + view->topleft.y = view->cursor.y; + else if (view->cursor.y >= view->topleft.y + view->visible.y - 1) + view->topleft.y = view->cursor.y - view->visible.y + 2; +} + + + +/*************************************************************************** + INITIALIZATION AND SHUTDOWN ***************************************************************************/ /*------------------------------------------------- @@ -244,7 +337,7 @@ void debug_view_init(running_machine *machine) debug_view_exit - exits the view system -------------------------------------------------*/ -void debug_view_exit(running_machine *machine) +static void debug_view_exit(running_machine *machine) { /* kill all the views */ while (first_view != NULL) @@ -254,9 +347,7 @@ void debug_view_exit(running_machine *machine) /*************************************************************************** - - View creation/deletion - + VIEW CREATION/DELETION ***************************************************************************/ /*------------------------------------------------- @@ -264,13 +355,15 @@ void debug_view_exit(running_machine *machine) view -------------------------------------------------*/ -debug_view *debug_view_alloc(running_machine *machine, int type) +debug_view *debug_view_alloc(running_machine *machine, int type, debug_view_osd_update_func osdupdate, void *osdprivate) { debug_view *view; + + assert(type >= 0 && type < ARRAY_LENGTH(callback_table)); /* allocate memory for the view */ view = malloc(sizeof(*view)); - if (!view) + if (view == NULL) return NULL; memset(view, 0, sizeof(*view)); @@ -278,24 +371,24 @@ debug_view *debug_view_alloc(running_machine *machine, int type) view->machine = machine; view->type = type; view->cb = callback_table[type]; + view->osdupdate = osdupdate; + view->osdprivate = osdprivate; /* set up some reasonable defaults */ - view->visible_rows = 10; - view->visible_cols = 10; - view->total_rows = 10; - view->total_cols = 10; + view->visible.x = view->total.x = 10; + view->visible.y = view->total.y = 10; /* allocate memory for the buffer */ - view->viewdata_size = view->visible_rows*view->visible_cols; + view->viewdata_size = view->visible.y * view->visible.x; view->viewdata = malloc(sizeof(view->viewdata[0]) * view->viewdata_size); - if (!view->viewdata) + if (view->viewdata == NULL) { free(view); return NULL; } /* allocate extra memory */ - if (view->cb.alloc && !(*view->cb.alloc)(view)) + if (view->cb.alloc != NULL && !(*view->cb.alloc)(view)) { free(view->viewdata); free(view); @@ -306,6 +399,10 @@ debug_view *debug_view_alloc(running_machine *machine, int type) view->next = first_view; first_view = view; + /* require a recomputation on the first update */ + view->recompute = TRUE; + view->update_pending = TRUE; + return view; } @@ -316,22 +413,19 @@ debug_view *debug_view_alloc(running_machine *machine, int type) void debug_view_free(debug_view *view) { - debug_view *curview, *prevview; + debug_view **viewptr; /* find the view */ - for (prevview = NULL, curview = first_view; curview != NULL; prevview = curview, curview = curview->next) - if (curview == view) + for (viewptr = &first_view; *viewptr != NULL; viewptr = &(*viewptr)->next) + if (*viewptr == view) { /* unlink */ - if (prevview != NULL) - prevview->next = curview->next; - else - first_view = curview->next; + *viewptr = view->next; /* free memory */ - if (view->cb.free) + if (view->cb.free != NULL) (*view->cb.free)(view); - if (view->viewdata) + if (view->viewdata != NULL) free(view->viewdata); free(view); break; @@ -341,220 +435,7 @@ void debug_view_free(debug_view *view) /*************************************************************************** - - Property management - -***************************************************************************/ - -/*------------------------------------------------- - debug_view_get_property - return the value - of a given property --------------------------------------------------*/ - -void debug_view_get_property(debug_view *view, int property, debug_property_info *value) -{ - switch (property) - { - case DVP_VISIBLE_ROWS: - value->i = view->visible_rows; - break; - - case DVP_VISIBLE_COLS: - value->i = view->visible_cols; - break; - - case DVP_TOTAL_ROWS: - value->i = view->total_rows; - break; - - case DVP_TOTAL_COLS: - value->i = view->total_cols; - break; - - case DVP_TOP_ROW: - value->i = view->top_row; - break; - - case DVP_LEFT_COL: - value->i = view->left_col; - break; - - case DVP_UPDATE_CALLBACK: - value->f = (genf *) view->update_func; - break; - - case DVP_VIEW_DATA: - value->p = (void *) view->viewdata; - break; - - case DVP_SUPPORTS_CURSOR: - value->i = view->supports_cursor; - break; - - case DVP_CURSOR_VISIBLE: - value->i = view->cursor_visible; - break; - - case DVP_CURSOR_ROW: - value->i = view->cursor_row; - break; - - case DVP_CURSOR_COL: - value->i = view->cursor_col; - break; - - case DVP_OSD_PRIVATE: - value->p = view->osd_private_data; - break; - - default: - if (view->cb.getprop) - (*view->cb.getprop)(view, property, value); - else - fatalerror("Attempt to get invalid property %d on debug view type %d", property, view->type); - break; - } -} - - -/*------------------------------------------------- - debug_view_set_property - set the value - of a given property --------------------------------------------------*/ - -void debug_view_set_property(debug_view *view, int property, debug_property_info value) -{ - switch (property) - { - case DVP_VISIBLE_ROWS: - if (value.i != view->visible_rows) - { - debug_view_begin_update(view); - view->visible_rows = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_VISIBLE_COLS: - if (value.i != view->visible_cols) - { - debug_view_begin_update(view); - view->visible_cols = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_TOTAL_ROWS: - if (value.i != view->total_rows) - { - debug_view_begin_update(view); - view->total_rows = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_TOTAL_COLS: - if (value.i != view->total_cols) - { - debug_view_begin_update(view); - view->total_cols = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_TOP_ROW: - if (value.i != view->top_row) - { - debug_view_begin_update(view); - view->top_row = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_LEFT_COL: - if (value.i != view->left_col) - { - debug_view_begin_update(view); - view->left_col = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_UPDATE_CALLBACK: - debug_view_begin_update(view); - view->update_func = (void (*)(debug_view *)) value.f; - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - case DVP_VIEW_DATA: - /* read-only */ - break; - - case DVP_SUPPORTS_CURSOR: - /* read-only */ - break; - - case DVP_CURSOR_VISIBLE: - if (value.i != view->cursor_visible) - { - debug_view_begin_update(view); - view->cursor_visible = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_CURSOR_ROW: - if (value.i != view->cursor_row) - { - debug_view_begin_update(view); - view->cursor_row = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - if (view->type == DVT_DISASSEMBLY) - { - debug_view_disasm *dasmdata = view->extra_data; - dasmdata->active_address = dasmdata->address[view->cursor_row]; - } - break; - - case DVP_CURSOR_COL: - if (value.i != view->cursor_col) - { - debug_view_begin_update(view); - view->cursor_col = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_OSD_PRIVATE: - view->osd_private_data = value.p; - break; - - default: - if (view->cb.setprop) - (*view->cb.setprop)(view, property, value); - else - fatalerror("Attempt to set invalid property %d on debug view type %d", property, view->type); - break; - } -} - - - -/*************************************************************************** - - Update management - + UPDATE MANAGEMENT ***************************************************************************/ /*------------------------------------------------- @@ -584,10 +465,10 @@ void debug_view_end_update(debug_view *view) int size; /* no longer pending */ - view->update_pending = 0; + view->update_pending = FALSE; /* resize the viewdata if needed */ - size = view->visible_rows * view->visible_cols; + size = view->visible.x * view->visible.y; if (size > view->viewdata_size) { view->viewdata_size = size; @@ -595,12 +476,12 @@ void debug_view_end_update(debug_view *view) } /* update the view */ - if (view->cb.update) + if (view->cb.update != NULL) (*view->cb.update)(view); /* update the owner */ - if (view->update_func) - (*view->update_func)(view); + if (view->osdupdate != NULL) + (*view->osdupdate)(view, view->osdprivate); } } @@ -650,58 +531,327 @@ void debug_view_update_type(int type) /*************************************************************************** - - Console view - + STANDARD VIEW PROPERTIES ***************************************************************************/ /*------------------------------------------------- - console_alloc - allocate memory for the log view + debug_view_get_chars - return a pointer to + a 2-dimentional array of characters that + represent the visible area of the view -------------------------------------------------*/ -static int console_alloc(debug_view *view) +const debug_view_char *debug_view_get_chars(debug_view *view) { - return textbuf_alloc(view, debug_console_get_textbuf()); + return view->viewdata; +} + + +/*------------------------------------------------- + debug_view_type_character - type a character + into a view +-------------------------------------------------*/ + +void debug_view_type_character(debug_view *view, int character) +{ + /* if the view has a character handler, forward it on */ + if (view->cb.handlechar != NULL) + (*view->cb.handlechar)(view, character); } /*************************************************************************** - - Log view - + STANDARD VIEW SIZING ***************************************************************************/ /*------------------------------------------------- - log_alloc - allocate memory for the log view + debug_view_get_total_size - return the total + view size in rows and columns -------------------------------------------------*/ -static int log_alloc(debug_view *view) +debug_view_xy debug_view_get_total_size(debug_view *view) { - return textbuf_alloc(view, debug_errorlog_get_textbuf()); + debug_view_begin_update(view); + debug_view_end_update(view); + return view->total; +} + + +/*------------------------------------------------- + debug_view_get_visible_size - return the + visible size in rows and columns +-------------------------------------------------*/ + +debug_view_xy debug_view_get_visible_size(debug_view *view) +{ + debug_view_begin_update(view); + debug_view_end_update(view); + return view->visible; +} + + +/*------------------------------------------------- + debug_view_get_visible_position - return the + top left position of the visible area in rows + and columns +-------------------------------------------------*/ + +debug_view_xy debug_view_get_visible_position(debug_view *view) +{ + debug_view_begin_update(view); + debug_view_end_update(view); + return view->topleft; +} + + +/*------------------------------------------------- + debug_view_set_visible_size - set the visible + size in rows and columns +-------------------------------------------------*/ + +void debug_view_set_visible_size(debug_view *view, debug_view_xy size) +{ + if (size.x != view->visible.x || size.y != view->visible.y) + { + debug_view_begin_update(view); + view->visible = size; + view->update_pending = TRUE; + if (view->cb.notify != NULL) + (*view->cb.notify)(view, VIEW_NOTIFY_VISIBLE_CHANGED); + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + debug_view_set_visible_position - set the + top left position of the visible area in rows + and columns +-------------------------------------------------*/ + +void debug_view_set_visible_position(debug_view *view, debug_view_xy pos) +{ + if (pos.x != view->topleft.x || pos.y != view->topleft.y) + { + debug_view_begin_update(view); + view->topleft = pos; + view->update_pending = TRUE; + if (view->cb.notify != NULL) + (*view->cb.notify)(view, VIEW_NOTIFY_VISIBLE_CHANGED); + debug_view_end_update(view); + } } /*************************************************************************** - - Generic text buffer view - + STANDARD VIEW CURSOR MANAGEMENT ***************************************************************************/ /*------------------------------------------------- - textbuf_alloc - allocate memory for a text - buffer view + debug_view_get_cursor_position - return the + current cursor position as a row and column -------------------------------------------------*/ -static int textbuf_alloc(debug_view *view, text_buffer *textbuf) +debug_view_xy debug_view_get_cursor_position(debug_view *view) +{ + debug_view_begin_update(view); + debug_view_end_update(view); + return view->cursor; +} + + +/*------------------------------------------------- + debug_view_get_cursor_supported - return TRUE + if a cursor is supported for this view type +-------------------------------------------------*/ + +int debug_view_get_cursor_supported(debug_view *view) +{ + debug_view_begin_update(view); + debug_view_end_update(view); + return view->supports_cursor; +} + + +/*------------------------------------------------- + debug_view_get_cursor_visible - return TRUE + if a cursor is currently visible +-------------------------------------------------*/ + +int debug_view_get_cursor_visible(debug_view *view) +{ + debug_view_begin_update(view); + debug_view_end_update(view); + return view->cursor_visible; +} + + +/*------------------------------------------------- + debug_view_set_cursor_position - set the + current cursor position as a row and column +-------------------------------------------------*/ + +void debug_view_set_cursor_position(debug_view *view, debug_view_xy pos) +{ + if (pos.x != view->cursor.x || pos.y != view->cursor.y) + { + debug_view_begin_update(view); + view->cursor = pos; + view->update_pending = TRUE; + if (view->cb.notify != NULL) + (*view->cb.notify)(view, VIEW_NOTIFY_CURSOR_CHANGED); + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + debug_view_set_cursor_visible - set the + visible state of the cursor +-------------------------------------------------*/ + +void debug_view_set_cursor_visible(debug_view *view, int visible) +{ + if (visible != view->cursor_visible) + { + debug_view_begin_update(view); + view->cursor_visible = visible; + view->update_pending = TRUE; + if (view->cb.notify != NULL) + (*view->cb.notify)(view, VIEW_NOTIFY_CURSOR_CHANGED); + debug_view_end_update(view); + } +} + + + +/*************************************************************************** + GENERIC EXPRESSION HANDLING +***************************************************************************/ + +/*------------------------------------------------- + debug_view_expression_alloc - allocate data + for an expression +-------------------------------------------------*/ + +static void debug_view_expression_alloc(debug_view_expression *expression) +{ + expression->string = astring_alloc(); +} + + +/*------------------------------------------------- + debug_view_expression_free - free data + allocated for an expression +-------------------------------------------------*/ + +static void debug_view_expression_free(debug_view_expression *expression) +{ + if (expression->parsed != NULL) + expression_free(expression->parsed); + if (expression->string != NULL) + astring_free(expression->string); +} + + +/*------------------------------------------------- + debug_view_expression_set - set a new + expression string +-------------------------------------------------*/ + +static void debug_view_expression_set(debug_view_expression *expression, const char *string) +{ + astring_cpyc(expression->string, string); + expression->dirty = TRUE; +} + + +/*------------------------------------------------- + debug_view_expression_changed_value - update an + expression and return TRUE if its value has + changed +-------------------------------------------------*/ + +static int debug_view_expression_changed_value(debug_view *view, debug_view_expression *expression, const device_config *cpu) +{ + int changed = expression->dirty; + EXPRERR exprerr; + + /* if dirty, re-evaluate */ + if (expression->dirty) + { + symbol_table *symtable = (cpu != NULL) ? debug_cpu_get_symtable(cpu) : debug_cpu_get_global_symtable(view->machine); + parsed_expression *expr; + + /* parse the new expression */ + exprerr = expression_parse(astring_c(expression->string), symtable, &debug_expression_callbacks, view->machine, &expr); + + /* if it worked, update the expression */ + if (exprerr == EXPRERR_NONE) + { + if (expression->parsed != NULL) + expression_free(expression->parsed); + expression->parsed = expr; + } + } + + /* if we have a parsed expression, evalute it */ + if (expression->parsed != NULL) + { + UINT64 oldresult = expression->result; + + /* recompute the value of the expression */ + exprerr = expression_execute(expression->parsed, &expression->result); + changed |= (expression->result != oldresult); + } + + /* expression no longer dirty by definition */ + expression->dirty = FALSE; + return changed; +} + + + +/*************************************************************************** + TEXT BUFFER-BASED VIEWS +***************************************************************************/ + +/*------------------------------------------------- + console_view_alloc - allocate memory for the + console view +-------------------------------------------------*/ + +static int console_view_alloc(debug_view *view) +{ + return textbuf_view_alloc(view, debug_console_get_textbuf()); +} + + +/*------------------------------------------------- + log_view_alloc - allocate memory for the log + view +-------------------------------------------------*/ + +static int log_view_alloc(debug_view *view) +{ + return textbuf_view_alloc(view, debug_errorlog_get_textbuf()); +} + + +/*------------------------------------------------- + textbuf_view_alloc - allocate memory for a + text buffer-based view +-------------------------------------------------*/ + +static int textbuf_view_alloc(debug_view *view, text_buffer *textbuf) { debug_view_textbuf *textdata; /* allocate memory */ textdata = malloc(sizeof(*textdata)); - if (!textdata) - return 0; + if (textdata == NULL) + return FALSE; memset(textdata, 0, sizeof(*textdata)); /* by default we track live */ @@ -710,40 +860,42 @@ static int textbuf_alloc(debug_view *view, text_buffer *textbuf) /* stash the extra data pointer */ view->extra_data = textdata; - return 1; + return TRUE; } /*------------------------------------------------- - textbuf_free - free memory for the log view + textbuf_view_free - free memory for a text + buffer-based view -------------------------------------------------*/ -static void textbuf_free(debug_view *view) +static void textbuf_view_free(debug_view *view) { debug_view_textbuf *textdata = view->extra_data; /* free any memory we callocated */ - if (textdata) + if (textdata != NULL) free(textdata); view->extra_data = NULL; } /*------------------------------------------------- - textbuf_update - update the log view + textbuf_view_update - update a text buffer- + based view -------------------------------------------------*/ -static void textbuf_update(debug_view *view) +static void textbuf_view_update(debug_view *view) { debug_view_textbuf *textdata = view->extra_data; debug_view_char *dest = view->viewdata; UINT32 curseq = 0, row; /* update the console info */ - view->total_rows = text_buffer_num_lines(textdata->textbuf); - view->total_cols = text_buffer_max_width(textdata->textbuf); - if (view->total_cols < 80) - view->total_cols = 80; + view->total.x = text_buffer_max_width(textdata->textbuf); + view->total.y = text_buffer_num_lines(textdata->textbuf); + if (view->total.x < 80) + view->total.x = 80; /* determine the starting sequence number */ if (!textdata->at_bottom) @@ -754,16 +906,16 @@ static void textbuf_update(debug_view *view) } if (textdata->at_bottom) { - curseq = text_buffer_line_index_to_seqnum(textdata->textbuf, view->total_rows - 1); - if (view->total_rows < view->visible_rows) - curseq -= view->total_rows - 1; + curseq = text_buffer_line_index_to_seqnum(textdata->textbuf, view->total.y - 1); + if (view->total.y < view->visible.y) + curseq -= view->total.y - 1; else - curseq -= view->visible_rows - 1; + curseq -= view->visible.y - 1; } - view->top_row = curseq - text_buffer_line_index_to_seqnum(textdata->textbuf, 0); + view->topleft.y = curseq - text_buffer_line_index_to_seqnum(textdata->textbuf, 0); /* loop over visible rows */ - for (row = 0; row < view->visible_rows; row++) + for (row = 0; row < view->visible.y; row++) { const char *line = text_buffer_get_seqnum_line(textdata->textbuf, curseq++); UINT32 col = 0; @@ -772,10 +924,10 @@ static void textbuf_update(debug_view *view) if (line != NULL) { size_t len = strlen(line); - UINT32 effcol = view->left_col; + UINT32 effcol = view->topleft.x; /* copy data */ - while (col < view->visible_cols && effcol < len) + while (col < view->visible.x && effcol < len) { dest->byte = line[effcol++]; dest->attrib = DCA_NORMAL; @@ -785,7 +937,7 @@ static void textbuf_update(debug_view *view) } /* fill the rest with blanks */ - while (col < view->visible_cols) + while (col < view->visible.x) { dest->byte = ' '; dest->attrib = DCA_NORMAL; @@ -797,123 +949,74 @@ static void textbuf_update(debug_view *view) /*------------------------------------------------- - textbuf_getprop - return the value - of a given property + textbuf_view_notify - handle notification of + updates to visible area -------------------------------------------------*/ -static void textbuf_getprop(debug_view *view, UINT32 property, debug_property_info *value) +static void textbuf_view_notify(debug_view *view, view_notification type) { debug_view_textbuf *textdata = view->extra_data; - switch (property) + if (type == VIEW_NOTIFY_VISIBLE_CHANGED) { - case DVP_TEXTBUF_LINE_LOCK: - value->i = textdata->at_bottom ? (UINT32)-1 : textdata->topseq - text_buffer_line_index_to_seqnum(textdata->textbuf, 0); - break; - - default: - fatalerror("Attempt to get invalid property %d on debug view type %d", property, view->type); - break; - } -} - - -/*------------------------------------------------- - textbuf_setprop - set the value - of a given property --------------------------------------------------*/ - -static void textbuf_setprop(debug_view *view, UINT32 property, debug_property_info value) -{ - debug_view_textbuf *textdata = view->extra_data; - - switch (property) - { - case DVP_TEXTBUF_LINE_LOCK: - if (value.i == (UINT32)-1) - { - if (!textdata->at_bottom) - { - debug_view_begin_update(view); - textdata->at_bottom = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - } - else - { - UINT32 seq = text_buffer_line_index_to_seqnum(textdata->textbuf, value.i); - if (seq != textdata->topseq || textdata->at_bottom) - { - debug_view_begin_update(view); - textdata->topseq = seq; - textdata->at_bottom = FALSE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - } - break; - - default: - fatalerror("Attempt to set invalid property %d on debug view type %d", property, view->type); - break; + /* if the bottom line is visible, just track the bottom */ + textdata->at_bottom = (view->total.y >= view->topleft.y && view->total.y <= view->topleft.y + view->visible.y); + + /* otherwise, track the seqence number of the top line */ + if (!textdata->at_bottom) + textdata->topseq = text_buffer_line_index_to_seqnum(textdata->textbuf, view->topleft.y); } } /*************************************************************************** - - Registers view - + REGISTERS VIEW ***************************************************************************/ /*------------------------------------------------- - registers_alloc - allocate memory for the + registers_view_alloc - allocate memory for the registers view -------------------------------------------------*/ -static int registers_alloc(debug_view *view) +static int registers_view_alloc(debug_view *view) { debug_view_registers *regdata; /* allocate memory */ regdata = malloc(sizeof(*regdata)); - if (!regdata) - return 0; + if (regdata == NULL) + return FALSE; memset(regdata, 0, sizeof(*regdata)); - /* initialize */ - regdata->recompute = TRUE; - /* stash the extra data pointer */ view->extra_data = regdata; - return 1; + return TRUE; } /*------------------------------------------------- - registers_free - free memory for the + registers_view_free - free memory for the registers view -------------------------------------------------*/ -static void registers_free(debug_view *view) +static void registers_view_free(debug_view *view) { debug_view_registers *regdata = view->extra_data; /* free any memory we callocated */ - if (regdata) + if (regdata != NULL) free(regdata); view->extra_data = NULL; } /*------------------------------------------------- - add_register - adds a register to the - registers view + registers_view_add_register - adds a register + to the registers view -------------------------------------------------*/ -static void add_register(debug_view *view, int regnum, const char *str) +static void registers_view_add_register(debug_view *view, int regnum, const char *str) { debug_view_registers *regdata = view->extra_data; int tagstart, taglen, valstart, vallen; @@ -922,7 +1025,7 @@ static void add_register(debug_view *view, int regnum, const char *str) colon = strchr(str, ':'); /* if no colon, mark everything as tag */ - if (!colon) + if (colon == NULL) { tagstart = 0; taglen = (int)strlen(str); @@ -952,96 +1055,101 @@ static void add_register(debug_view *view, int regnum, const char *str) valstart++, vallen--; /* note the register number and info */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = cpu_get_reg(Machine->cpu[regdata->cpunum], regnum); - regdata->reg[view->total_rows].regnum = regnum; - regdata->reg[view->total_rows].tagstart = tagstart; - regdata->reg[view->total_rows].taglen = taglen; - regdata->reg[view->total_rows].valstart = valstart; - regdata->reg[view->total_rows].vallen = vallen; - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = cpu_get_reg(regdata->device, regnum); + regdata->reg[view->total.y].regnum = regnum; + regdata->reg[view->total.y].tagstart = tagstart; + regdata->reg[view->total.y].taglen = taglen; + regdata->reg[view->total.y].valstart = valstart; + regdata->reg[view->total.y].vallen = vallen; + view->total.y++; /* adjust the divider and total cols, if necessary */ regdata->divider = MAX(regdata->divider, 1 + taglen + 1); - view->total_cols = MAX(view->total_cols, 1 + taglen + 2 + vallen + 1); + view->total.x = MAX(view->total.x, 1 + taglen + 2 + vallen + 1); } /*------------------------------------------------- - registers_recompute - recompute all info + registers_view_recompute - recompute all info for the registers view -------------------------------------------------*/ -static void registers_recompute(debug_view *view) +static void registers_view_recompute(debug_view *view) { debug_view_registers *regdata = view->extra_data; - const int *list = cpu_get_debug_register_list(Machine->cpu[regdata->cpunum]); int regnum, maxtaglen, maxvallen; + const int *list; + + /* if no CPU, reset to the first one */ + if (regdata->device == NULL) + regdata->device = view->machine->cpu[0]; + list = cpu_get_debug_register_list(regdata->device); /* reset the view parameters */ - view->top_row = 0; - view->left_col = 0; - view->total_rows = 0; - view->total_cols = 0; + view->topleft.y = 0; + view->topleft.x = 0; + view->total.y = 0; + view->total.x = 0; regdata->divider = 0; /* add a cycles entry: cycles:99999999 */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = 0; - regdata->reg[view->total_rows].regnum = MAX_REGS + 1; - regdata->reg[view->total_rows].tagstart = 0; - regdata->reg[view->total_rows].taglen = 6; - regdata->reg[view->total_rows].valstart = 7; - regdata->reg[view->total_rows].vallen = 8; - maxtaglen = regdata->reg[view->total_rows].taglen; - maxvallen = regdata->reg[view->total_rows].vallen; - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = 0; + regdata->reg[view->total.y].regnum = MAX_REGS + 1; + regdata->reg[view->total.y].tagstart = 0; + regdata->reg[view->total.y].taglen = 6; + regdata->reg[view->total.y].valstart = 7; + regdata->reg[view->total.y].vallen = 8; + maxtaglen = regdata->reg[view->total.y].taglen; + maxvallen = regdata->reg[view->total.y].vallen; + view->total.y++; /* add a beam entry: beamx:123 */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = 0; - regdata->reg[view->total_rows].regnum = MAX_REGS + 2; - regdata->reg[view->total_rows].tagstart = 0; - regdata->reg[view->total_rows].taglen = 5; - regdata->reg[view->total_rows].valstart = 6; - regdata->reg[view->total_rows].vallen = 3; - maxtaglen = MAX(maxtaglen, regdata->reg[view->total_rows].taglen); - maxvallen = MAX(maxvallen, regdata->reg[view->total_rows].vallen); - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = 0; + regdata->reg[view->total.y].regnum = MAX_REGS + 2; + regdata->reg[view->total.y].tagstart = 0; + regdata->reg[view->total.y].taglen = 5; + regdata->reg[view->total.y].valstart = 6; + regdata->reg[view->total.y].vallen = 3; + maxtaglen = MAX(maxtaglen, regdata->reg[view->total.y].taglen); + maxvallen = MAX(maxvallen, regdata->reg[view->total.y].vallen); + view->total.y++; /* add a beam entry: beamy:456 */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = 0; - regdata->reg[view->total_rows].regnum = MAX_REGS + 3; - regdata->reg[view->total_rows].tagstart = 0; - regdata->reg[view->total_rows].taglen = 5; - regdata->reg[view->total_rows].valstart = 6; - regdata->reg[view->total_rows].vallen = 3; - maxtaglen = MAX(maxtaglen, regdata->reg[view->total_rows].taglen); - maxvallen = MAX(maxvallen, regdata->reg[view->total_rows].vallen); - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = 0; + regdata->reg[view->total.y].regnum = MAX_REGS + 3; + regdata->reg[view->total.y].tagstart = 0; + regdata->reg[view->total.y].taglen = 5; + regdata->reg[view->total.y].valstart = 6; + regdata->reg[view->total.y].vallen = 3; + maxtaglen = MAX(maxtaglen, regdata->reg[view->total.y].taglen); + maxvallen = MAX(maxvallen, regdata->reg[view->total.y].vallen); + view->total.y++; /* add a flags entry: flags:xxxxxxxx */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = 0; - regdata->reg[view->total_rows].regnum = MAX_REGS + 4; - regdata->reg[view->total_rows].tagstart = 0; - regdata->reg[view->total_rows].taglen = 5; - regdata->reg[view->total_rows].valstart = 6; - regdata->reg[view->total_rows].vallen = (UINT32)strlen(cpu_get_flags_string(Machine->cpu[regdata->cpunum])); - maxtaglen = MAX(maxtaglen, regdata->reg[view->total_rows].taglen); - maxvallen = MAX(maxvallen, regdata->reg[view->total_rows].vallen); - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = 0; + regdata->reg[view->total.y].regnum = MAX_REGS + 4; + regdata->reg[view->total.y].tagstart = 0; + regdata->reg[view->total.y].taglen = 5; + regdata->reg[view->total.y].valstart = 6; + regdata->reg[view->total.y].vallen = (UINT32)strlen(cpu_get_flags_string(regdata->device)); + maxtaglen = MAX(maxtaglen, regdata->reg[view->total.y].taglen); + maxvallen = MAX(maxvallen, regdata->reg[view->total.y].vallen); + view->total.y++; /* add a divider entry */ - regdata->reg[view->total_rows].lastval = - regdata->reg[view->total_rows].currval = 0; - regdata->reg[view->total_rows].regnum = MAX_REGS; - view->total_rows++; + regdata->reg[view->total.y].lastval = + regdata->reg[view->total.y].currval = 0; + regdata->reg[view->total.y].regnum = MAX_REGS; + view->total.y++; /* set the current divider and total cols */ regdata->divider = 1 + maxtaglen + 1; - view->total_cols = 1 + maxtaglen + 2 + maxvallen + 1; + view->total.x = 1 + maxtaglen + 2 + maxvallen + 1; /* add all registers into it */ for (regnum = 0; regnum < MAX_REGS; regnum++) @@ -1055,51 +1163,49 @@ static void registers_recompute(debug_view *view) break; /* retrieve the string for this register */ - str = cpu_get_reg_string(Machine->cpu[regdata->cpunum], regid); + str = cpu_get_reg_string(regdata->device, regid); /* did we get a string? */ if (str && str[0] != '\0' && str[0] != '~') - add_register(view, regid, str); + registers_view_add_register(view, regid, str); } /* no longer need to recompute */ - regdata->recompute = FALSE; + view->recompute = FALSE; } /*------------------------------------------------- - registers_update - update the contents of + registers_view_update - update the contents of the register view -------------------------------------------------*/ -static void registers_update(debug_view *view) +static void registers_view_update(debug_view *view) { + const device_config *screen = view->machine->primary_screen; debug_view_registers *regdata = view->extra_data; debug_view_char *dest = view->viewdata; UINT64 total_cycles; UINT32 row, i; - const device_config *screen = Machine->primary_screen; - - /* cannot update if no active CPU */ - if (Machine->activecpu == NULL) - return; - total_cycles = cpu_get_total_cycles(Machine->activecpu); /* if our assumptions changed, revisit them */ - if (regdata->recompute) - registers_recompute(view); + if (view->recompute || regdata->device == NULL) + registers_view_recompute(view); + + /* cannot update if no active CPU */ + total_cycles = cpu_get_total_cycles(regdata->device); /* loop over visible rows */ - for (row = 0; row < view->visible_rows; row++) + for (row = 0; row < view->visible.y; row++) { - UINT32 effrow = view->top_row + row; + UINT32 effrow = view->topleft.y + row; UINT32 col = 0; /* if this visible row is valid, add it to the buffer */ - if (effrow < view->total_rows) + if (effrow < view->total.y) { debug_view_register *reg = ®data->reg[effrow]; - UINT32 effcol = view->left_col; + UINT32 effcol = view->topleft.x; char temp[256], dummy[100]; UINT8 attrib = DCA_NORMAL; UINT32 len = 0; @@ -1114,15 +1220,15 @@ static void registers_update(debug_view *view) { case MAX_REGS: reg->tagstart = reg->valstart = reg->vallen = 0; - reg->taglen = view->total_cols; - for (i = 0; i < view->total_cols; i++) + reg->taglen = view->total.x; + for (i = 0; i < view->total.x; i++) dummy[i] = '-'; dummy[i] = 0; break; case MAX_REGS + 1: - sprintf(dummy, "cycles:%-8d", *cpu_get_icount_ptr(Machine->activecpu)); - reg->currval = *cpu_get_icount_ptr(Machine->activecpu); + sprintf(dummy, "cycles:%-8d", *cpu_get_icount_ptr(regdata->device)); + reg->currval = *cpu_get_icount_ptr(regdata->device); break; case MAX_REGS + 2: @@ -1136,16 +1242,16 @@ static void registers_update(debug_view *view) break; case MAX_REGS + 4: - sprintf(dummy, "flags:%s", cpu_get_flags_string(Machine->activecpu)); + sprintf(dummy, "flags:%s", cpu_get_flags_string(regdata->device)); break; } } else { - data = (char *)cpu_get_reg_string(Machine->cpu[regdata->cpunum], reg->regnum); + data = (char *)cpu_get_reg_string(regdata->device, reg->regnum); if (regdata->last_update != total_cycles) reg->lastval = reg->currval; - reg->currval = cpu_get_reg(Machine->cpu[regdata->cpunum], reg->regnum); + reg->currval = cpu_get_reg(regdata->device, reg->regnum); } /* see if we changed */ @@ -1172,7 +1278,7 @@ static void registers_update(debug_view *view) temp[len] = 0; /* copy data */ - while (col < view->visible_cols && effcol < len) + while (col < view->visible.x && effcol < len) { dest->byte = temp[effcol++]; dest->attrib = attrib | ((effcol <= regdata->divider) ? DCA_ANCILLARY : DCA_NORMAL); @@ -1182,7 +1288,7 @@ static void registers_update(debug_view *view) } /* fill the rest with blanks */ - while (col < view->visible_cols) + while (col < view->visible.x) { dest->byte = ' '; dest->attrib = DCA_NORMAL; @@ -1197,122 +1303,100 @@ static void registers_update(debug_view *view) /*------------------------------------------------- - registers_getprop - return the value - of a given property + registers_view_get_cpu - return the CPU whose + registers are currently displayed -------------------------------------------------*/ -static void registers_getprop(debug_view *view, UINT32 property, debug_property_info *value) +const device_config *registers_view_get_cpu(debug_view *view) { debug_view_registers *regdata = view->extra_data; - - switch (property) - { - case DVP_REGS_CPUNUM: - value->i = regdata->cpunum; - break; - - default: - fatalerror("Attempt to get invalid property %d on debug view type %d", property, view->type); - break; - } + assert(view->type == DVT_REGISTERS); + debug_view_begin_update(view); + debug_view_end_update(view); + return regdata->device; } /*------------------------------------------------- - registers_getprop - set the value - of a given property + registers_view_set_cpu - specify the CPU whose + registers are to be displayed -------------------------------------------------*/ -static void registers_setprop(debug_view *view, UINT32 property, debug_property_info value) +void registers_view_set_cpu(debug_view *view, const device_config *device) { debug_view_registers *regdata = view->extra_data; - - switch (property) + assert(view->type == DVT_REGISTERS); + if (device != regdata->device) { - case DVP_REGS_CPUNUM: - if (value.i != regdata->cpunum) - { - debug_view_begin_update(view); - regdata->cpunum = value.i; - regdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - default: - fatalerror("Attempt to set invalid property %d on debug view type %d", property, view->type); - break; + debug_view_begin_update(view); + regdata->device = device; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); } } /*************************************************************************** - - Disassembly view - + DISASSEMBLY VIEW ***************************************************************************/ /*------------------------------------------------- - disasm_alloc - allocate disasm for the + disasm_view_alloc - allocate disasm for the disassembly view -------------------------------------------------*/ -static int disasm_alloc(debug_view *view) +static int disasm_view_alloc(debug_view *view) { debug_view_disasm *dasmdata; int total_comments = 0; - int i; + int cpunum; /* allocate disasm */ dasmdata = malloc(sizeof(*dasmdata)); - if (!dasmdata) - return 0; + if (dasmdata == NULL) + return FALSE; memset(dasmdata, 0, sizeof(*dasmdata)); + + /* allocate the expression data */ + debug_view_expression_alloc(&dasmdata->expression); /* count the number of comments */ - for (i = 0; i < ARRAY_LENGTH(Machine->cpu); i++) - if (Machine->cpu[i] != NULL) - total_comments += debug_comment_get_count(Machine->cpu[i]); + for (cpunum = 0; cpunum < ARRAY_LENGTH(view->machine->cpu); cpunum++) + if (view->machine->cpu[cpunum] != NULL) + total_comments += debug_comment_get_count(view->machine->cpu[cpunum]); /* initialize */ - dasmdata->recompute = TRUE; - dasmdata->right_column = (total_comments > 0) ? DVP_DASM_RIGHTCOL_COMMENTS : DVP_DASM_RIGHTCOL_RAW; + dasmdata->right_column = (total_comments > 0) ? DASM_RIGHTCOL_COMMENTS : DASM_RIGHTCOL_RAW; dasmdata->backwards_steps = 3; dasmdata->dasm_width = DEFAULT_DASM_WIDTH; - dasmdata->active_address = 0; /* stash the extra data pointer */ - view->total_rows = DEFAULT_DASM_LINES; + view->total.y = DEFAULT_DASM_LINES; view->extra_data = dasmdata; /* we support cursors */ view->supports_cursor = TRUE; - - return 1; + return TRUE; } /*------------------------------------------------- - disasm_free - free disasm for the + disasm_view_free - free disasm for the disassembly view -------------------------------------------------*/ -static void disasm_free(debug_view *view) +static void disasm_view_free(debug_view *view) { debug_view_disasm *dasmdata = view->extra_data; /* free any disasm we callocated */ - if (dasmdata) + if (dasmdata != NULL) { - if (dasmdata->expression) - expression_free(dasmdata->expression); - if (dasmdata->expression_string) - free(dasmdata->expression_string); - if (dasmdata->address) - free(dasmdata->address); - if (dasmdata->dasm) + debug_view_expression_free(&dasmdata->expression); + if (dasmdata->byteaddress != NULL) + free(dasmdata->byteaddress); + if (dasmdata->dasm != NULL) free(dasmdata->dasm); free(dasmdata); } @@ -1321,17 +1405,102 @@ static void disasm_free(debug_view *view) /*------------------------------------------------- - disasm_back_up - back up the specified number - of instructions from the given PC + disasm_view_notify - handle notification of + updates to cursor changes -------------------------------------------------*/ -static offs_t disasm_back_up(int cpunum, const cpu_debug_data *cpuinfo, offs_t startpc, int numinstrs) +static void disasm_view_notify(debug_view *view, view_notification type) { - int minlen = BYTE2ADDR(cpu_get_min_opcode_bytes(cpuinfo->device), cpuinfo, ADDRESS_SPACE_PROGRAM); - int maxlen = BYTE2ADDR(cpu_get_max_opcode_bytes(cpuinfo->device), cpuinfo, ADDRESS_SPACE_PROGRAM); - const address_space *space = cpu_get_address_space(cpuinfo->device, ADDRESS_SPACE_PROGRAM); - UINT32 addrmask = cpuinfo->space[ADDRESS_SPACE_PROGRAM].logaddrmask; - offs_t curpc, lastgoodpc = startpc, temppc; + if (type == VIEW_NOTIFY_CURSOR_CHANGED) + adjust_visible_y_for_cursor(view); +} + + +/*------------------------------------------------- + disasm_view_char - handle a character typed + within the current view +-------------------------------------------------*/ + +static void disasm_view_char(debug_view *view, int chval) +{ + debug_view_disasm *dasmdata = view->extra_data; + debug_view_xy origcursor = view->cursor; + UINT8 end_buffer = 3; + INT32 temp; + + switch (chval) + { + case DCH_UP: + if (view->cursor.y > 0) + view->cursor.y--; + break; + + case DCH_DOWN: + if (view->cursor.y < view->total.y - 1) + view->cursor.y++; + break; + + case DCH_PUP: + temp = view->cursor.y - (view->visible.y - end_buffer); + if (temp < 0) + view->cursor.y = 0; + else + view->cursor.y = temp; + break; + + case DCH_PDOWN: + temp = view->cursor.y + (view->visible.y - end_buffer); + if (temp > view->total.y - 1) + view->cursor.y = view->total.y - 1; + else + view->cursor.y = temp; + break; + + case DCH_HOME: /* set the active column to the PC */ + { + offs_t pc = memory_address_to_byte(dasmdata->space, cpu_get_pc(dasmdata->space->cpu)) & dasmdata->space->logbytemask; + int curline; + + /* figure out which row the pc is on */ + for (curline = 0; curline < dasmdata->allocated.y; curline++) + if (dasmdata->byteaddress[curline] == pc) + view->cursor.y = curline; + break; + } + + case DCH_CTRLHOME: + view->cursor.y = 0; + break; + + case DCH_CTRLEND: + view->cursor.y = view->total.y - 1; + break; + } + + /* send a cursor changed notification */ + if (view->cursor.y != origcursor.y) + { + debug_view_begin_update(view); + disasm_view_notify(view, VIEW_NOTIFY_CURSOR_CHANGED); + view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + disasm_view_find_pc_backwards - back up the + specified numberof instructions from the given + PC +-------------------------------------------------*/ + +static offs_t disasm_view_find_pc_backwards(const address_space *space, offs_t targetpc, int numinstrs) +{ + int minlen = memory_byte_to_address(space, cpu_get_min_opcode_bytes(space->cpu)); + int maxlen = memory_byte_to_address(space, cpu_get_max_opcode_bytes(space->cpu)); + offs_t targetpcbyte = memory_address_to_byte(space, targetpc); + offs_t lastgoodpc = targetpc; + offs_t fillpcbyte, curpc; UINT8 opbuf[1024], argbuf[1024]; char dasmbuffer[100]; @@ -1340,43 +1509,48 @@ static offs_t disasm_back_up(int cpunum, const cpu_debug_data *cpuinfo, offs_t s if (maxlen == 0) maxlen = 1; /* start off numinstrs back */ - curpc = startpc - minlen * numinstrs; - if (curpc > startpc) + curpc = targetpc - minlen * numinstrs; + if (curpc > targetpc) curpc = 0; - /* prefetch the opcode bytes */ - for (temppc = curpc; temppc < startpc; temppc++) - { - opbuf[1000 + temppc - startpc] = debug_read_opcode(space, temppc, 1, FALSE); - argbuf[1000 + temppc - startpc] = debug_read_opcode(space, temppc, 1, TRUE); - } - - /* loop until we hit it */ + /* loop until we find what we are looking for */ + fillpcbyte = targetpcbyte; while (1) { - offs_t testpc, nextcurpc, instlen, instcount = 0; + offs_t curpcbyte = memory_address_to_byte(space, curpc); + offs_t scanpc; + int instcount = 0; + int instlen; + + /* fill the buffer up to the target */ + while (curpcbyte < fillpcbyte) + { + fillpcbyte--; + opbuf[1000 + fillpcbyte - targetpcbyte] = debug_read_opcode(space, fillpcbyte, 1, FALSE); + argbuf[1000 + fillpcbyte - targetpcbyte] = debug_read_opcode(space, fillpcbyte, 1, TRUE); + } /* loop until we get past the target instruction */ - for (testpc = curpc; testpc < startpc; testpc += instlen) + for (scanpc = curpc; scanpc < targetpc; scanpc += instlen) { - /* convert PC to a byte offset */ - offs_t pcbyte = ADDR2BYTE_MASKED(testpc, cpuinfo, ADDRESS_SPACE_PROGRAM); - + offs_t scanpcbyte = memory_address_to_byte(space, scanpc); + offs_t physpcbyte = scanpcbyte; + /* get the disassembly, but only if mapped */ instlen = 1; - if (cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH_DEBUG, &pcbyte)) - instlen = cpu_dasm(cpuinfo->device, dasmbuffer, testpc & addrmask, &opbuf[1000 + testpc - startpc], &argbuf[1000 + testpc - startpc]) & DASMFLAG_LENGTHMASK; + if (memory_address_physical(space, TRANSLATE_FETCH, &physpcbyte)) + instlen = cpu_dasm(space->cpu, dasmbuffer, scanpc, &opbuf[1000 + scanpcbyte - targetpcbyte], &argbuf[1000 + scanpcbyte - targetpcbyte]) & DASMFLAG_LENGTHMASK; /* count this one */ instcount++; } - /* if we ended up right on startpc, this is a good candidate */ - if (testpc == startpc && instcount <= numinstrs) + /* if we ended up right on targetpc, this is a good candidate */ + if (scanpc == targetpc && instcount <= numinstrs) lastgoodpc = curpc; /* we're also done if we go back too far */ - if (startpc - curpc >= numinstrs * maxlen) + if (targetpc - curpc >= numinstrs * maxlen) break; /* and if we hit 0, we're done */ @@ -1384,19 +1558,9 @@ static offs_t disasm_back_up(int cpunum, const cpu_debug_data *cpuinfo, offs_t s break; /* back up one more and try again */ - nextcurpc = curpc - minlen; - if (nextcurpc > startpc) - nextcurpc = 0; - - /* prefetch the opcode bytes */ - for (temppc = nextcurpc; temppc < curpc; temppc++) - { - opbuf[1000 + temppc - startpc] = debug_read_opcode(space, temppc, 1, FALSE); - argbuf[1000 + temppc - startpc] = debug_read_opcode(space, temppc, 1, TRUE); - } - - /* update curpc once we're done fetching */ - curpc = nextcurpc; + curpc -= minlen; + if (curpc > targetpc) + curpc = 0; } return lastgoodpc; @@ -1404,13 +1568,12 @@ static offs_t disasm_back_up(int cpunum, const cpu_debug_data *cpuinfo, offs_t s /*------------------------------------------------- - disasm_generate_bytes - generate the opcode - byte values + disasm_view_generate_bytes - generate the + opcode byte values -------------------------------------------------*/ -static void disasm_generate_bytes(offs_t pcbyte, int numbytes, const cpu_debug_data *cpuinfo, int minbytes, char *string, int maxchars, int encrypted) +static void disasm_view_generate_bytes(const address_space *space, offs_t pcbyte, int numbytes, int minbytes, char *string, int maxchars, int encrypted) { - const address_space *space = cpu_get_address_space(cpuinfo->device, ADDRESS_SPACE_PROGRAM); int byte, offset = 0; UINT64 val; @@ -1438,9 +1601,11 @@ static void disasm_generate_bytes(offs_t pcbyte, int numbytes, const cpu_debug_d break; case 8: - val = debug_read_opcode(space, pcbyte, 8, FALSE); if (maxchars >= 16) + { + val = debug_read_opcode(space, pcbyte, 8, FALSE); offset = sprintf(string, "%08X%08X", (UINT32)(val >> 32), (UINT32)val); + } for (byte = 8; byte < numbytes && offset + 17 < maxchars; byte += 8) { val = debug_read_opcode(space, pcbyte + byte, 8, encrypted); @@ -1449,7 +1614,7 @@ static void disasm_generate_bytes(offs_t pcbyte, int numbytes, const cpu_debug_d break; default: - fatalerror("disasm_generate_bytes: unknown size = %d", minbytes); + fatalerror("disasm_view_generate_bytes: unknown size = %d", minbytes); break; } @@ -1461,89 +1626,80 @@ static void disasm_generate_bytes(offs_t pcbyte, int numbytes, const cpu_debug_d /*------------------------------------------------- - disasm_recompute - recompute selected info + disasm_view_recompute - recompute selected info for the disassembly view -------------------------------------------------*/ -static int disasm_recompute(debug_view *view, offs_t pc, int startline, int lines) +static int disasm_view_recompute(debug_view *view, offs_t pc, int startline, int lines) { debug_view_disasm *dasmdata = view->extra_data; - const cpu_debug_data *cpuinfo = cpu_get_debug_data(Machine->cpu[dasmdata->cpunum]); - const address_space *space = cpu_get_address_space(cpuinfo->device, ADDRESS_SPACE_PROGRAM); - int chunksize, minbytes, maxbytes, maxbytes_clamped; + const address_space *space = dasmdata->space; + int minbytes, maxbytes, maxbytes_clamped; int changed = FALSE; - UINT32 addrmask; int line; - /* switch to the context of the CPU in question */ - addrmask = cpuinfo->space[ADDRESS_SPACE_PROGRAM].logaddrmask; - /* determine how many characters we need for an address and set the divider */ - dasmdata->divider1 = 1 + cpuinfo->space[ADDRESS_SPACE_PROGRAM].logchars + 1; + dasmdata->divider1 = 1 + space->logaddrchars + 1; /* assume a fixed number of characters for the disassembly */ dasmdata->divider2 = dasmdata->divider1 + 1 + dasmdata->dasm_width + 1; /* determine how many bytes we might need to display */ - minbytes = cpu_get_min_opcode_bytes(cpuinfo->device); - maxbytes = cpu_get_max_opcode_bytes(cpuinfo->device); + minbytes = cpu_get_min_opcode_bytes(space->cpu); + maxbytes = cpu_get_max_opcode_bytes(space->cpu); /* set the width of the third column according to display mode */ - if (dasmdata->right_column == DVP_DASM_RIGHTCOL_RAW || dasmdata->right_column == DVP_DASM_RIGHTCOL_ENCRYPTED) + if (dasmdata->right_column == DASM_RIGHTCOL_RAW || dasmdata->right_column == DASM_RIGHTCOL_ENCRYPTED) { - chunksize = cpu_get_databus_width(cpuinfo->device, ADDRESS_SPACE_PROGRAM) / 8; - maxbytes_clamped = maxbytes; - if (maxbytes_clamped > DASM_MAX_BYTES) - maxbytes_clamped = DASM_MAX_BYTES; - view->total_cols = dasmdata->divider2 + 1 + 2 * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1; + maxbytes_clamped = MIN(maxbytes, DASM_MAX_BYTES); + view->total.x = dasmdata->divider2 + 1 + 2 * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1; } - else if (dasmdata->right_column == DVP_DASM_RIGHTCOL_COMMENTS) - view->total_cols = dasmdata->divider2 + 1 + 50; /* DEBUG_COMMENT_MAX_LINE_LENGTH */ + else if (dasmdata->right_column == DASM_RIGHTCOL_COMMENTS) + view->total.x = dasmdata->divider2 + 1 + 50; /* DEBUG_COMMENT_MAX_LINE_LENGTH */ else - view->total_cols = dasmdata->divider2 + 1; + view->total.x = dasmdata->divider2 + 1; /* reallocate memory if we don't have enough */ - if (dasmdata->allocated_rows < view->total_rows || dasmdata->allocated_cols < view->total_cols) + if (dasmdata->allocated.x < view->total.x || dasmdata->allocated.y < view->total.y) { /* update our values */ - dasmdata->allocated_rows = view->total_rows; - dasmdata->allocated_cols = view->total_cols; + dasmdata->allocated.x = view->total.x; + dasmdata->allocated.y = view->total.y; /* allocate address array */ - if (dasmdata->address) - free(dasmdata->address); - dasmdata->address = malloc_or_die(sizeof(dasmdata->address[0]) * dasmdata->allocated_rows); + if (dasmdata->byteaddress != NULL) + free(dasmdata->byteaddress); + dasmdata->byteaddress = malloc_or_die(sizeof(dasmdata->byteaddress[0]) * dasmdata->allocated.y); /* allocate disassembly buffer */ - if (dasmdata->dasm) + if (dasmdata->dasm != NULL) free(dasmdata->dasm); - dasmdata->dasm = malloc_or_die(sizeof(dasmdata->dasm[0]) * dasmdata->allocated_rows * dasmdata->allocated_cols); + dasmdata->dasm = malloc_or_die(sizeof(dasmdata->dasm[0]) * dasmdata->allocated.x * dasmdata->allocated.y); } /* iterate over lines */ for (line = 0; line < lines; line++) { - offs_t pcbyte, tempaddr; - char buffer[100]; - int numbytes = 0; int instr = startline + line; - char oldbuf[100]; - char *destbuf = &dasmdata->dasm[instr * dasmdata->allocated_cols]; + char *destbuf = &dasmdata->dasm[instr * dasmdata->allocated.x]; + char buffer[100], oldbuf[100]; + offs_t pcbyte, physpcbyte; + int numbytes = 0; /* convert PC to a byte offset */ - pcbyte = ADDR2BYTE_MASKED(pc, cpuinfo, ADDRESS_SPACE_PROGRAM); + pcbyte = memory_address_to_byte(space, pc) & space->bytemask; /* save a copy of the previous line as a backup if we're only doing one line */ if (lines == 1) - strncpy(oldbuf, destbuf, MIN(sizeof(oldbuf), dasmdata->allocated_cols)); + strncpy(oldbuf, destbuf, MIN(sizeof(oldbuf), dasmdata->allocated.x)); /* convert back and set the address of this instruction */ - dasmdata->address[instr] = pcbyte; // ! This might make more sense as the following : BYTE2ADDR(pcbyte, cpuinfo, ADDRESS_SPACE_PROGRAM); ! - sprintf(&destbuf[0], " %0*X ", cpuinfo->space[ADDRESS_SPACE_PROGRAM].logchars, BYTE2ADDR(pcbyte, cpuinfo, ADDRESS_SPACE_PROGRAM)); + dasmdata->byteaddress[instr] = pcbyte; + sprintf(&destbuf[0], " %0*X ", space->logaddrchars, memory_byte_to_address(space, pcbyte)); - /* make sure we can translate the address */ - tempaddr = pcbyte; - if (cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH_DEBUG, &tempaddr)) + /* make sure we can translate the address, and then disassemble the result */ + physpcbyte = pcbyte; + if (memory_address_physical(space, TRANSLATE_FETCH_DEBUG, &physpcbyte)) { UINT8 opbuf[64], argbuf[64]; @@ -1555,160 +1711,155 @@ static int disasm_recompute(debug_view *view, offs_t pc, int startline, int line } /* disassemble the result */ - pc += numbytes = cpu_dasm(cpuinfo->device, buffer, pc & addrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK; + pc += numbytes = cpu_dasm(space->cpu, buffer, pc & space->logaddrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK; } else - sprintf(buffer, ""); + strcpy(buffer, ""); + /* append the disassembly to the buffer */ sprintf(&destbuf[dasmdata->divider1 + 1], "%-*s ", dasmdata->dasm_width, buffer); - if (dasmdata->right_column == DVP_DASM_RIGHTCOL_RAW || dasmdata->right_column == DVP_DASM_RIGHTCOL_ENCRYPTED) + /* output the right column */ + if (dasmdata->right_column == DASM_RIGHTCOL_RAW || dasmdata->right_column == DASM_RIGHTCOL_ENCRYPTED) { /* get the bytes */ - numbytes = ADDR2BYTE(numbytes, cpuinfo, ADDRESS_SPACE_PROGRAM); - disasm_generate_bytes(pcbyte, numbytes, cpuinfo, minbytes, &destbuf[dasmdata->divider2], dasmdata->allocated_cols - dasmdata->divider2, dasmdata->right_column == DVP_DASM_RIGHTCOL_ENCRYPTED); + numbytes = memory_address_to_byte(space, numbytes); + disasm_view_generate_bytes(space, pcbyte, numbytes, minbytes, &destbuf[dasmdata->divider2], dasmdata->allocated.x - dasmdata->divider2, dasmdata->right_column == DASM_RIGHTCOL_ENCRYPTED); } - else if (dasmdata->right_column == DVP_DASM_RIGHTCOL_COMMENTS) + else if (dasmdata->right_column == DASM_RIGHTCOL_COMMENTS) { - offs_t comment_address = BYTE2ADDR(dasmdata->address[instr], cpuinfo, ADDRESS_SPACE_PROGRAM) ; + offs_t comment_address = memory_byte_to_address(space, dasmdata->byteaddress[instr]); + const char *text; - /* get and add the comment */ - if (debug_comment_get_text(cpuinfo->device, comment_address, debug_comment_get_opcode_crc32(cpuinfo->device, comment_address)) != 0x00) - { - int i ; - char bob[DEBUG_COMMENT_MAX_LINE_LENGTH] ; - char pre[8] ; - - // Stick in the 'comment' symbol - sprintf(pre, "// ") ; - for (i = 0; i < strlen(pre); i++) - destbuf[dasmdata->divider2+i] = pre[i] ; - - // Stick in the comment itself - strcpy(bob, debug_comment_get_text(cpuinfo->device, comment_address, debug_comment_get_opcode_crc32(cpuinfo->device, comment_address))) ; - for (i = 0; i < (dasmdata->allocated_cols - dasmdata->divider2 - strlen(pre) - 1); i++) - destbuf[dasmdata->divider2+i+strlen(pre)] = bob[i] ; - } - else - sprintf(&destbuf[dasmdata->divider2], " "); + /* get and add the comment, if present */ + text = debug_comment_get_text(space->cpu, comment_address, debug_comment_get_opcode_crc32(space->cpu, comment_address)); + if (text != NULL) + sprintf(&destbuf[dasmdata->divider2], "// %.*s", dasmdata->allocated.x - dasmdata->divider2 - 1, text); } /* see if the line changed at all */ - if (lines == 1 && strncmp(oldbuf, destbuf, MIN(sizeof(oldbuf), dasmdata->allocated_cols)) != 0) + if (lines == 1 && strncmp(oldbuf, destbuf, MIN(sizeof(oldbuf), dasmdata->allocated.x)) != 0) changed = TRUE; } /* update opcode base information */ dasmdata->last_direct_decrypted = space->direct.decrypted; dasmdata->last_direct_raw = space->direct.raw; - dasmdata->last_change_count = debug_comment_all_change_count(Machine); + dasmdata->last_change_count = debug_comment_all_change_count(space->machine); /* now longer need to recompute */ - dasmdata->recompute = FALSE; + view->recompute = FALSE; return changed; } /*------------------------------------------------- - disasm_update - update the contents of + disasm_view_update - update the contents of the disassembly view -------------------------------------------------*/ -static void disasm_update(debug_view *view) +static void disasm_view_update(debug_view *view) { debug_view_disasm *dasmdata = view->extra_data; - const cpu_debug_data *cpuinfo = cpu_get_debug_data(Machine->cpu[dasmdata->cpunum]); - const address_space *space = cpu_get_address_space(cpuinfo->device, ADDRESS_SPACE_PROGRAM); - offs_t pc = cpu_get_reg(Machine->cpu[dasmdata->cpunum], REG_PC); - offs_t pcbyte = ADDR2BYTE_MASKED(pc, cpuinfo, ADDRESS_SPACE_PROGRAM); + const address_space *space = dasmdata->space; debug_view_char *dest = view->viewdata; int recomputed_this_time = FALSE; + offs_t pc, pcbyte; EXPRERR exprerr; UINT32 row; + + /* no space, do nothing */ + if (space == NULL) + return; + pc = cpu_get_pc(space->cpu); + pcbyte = memory_address_to_byte(space, pc) & space->logbytemask; /* switch to the CPU's context */ - cpu_push_context(Machine->cpu[dasmdata->cpunum]); + cpu_push_context(space->cpu); /* if our expression is dirty, fix it */ - if (dasmdata->expression_dirty && dasmdata->expression_string) + if (dasmdata->expression.dirty) { parsed_expression *expr; /* parse the new expression */ - exprerr = expression_parse(dasmdata->expression_string, cpu_get_debug_data(Machine->cpu[dasmdata->cpunum])->symtable, &debug_expression_callbacks, Machine, &expr); + exprerr = expression_parse(astring_c(dasmdata->expression.string), debug_cpu_get_symtable(space->cpu), &debug_expression_callbacks, space->machine, &expr); /* if it worked, update the expression */ if (exprerr == EXPRERR_NONE) { - if (dasmdata->expression) - expression_free(dasmdata->expression); - dasmdata->expression = expr; + if (dasmdata->expression.parsed != NULL) + expression_free(dasmdata->expression.parsed); + dasmdata->expression.parsed = expr; } + + /* always recompute if the expression is dirty */ + view->recompute = TRUE; } /* if we're tracking a value, make sure it is visible */ - if (dasmdata->expression && (dasmdata->live_tracking || dasmdata->expression_dirty)) + if (dasmdata->expression.parsed != NULL) { UINT64 result; /* recompute the value of the expression */ - exprerr = expression_execute(dasmdata->expression, &result); - if (exprerr == EXPRERR_NONE && result != dasmdata->last_result) + exprerr = expression_execute(dasmdata->expression.parsed, &result); + if (exprerr == EXPRERR_NONE && result != dasmdata->expression.result) { - offs_t resultbyte = ADDR2BYTE_MASKED(result, cpuinfo, ADDRESS_SPACE_PROGRAM); + offs_t resultbyte = memory_address_to_byte(space, result) & space->bytemask; /* update the result */ - dasmdata->last_result = result; + dasmdata->expression.result = result; /* see if the new result is an address we already have */ - for (row = 0; row < dasmdata->allocated_rows; row++) - if (dasmdata->address[row] == resultbyte) + for (row = 0; row < dasmdata->allocated.y; row++) + if (dasmdata->byteaddress[row] == resultbyte) break; /* if we didn't find it, or if it's really close to the bottom, recompute */ - if (row == dasmdata->allocated_rows || row >= view->total_rows - view->visible_rows) - dasmdata->recompute = TRUE; + if (row == dasmdata->allocated.y || row >= view->total.y - view->visible.y) + view->recompute = TRUE; /* otherwise, if it's not visible, adjust the view so it is */ - else if (row < view->top_row || row >= view->top_row + view->visible_rows - 2) - view->top_row = (row > 3) ? row - 3 : 0; + else if (row < view->topleft.y || row >= view->topleft.y + view->visible.y - 2) + view->topleft.y = (row > 3) ? row - 3 : 0; } /* no longer dirty */ - dasmdata->expression_dirty = FALSE; + dasmdata->expression.dirty = FALSE; } /* if the opcode base has changed, rework things */ if (space->direct.decrypted != dasmdata->last_direct_decrypted || space->direct.raw != dasmdata->last_direct_raw) - dasmdata->recompute = TRUE; + view->recompute = TRUE; /* if the comments have changed, redo it */ - if (dasmdata->last_change_count != debug_comment_all_change_count(Machine)) - dasmdata->recompute = TRUE; + if (dasmdata->last_change_count != debug_comment_all_change_count(space->machine)) + view->recompute = TRUE; /* if we need to recompute, do it */ recompute: - if (dasmdata->recompute) + if (view->recompute) { - /* determine the addresses of what we will display */ - offs_t backpc = disasm_back_up(dasmdata->cpunum, cpuinfo, (UINT32)dasmdata->last_result, dasmdata->backwards_steps); - /* recompute the view */ - if (dasmdata->last_change_count != debug_comment_all_change_count(Machine)) + if (dasmdata->last_change_count != debug_comment_all_change_count(space->machine)) { /* smoosh us against the left column, but not the top row */ - view->left_col = 0; + view->topleft.x = 0; /* recompute from where we last recomputed! */ - disasm_recompute(view, BYTE2ADDR(dasmdata->address[0], cpuinfo, ADDRESS_SPACE_PROGRAM), 0, view->total_rows); + disasm_view_recompute(view, memory_byte_to_address(space, dasmdata->byteaddress[0]), 0, view->total.y); } else { - /* put ourselves back in the top left */ - view->top_row = 0; - view->left_col = 0; + /* determine the addresses of what we will display */ + offs_t backpc = disasm_view_find_pc_backwards(space, (UINT32)dasmdata->expression.result, dasmdata->backwards_steps); - disasm_recompute(view, backpc, 0, view->total_rows); + /* put ourselves back in the top left */ + view->topleft.y = 0; + view->topleft.x = 0; + + disasm_view_recompute(view, backpc, 0, view->total.y); } recomputed_this_time = TRUE; } @@ -1717,74 +1868,71 @@ recompute: if (pcbyte != dasmdata->last_pcbyte) { /* find the row with the PC on it */ - for (row = 0; row < view->visible_rows; row++) + for (row = 0; row < view->visible.y; row++) { - UINT32 effrow = view->top_row + row; - if (effrow >= dasmdata->allocated_rows) + UINT32 effrow = view->topleft.y + row; + if (effrow >= dasmdata->allocated.y) break; - if (pcbyte == dasmdata->address[effrow]) + if (pcbyte == dasmdata->byteaddress[effrow]) { /* see if we changed */ - int changed = disasm_recompute(view, pc, effrow, 1); + int changed = disasm_view_recompute(view, pc, effrow, 1); if (changed && !recomputed_this_time) { - dasmdata->recompute = TRUE; + view->recompute = TRUE; goto recompute; } /* set the effective row and PC */ - view->cursor_row = effrow; - dasmdata->active_address = pcbyte; + view->cursor.y = effrow; } } dasmdata->last_pcbyte = pcbyte; } /* loop over visible rows */ - for (row = 0; row < view->visible_rows; row++) + for (row = 0; row < view->visible.y; row++) { - UINT32 effrow = view->top_row + row; + UINT32 effrow = view->topleft.y + row; UINT8 attrib = DCA_NORMAL; debug_cpu_breakpoint *bp; UINT32 col = 0; /* if this visible row is valid, add it to the buffer */ - if (effrow < dasmdata->allocated_rows) + if (effrow < dasmdata->allocated.y) { - const char *data = &dasmdata->dasm[effrow * dasmdata->allocated_cols]; - UINT32 effcol = view->left_col; + const char *data = &dasmdata->dasm[effrow * dasmdata->allocated.x]; + UINT32 effcol = view->topleft.x; UINT32 len = 0; /* if we're on the line with the PC, recompute and hilight it */ - if (pcbyte == dasmdata->address[effrow]) + if (pcbyte == dasmdata->byteaddress[effrow]) attrib = DCA_CURRENT; /* if we're on a line with a breakpoint, tag it changed */ else { + const cpu_debug_data *cpuinfo = cpu_get_debug_data(space->cpu); for (bp = cpuinfo->bplist; bp != NULL; bp = bp->next) - if (dasmdata->address[effrow] == ADDR2BYTE_MASKED(bp->address, cpuinfo, ADDRESS_SPACE_PROGRAM)) + if (dasmdata->byteaddress[effrow] == (memory_address_to_byte(space, bp->address) & space->bytemask)) attrib = DCA_CHANGED; } /* if we're on the active column and everything is couth, highlight it */ - if (view->cursor_visible && effrow == view->cursor_row) - { - if (dasmdata->active_address == dasmdata->address[effrow]) - attrib |= DCA_SELECTED; - } + if (view->cursor_visible && effrow == view->cursor.y) + attrib |= DCA_SELECTED; /* get the effective string */ len = (UINT32)strlen(data); /* copy data */ - while (col < view->visible_cols && effcol < len) + while (col < view->visible.x && effcol < len) { dest->byte = data[effcol++]; dest->attrib = (effcol <= dasmdata->divider1 || effcol >= dasmdata->divider2) ? (attrib | DCA_ANCILLARY) : attrib; /* comments are just green for now - maybe they shouldn't even be this? */ - if (effcol >= dasmdata->divider2 && dasmdata->right_column == DVP_DASM_RIGHTCOL_COMMENTS) + if (effcol >= dasmdata->divider2 && dasmdata->right_column == DASM_RIGHTCOL_COMMENTS) attrib |= DCA_COMMENT; dest++; @@ -1793,10 +1941,10 @@ recompute: } /* fill the rest with blanks */ - while (col < view->visible_cols) + while (col < view->visible.x) { dest->byte = ' '; - dest->attrib = (effrow < view->total_rows) ? (attrib | DCA_ANCILLARY) : attrib; + dest->attrib = (effrow < view->total.y) ? (attrib | DCA_ANCILLARY) : attrib; dest++; col++; } @@ -1808,232 +1956,231 @@ recompute: /*------------------------------------------------- - disasm_handle_char - handle a character typed - within the current view + disasm_view_get_address_space - return the + address space whose disassembly is being + displayed -------------------------------------------------*/ -static void disasm_handle_char(debug_view *view, char chval) +const address_space *disasm_view_get_address_space(debug_view *view) { debug_view_disasm *dasmdata = view->extra_data; - UINT8 end_buffer = 3; - INT32 temp; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return dasmdata->space; +} - switch (chval) + +/*------------------------------------------------- + disasm_view_get_expression - return the + expression string describing the home address +-------------------------------------------------*/ + +const char *disasm_view_get_expression(debug_view *view) +{ + debug_view_disasm *dasmdata = view->extra_data; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return astring_c(dasmdata->expression.string); +} + + +/*------------------------------------------------- + disasm_view_get_right_column - return the + contents of the right column +-------------------------------------------------*/ + +disasm_right_column disasm_view_get_right_column(debug_view *view) +{ + debug_view_disasm *dasmdata = view->extra_data; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return dasmdata->right_column; +} + + +/*------------------------------------------------- + disasm_view_get_backward_steps - return the + number of instructions displayed before the + home address +-------------------------------------------------*/ + +UINT32 disasm_view_get_backward_steps(debug_view *view) +{ + debug_view_disasm *dasmdata = view->extra_data; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return dasmdata->backwards_steps; +} + + +/*------------------------------------------------- + disasm_view_get_disasm_width - return the + width in characters of the main disassembly + section +-------------------------------------------------*/ + +UINT32 disasm_view_get_disasm_width(debug_view *view) +{ + debug_view_disasm *dasmdata = view->extra_data; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return dasmdata->dasm_width; +} + + +/*------------------------------------------------- + disasm_view_get_selected_address - return the + PC of the currently selected address in the + view +-------------------------------------------------*/ + +offs_t disasm_view_get_selected_address(debug_view *view) +{ + debug_view_disasm *dasmdata = view->extra_data; + assert(view->type == DVT_DISASSEMBLY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memory_byte_to_address(dasmdata->space, dasmdata->byteaddress[view->cursor.y]); +} + + +/*------------------------------------------------- + disasm_view_set_address_space - set the + address space whose disassembly is being + displayed +-------------------------------------------------*/ + +void disasm_view_set_address_space(debug_view *view, const address_space *space) +{ + debug_view_disasm *dasmdata = view->extra_data; + + assert(view->type == DVT_DISASSEMBLY); + assert(space != NULL); + + if (space != dasmdata->space) { - case DCH_UP: - if (view->cursor_row > 0) - view->cursor_row--; - break; + debug_view_begin_update(view); + dasmdata->space = space; - case DCH_DOWN: - if (view->cursor_row < view->total_rows - 1) - view->cursor_row++; - break; + /* we need to recompute the expression in the context of the new CPU */ + dasmdata->expression.dirty = TRUE; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} - case DCH_PUP: - temp = view->cursor_row - (view->visible_rows - end_buffer); - if (temp < 0) - view->cursor_row = 0; - else - view->cursor_row = temp; - break; +/*------------------------------------------------- + disasm_view_set_expression - set the + expression string describing the home address +-------------------------------------------------*/ - case DCH_PDOWN: - temp = view->cursor_row + (view->visible_rows - end_buffer); +void disasm_view_set_expression(debug_view *view, const char *expression) +{ + debug_view_disasm *dasmdata = view->extra_data; - if (temp > (view->total_rows - 1)) - view->cursor_row = (view->total_rows - 1); - else - view->cursor_row = temp; - break; + assert(view->type == DVT_DISASSEMBLY); + assert(expression != NULL); - case DCH_HOME: /* set the active column to the PC */ + debug_view_begin_update(view); + debug_view_expression_set(&dasmdata->expression, expression); + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); +} + + +/*------------------------------------------------- + disasm_view_set_right_column - set the + contents of the right column +-------------------------------------------------*/ + +void disasm_view_set_right_column(debug_view *view, disasm_right_column contents) +{ + debug_view_disasm *dasmdata = view->extra_data; + + assert(view->type == DVT_DISASSEMBLY); + assert(contents == DASM_RIGHTCOL_RAW || contents == DASM_RIGHTCOL_ENCRYPTED || contents == DASM_RIGHTCOL_COMMENTS); + + if (contents != dasmdata->right_column) + { + debug_view_begin_update(view); + dasmdata->right_column = contents; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + disasm_view_set_backward_steps - set the + number of instructions displayed before the + home address +-------------------------------------------------*/ + +void disasm_view_set_backward_steps(debug_view *view, UINT32 steps) +{ + debug_view_disasm *dasmdata = view->extra_data; + + assert(view->type == DVT_DISASSEMBLY); + + if (steps != dasmdata->backwards_steps) + { + debug_view_begin_update(view); + dasmdata->backwards_steps = steps; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + disasm_view_set_disasm_width - set the + width in characters of the main disassembly + section +-------------------------------------------------*/ + +void disasm_view_set_disasm_width(debug_view *view, UINT32 width) +{ + debug_view_disasm *dasmdata = view->extra_data; + + assert(view->type == DVT_DISASSEMBLY); + + if (width != dasmdata->dasm_width) + { + debug_view_begin_update(view); + dasmdata->dasm_width = width; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + disasm_view_set_selected_address - set the + PC of the currently selected address in the + view +-------------------------------------------------*/ + +void disasm_view_set_selected_address(debug_view *view, offs_t address) +{ + debug_view_disasm *dasmdata = view->extra_data; + offs_t byteaddress = memory_address_to_byte(dasmdata->space, address) & dasmdata->space->logbytemask; + int line; + + assert(view->type == DVT_DISASSEMBLY); + + for (line = 0; line < view->total.y; line++) + if (dasmdata->byteaddress[line] == byteaddress) { - const cpu_debug_data *cpuinfo = cpu_get_debug_data(Machine->cpu[dasmdata->cpunum]); - offs_t pc = cpu_get_reg(Machine->cpu[dasmdata->cpunum], REG_PC); - int i; - - pc = ADDR2BYTE_MASKED(pc, cpuinfo, ADDRESS_SPACE_PROGRAM); - - /* figure out which row the pc is on */ - for (i = 0; i < dasmdata->allocated_rows; i++) - { - if (dasmdata->address[i] == pc) - view->cursor_row = i; - } + view->cursor.y = line; + debug_view_set_cursor_position(view, view->cursor); break; } - - case DCH_CTRLHOME: - view->cursor_row = 0; - break; - - case DCH_CTRLEND: - view->cursor_row = view->total_rows - 1; - break; - } - - /* get the address under the cursor_row */ - dasmdata->active_address = dasmdata->address[view->cursor_row]; - - /* scroll if out of range */ - if (view->cursor_row < view->top_row) - view->top_row = view->cursor_row; - if (view->cursor_row >= view->top_row + view->visible_rows - end_buffer) - view->top_row = view->cursor_row - view->visible_rows + end_buffer; -} - - -/*------------------------------------------------- - disasm_getprop - return the value - of a given property --------------------------------------------------*/ - -static void disasm_getprop(debug_view *view, UINT32 property, debug_property_info *value) -{ - debug_view_disasm *dasmdata = view->extra_data; - - switch (property) - { - case DVP_DASM_CPUNUM: - value->i = dasmdata->cpunum; - break; - - case DVP_DASM_EXPRESSION: - value->s = dasmdata->expression_string; - break; - - case DVP_DASM_TRACK_LIVE: - value->i = dasmdata->live_tracking; - break; - - case DVP_DASM_RIGHT_COLUMN: - value->i = dasmdata->right_column; - break; - - case DVP_DASM_BACKWARD_STEPS: - value->i = dasmdata->backwards_steps; - break; - - case DVP_DASM_WIDTH: - value->i = dasmdata->dasm_width; - break; - - case DVP_DASM_ACTIVE_ADDRESS: - value->i = dasmdata->active_address; - break; - - default: - fatalerror("Attempt to get invalid property %d on debug view type %d", property, view->type); - break; - } -} - - -/*------------------------------------------------- - disasm_setprop - set the value - of a given property --------------------------------------------------*/ - -static void disasm_setprop(debug_view *view, UINT32 property, debug_property_info value) -{ - debug_view_disasm *dasmdata = view->extra_data; - - switch (property) - { - case DVP_DASM_CPUNUM: - if (value.i != dasmdata->cpunum) - { - debug_view_begin_update(view); - dasmdata->cpunum = value.i; - - /* we need to recompute the expression in the context of the new CPU */ - dasmdata->expression_dirty = TRUE; - dasmdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_DASM_EXPRESSION: - debug_view_begin_update(view); - - /* free the old expression string and allocate a new one */ - if (dasmdata->expression_string) - free(dasmdata->expression_string); - dasmdata->expression_string = malloc(strlen(value.s) + 1); - if (dasmdata->expression_string) - strcpy(dasmdata->expression_string, value.s); - - /* update everything as a result */ - dasmdata->expression_dirty = TRUE; - dasmdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - case DVP_DASM_TRACK_LIVE: - if (value.i != dasmdata->live_tracking) - { - debug_view_begin_update(view); - dasmdata->live_tracking = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_DASM_RIGHT_COLUMN: - if (value.i != dasmdata->right_column && value.i >= DVP_DASM_RIGHTCOL_NONE && value.i <= DVP_DASM_RIGHTCOL_COMMENTS) - { - debug_view_begin_update(view); - dasmdata->right_column = value.i; - dasmdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_DASM_BACKWARD_STEPS: - if (value.i != dasmdata->backwards_steps) - { - debug_view_begin_update(view); - dasmdata->backwards_steps = value.i; - dasmdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_DASM_WIDTH: - if (value.i != dasmdata->dasm_width) - { - debug_view_begin_update(view); - dasmdata->dasm_width = value.i; - dasmdata->recompute = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_CHARACTER: - debug_view_begin_update(view); - disasm_handle_char(view, value.i); - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - case DVP_DASM_ACTIVE_ADDRESS: - debug_view_begin_update(view); - dasmdata->active_address = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - default: - fatalerror("Attempt to set invalid property %d on debug view type %d", property, view->type); - break; - } } @@ -2052,9 +2199,8 @@ void debug_disasm_update_all(void) { debug_view_disasm *dasmdata = view->extra_data; debug_view_begin_update(view); - view->update_pending = TRUE; - dasmdata->recompute = TRUE; dasmdata->last_pcbyte = ~0; + view->recompute = view->update_pending = TRUE; debug_view_end_update(view); } } @@ -2062,67 +2208,66 @@ void debug_disasm_update_all(void) /*************************************************************************** - - Memory view - + MEMORY VIEW ***************************************************************************/ -/* -00000000 00 11 22 33 44 55 66 77-88 99 aa bb cc dd ee ff 0123456789abcdef -00000000 0011 2233 4455 6677- 8899 aabb ccdd eeff 0123456789abcdef -00000000 00112233 44556677 - 8899aabb ccddeeff 0123456789abcdef -00000000 0011223344556677 - 8899aabbccddeeff 0123456789abcdef -*/ - /*------------------------------------------------- - memory_alloc - allocate memory for the + memory_view_alloc - allocate memory for the memory view -------------------------------------------------*/ -static int memory_alloc(debug_view *view) +static int memory_view_alloc(debug_view *view) { debug_view_memory *memdata; /* allocate memory */ memdata = malloc(sizeof(*memdata)); - if (!memdata) - return 0; + if (memdata == NULL) + return FALSE; memset(memdata, 0, sizeof(*memdata)); - /* by default we track live */ - memdata->live_tracking = TRUE; - memdata->ascii_view = TRUE; + /* allocate the expression data */ + debug_view_expression_alloc(&memdata->expression); /* stash the extra data pointer */ view->extra_data = memdata; /* we support cursors */ view->supports_cursor = TRUE; + + /* dummy up a raw location to start */ + memdata->raw.base = &memdata->raw; + memdata->raw.length = 1; + memdata->raw.offsetxor = 0; +#ifdef LITTLE_ENDIAN + memdata->raw.endianness = CPU_IS_LE; +#else + memdata->raw.endianness = CPU_IS_BE; +#endif - /* start out with 16 bytes in a single column */ + /* start out with 16 bytes in a single column and ASCII displayed */ + memdata->chunks_per_row = 16; memdata->bytes_per_chunk = 1; - memdata->chunks_displayed = 16; + memdata->bytes_per_row = 16; + memdata->ascii_view = TRUE; - return 1; + return TRUE; } /*------------------------------------------------- - memory_free - free memory for the + memory_view_free - free memory for the memory view -------------------------------------------------*/ -static void memory_free(debug_view *view) +static void memory_view_free(debug_view *view) { debug_view_memory *memdata = view->extra_data; - /* free any memory we callocated */ - if (memdata) + /* free any memory we allocated */ + if (memdata != NULL) { - if (memdata->expression) - expression_free(memdata->expression); - if (memdata->expression_string) - free(memdata->expression_string); + debug_view_expression_free(&memdata->expression); free(memdata); } view->extra_data = NULL; @@ -2130,257 +2275,511 @@ static void memory_free(debug_view *view) /*------------------------------------------------- - memory_get_cursor_pos - return the cursor - position as an address and a shift value + memory_view_notify - handle notification of + updates to cursor changes -------------------------------------------------*/ -static int memory_get_cursor_pos(debug_view *view, offs_t *address, UINT8 *shift) +static void memory_view_notify(debug_view *view, view_notification type) { - debug_view_memory *memdata = view->extra_data; - int curx = view->cursor_col, cury = view->cursor_row; - UINT32 bytes_per_row; - int modval; - - /* if not in the middle section, punt */ - if (curx <= memdata->divider1) - curx = memdata->divider1 + 1; - if (curx >= memdata->divider2) - curx = memdata->divider2 - 1; - curx -= memdata->divider1; - - /* compute the base address */ - bytes_per_row = memdata->chunks_displayed * memdata->bytes_per_chunk; - *address = bytes_per_row * cury + memdata->byte_offset; - - /* the rest depends on the current format */ - switch (memdata->bytes_per_chunk) + if (type == VIEW_NOTIFY_CURSOR_CHANGED) { - default: - case 1: - modval = curx % 3; - if (modval == 0) modval = 1; - modval -= 1; - if (!memdata->reverse_view) - *address += curx / 3; - else - *address += 15 - curx / 3; - *shift = 8-4 - 4 * modval; - break; - - case 2: - modval = curx % 6; - if (modval <= 1) modval = 2; - modval -= 2; - if (!memdata->reverse_view) - *address += 2 * (curx / 6); - else - *address += 14 - 2 * (curx / 6); - *shift = 16-4 - 4 * modval; - break; - - case 4: - modval = curx % 12; - if (modval <= 2) modval = 3; - if (modval == 11) modval = 10; - modval -= 3; - if (!memdata->reverse_view) - *address += 4 * (curx / 12); - else - *address += 12 - 4 * (curx / 12); - *shift = 32-4 - 4 * modval; - break; - - case 8: - modval = curx % 24; - if (modval <= 4) modval = 5; - if (modval >= 21) modval = 20; - modval -= 5; - if (!memdata->reverse_view) - *address += 8 * (curx / 24); - else - *address += 8 - 8 * (curx / 24); - *shift = 64-4 - 4 * modval; - break; + offs_t address; + UINT8 shift; + + /* normalize the cursor */ + memory_view_get_cursor_pos(view, &address, &shift); + memory_view_set_cursor_pos(view, address, shift); } - - return 1; } /*------------------------------------------------- - memory_set_cursor_pos - set the cursor + memory_view_update - update the contents of + the memory view +-------------------------------------------------*/ + +static void memory_view_update(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + const address_space *space = memdata->space; + const memory_view_pos *posdata; + UINT32 row; + + /* if we need to recompute, do it now */ + if (memory_view_needs_recompute(view)) + memory_view_recompute(view); + + /* get positional data */ + posdata = &memory_pos_table[memdata->bytes_per_chunk]; + + /* switch to the CPU's context */ + if (space != NULL) + cpu_push_context(space->cpu); + + /* loop over visible rows */ + for (row = 0; row < view->visible.y; row++) + { + debug_view_char *destmin = view->viewdata + row * view->visible.x; + debug_view_char *destmax = destmin + view->visible.x; + debug_view_char *destrow = destmin - view->topleft.x; + UINT32 effrow = view->topleft.y + row; + debug_view_char *dest; + int ch, chunknum; + + /* reset the line of data; section 1 is normal, others are ancillary, cursor is selected */ + dest = destmin; + for (ch = 0; ch < view->visible.x; ch++, dest++) + { + UINT32 effcol = view->topleft.x + ch; + dest->byte = ' '; + dest->attrib = DCA_ANCILLARY; + if (in_section(effcol, &memdata->section[1])) + { + dest->attrib = DCA_NORMAL; + if (view->cursor_visible && effrow == view->cursor.y && effcol == view->cursor.x) + dest->attrib |= DCA_SELECTED; + } + } + + /* if this visible row is valid, add it to the buffer */ + if (effrow < view->total.y) + { + offs_t addrbyte = memdata->byte_offset + effrow * memdata->bytes_per_row; + offs_t address = (space != NULL) ? memory_byte_to_address(space, addrbyte) : addrbyte; + char addrtext[20]; + + /* generate the address */ + sprintf(addrtext, memdata->addrformat, address); + dest = destrow + memdata->section[0].pos + 1; + for (ch = 0; addrtext[ch] != 0 && ch < memdata->section[0].width - 1; ch++, dest++) + if (dest >= destmin && dest < destmax) + dest->byte = addrtext[ch]; + + /* generate the data */ + for (chunknum = 0; chunknum < memdata->chunks_per_row; chunknum++) + { + UINT64 chunkdata = memory_view_read(memdata, memdata->bytes_per_chunk, addrbyte + chunknum * memdata->bytes_per_chunk); + int chunkindex = memdata->reverse_view ? (memdata->chunks_per_row - 1 - chunknum) : chunknum; + + dest = destrow + memdata->section[1].pos + 1 + chunkindex * posdata->spacing; + for (ch = 0; ch < posdata->spacing; ch++, dest++) + if (dest >= destmin && dest < destmax) + { + UINT8 shift = posdata->shift[ch]; + if (shift < 64) + dest->byte = "0123456789ABCDEF"[(chunkdata >> shift) & 0x0f]; + } + } + + /* generate the ASCII data */ + if (memdata->section[2].width > 0) + { + dest = destrow + memdata->section[2].pos + 1; + for (ch = 0; ch < memdata->bytes_per_row; ch++, dest++) + if (dest >= destmin && dest < destmax) + { + UINT8 chval = memory_view_read(memdata, 1, addrbyte + ch); + dest->byte = isprint(chval) ? chval : '.'; + } + } + } + } + + /* restore the context */ + if (memdata->raw.base == NULL) + cpu_pop_context(); +} + + +/*------------------------------------------------- + memory_view_char - handle a character typed + within the current view +-------------------------------------------------*/ + +static void memory_view_char(debug_view *view, int chval) +{ + static const char hexvals[] = "0123456789abcdef"; + debug_view_memory *memdata = view->extra_data; + offs_t address; + char *hexchar; + UINT64 data; + UINT32 delta; + UINT8 shift; + + /* get the position */ + memory_view_get_cursor_pos(view, &address, &shift); + + /* handle the incoming key */ + switch (chval) + { + case DCH_UP: + if (address >= memdata->byte_offset + memdata->bytes_per_row) + address -= memdata->bytes_per_row; + break; + + case DCH_DOWN: + if (address <= memdata->maxaddr - memdata->bytes_per_row) + address += memdata->bytes_per_row; + break; + + case DCH_PUP: + for (delta = (view->visible.y - 2) * memdata->bytes_per_row; delta > 0; delta -= memdata->bytes_per_row) + if (address >= memdata->byte_offset + delta) + { + address -= delta; + break; + } + break; + + case DCH_PDOWN: + for (delta = (view->visible.y - 2) * memdata->bytes_per_row; delta > 0; delta -= memdata->bytes_per_row) + if (address <= memdata->maxaddr - delta) + { + address += delta; + break; + } + break; + + case DCH_HOME: + address -= address % memdata->bytes_per_row; + shift = (memdata->bytes_per_chunk * 8) - 4; + break; + + case DCH_CTRLHOME: + address = memdata->byte_offset; + shift = (memdata->bytes_per_chunk * 8) - 4; + break; + + case DCH_END: + address += (memdata->bytes_per_row - (address % memdata->bytes_per_row) - 1); + shift = 0; + break; + + case DCH_CTRLEND: + address = memdata->maxaddr; + shift = 0; + break; + + case DCH_CTRLLEFT: + if (address >= memdata->byte_offset + memdata->bytes_per_chunk) + address -= memdata->bytes_per_chunk; + break; + + case DCH_CTRLRIGHT: + if (address <= memdata->maxaddr - memdata->bytes_per_chunk) + address += memdata->bytes_per_chunk; + break; + + default: + hexchar = strchr(hexvals, tolower(chval)); + if (hexchar == NULL) + break; + data = memory_view_read(memdata, memdata->bytes_per_chunk, address); + data &= ~((UINT64)0x0f << shift); + data |= (UINT64)(hexchar - hexvals) << shift; + memory_view_write(memdata, memdata->bytes_per_chunk, address, data); + /* fall through... */ + + case DCH_RIGHT: + if (shift == 0 && address != memdata->maxaddr) + { + shift = memdata->bytes_per_chunk * 8 - 4; + address += memdata->bytes_per_chunk; + } + else + shift -= 4; + break; + + case DCH_LEFT: + if (shift == memdata->bytes_per_chunk * 8 - 4 && address != memdata->byte_offset) + { + shift = 0; + address -= memdata->bytes_per_chunk; + } + else + shift += 4; + break; + } + + /* set a new position */ + debug_view_begin_update(view); + memory_view_set_cursor_pos(view, address, shift); + view->update_pending = TRUE; + debug_view_end_update(view); +} + + +/*------------------------------------------------- + memory_view_recompute - recompute the internal + data and structure of the memory view +-------------------------------------------------*/ + +static void memory_view_recompute(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + const address_space *space = memdata->space; + offs_t cursoraddr; + UINT8 cursorshift; + int addrchars; + + /* get the current cursor position */ + memory_view_get_cursor_pos(view, &cursoraddr, &cursorshift); + + /* determine the maximum address and address format string from the raw information */ + if (space != NULL) + { + memdata->maxaddr = memdata->no_translation ? space->bytemask : space->logbytemask; + addrchars = memdata->no_translation ? space->addrchars : space->logaddrchars; + } + else + { + memdata->maxaddr = memdata->raw.length - 1; + addrchars = sprintf(memdata->addrformat, "%X", memdata->maxaddr); + } + + /* generate an 8-byte aligned format for the address */ + if (!memdata->reverse_view) + sprintf(memdata->addrformat, "%*s%%0%dX", 8 - addrchars, "", addrchars); + else + sprintf(memdata->addrformat, "%%0%dX%*s", addrchars, 8 - addrchars, ""); + + /* if we are viewing a space with a minimum chunk size, clamp the bytes per chunk */ + if (space != NULL && space->ashift < 0) + { + UINT32 min_bytes_per_chunk = 1 << -space->ashift; + while (memdata->bytes_per_chunk < min_bytes_per_chunk) + { + memdata->bytes_per_chunk *= 2; + memdata->chunks_per_row /= 2; + } + memdata->chunks_per_row = MAX(1, memdata->chunks_per_row); + } + + /* recompute the byte offset based on the most recent expression result */ + memdata->bytes_per_row = memdata->bytes_per_chunk * memdata->chunks_per_row; + memdata->byte_offset = memdata->expression.result % memdata->bytes_per_row; + + /* compute the section widths */ + memdata->section[0].width = 1 + 8 + 1; + memdata->section[1].width = 1 + 3 * memdata->bytes_per_row + 1; + memdata->section[2].width = memdata->ascii_view ? (1 + memdata->bytes_per_row + 1) : 0; + + /* compute the section positions */ + if (!memdata->reverse_view) + { + memdata->section[0].pos = 0; + memdata->section[1].pos = memdata->section[0].pos + memdata->section[0].width; + memdata->section[2].pos = memdata->section[1].pos + memdata->section[1].width; + view->total.x = memdata->section[2].pos + memdata->section[2].width; + } + else + { + memdata->section[2].pos = 0; + memdata->section[1].pos = memdata->section[2].pos + memdata->section[2].width; + memdata->section[0].pos = memdata->section[1].pos + memdata->section[1].width; + view->total.x = memdata->section[0].pos + memdata->section[0].width; + } + + /* derive total sizes from that */ + view->total.y = (memdata->maxaddr - memdata->byte_offset + memdata->bytes_per_row - 1) / memdata->bytes_per_row; + + /* reset the current cursor position */ + memory_view_set_cursor_pos(view, cursoraddr, cursorshift); +} + + +/*------------------------------------------------- + memory_view_needs_recompute - determine if + anything has changed that requires a + recomputation +-------------------------------------------------*/ + +static int memory_view_needs_recompute(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + int recompute = view->recompute; + + /* handle expression changes */ + if (debug_view_expression_changed_value(view, &memdata->expression, (memdata->space != NULL) ? memdata->space->cpu : NULL)) + { + recompute = TRUE; + memory_view_set_cursor_pos(view, memdata->expression.result, memdata->bytes_per_chunk * 8 - 4); + } + + /* expression is clean at this point, and future recomputation is not necessary */ + view->recompute = FALSE; + return recompute; +} + + +/*------------------------------------------------- + memory_view_get_cursor_pos - return the cursor + position as an address and a shift value +-------------------------------------------------*/ + +static void memory_view_get_cursor_pos(debug_view *view, offs_t *address, UINT8 *shift) +{ + debug_view_memory *memdata = view->extra_data; + const memory_view_pos *posdata = &memory_pos_table[memdata->bytes_per_chunk]; + int xposition, chunknum, chunkoffs; + + /* start with the base address for this row */ + *address = memdata->byte_offset + view->cursor.y * memdata->bytes_per_chunk * memdata->chunks_per_row; + + /* determine the X position within the middle section, clamping as necessary */ + xposition = view->cursor.x - memdata->section[1].pos - 1; + if (xposition < 0) + xposition = 0; + else if (xposition >= posdata->spacing * memdata->chunks_per_row) + xposition = posdata->spacing * memdata->chunks_per_row - 1; + + /* compute chunk number and offset within that chunk */ + chunknum = xposition / posdata->spacing; + chunkoffs = xposition % posdata->spacing; + + /* reverse the chunknum if we're reversed */ + if (memdata->reverse_view) + chunknum = memdata->chunks_per_row - 1 - chunknum; + + /* compute the address and shift */ + *address += chunknum * memdata->bytes_per_chunk; + *shift = posdata->shift[chunkoffs] & 0x7f; +} + + +/*------------------------------------------------- + memory_view_set_cursor_pos - set the cursor position as a function of an address and a shift value -------------------------------------------------*/ -static void memory_set_cursor_pos(debug_view *view, offs_t address, UINT8 shift) +static void memory_view_set_cursor_pos(debug_view *view, offs_t address, UINT8 shift) { debug_view_memory *memdata = view->extra_data; - UINT32 bytes_per_row; - int curx, cury; - UINT8 end_buffer = 2; + const memory_view_pos *posdata = &memory_pos_table[memdata->bytes_per_chunk]; + int chunknum; /* offset the address by the byte offset */ + if (address < memdata->byte_offset) + address = memdata->byte_offset; address -= memdata->byte_offset; - /* compute the y coordinate */ - bytes_per_row = memdata->chunks_displayed * memdata->bytes_per_chunk; - cury = address / bytes_per_row; + /* compute the Y coordinate and chunk index */ + view->cursor.y = address / memdata->bytes_per_row; + chunknum = (address % memdata->bytes_per_row) / memdata->bytes_per_chunk; + + /* reverse the chunknum if we're reversed */ + if (memdata->reverse_view) + chunknum = memdata->chunks_per_row - 1 - chunknum; + + /* scan within the chunk to find the shift */ + for (view->cursor.x = 0; view->cursor.x < posdata->spacing; view->cursor.x++) + if (posdata->shift[view->cursor.x] == shift) + break; + + /* add in the chunk offset and shift to the right of divider1 */ + view->cursor.x += memdata->section[1].pos + 1 + posdata->spacing * chunknum; - /* the rest depends on the current format */ - - /* non-reverse case */ - if (!memdata->reverse_view) - { - switch (memdata->bytes_per_chunk) - { - default: - case 1: - curx = memdata->divider1 + 1 + 3 * (address % bytes_per_row) + (1 - (shift / 4)); - break; - - case 2: - curx = memdata->divider1 + 2 + 6 * ((address % bytes_per_row) / 2) + (3 - (shift / 4)); - break; - - case 4: - curx = memdata->divider1 + 3 + 12 * ((address % bytes_per_row) / 4) + (7 - (shift / 4)); - break; - - case 8: - curx = memdata->divider1 + 5 + 24 * ((address % bytes_per_row) / 8) + (15 - (shift / 4)); - break; - } - } - else - { - switch (memdata->bytes_per_chunk) - { - default: - case 1: - curx = memdata->divider1 + 1 + 3 * (15 - address % bytes_per_row) + (1 - (shift / 4)); - break; - - case 2: - curx = memdata->divider1 + 2 + 6 * (7 - (address % bytes_per_row) / 2) + (3 - (shift / 4)); - break; - - case 4: - curx = memdata->divider1 + 3 + 12 * (3 - (address % bytes_per_row) / 4) + (7 - (shift / 4)); - break; - - case 8: - curx = memdata->divider1 + 5 + 24 * (1 - (address % bytes_per_row) / 8) + (15 - (shift / 4)); - break; - } - } - - /* set the position, clamping to the window bounds */ - view->cursor_col = (curx < 0) ? 0 : (curx >= view->total_cols) ? (view->total_cols - end_buffer) : curx; - view->cursor_row = (cury < 0) ? 0 : (cury >= view->total_rows) ? (view->total_rows - end_buffer) : cury; + /* clamp to the window bounds */ + view->cursor.x = MIN(view->cursor.x, view->total.x); + view->cursor.y = MIN(view->cursor.y, view->total.y); /* scroll if out of range */ - if (view->cursor_row < view->top_row) - view->top_row = view->cursor_row; - if (view->cursor_row >= view->top_row + view->visible_rows - end_buffer) - view->top_row = view->cursor_row - view->visible_rows + end_buffer; + adjust_visible_x_for_cursor(view); + adjust_visible_y_for_cursor(view); } /*------------------------------------------------- - generic_read_byte - generic byte reader + memory_view_read - generic memory view data + reader -------------------------------------------------*/ -static UINT8 generic_read_byte(debug_view_memory *memdata, offs_t offs, int apply_translation) +static UINT64 memory_view_read(debug_view_memory *memdata, UINT8 size, offs_t offs) { /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - return debug_read_byte(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, apply_translation); - - /* all 0xff if out of bounds */ - offs ^= memdata->raw_offset_xor; - if (offs >= memdata->raw_length) - return 0xff; - return *((UINT8 *)memdata->raw_base + offs); -} - - -/*------------------------------------------------- - generic_read_word - generic word reader --------------------------------------------------*/ - -static UINT16 generic_read_word(debug_view_memory *memdata, offs_t offs, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - return debug_read_word(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, apply_translation); - - /* otherwise, decompose into bytes */ - if (memdata->raw_little_endian) - return generic_read_byte(memdata, offs + 0, apply_translation) | (generic_read_byte(memdata, offs + 1, apply_translation) << 8); - else - return generic_read_byte(memdata, offs + 1, apply_translation) | (generic_read_byte(memdata, offs + 0, apply_translation) << 8); -} - - -/*------------------------------------------------- - generic_read_dword - generic dword reader --------------------------------------------------*/ - -static UINT32 generic_read_dword(debug_view_memory *memdata, offs_t offs, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - return debug_read_dword(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, apply_translation); - - /* otherwise, decompose into words */ - if (memdata->raw_little_endian) - return generic_read_word(memdata, offs + 0, apply_translation) | (generic_read_word(memdata, offs + 2, apply_translation) << 16); - else - return generic_read_word(memdata, offs + 2, apply_translation) | (generic_read_word(memdata, offs + 0, apply_translation) << 16); -} - - -/*------------------------------------------------- - generic_read_qword - generic qword reader --------------------------------------------------*/ - -static UINT64 generic_read_qword(debug_view_memory *memdata, offs_t offs, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - return debug_read_qword(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, apply_translation); - - /* otherwise, decompose into dwords */ - if (memdata->raw_little_endian) - return generic_read_dword(memdata, offs + 0, apply_translation) | ((UINT64)generic_read_dword(memdata, offs + 4, apply_translation) << 32); - else - return generic_read_dword(memdata, offs + 4, apply_translation) | ((UINT64)generic_read_dword(memdata, offs + 0, apply_translation) << 32); -} - - -/*------------------------------------------------- - generic_write_byte - generic byte writer --------------------------------------------------*/ - -static void generic_write_byte(debug_view_memory *memdata, offs_t offs, UINT8 data, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) + if (memdata->space != NULL) { - debug_write_byte(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, data, apply_translation); + UINT64 result = ~(UINT64)0; + + cpu_push_context(memdata->space->cpu); + switch (size) + { + case 1: result = debug_read_byte(memdata->space, offs, !memdata->no_translation); break; + case 2: result = debug_read_word(memdata->space, offs, !memdata->no_translation); break; + case 4: result = debug_read_dword(memdata->space, offs, !memdata->no_translation); break; + case 8: result = debug_read_qword(memdata->space, offs, !memdata->no_translation); break; + } + cpu_pop_context(); + return result; + } + + /* if larger than a byte, reduce by half and recurse */ + if (size > 1) + { + size /= 2; + if (memdata->raw.endianness == CPU_IS_LE) + return memory_view_read(memdata, size, offs + 0 * size) | ((UINT64)memory_view_read(memdata, size, offs + 1 * size) << (size * 8)); + else + return memory_view_read(memdata, size, offs + 1 * size) | ((UINT64)memory_view_read(memdata, size, offs + 0 * size) << (size * 8)); + } + + /* all 0xff if out of bounds */ + offs ^= memdata->raw.offsetxor; + if (offs >= memdata->raw.length) + return 0xff; + return *((UINT8 *)memdata->raw.base + offs); +} + + +/*------------------------------------------------- + memory_view_write - generic memory view data + writer +-------------------------------------------------*/ + +static void memory_view_write(debug_view_memory *memdata, UINT8 size, offs_t offs, UINT64 data) +{ + /* if no raw data, just use the standard debug routines */ + if (memdata->space != NULL) + { + cpu_push_context(memdata->space->cpu); + switch (size) + { + case 1: debug_write_byte(memdata->space, offs, data, !memdata->no_translation); break; + case 2: debug_write_word(memdata->space, offs, data, !memdata->no_translation); break; + case 4: debug_write_dword(memdata->space, offs, data, !memdata->no_translation); break; + case 8: debug_write_qword(memdata->space, offs, data, !memdata->no_translation); break; + } + cpu_pop_context(); + return; + } + + /* if larger than a byte, reduce by half and recurse */ + if (size > 1) + { + size /= 2; + if (memdata->raw.endianness == CPU_IS_LE) + { + memory_view_write(memdata, size, offs + 0 * size, data); + memory_view_write(memdata, size, offs + 1 * size, data >> (8 * size)); + } + else + { + memory_view_write(memdata, size, offs + 1 * size, data); + memory_view_write(memdata, size, offs + 0 * size, data >> (8 * size)); + } return; } /* ignore if out of bounds */ - offs ^= memdata->raw_offset_xor; - if (offs >= memdata->raw_length) + offs ^= memdata->raw.offsetxor; + if (offs >= memdata->raw.length) return; - *((UINT8 *)memdata->raw_base + offs) = data; + *((UINT8 *)memdata->raw.base + offs) = data; /* hack for FD1094 editing */ #ifdef FD1094_HACK - if (memdata->raw_base == memory_region(Machine, "user2")) + if (memdata->raw.base == memory_region(view->machine, "user2")) { extern void fd1094_regenerate_key(void); fd1094_regenerate_key(); @@ -2390,808 +2789,296 @@ static void generic_write_byte(debug_view_memory *memdata, offs_t offs, UINT8 da /*------------------------------------------------- - generic_write_word - generic word writer + memory_view_get_address_space - return the + address space whose memory is being displayed -------------------------------------------------*/ -static void generic_write_word(debug_view_memory *memdata, offs_t offs, UINT16 data, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - { - debug_write_word(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, data, apply_translation); - return; - } - - /* otherwise, decompose into bytes */ - if (memdata->raw_little_endian) - { - generic_write_byte(memdata, offs + 0, data, apply_translation); - generic_write_byte(memdata, offs + 1, data >> 8, apply_translation); - } - else - { - generic_write_byte(memdata, offs + 1, data, apply_translation); - generic_write_byte(memdata, offs + 0, data >> 8, apply_translation); - } -} - - -/*------------------------------------------------- - generic_write_dword - generic dword writer --------------------------------------------------*/ - -static void generic_write_dword(debug_view_memory *memdata, offs_t offs, UINT32 data, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - { - debug_write_dword(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, data, apply_translation); - return; - } - - /* otherwise, decompose into words */ - if (memdata->raw_little_endian) - { - generic_write_word(memdata, offs + 0, data, apply_translation); - generic_write_word(memdata, offs + 2, data >> 16, apply_translation); - } - else - { - generic_write_word(memdata, offs + 2, data, apply_translation); - generic_write_word(memdata, offs + 0, data >> 16, apply_translation); - } -} - - -/*------------------------------------------------- - generic_write_qword - generic qword writer --------------------------------------------------*/ - -static void generic_write_qword(debug_view_memory *memdata, offs_t offs, UINT64 data, int apply_translation) -{ - /* if no raw data, just use the standard debug routines */ - if (memdata->raw_base == NULL) - { - debug_write_qword(cpu_get_address_space(Machine->activecpu, memdata->spacenum), offs, data, apply_translation); - return; - } - - /* otherwise, decompose into dwords */ - if (memdata->raw_little_endian) - { - generic_write_dword(memdata, offs + 0, data, apply_translation); - generic_write_dword(memdata, offs + 4, data >> 32, apply_translation); - } - else - { - generic_write_dword(memdata, offs + 4, data, apply_translation); - generic_write_dword(memdata, offs + 0, data >> 32, apply_translation); - } -} - - -/*------------------------------------------------- - memory_handle_char - handle a character typed - within the current view --------------------------------------------------*/ - -static void memory_handle_char(debug_view *view, char chval) +const address_space *memory_view_get_address_space(debug_view *view) { debug_view_memory *memdata = view->extra_data; - const cpu_debug_data *cpuinfo = cpu_get_debug_data(Machine->cpu[memdata->cpunum]); - static const char hexvals[] = "0123456789abcdef"; - char *hexchar = strchr(hexvals, tolower(chval)); - UINT32 bytes_per_row; - UINT32 tempaddr; - offs_t maxaddr; - offs_t address; - UINT8 shift; - - /* determine the max address */ - maxaddr = memdata->raw_base ? (memdata->raw_length - 1) : cpuinfo->space[memdata->spacenum].logbytemask; - - /* get the position */ - if (!memory_get_cursor_pos(view, &address, &shift)) - return; - - /* handle the incoming key */ - /* up/down work the same regardless */ - bytes_per_row = memdata->chunks_displayed * memdata->bytes_per_chunk; - - switch (chval) - { - case DCH_UP: - if (view->cursor_row > 0) - address -= bytes_per_row; - break; - - case DCH_DOWN: - if (view->cursor_row < view->total_rows - 1) - address += bytes_per_row; - break; - - case DCH_PUP: - tempaddr = address - (bytes_per_row * (view->visible_rows-2)) ; - if (tempaddr > address) /* unsigned wraparound */ - address = address % bytes_per_row; - else - address = tempaddr; - break; - - case DCH_PDOWN: - tempaddr = address + (bytes_per_row * (view->visible_rows-2)) ; - if (tempaddr > maxaddr) - address = (maxaddr - (bytes_per_row-1)) + (address % bytes_per_row); - else - address = tempaddr; - break; - - case DCH_HOME: - address -= address % bytes_per_row; - shift = (memdata->bytes_per_chunk * 8) - 1; - break; - - case DCH_CTRLHOME: - address = 0; - shift = (memdata->bytes_per_chunk * 8) - 1; - break; - - case DCH_END: - address += (bytes_per_row - (address % bytes_per_row) - 1); - shift = 0; - break; - - case DCH_CTRLEND: - address = maxaddr; - shift = 0; - break; - - case DCH_CTRLRIGHT: - if (address < maxaddr-memdata->bytes_per_chunk) - address += memdata->bytes_per_chunk; - break; - - case DCH_CTRLLEFT: - if (address >= memdata->bytes_per_chunk) - address -= memdata->bytes_per_chunk; - break; - } - - /* switch off of the current chunk size */ - cpu_push_context(Machine->cpu[memdata->cpunum]); - switch (memdata->bytes_per_chunk) - { - default: - case 1: - if (hexchar) - generic_write_byte(memdata, address, (generic_read_byte(memdata, address, !memdata->no_translation) & ~(0xf << shift)) | ((hexchar - hexvals) << shift), !memdata->no_translation); - if (hexchar || chval == DCH_RIGHT) - { - if (shift == 0) { shift = 8-4; if (address != maxaddr) address++; } - else shift -= 4; - } - else if (chval == DCH_LEFT) - { - if (shift == 8-4) { shift = 0; if (address != 0) address--; } - else shift += 4; - } - break; - - case 2: - if (hexchar) - generic_write_word(memdata, address, (generic_read_word(memdata, address, !memdata->no_translation) & ~(0xf << shift)) | ((hexchar - hexvals) << shift), !memdata->no_translation); - if (hexchar || chval == DCH_RIGHT) - { - if (shift == 0) { shift = 16-4; if (address != maxaddr) address += 2; } - else shift -= 4; - } - else if (chval == DCH_LEFT) - { - if (shift == 16-4) { shift = 0; if (address != 0) address -= 2; } - else shift += 4; - } - break; - - case 4: - if (hexchar) - generic_write_dword(memdata, address, (generic_read_dword(memdata, address, !memdata->no_translation) & ~(0xf << shift)) | ((hexchar - hexvals) << shift), !memdata->no_translation); - if (hexchar || chval == DCH_RIGHT) - { - if (shift == 0) { shift = 32-4; if (address != maxaddr) address += 4; } - else shift -= 4; - } - else if (chval == DCH_LEFT) - { - if (shift == 32-4) { shift = 0; if (address != 0) address -= 4; } - else shift += 4; - } - break; - - case 8: - if (hexchar) - generic_write_qword(memdata, address, (generic_read_qword(memdata, address, !memdata->no_translation) & ~((UINT64)0xf << shift)) | ((UINT64)(hexchar - hexvals) << shift), !memdata->no_translation); - if (hexchar || chval == DCH_RIGHT) - { - if (shift == 0) { shift = 64-4; if (address != maxaddr) address += 8; } - else shift -= 4; - } - else if (chval == DCH_LEFT) - { - if (shift == 64-4) { shift = 0; if (address != 0) address -= 8; } - else shift += 4; - } - break; - } - cpu_pop_context(); - - /* set a new position */ - memory_set_cursor_pos(view, address, shift); + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->space; } /*------------------------------------------------- - memory_update - update the contents of - the register view + memory_view_get_raw - return a raw description + of the memory being displayed -------------------------------------------------*/ -static void memory_update(debug_view *view) +const memory_view_raw *memory_view_get_raw(debug_view *view) { debug_view_memory *memdata = view->extra_data; - const cpu_debug_data *cpuinfo = cpu_get_debug_data(Machine->cpu[memdata->cpunum]); - debug_view_char *dest = view->viewdata; - char addrformat[16]; - EXPRERR exprerr; - UINT8 addrchars; - UINT32 maxaddr; - offs_t addrmask; - UINT32 row; - UINT32 memory_display_width; - UINT32 bytes_per_line; - - /* switch to the CPU's context */ - if (memdata->raw_base == NULL) - cpu_push_context(Machine->cpu[memdata->cpunum]); - - /* determine maximum address and number of characters for that */ - if (memdata->raw_base != NULL) - { - maxaddr = memdata->raw_length - 1; - sprintf(addrformat, "%X", maxaddr); - addrchars = (UINT8)strlen(addrformat); - addrmask = maxaddr; - for (row = 0; row < 32; row++) - addrmask |= addrmask >> row; - } - else - { - maxaddr = cpuinfo->space[memdata->spacenum].logbytemask; - addrchars = cpuinfo->space[memdata->spacenum].logchars; - addrmask = cpuinfo->space[memdata->spacenum].logbytemask; - - /* clamp the bytes per chunk */ - while (memdata->bytes_per_chunk < (1 << cpuinfo->space[memdata->spacenum].addr2byte_lshift)) - { - memdata->bytes_per_chunk *= 2; - memdata->chunks_displayed /= 2; - if (memdata->chunks_displayed == 0) - memdata->chunks_displayed = 1; - } - } - - /* determine how many characters we need for an address and set the divider */ - sprintf(addrformat, " %*s%%0%dX ", 8 - addrchars, "", addrchars); - - /* determine how wide the memory display area is */ - bytes_per_line = memdata->chunks_displayed * memdata->bytes_per_chunk; - memory_display_width = 1 + (bytes_per_line * 3) + 1; /* characters + spaces */ - - /* compute total displayed rows and columns */ - view->total_rows = (maxaddr / bytes_per_line) + 1; - view->total_cols = (1 + 8 + 1) + memory_display_width; - view->total_cols += memdata->ascii_view ? 1 + bytes_per_line : 0 ; /* +1 ??? */ /* 77 : 59; */ - - /* set up the dividers */ - memdata->divider1 = 1 + 8 + 1; - memdata->divider2 = memdata->divider1 + memory_display_width; - if (memdata->reverse_view) - { - int temp = view->total_cols + 1 - memdata->divider2; - memdata->divider2 = view->total_cols + 1 - memdata->divider1; - memdata->divider1 = temp; - } - - /* if our expression is dirty, fix it */ - if (memdata->expression_dirty && memdata->expression_string) - { - parsed_expression *expr; - - /* parse the new expression */ - exprerr = expression_parse(memdata->expression_string, cpu_get_debug_data(Machine->cpu[memdata->cpunum])->symtable, &debug_expression_callbacks, Machine, &expr); - - /* if it worked, update the expression */ - if (exprerr == EXPRERR_NONE) - { - if (memdata->expression) - expression_free(memdata->expression); - memdata->expression = expr; - memdata->expression_dirty = FALSE; - memdata->recompute = TRUE; - } - } - - /* if we're tracking a value, make sure it is visible */ - if (memdata->expression && (memdata->live_tracking || memdata->recompute)) - { - UINT64 result; - - /* recompute the value of the expression */ - exprerr = expression_execute(memdata->expression, &result); - - /* reset the row number */ - if (result != memdata->last_result || memdata->expression_dirty || memdata->cpunum != memdata->cpunum) - { - memdata->last_result = result; - if (memdata->raw_base == NULL) - result = ADDR2BYTE_MASKED(memdata->last_result, cpuinfo, memdata->spacenum); - view->top_row = result / bytes_per_line; - memdata->byte_offset = result % bytes_per_line; - view->cursor_row = view->top_row; - } - memdata->recompute = FALSE; - } - - /* loop over visible rows */ - for (row = 0; row < view->visible_rows; row++) - { - UINT32 effrow = view->top_row + row; - offs_t addrbyte = effrow * bytes_per_line + memdata->byte_offset; - UINT8 attrib = DCA_NORMAL; - UINT32 col = 0; - - /* if this visible row is valid, add it to the buffer */ - if (effrow < view->total_rows) - { - UINT32 effcol = view->left_col; - UINT32 len = 0; - char data[MEM_MAX_LINE_WIDTH]; - int i; - - /* generate the string */ - if (!memdata->reverse_view) - { - len = sprintf(&data[len], addrformat, BYTE2ADDR(addrbyte & addrmask, cpuinfo, memdata->spacenum)); - len += sprintf(&data[len], " "); - switch (memdata->bytes_per_chunk) - { - default: - case 1: - for (i = 0; i < memdata->chunks_displayed; i++) - { - offs_t curaddr = addrbyte + i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], "%02X ", generic_read_byte(memdata, addrbyte + i, !memdata->no_translation)); - else - len += sprintf(&data[len], "** "); - } - break; - - case 2: - for (i = 0; i < memdata->chunks_displayed; i++) - { - offs_t curaddr = addrbyte + 2 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], " %04X ", generic_read_word(memdata, addrbyte + 2 * i, !memdata->no_translation)); - else - len += sprintf(&data[len], " **** "); - } - break; - - case 4: - for (i = 0; i < memdata->chunks_displayed; i++) - { - offs_t curaddr = addrbyte + 4 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], " %08X ", generic_read_dword(memdata, addrbyte + 4 * i, !memdata->no_translation)); - else - len += sprintf(&data[len], " ******** "); - } - break; - - case 8: - for (i = 0; i < memdata->chunks_displayed; i++) - { - offs_t curaddr = addrbyte + 8 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - { - UINT64 qword = generic_read_qword(memdata, addrbyte + 8 * i, !memdata->no_translation); - len += sprintf(&data[len], " %08X%08X ", (UINT32)(qword >> 32), (UINT32)qword); - } - else - len += sprintf(&data[len], " **************** "); - } - break; - } - len += sprintf(&data[len], " "); - if (memdata->ascii_view) - { - for (i = 0; i < bytes_per_line; i++) - { - if (addrbyte + i <= maxaddr) - { - char c = generic_read_byte(memdata, addrbyte + i, !memdata->no_translation); - len += sprintf(&data[len], "%c", isprint((UINT8)c) ? c : '.'); - } - else - len += sprintf(&data[len], " "); - } - len += sprintf(&data[len], " "); - } - } - else - { - len = sprintf(&data[len], " "); - if (memdata->ascii_view) - { - for (i = 0; i < bytes_per_line; i++) - { - if (addrbyte + i <= maxaddr) - { - char c = generic_read_byte(memdata, addrbyte + i, !memdata->no_translation); - len += sprintf(&data[len], "%c", isprint((UINT8)c) ? c : '.'); - } - else - len += sprintf(&data[len], " "); - } - len += sprintf(&data[len], " "); - } - len += sprintf(&data[len], " "); - switch (memdata->bytes_per_chunk) - { - default: - case 1: - for (i = memdata->chunks_displayed - 1; i >= 0; i--) - { - offs_t curaddr = addrbyte + i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], "%02X ", generic_read_byte(memdata, addrbyte + i, !memdata->no_translation)); - else - len += sprintf(&data[len], "** "); - } - break; - - case 2: - for (i = memdata->chunks_displayed - 1; i >= 0; i--) - { - offs_t curaddr = addrbyte + 2 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], " %04X ", generic_read_word(memdata, addrbyte + 2 * i, !memdata->no_translation)); - else - len += sprintf(&data[len], " **** "); - } - break; - - case 4: - for (i = memdata->chunks_displayed - 1; i >= 0; i--) - { - offs_t curaddr = addrbyte + 4 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - len += sprintf(&data[len], " %08X ", generic_read_dword(memdata, addrbyte + 4 * i, !memdata->no_translation)); - else - len += sprintf(&data[len], " ******** "); - } - break; - - case 8: - for (i = memdata->chunks_displayed - 1; i >= 0; i--) - { - offs_t curaddr = addrbyte + 8 * i; - if (curaddr > maxaddr) - len += sprintf(&data[len], " "); - else if (memdata->raw_base != NULL || memdata->no_translation || - cpuinfo->translate == NULL || (*cpuinfo->translate)(cpuinfo->device, memdata->spacenum, TRANSLATE_READ_DEBUG, &curaddr)) - { - UINT64 qword = generic_read_qword(memdata, addrbyte + 8 * i, !memdata->no_translation); - len += sprintf(&data[len], " %08X%08X ", (UINT32)(qword >> 32), (UINT32)qword); - } - else - len += sprintf(&data[len], " **************** "); - } - break; - } - len += sprintf(&data[len], addrformat, BYTE2ADDR(addrbyte & addrmask, cpuinfo, memdata->spacenum)); - } - - /* copy data */ - while (col < view->visible_cols && effcol < len) - { - dest->byte = data[effcol++]; - if (effcol <= memdata->divider1 || effcol >= memdata->divider2) - dest->attrib = attrib | DCA_ANCILLARY; - else if (view->cursor_visible && effcol - 1 == view->cursor_col && effrow == view->cursor_row && dest->byte != ' ') - dest->attrib = attrib | DCA_SELECTED; - else - dest->attrib = attrib; - dest++; - col++; - } - } - - /* fill the rest with blanks */ - while (col < view->visible_cols) - { - dest->byte = ' '; - dest->attrib = (effrow < view->total_rows) ? (attrib | DCA_ANCILLARY) : attrib; - dest++; - col++; - } - } - - /* restore the context */ - if (memdata->raw_base == NULL) - cpu_pop_context(); + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return &memdata->raw; } /*------------------------------------------------- - memory_getprop - return the value - of a given property + memory_view_get_expression - return the + expression string describing the home address -------------------------------------------------*/ -static void memory_getprop(debug_view *view, UINT32 property, debug_property_info *value) +const char *memory_view_get_expression(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return astring_c(memdata->expression.string); +} + + +/*------------------------------------------------- + memory_view_get_bytes_per_chunk - return the + currently displayed bytes per chunk +-------------------------------------------------*/ + +UINT8 memory_view_get_bytes_per_chunk(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->bytes_per_chunk; +} + + +/*------------------------------------------------- + memory_view_get_chunks_per_row - return the + number of chunks displayed across a row +-------------------------------------------------*/ + +UINT32 memory_view_get_chunks_per_row(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->chunks_per_row; +} + + +/*------------------------------------------------- + memory_view_get_reverse - return TRUE if the + memory view is displayed reverse +-------------------------------------------------*/ + +UINT8 memory_view_get_reverse(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->reverse_view; +} + + +/*------------------------------------------------- + memory_view_get_ascii - return TRUE if the + memory view is displaying an ASCII + representation +-------------------------------------------------*/ + +UINT8 memory_view_get_ascii(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->ascii_view; +} + + +/*------------------------------------------------- + memory_view_get_physical - return TRUE if the + memory view is displaying physical addresses + versus logical addresses +-------------------------------------------------*/ + +UINT8 memory_view_get_physical(debug_view *view) +{ + debug_view_memory *memdata = view->extra_data; + assert(view->type == DVT_MEMORY); + debug_view_begin_update(view); + debug_view_end_update(view); + return memdata->no_translation; +} + + +/*------------------------------------------------- + memory_view_set_address_space - set the + address space whose memory is being displayed +-------------------------------------------------*/ + +void memory_view_set_address_space(debug_view *view, const address_space *space) { debug_view_memory *memdata = view->extra_data; - switch (property) + assert(view->type == DVT_MEMORY); + assert(space != NULL); + + if (space != memdata->space) { - case DVP_MEM_EXPRESSION: - value->s = memdata->expression_string; - break; - - case DVP_MEM_TRACK_LIVE: - value->i = memdata->live_tracking; - break; - - case DVP_MEM_NO_TRANSLATION: - value->i = memdata->no_translation; - break; - - case DVP_MEM_CPUNUM: - value->i = memdata->cpunum; - break; - - case DVP_MEM_SPACENUM: - value->i = memdata->spacenum; - break; - - case DVP_MEM_BYTES_PER_CHUNK: - value->i = memdata->bytes_per_chunk; - break; - - case DVP_MEM_REVERSE_VIEW: - value->i = memdata->reverse_view; - break; - - case DVP_MEM_ASCII_VIEW: - value->i = memdata->ascii_view; - break; - - case DVP_MEM_RAW_BASE: - value->p = memdata->raw_base; - break; - - case DVP_MEM_RAW_LENGTH: - value->i = memdata->raw_length; - break; - - case DVP_MEM_RAW_OFFSET_XOR: - value->i = memdata->raw_offset_xor; - break; - - case DVP_MEM_RAW_LITTLE_ENDIAN: - value->i = memdata->raw_little_endian; - break; - - case DVP_MEM_WIDTH: - value->i = memdata->chunks_displayed; - break; - - default: - fatalerror("Attempt to get invalid property %d on debug view type %d", property, view->type); - break; + debug_view_begin_update(view); + memdata->space = space; + memdata->raw.base = NULL; + memdata->expression.dirty = TRUE; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); } } /*------------------------------------------------- - memory_setprop - set the value - of a given property + memory_view_set_raw - provide a raw + description of the memory to be displayed -------------------------------------------------*/ -static void memory_setprop(debug_view *view, UINT32 property, debug_property_info value) +void memory_view_set_raw(debug_view *view, const memory_view_raw *raw) { debug_view_memory *memdata = view->extra_data; - switch (property) + assert(view->type == DVT_MEMORY); + assert(raw->base != NULL); + + debug_view_begin_update(view); + memdata->raw = *raw; + memdata->space = NULL; + memdata->expression.dirty = TRUE; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); +} + + +/*------------------------------------------------- + memory_view_set_expression - set the + expression string describing the home address +-------------------------------------------------*/ + +void memory_view_set_expression(debug_view *view, const char *expression) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + assert(expression != NULL); + + debug_view_begin_update(view); + debug_view_expression_set(&memdata->expression, expression); + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); +} + + +/*------------------------------------------------- + memory_view_set_bytes_per_chunk - specify the + number of bytes displayed per chunk +-------------------------------------------------*/ + +void memory_view_set_bytes_per_chunk(debug_view *view, UINT8 chunkbytes) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + assert(chunkbytes < ARRAY_LENGTH(memory_pos_table) && memory_pos_table[chunkbytes].spacing != 0); + + if (chunkbytes != memdata->bytes_per_chunk) { - case DVP_MEM_EXPRESSION: - debug_view_begin_update(view); - - /* free the old expression and allocate a new copy */ - if (memdata->expression_string) - free(memdata->expression_string); - memdata->expression_string = malloc(strlen(value.s) + 1); - if (memdata->expression_string) - strcpy(memdata->expression_string, value.s); - - memdata->expression_dirty = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - case DVP_MEM_NO_TRANSLATION: - if (value.i != memdata->no_translation) - { - debug_view_begin_update(view); - memdata->no_translation = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_TRACK_LIVE: - if (value.i != memdata->live_tracking) - { - debug_view_begin_update(view); - memdata->live_tracking = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_CPUNUM: - if (value.i != memdata->cpunum) - { - debug_view_begin_update(view); - memdata->cpunum = value.i; - view->update_pending = TRUE; - memdata->expression_dirty = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_SPACENUM: - if (value.i != memdata->spacenum) - { - debug_view_begin_update(view); - memdata->spacenum = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_BYTES_PER_CHUNK: - if (value.i != memdata->bytes_per_chunk) - { - debug_view_begin_update(view); - - /* Change chunks_displayed based on the new bytes_per_chunk */ - memdata->chunks_displayed = memdata->chunks_displayed * - memdata->bytes_per_chunk / value.i; - - if (memdata->chunks_displayed <= 0) - memdata->chunks_displayed = 1; - - memdata->bytes_per_chunk = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_REVERSE_VIEW: - if (value.i != memdata->reverse_view) - { - debug_view_begin_update(view); - memdata->reverse_view = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_ASCII_VIEW: - if (value.i != memdata->ascii_view) - { - debug_view_begin_update(view); - memdata->ascii_view = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_RAW_BASE: - if (value.p != memdata->raw_base) - { - debug_view_begin_update(view); - memdata->raw_base = value.p; - memdata->expression_dirty = TRUE; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_RAW_LENGTH: - if (value.i != memdata->raw_length) - { - debug_view_begin_update(view); - memdata->raw_length = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_RAW_OFFSET_XOR: - if (value.i != memdata->raw_offset_xor) - { - debug_view_begin_update(view); - memdata->raw_offset_xor = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_MEM_RAW_LITTLE_ENDIAN: - if (value.i != memdata->raw_little_endian) - { - debug_view_begin_update(view); - memdata->raw_little_endian = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - case DVP_CHARACTER: - debug_view_begin_update(view); - memory_handle_char(view, value.i); - view->update_pending = TRUE; - debug_view_end_update(view); - break; - - case DVP_MEM_WIDTH: - if (value.i != memdata->chunks_displayed) - { - /* lower bounds check - maybe upper bounds check someday? */ - if (value.i < 1) break; - - debug_view_begin_update(view); - memdata->chunks_displayed = value.i; - view->update_pending = TRUE; - debug_view_end_update(view); - } - break; - - - default: - fatalerror("Attempt to set invalid property %d on debug view type %d", property, view->type); - break; + debug_view_begin_update(view); + memdata->bytes_per_chunk = chunkbytes; + memdata->chunks_per_row = memdata->bytes_per_row / chunkbytes; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + memory_view_set_chunks_per_row - specify the + number of chunks displayed across a row +-------------------------------------------------*/ + +void memory_view_set_chunks_per_row(debug_view *view, UINT32 rowchunks) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + assert(rowchunks > 0); + + if (rowchunks != memdata->chunks_per_row) + { + debug_view_begin_update(view); + memdata->chunks_per_row = rowchunks; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + memory_view_set_reverse - specify TRUE if the + memory view is displayed reverse +-------------------------------------------------*/ + +void memory_view_set_reverse(debug_view *view, UINT8 reverse) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + + if (reverse != memdata->reverse_view) + { + debug_view_begin_update(view); + memdata->reverse_view = reverse; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + memory_view_set_ascii - specify TRUE if the + memory view should display an ASCII + representation +-------------------------------------------------*/ + +void memory_view_set_ascii(debug_view *view, UINT8 ascii) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + + if (ascii != memdata->ascii_view) + { + debug_view_begin_update(view); + memdata->ascii_view = ascii; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); + } +} + + +/*------------------------------------------------- + memory_view_set_physical - specify TRUE if the + memory view should display physical addresses + versus logical addresses +-------------------------------------------------*/ + +void memory_view_set_physical(debug_view *view, UINT8 physical) +{ + debug_view_memory *memdata = view->extra_data; + + assert(view->type == DVT_MEMORY); + + if (physical != memdata->no_translation) + { + debug_view_begin_update(view); + memdata->no_translation = physical; + view->recompute = view->update_pending = TRUE; + debug_view_end_update(view); } } diff --git a/src/emu/debug/debugvw.h b/src/emu/debug/debugvw.h index 066bbc6d76d..26e70be9620 100644 --- a/src/emu/debug/debugvw.h +++ b/src/emu/debug/debugvw.h @@ -26,40 +26,25 @@ #define DVT_TIMERS (6) #define DVT_ALLOCS (7) -/* properties available for all views */ -#define DVP_VISIBLE_ROWS (1) /* r/w - UINT32 */ -#define DVP_VISIBLE_COLS (2) /* r/w - UINT32 */ -#define DVP_TOTAL_ROWS (3) /* r/w - UINT32 */ -#define DVP_TOTAL_COLS (4) /* r/w - UINT32 */ -#define DVP_TOP_ROW (5) /* r/w - UINT32 */ -#define DVP_LEFT_COL (6) /* r/w - UINT32 */ -#define DVP_UPDATE_CALLBACK (7) /* r/w - void (*update)(debug_view *) */ -#define DVP_VIEW_DATA (8) /* r/o - debug_view_char * */ -#define DVP_SUPPORTS_CURSOR (9) /* r/o - UINT32 */ -#define DVP_CURSOR_VISIBLE (10) /* r/w - UINT32 */ -#define DVP_CURSOR_ROW (11) /* r/w - UINT32 */ -#define DVP_CURSOR_COL (12) /* r/w - UINT32 */ -#define DVP_CHARACTER (13) /* w/o - UINT32 */ -#define DVP_OSD_PRIVATE (14) /* r/w - void * */ - -/* properties available for register views */ -#define DVP_REGS_CPUNUM (100) /* r/w - UINT32 */ +enum _disasm_right_column +{ + DASM_RIGHTCOL_NONE, + DASM_RIGHTCOL_RAW, + DASM_RIGHTCOL_ENCRYPTED, + DASM_RIGHTCOL_COMMENTS +}; +typedef enum _disasm_right_column disasm_right_column; /* properties available for disassembly views */ -#define DVP_DASM_CPUNUM (100) /* r/w - UINT32 */ #define DVP_DASM_EXPRESSION (101) /* r/w - const char * */ #define DVP_DASM_TRACK_LIVE (102) /* r/w - UINT32 */ #define DVP_DASM_RIGHT_COLUMN (103) /* r/w - UINT32 */ -#define DVP_DASM_RIGHTCOL_NONE (0) -#define DVP_DASM_RIGHTCOL_RAW (1) -#define DVP_DASM_RIGHTCOL_ENCRYPTED (2) -#define DVP_DASM_RIGHTCOL_COMMENTS (3) #define DVP_DASM_BACKWARD_STEPS (104) /* r/w - UINT32 */ #define DVP_DASM_WIDTH (105) /* r/w - UINT32 */ #define DVP_DASM_ACTIVE_ADDRESS (112) /* r/w - UINT32 */ /* properties available for memory views */ -#define DVP_MEM_CPUNUM (100) /* r/w - UINT32 */ +#define DVP_MEM_SPACE (100) /* r/w - address space * */ #define DVP_MEM_EXPRESSION (101) /* r/w - const char * */ #define DVP_MEM_TRACK_LIVE (102) /* r/w - UINT32 */ #define DVP_MEM_SPACENUM (103) /* r/w - UINT32 */ @@ -73,9 +58,6 @@ #define DVP_MEM_WIDTH (111) /* r/w - UINT32 */ #define DVP_MEM_NO_TRANSLATION (113) /* r/w - UINT32 */ -/* properties available for textbuffer views */ -#define DVP_TEXTBUF_LINE_LOCK (100) /* r/w - UINT32 */ - /* attribute bits for debug_view_char.attrib */ #define DCA_NORMAL (0x00) /* in Windows: black on white */ #define DCA_CHANGED (0x01) /* in Windows: red foreground */ @@ -101,11 +83,6 @@ #define DCH_CTRLLEFT (12) /* ctrl+left */ -/*************************************************************************** - MACROS -***************************************************************************/ - - /*************************************************************************** TYPE DEFINITIONS @@ -115,23 +92,37 @@ typedef struct _debug_view debug_view; +/* OSD callback function for a view */ +typedef void (*debug_view_osd_update_func)(debug_view *view, void *osdprivate); + + +/* pair of X,Y coordinates for sizing */ +typedef struct _debug_view_xy debug_view_xy; +struct _debug_view_xy +{ + INT32 x; + INT32 y; +}; + + /* a single "character" in the debug view has an ASCII value and an attribute byte */ +typedef struct _debug_view_char debug_view_char; struct _debug_view_char { UINT8 byte; UINT8 attrib; }; -typedef struct _debug_view_char debug_view_char; -union _debug_property_info +/* description of a raw memory space */ +typedef struct _memory_view_raw memory_view_raw; +struct _memory_view_raw { - UINT32 i; - const char *s; - void *p; - genf *f; + void * base; + offs_t length; + offs_t offsetxor; + UINT8 endianness; }; -typedef union _debug_property_info debug_property_info; @@ -139,90 +130,190 @@ typedef union _debug_property_info debug_property_info; FUNCTION PROTOTYPES ***************************************************************************/ -/* initialization */ -void debug_view_init(running_machine *machine); -void debug_view_exit(running_machine *machine); -/* view creation/deletion */ -debug_view * debug_view_alloc(running_machine *machine, int type); -void debug_view_free(debug_view *view); +/* ----- initialization and cleanup ----- */ -/* property management */ -void debug_view_get_property(debug_view *view, int property, debug_property_info *value); -void debug_view_set_property(debug_view *view, int property, debug_property_info value); - -/* update management */ -void debug_view_begin_update(debug_view *view); -void debug_view_end_update(debug_view *view); -void debug_view_update_all(void); -void debug_view_update_type(int type); - -/* misc stuff */ -void debug_disasm_update_all(void); +/* initializes the view system */ +void debug_view_init(running_machine *machine); -/*************************************************************************** - INLINE HELPERS -***************************************************************************/ +/* ----- view creation/deletion ----- */ -INLINE UINT32 debug_view_get_property_UINT32(debug_view *view, int property) -{ - debug_property_info value; - debug_view_get_property(view, property, &value); - return value.i; -} +/* allocate a new debug view */ +debug_view *debug_view_alloc(running_machine *machine, int type, debug_view_osd_update_func osdupdate, void *osdprivate); -INLINE void debug_view_set_property_UINT32(debug_view *view, int property, UINT32 value) -{ - debug_property_info info; - info.i = value; - debug_view_set_property(view, property, info); -} +/* free a debug view */ +void debug_view_free(debug_view *view); -INLINE const char *debug_view_get_property_string(debug_view *view, int property) -{ - debug_property_info value; - debug_view_get_property(view, property, &value); - return value.s; -} -INLINE void debug_view_set_property_string(debug_view *view, int property, const char *value) -{ - debug_property_info info; - info.s = value; - debug_view_set_property(view, property, info); -} +/* ----- update management ----- */ + +/* begin a sequence of changes so that only one update occurs */ +void debug_view_begin_update(debug_view *view); + +/* complete a sequence of changes so that only one update occurs */ +void debug_view_end_update(debug_view *view); + +/* force all views to refresh */ +void debug_view_update_all(void); + +/* force all views of a given type to refresh */ +void debug_view_update_type(int type); + +/* force all disassembly views to refresh */ +void debug_disasm_update_all(void); -INLINE void *debug_view_get_property_ptr(debug_view *view, int property) -{ - debug_property_info value; - debug_view_get_property(view, property, &value); - return value.p; -} -INLINE void debug_view_set_property_ptr(debug_view *view, int property, void *value) -{ - debug_property_info info; - info.s = value; - debug_view_set_property(view, property, info); -} +/* ----- standard view properties ----- */ + +/* return a pointer to a 2-dimentional array of characters that represent the visible area of the view */ +const debug_view_char *debug_view_get_chars(debug_view *view); + +/* type a character into a view */ +void debug_view_type_character(debug_view *view, int character); -INLINE genf *debug_view_get_property_fct(debug_view *view, int property) -{ - debug_property_info value; - debug_view_get_property(view, property, &value); - return value.f; -} -INLINE void debug_view_set_property_fct(debug_view *view, int property, genf *value) -{ - debug_property_info info; - info.f = value; - debug_view_set_property(view, property, info); -} +/* ----- standard view sizing ----- */ + +/* return the total view size in rows and columns */ +debug_view_xy debug_view_get_total_size(debug_view *view); + +/* return the visible size in rows and columns */ +debug_view_xy debug_view_get_visible_size(debug_view *view); + +/* return the top left position of the visible area in rows and columns */ +debug_view_xy debug_view_get_visible_position(debug_view *view); + +/* set the visible size in rows and columns */ +void debug_view_set_visible_size(debug_view *view, debug_view_xy size); + +/* set the top left position of the visible area in rows and columns */ +void debug_view_set_visible_position(debug_view *view, debug_view_xy pos); + + + +/* ----- standard view cursor management ----- */ + +/* return the current cursor position as a row and column */ +debug_view_xy debug_view_get_cursor_position(debug_view *view); + +/* return TRUE if a cursor is supported for this view type */ +int debug_view_get_cursor_supported(debug_view *view); + +/* return TRUE if a cursor is currently visible */ +int debug_view_get_cursor_visible(debug_view *view); + +/* set the current cursor position as a row and column */ +void debug_view_set_cursor_position(debug_view *view, debug_view_xy pos); + +/* set the visible state of the cursor */ +void debug_view_set_cursor_visible(debug_view *view, int visible); + + + +/* ----- registers view-specific properties ----- */ + +/* return the CPU whose registers are currently displayed */ +const device_config *registers_view_get_cpu(debug_view *view); + +/* specify the CPU whose registers are to be displayed */ +void registers_view_set_cpu(debug_view *view, const device_config *device); + + + +/* ----- disassembly view-specific properties ----- */ + +/* return the address space whose disassembly is being displayed */ +const address_space *disasm_view_get_address_space(debug_view *view); + +/* return the expression string describing the home address */ +const char *disasm_view_get_expression(debug_view *view); + +/* return the contents of the right column */ +disasm_right_column disasm_view_get_right_column(debug_view *view); + +/* return the number of instructions displayed before the home address */ +UINT32 disasm_view_get_backward_steps(debug_view *view); + +/* return the width in characters of the main disassembly section */ +UINT32 disasm_view_get_disasm_width(debug_view *view); + +/* return the PC of the currently selected address in the view */ +offs_t disasm_view_get_selected_address(debug_view *view); + +/* set the address space whose disassembly is being displayed */ +void disasm_view_set_address_space(debug_view *view, const address_space *space); + +/* set the expression string describing the home address */ +void disasm_view_set_expression(debug_view *view, const char *expression); + +/* set the contents of the right column */ +void disasm_view_set_right_column(debug_view *view, disasm_right_column contents); + +/* set the number of instructions displayed before the home address */ +void disasm_view_set_backward_steps(debug_view *view, UINT32 steps); + +/* set the width in characters of the main disassembly section */ +void disasm_view_set_disasm_width(debug_view *view, UINT32 width); + +/* set the PC of the currently selected address in the view */ +void disasm_view_set_selected_address(debug_view *view, offs_t address); + + + +/* ----- memory view-specific properties ----- */ + +/* return the address space whose memory is being displayed */ +const address_space *memory_view_get_address_space(debug_view *view); + +/* return a raw description of the memory being displayed */ +const memory_view_raw *memory_view_get_raw(debug_view *view); + +/* return the expression string describing the home address */ +const char *memory_view_get_expression(debug_view *view); + +/* return the currently displayed bytes per chunk */ +UINT8 memory_view_get_bytes_per_chunk(debug_view *view); + +/* return the number of chunks displayed across a row */ +UINT32 memory_view_get_chunks_per_row(debug_view *view); + +/* return TRUE if the memory view is displayed reverse */ +UINT8 memory_view_get_reverse(debug_view *view); + +/* return TRUE if the memory view is displaying an ASCII representation */ +UINT8 memory_view_get_ascii(debug_view *view); + +/* return TRUE if the memory view is displaying physical addresses versus logical addresses */ +UINT8 memory_view_get_physical(debug_view *view); + +/* set the address space whose memory is being displayed */ +void memory_view_set_address_space(debug_view *view, const address_space *space); + +/* provide a raw description of the memory to be displayed */ +void memory_view_set_raw(debug_view *view, const memory_view_raw *raw); + +/* set the expression string describing the home address */ +void memory_view_set_expression(debug_view *view, const char *expression); + +/* specify the number of bytes displayed per chunk */ +void memory_view_set_bytes_per_chunk(debug_view *view, UINT8 chunkbytes); + +/* specify the number of chunks displayed across a row */ +void memory_view_set_chunks_per_row(debug_view *view, UINT32 rowchunks); + +/* specify TRUE if the memory view is displayed reverse */ +void memory_view_set_reverse(debug_view *view, UINT8 reverse); + +/* specify TRUE if the memory view should display an ASCII representation */ +void memory_view_set_ascii(debug_view *view, UINT8 ascii); + +/* specify TRUE if the memory view should display physical addresses versus logical addresses */ +void memory_view_set_physical(debug_view *view, UINT8 physical); + #endif diff --git a/src/emu/memory.c b/src/emu/memory.c index a7fde05120a..ef996c1bd9a 100644 --- a/src/emu/memory.c +++ b/src/emu/memory.c @@ -1316,6 +1316,27 @@ UINT64 *_memory_install_device_handler64(const address_space *space, const devic +/*************************************************************************** + MISCELLANEOUS UTILITIES +***************************************************************************/ + +/*------------------------------------------------- + memory_address_physical - return the physical + address corresponding to the given logical + address +-------------------------------------------------*/ + +int memory_address_physical(const address_space *space, int intention, offs_t *address) +{ + cpu_class_header *classheader = space->cpu->classtoken; + if (classheader->translate != NULL) + return (*classheader->translate)(space->cpu, space->spacenum, intention, address); + else + return TRUE; +} + + + /*************************************************************************** DEBUGGER HELPERS ***************************************************************************/ @@ -1473,24 +1494,36 @@ static void memory_init_spaces(running_machine *machine) if (cputype_get_addrbus_width(cputype, spacenum) > 0) { address_space *space = malloc_or_die(sizeof(*space)); - int accessorindex; + int logbits = cputype_get_logaddr_width(cputype, spacenum); + int ashift = cputype_get_addrbus_shift(cputype, spacenum); + int abits = cputype_get_addrbus_width(cputype, spacenum); + int dbits = cputype_get_databus_width(cputype, spacenum); + int endianness = cputype_get_endianness(cputype); + int accessorindex = (dbits == 8) ? 0 : (dbits == 16) ? 1 : (dbits == 32) ? 2 : 3; int entrynum; + + /* if logbits is 0, revert to abits */ + if (logbits == 0) + logbits = abits; /* determine the address and data bits */ memset(space, 0, sizeof(*space)); space->machine = machine; space->cpu = machine->cpu[cpunum]; - space->spacenum = spacenum; space->name = address_space_names[spacenum]; - space->endianness = cputype_get_endianness(cputype); - space->ashift = cputype_get_addrbus_shift(cputype, spacenum); - space->abits = cputype_get_addrbus_width(cputype, spacenum); - space->dbits = cputype_get_databus_width(cputype, spacenum); - space->addrmask = 0xffffffffUL >> (32 - space->abits); - space->bytemask = ADDR2BYTE_END(space, space->addrmask); - accessorindex = (space->dbits == 8) ? 0 : (space->dbits == 16) ? 1 : (space->dbits == 32) ? 2 : 3; - space->accessors = memory_accessors[accessorindex][(space->endianness == CPU_IS_LE) ? 0 : 1]; - space->map = NULL; + space->accessors = memory_accessors[accessorindex][(endianness == CPU_IS_LE) ? 0 : 1]; + space->addrmask = 0xffffffffUL >> (32 - abits); + space->bytemask = (ashift < 0) ? ((space->addrmask << -ashift) | ((1 << -ashift) - 1)) : (space->addrmask >> ashift); + space->logaddrmask = 0xffffffffUL >> (32 - logbits); + space->logbytemask = (ashift < 0) ? ((space->logaddrmask << -ashift) | ((1 << -ashift) - 1)) : (space->logaddrmask >> ashift); + space->spacenum = spacenum; + space->endianness = endianness; + space->ashift = ashift; + space->pageshift = cputype_get_page_shift(cputype, spacenum); + space->abits = abits; + space->dbits = dbits; + space->addrchars = (abits + 3) / 4; + space->logaddrchars = (logbits + 3) / 4; space->log_unmap = TRUE; /* allocate subtable information; we malloc this manually because it will be realloc'ed */ @@ -2931,40 +2964,40 @@ static address_map_entry *block_assign_intersecting(address_space *space, offs_t static READ8_HANDLER( unmap_read8 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory byte read from %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset)); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory byte read from %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset)); return space->unmap; } static READ16_HANDLER( unmap_read16 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory word read from %08X & %04X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*2), mem_mask); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory word read from %08X & %04X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*2), mem_mask); return space->unmap; } static READ32_HANDLER( unmap_read32 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory dword read from %08X & %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*4), mem_mask); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory dword read from %08X & %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*4), mem_mask); return space->unmap; } static READ64_HANDLER( unmap_read64 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory qword read from %08X & %08X%08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*8), (int)(mem_mask >> 32), (int)(mem_mask & 0xffffffff)); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory qword read from %08X & %08X%08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*8), (int)(mem_mask >> 32), (int)(mem_mask & 0xffffffff)); return space->unmap; } static WRITE8_HANDLER( unmap_write8 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory byte write to %08X = %02X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset), data); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory byte write to %08X = %02X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset), data); } static WRITE16_HANDLER( unmap_write16 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory word write to %08X = %04X & %04X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*2), data, mem_mask); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory word write to %08X = %04X & %04X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*2), data, mem_mask); } static WRITE32_HANDLER( unmap_write32 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory dword write to %08X = %08X & %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*4), data, mem_mask); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory dword write to %08X = %08X & %08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*4), data, mem_mask); } static WRITE64_HANDLER( unmap_write64 ) { - if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory qword write to %08X = %08X%08X & %08X%08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, cpu_byte_to_address(space->cpu, space->spacenum, offset*8), (int)(data >> 32), (int)(data & 0xffffffff), (int)(mem_mask >> 32), (int)(mem_mask & 0xffffffff)); + if (space->log_unmap && !space->debugger_access) logerror("CPU '%s' (PC=%08X): unmapped %s memory qword write to %08X = %08X%08X & %08X%08X\n", space->cpu->tag, cpu_get_pc(space->cpu), space->name, memory_byte_to_address(space, offset*8), (int)(data >> 32), (int)(data & 0xffffffff), (int)(mem_mask >> 32), (int)(mem_mask & 0xffffffff)); } diff --git a/src/emu/memory.h b/src/emu/memory.h index 4c981ca1ca8..e6ef8ef4923 100644 --- a/src/emu/memory.h +++ b/src/emu/memory.h @@ -280,13 +280,18 @@ struct _address_space direct_read_data direct; /* fast direct-access read info */ direct_update_func directupdate; /* fast direct-access update callback */ UINT64 unmap; /* unmapped value */ - offs_t addrmask; /* global address mask */ - offs_t bytemask; /* byte-converted global address mask */ + offs_t addrmask; /* physical address mask */ + offs_t bytemask; /* byte-converted physical address mask */ + offs_t logaddrmask; /* logical address mask */ + offs_t logbytemask; /* byte-converted logical address mask */ UINT8 spacenum; /* address space index */ UINT8 endianness; /* endianness of this space */ INT8 ashift; /* address shift */ + UINT8 pageshift; /* page shift */ UINT8 abits; /* address bits */ UINT8 dbits; /* data bits */ + UINT8 addrchars; /* number of characters to use for physical addresses */ + UINT8 logaddrchars; /* number of characters to use for logical addresses */ UINT8 debugger_access; /* treat accesses as coming from the debugger */ UINT8 log_unmap; /* log unmapped accesses in this space? */ address_table read; /* memory read lookup table */ @@ -935,6 +940,13 @@ UINT64 *_memory_install_device_handler64(const address_space *space, const devic +/* ----- miscellaneous utilities ----- */ + +/* return the physical address corresponding to the given logical address */ +int memory_address_physical(const address_space *space, int intention, offs_t *address); + + + /* ----- debugger helpers ----- */ /* return a string describing the handler at a particular offset */ @@ -964,6 +976,54 @@ void memory_dump(running_machine *machine, FILE *file); INLINE FUNCTIONS ***************************************************************************/ +/*------------------------------------------------- + memory_address_to_byte - convert an address in + the specified address space to a byte offset +-------------------------------------------------*/ + +INLINE offs_t memory_address_to_byte(const address_space *space, offs_t address) +{ + return (space->ashift < 0) ? (address << -space->ashift) : (address >> space->ashift); +} + + +/*------------------------------------------------- + memory_address_to_byte_end - convert an address + in the specified address space to a byte + offset specifying the last byte covered by + the address +-------------------------------------------------*/ + +INLINE offs_t memory_address_to_byte_end(const address_space *space, offs_t address) +{ + return (space->ashift < 0) ? ((address << -space->ashift) | ((1 << -space->ashift) - 1)) : (address >> space->ashift); +} + + +/*------------------------------------------------- + memory_byte_to_address - convert a byte offset + to an address in the specified address space +-------------------------------------------------*/ + +INLINE offs_t memory_byte_to_address(const address_space *space, offs_t address) +{ + return (space->ashift < 0) ? (address >> -space->ashift) : (address << space->ashift); +} + + +/*------------------------------------------------- + memory_byte_to_address_end - convert a byte + offset to an address in the specified address + space specifying the last address covered by + the byte +-------------------------------------------------*/ + +INLINE offs_t memory_byte_to_address_end(const address_space *space, offs_t address) +{ + return (space->ashift < 0) ? (address >> -space->ashift) : ((address << space->ashift) | ((1 << space->ashift) - 1)); +} + + /*------------------------------------------------- memory_read_byte/word/dword/qword - read a value from the specified address space diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index 529c5cd3cc8..766eef88c67 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -97,7 +97,7 @@ void osd_init(running_machine *machine); -void osd_wait_for_debugger(running_machine *machine, int firststop); +void osd_wait_for_debugger(const device_config *device, int firststop); diff --git a/src/osd/windows/debugwin.c b/src/osd/windows/debugwin.c index 5e6cb50caa8..43959cae57b 100644 --- a/src/osd/windows/debugwin.c +++ b/src/osd/windows/debugwin.c @@ -121,7 +121,6 @@ struct _debugview_info HWND wnd; HWND hscroll; HWND vscroll; - UINT8 is_textbuf; }; @@ -162,12 +161,8 @@ struct _memorycombo_item { memorycombo_item * next; TCHAR name[256]; - UINT8 cpunum; - UINT8 spacenum; - void * base; - UINT32 length; - UINT8 offset_xor; - UINT8 little_endian; + const address_space * space; + memory_view_raw raw; UINT8 prefsize; }; @@ -204,17 +199,16 @@ static DWORD last_debugger_update; // PROTOTYPES //============================================================ -static debugwin_info *debug_window_create(running_machine *machine, LPCSTR title, WNDPROC handler); -static void debug_window_free(debugwin_info *info); -static LRESULT CALLBACK debug_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); +static debugwin_info *debugwin_window_create(running_machine *machine, LPCSTR title, WNDPROC handler); +static void debugwin_window_free(debugwin_info *info); +static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); -static void debug_view_draw_contents(debugview_info *view, HDC dc); -static debugview_info *debug_view_find(debug_view *view); -static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); -static void debug_view_update(debug_view *view); -static int debug_view_create(debugwin_info *info, int which, int type); +static void debugwin_view_draw_contents(debugview_info *view, HDC dc); +static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); +static void debugwin_view_update(debug_view *view, void *osdprivate); +static int debugwin_view_create(debugwin_info *info, int which, int type); -static LRESULT CALLBACK debug_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); +static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam); //static void generic_create_window(int type); static void generic_recompute_children(debugwin_info *info); @@ -237,7 +231,7 @@ static void disasm_update_caption(running_machine *machine, HWND wnd); static void console_create_window(running_machine *machine); static void console_recompute_children(debugwin_info *info); static void console_process_string(debugwin_info *info, const char *string); -static void console_set_cpunum(running_machine *machine, int cpunum); +static void console_set_cpu(const device_config *device); static HMENU create_standard_menubar(void); static int global_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam); @@ -252,17 +246,17 @@ static void smart_show_all(BOOL show); // osd_wait_for_debugger //============================================================ -void osd_wait_for_debugger(running_machine *machine, int firststop) +void osd_wait_for_debugger(const device_config *device, int firststop) { MSG message; // create a console window if (main_console == NULL) - console_create_window(machine); + console_create_window(device->machine); // update the views in the console to reflect the current CPU if (main_console != NULL) - console_set_cpunum(machine, cpunum_get_active()); + console_set_cpu(device); // when we are first stopped, adjust focus to us if (firststop && main_console != NULL) @@ -277,7 +271,7 @@ void osd_wait_for_debugger(running_machine *machine, int firststop) smart_show_all(TRUE); // run input polling to ensure that our status is in sync - wininput_poll(machine); + wininput_poll(device->machine); // get and process messages GetMessage(&message, NULL, 0, 0); @@ -296,7 +290,7 @@ void osd_wait_for_debugger(running_machine *machine, int firststop) // process everything else default: - winwindow_dispatch_message(machine, &message); + winwindow_dispatch_message(device->machine, &message); break; } @@ -381,7 +375,7 @@ void debugwin_init_windows(void) // initialize the description of the window class wc.lpszClassName = TEXT("MAMEDebugWindow"); wc.hInstance = GetModuleHandle(NULL); - wc.lpfnWndProc = debug_window_proc; + wc.lpfnWndProc = debugwin_window_proc; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.lpszMenuName = NULL; @@ -396,7 +390,7 @@ void debugwin_init_windows(void) // initialize the description of the view class wc.lpszClassName = TEXT("MAMEDebugView"); - wc.lpfnWndProc = debug_view_proc; + wc.lpfnWndProc = debugwin_view_proc; // register the class; fail if we can't if (!RegisterClass(&wc)) @@ -510,10 +504,10 @@ void debugwin_update_during_game(running_machine *machine) //============================================================ -// debug_window_create +// debugwin_window_create //============================================================ -static debugwin_info *debug_window_create(running_machine *machine, LPCSTR title, WNDPROC handler) +static debugwin_info *debugwin_window_create(running_machine *machine, LPCSTR title, WNDPROC handler) { debugwin_info *info = NULL; RECT work_bounds; @@ -559,10 +553,10 @@ cleanup: //============================================================ -// debug_window_free +// debugwin_window_free //============================================================ -static void debug_window_free(debugwin_info *info) +static void debugwin_window_free(debugwin_info *info) { debugwin_info *prev, *curr; int viewnum; @@ -593,10 +587,10 @@ static void debug_window_free(debugwin_info *info) //============================================================ -// debug_window_draw_contents +// debugwin_window_draw_contents //============================================================ -static void debug_window_draw_contents(debugwin_info *info, HDC dc) +static void debugwin_window_draw_contents(debugwin_info *info, HDC dc) { RECT bounds, parent; int curview, curwnd; @@ -650,10 +644,10 @@ static void debug_window_draw_contents(debugwin_info *info, HDC dc) //============================================================ -// debug_window_proc +// debugwin_window_proc //============================================================ -static LRESULT CALLBACK debug_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) +static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA); @@ -676,7 +670,7 @@ static LRESULT CALLBACK debug_window_proc(HWND wnd, UINT message, WPARAM wparam, { PAINTSTRUCT pstruct; HDC dc = BeginPaint(wnd, &pstruct); - debug_window_draw_contents(info, dc); + debugwin_window_draw_contents(info, dc); EndPaint(wnd, &pstruct); break; } @@ -786,7 +780,7 @@ static LRESULT CALLBACK debug_window_proc(HWND wnd, UINT message, WPARAM wparam, // destroy: close down the window case WM_NCDESTROY: - debug_window_free(info); + debugwin_window_free(info); break; // everything else: defaults @@ -800,13 +794,12 @@ static LRESULT CALLBACK debug_window_proc(HWND wnd, UINT message, WPARAM wparam, //============================================================ -// debug_view_create +// debugwin_view_create //============================================================ -static int debug_view_create(debugwin_info *info, int which, int type) +static int debugwin_view_create(debugwin_info *info, int which, int type) { debugview_info *view = &info->view[which]; - void *callback = (void *)debug_view_update; // set the owner view->owner = info; @@ -826,12 +819,10 @@ static int debug_view_create(debugwin_info *info, int which, int type) goto cleanup; // create the debug view - view->view = debug_view_alloc(info->machine, type); + view->view = debug_view_alloc(info->machine, type, debugwin_view_update, view); if (view->view == NULL) goto cleanup; - // set the update handler - debug_view_set_property_fct(view->view, DVP_UPDATE_CALLBACK, callback); return 1; cleanup: @@ -849,10 +840,10 @@ cleanup: //============================================================ -// debug_view_set_bounds +// debugwin_view_set_bounds //============================================================ -static void debug_view_set_bounds(debugview_info *info, HWND parent, const RECT *newbounds) +static void debugwin_view_set_bounds(debugview_info *info, HWND parent, const RECT *newbounds) { RECT bounds = *newbounds; @@ -861,20 +852,20 @@ static void debug_view_set_bounds(debugview_info *info, HWND parent, const RECT smart_set_window_bounds(info->wnd, parent, &bounds); // update - debug_view_update(info->view); + debugwin_view_update(info->view, info); } //============================================================ -// debug_view_draw_contents +// debugwin_view_draw_contents //============================================================ -static void debug_view_draw_contents(debugview_info *view, HDC windc) +static void debugwin_view_draw_contents(debugview_info *view, HDC windc) { - debug_view_char *viewdata; + const debug_view_char *viewdata = debug_view_get_chars(view->view); + debug_view_xy visarea = debug_view_get_visible_size(view->view); HGDIOBJ oldfont, oldbitmap; - UINT32 visrows, viscols; COLORREF oldfgcolor; UINT32 col, row; HBITMAP bitmap; @@ -897,11 +888,6 @@ static void debug_view_draw_contents(debugview_info *view, HDC windc) } oldbitmap = SelectObject(dc, bitmap); - // first get the visible size from the view and a pointer to the data - visrows = debug_view_get_property_UINT32(view->view, DVP_VISIBLE_ROWS); - viscols = debug_view_get_property_UINT32(view->view, DVP_VISIBLE_COLS); - viewdata = debug_view_get_property_ptr(view->view, DVP_VIEW_DATA); - // set the font oldfont = SelectObject(dc, debug_font); oldfgcolor = GetTextColor(dc); @@ -909,7 +895,7 @@ static void debug_view_draw_contents(debugview_info *view, HDC windc) SetBkMode(dc, TRANSPARENT); // iterate over rows and columns - for (row = 0; row < visrows; row++) + for (row = 0; row < visarea.y; row++) { int iter; @@ -934,7 +920,7 @@ static void debug_view_draw_contents(debugview_info *view, HDC windc) bgbrush = CreateSolidBrush(bgcolor); // iterate over columns - for (col = 0; col < viscols; col++) + for (col = 0; col < visarea.x; col++) { // if the attribute changed, adjust the colors if (viewdata[col].attrib != last_attrib) @@ -1003,12 +989,12 @@ static void debug_view_draw_contents(debugview_info *view, HDC windc) } // advance viewdata - viewdata += viscols; + viewdata += visarea.x; } // erase anything beyond the bottom with white GetClientRect(view->wnd, &client); - client.top = visrows * debug_font_height; + client.top = visarea.y * debug_font_height; FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH)); // reset the font @@ -1028,154 +1014,115 @@ static void debug_view_draw_contents(debugview_info *view, HDC windc) //============================================================ -// debug_view_update +// debugwin_view_update //============================================================ -static void debug_view_update(debug_view *view) +static void debugwin_view_update(debug_view *view, void *osdprivate) { - debugview_info *info = debug_view_find(view); + debugview_info *info = osdprivate; + RECT bounds, vscroll_bounds, hscroll_bounds; + debug_view_xy totalsize, visiblesize, topleft; + int show_vscroll, show_hscroll; + SCROLLINFO scrollinfo; + + assert(info->view == view); - // if we have a view window, process it - if (info && info->view) + // get the view window bounds + GetClientRect(info->wnd, &bounds); + visiblesize.x = (bounds.right - bounds.left) / debug_font_width; + visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height; + + // get the updated total rows/cols and left row/col + totalsize = debug_view_get_total_size(view); + topleft = debug_view_get_visible_position(view); + + // determine if we need to show the scrollbars + show_vscroll = show_hscroll = FALSE; + if (totalsize.x > visiblesize.x && bounds.bottom >= hscroll_height) { - RECT bounds, vscroll_bounds, hscroll_bounds; - int show_vscroll, show_hscroll; - UINT32 visible_rows, visible_cols; - UINT32 total_rows, total_cols; - UINT32 top_row, left_col; - SCROLLINFO scrollinfo; + bounds.bottom -= hscroll_height; + visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height; + show_hscroll = TRUE; + } + if (totalsize.y > visiblesize.y && bounds.right >= vscroll_width) + { + bounds.right -= vscroll_width; + visiblesize.x = (bounds.right - bounds.left) / debug_font_width; + show_vscroll = TRUE; + } + if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= vscroll_width) + { + bounds.right -= vscroll_width; + visiblesize.x = (bounds.right - bounds.left) / debug_font_width; + show_vscroll = TRUE; + } - // get the view window bounds - GetClientRect(info->wnd, &bounds); - visible_rows = (bounds.bottom - bounds.top) / debug_font_height; - visible_cols = (bounds.right - bounds.left) / debug_font_width; + // compute the bounds of the scrollbars + GetClientRect(info->wnd, &vscroll_bounds); + vscroll_bounds.left = vscroll_bounds.right - vscroll_width; + if (show_hscroll) + vscroll_bounds.bottom -= hscroll_height; - // get the updated total rows/cols and left row/col - total_rows = debug_view_get_property_UINT32(view, DVP_TOTAL_ROWS); - total_cols = debug_view_get_property_UINT32(view, DVP_TOTAL_COLS); - top_row = debug_view_get_property_UINT32(view, DVP_TOP_ROW); - left_col = debug_view_get_property_UINT32(view, DVP_LEFT_COL); + GetClientRect(info->wnd, &hscroll_bounds); + hscroll_bounds.top = hscroll_bounds.bottom - hscroll_height; + if (show_vscroll) + hscroll_bounds.right -= vscroll_width; - // determine if we need to show the scrollbars - show_vscroll = show_hscroll = 0; - if (total_rows > visible_rows && bounds.right >= vscroll_width) - { - bounds.right -= vscroll_width; - visible_cols = (bounds.right - bounds.left) / debug_font_width; - show_vscroll = TRUE; - } - if (total_cols > visible_cols && bounds.bottom >= hscroll_height) - { - bounds.bottom -= hscroll_height; - visible_rows = (bounds.bottom - bounds.top) / debug_font_height; - show_hscroll = TRUE; - } - if (!show_vscroll && total_rows > visible_rows && bounds.right >= vscroll_width) - { - bounds.right -= vscroll_width; - visible_cols = (bounds.right - bounds.left) / debug_font_width; - show_vscroll = TRUE; - } + // if we hid the scrollbars, make sure we reset the top/left corners + if (topleft.y + visiblesize.y > totalsize.y) + topleft.y = MAX(totalsize.y - visiblesize.y, 0); + if (topleft.x + visiblesize.x > totalsize.x) + topleft.x = MAX(totalsize.x - visiblesize.x, 0); - // compute the bounds of the scrollbars - GetClientRect(info->wnd, &vscroll_bounds); - vscroll_bounds.left = vscroll_bounds.right - vscroll_width; - if (show_hscroll) - vscroll_bounds.bottom -= hscroll_height; + // fill out the scroll info struct for the vertical scrollbar + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.y - 1; + scrollinfo.nPage = visiblesize.y; + scrollinfo.nPos = topleft.y; + SetScrollInfo(info->vscroll, SB_CTL, &scrollinfo, TRUE); - GetClientRect(info->wnd, &hscroll_bounds); - hscroll_bounds.top = hscroll_bounds.bottom - hscroll_height; + // fill out the scroll info struct for the horizontal scrollbar + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.x - 1; + scrollinfo.nPage = visiblesize.x; + scrollinfo.nPos = topleft.x; + SetScrollInfo(info->hscroll, SB_CTL, &scrollinfo, TRUE); + + // update window info + visiblesize.y++; + visiblesize.x++; + debug_view_set_visible_size(view, visiblesize); + debug_view_set_visible_position(view, topleft); + + // invalidate the bounds + InvalidateRect(info->wnd, NULL, FALSE); + + // adjust the bounds of the scrollbars and show/hide them + if (info->vscroll) + { if (show_vscroll) - hscroll_bounds.right -= vscroll_width; - - // if we hid the scrollbars, make sure we reset the top/left corners - if (top_row + visible_rows > total_rows) - top_row = (total_rows > visible_rows) ? (total_rows - visible_rows) : 0; - if (left_col + visible_cols > total_cols) - left_col = (total_cols > visible_cols) ? (total_cols - visible_cols) : 0; - - // fill out the scroll info struct for the vertical scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = total_rows - 1; - scrollinfo.nPage = visible_rows; - scrollinfo.nPos = top_row; - SetScrollInfo(info->vscroll, SB_CTL, &scrollinfo, TRUE); - - // fill out the scroll info struct for the horizontal scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = total_cols - 1; - scrollinfo.nPage = visible_cols; - scrollinfo.nPos = left_col; - SetScrollInfo(info->hscroll, SB_CTL, &scrollinfo, TRUE); - - // update window info - visible_rows++; - visible_cols++; - debug_view_set_property_UINT32(view, DVP_VISIBLE_ROWS, visible_rows); - debug_view_set_property_UINT32(view, DVP_VISIBLE_COLS, visible_cols); - debug_view_set_property_UINT32(view, DVP_TOP_ROW, top_row); - debug_view_set_property_UINT32(view, DVP_LEFT_COL, left_col); - - // invalidate the bounds - InvalidateRect(info->wnd, NULL, FALSE); - - // adjust the bounds of the scrollbars and show/hide them - if (info->vscroll) - { - if (show_vscroll) - smart_set_window_bounds(info->vscroll, info->wnd, &vscroll_bounds); - smart_show_window(info->vscroll, show_vscroll); - } - if (info->hscroll) - { - if (show_hscroll) - smart_set_window_bounds(info->hscroll, info->wnd, &hscroll_bounds); - smart_show_window(info->hscroll, show_hscroll); - } - - // if we're in some tight busy loop, handle messages to keep ourselves alive -/* if (GetTickCount() - last_debugger_update > 1000) - { - MSG message; - while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&message); - DispatchMessage(&message); - } - }*/ + smart_set_window_bounds(info->vscroll, info->wnd, &vscroll_bounds); + smart_show_window(info->vscroll, show_vscroll); + } + if (info->hscroll) + { + if (show_hscroll) + smart_set_window_bounds(info->hscroll, info->wnd, &hscroll_bounds); + smart_show_window(info->hscroll, show_hscroll); } } //============================================================ -// debug_view_find +// debugwin_view_process_scroll //============================================================ -static debugview_info *debug_view_find(debug_view *view) -{ - debugwin_info *info; - int curview; - - // loop over windows and find the view - for (info = window_list; info; info = info->next) - for (curview = 0; curview < MAX_VIEWS; curview++) - if (info->view[curview].view == view) - return &info->view[curview]; - return NULL; -} - - - -//============================================================ -// debug_view_process_scroll -//============================================================ - -static UINT32 debug_view_process_scroll(debugview_info *info, WORD type, HWND wnd) +static UINT32 debugwin_view_process_scroll(debugview_info *info, WORD type, HWND wnd) { SCROLLINFO scrollinfo; INT32 maxval; @@ -1235,20 +1182,16 @@ static UINT32 debug_view_process_scroll(debugview_info *info, WORD type, HWND wn scrollinfo.nPos = result; SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE); - // note if we are at the bottom - if (wnd == info->vscroll && info->is_textbuf && result >= maxval - 1) - return (UINT32)-1; - return (UINT32)result; } //============================================================ -// debug_view_prev_view +// debugwin_view_prev_view //============================================================ -static void debug_view_prev_view(debugwin_info *info, debugview_info *curview) +static void debugwin_view_prev_view(debugwin_info *info, debugview_info *curview) { int curindex = 1; int numviews; @@ -1278,7 +1221,7 @@ static void debug_view_prev_view(debugwin_info *info, debugview_info *curview) } // positive numbers mean a view - else if (curindex >= 0 && info->view[curindex].wnd != NULL && debug_view_get_property_UINT32(info->view[curindex].view, DVP_SUPPORTS_CURSOR)) + else if (curindex >= 0 && info->view[curindex].wnd != NULL && debug_view_get_cursor_supported(info->view[curindex].view)) { SetFocus(info->view[curindex].wnd); break; @@ -1289,10 +1232,10 @@ static void debug_view_prev_view(debugwin_info *info, debugview_info *curview) //============================================================ -// debug_view_next_view +// debugwin_view_next_view //============================================================ -static void debug_view_next_view(debugwin_info *info, debugview_info *curview) +static void debugwin_view_next_view(debugwin_info *info, debugview_info *curview) { int curindex = -1; int numviews; @@ -1322,7 +1265,7 @@ static void debug_view_next_view(debugwin_info *info, debugview_info *curview) } // positive numbers mean a view - else if (curindex >= 0 && info->view[curindex].wnd != NULL && debug_view_get_property_UINT32(info->view[curindex].view, DVP_SUPPORTS_CURSOR)) + else if (curindex >= 0 && info->view[curindex].wnd != NULL && debug_view_get_cursor_supported(info->view[curindex].view)) { SetFocus(info->view[curindex].wnd); InvalidateRect(info->view[curindex].wnd, NULL, FALSE); @@ -1334,10 +1277,10 @@ static void debug_view_next_view(debugwin_info *info, debugview_info *curview) //============================================================ -// debug_view_proc +// debugwin_view_proc //============================================================ -static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) +static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { debugview_info *info = (debugview_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA); @@ -1357,7 +1300,7 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L { PAINTSTRUCT pstruct; HDC dc = BeginPaint(wnd, &pstruct); - debug_view_draw_contents(info, dc); + debugwin_view_draw_contents(info, dc); EndPaint(wnd, &pstruct); break; } @@ -1372,54 +1315,54 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L switch (wparam) { case VK_UP: - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_UP); + debug_view_type_character(info->view, DCH_UP); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_DOWN: - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_DOWN); + debug_view_type_character(info->view, DCH_DOWN); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_LEFT: if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_CTRLLEFT); + debug_view_type_character(info->view, DCH_CTRLLEFT); else - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_LEFT); + debug_view_type_character(info->view, DCH_LEFT); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_RIGHT: if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_CTRLRIGHT); + debug_view_type_character(info->view, DCH_CTRLRIGHT); else - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_RIGHT); + debug_view_type_character(info->view, DCH_RIGHT); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_PRIOR: - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_PUP); + debug_view_type_character(info->view, DCH_PUP); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_NEXT: - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_PDOWN); + debug_view_type_character(info->view, DCH_PDOWN); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_HOME: if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_CTRLHOME); + debug_view_type_character(info->view, DCH_CTRLHOME); else - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_HOME); + debug_view_type_character(info->view, DCH_HOME); info->owner->ignore_char_lparam = lparam >> 16; break; case VK_END: if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_CTRLEND); + debug_view_type_character(info->view, DCH_CTRLEND); else - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, DCH_END); + debug_view_type_character(info->view, DCH_END); info->owner->ignore_char_lparam = lparam >> 16; break; @@ -1431,9 +1374,9 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L case VK_TAB: if (GetAsyncKeyState(VK_SHIFT) & 0x8000) - debug_view_prev_view(info->owner, info); + debugwin_view_prev_view(info->owner, info); else - debug_view_next_view(info->owner, info); + debugwin_view_next_view(info->owner, info); info->owner->ignore_char_lparam = lparam >> 16; break; } @@ -1448,8 +1391,8 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L info->owner->ignore_char_lparam = 0; else if (waiting_for_debugger || !debugwin_seq_pressed(info->owner->machine)) { - if (wparam >= 32 && wparam < 127 && debug_view_get_property_UINT32(info->view, DVP_SUPPORTS_CURSOR)) - debug_view_set_property_UINT32(info->view, DVP_CHARACTER, wparam); + if (wparam >= 32 && wparam < 127 && debug_view_get_cursor_supported(info->view)) + debug_view_type_character(info->view, wparam); else return DefWindowProc(wnd, message, wparam, lparam); } @@ -1459,30 +1402,28 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L // gaining focus case WM_SETFOCUS: { - if (debug_view_get_property_UINT32(info->view, DVP_SUPPORTS_CURSOR)) - debug_view_set_property_UINT32(info->view, DVP_CURSOR_VISIBLE, 1); + if (debug_view_get_cursor_supported(info->view)) + debug_view_set_cursor_visible(info->view, TRUE); break; } // losing focus case WM_KILLFOCUS: { - if (debug_view_get_property_UINT32(info->view, DVP_SUPPORTS_CURSOR)) - debug_view_set_property_UINT32(info->view, DVP_CURSOR_VISIBLE, 0); + if (debug_view_get_cursor_supported(info->view)) + debug_view_set_cursor_visible(info->view, FALSE); break; } // mouse click case WM_LBUTTONDOWN: { - if (debug_view_get_property_UINT32(info->view, DVP_SUPPORTS_CURSOR)) + if (debug_view_get_cursor_supported(info->view)) { - int x = GET_X_LPARAM(lparam) / debug_font_width; - int y = GET_Y_LPARAM(lparam) / debug_font_height; - debug_view_begin_update(info->view); - debug_view_set_property_UINT32(info->view, DVP_CURSOR_ROW, debug_view_get_property_UINT32(info->view, DVP_TOP_ROW) + y); - debug_view_set_property_UINT32(info->view, DVP_CURSOR_COL, debug_view_get_property_UINT32(info->view, DVP_LEFT_COL) + x); - debug_view_end_update(info->view); + debug_view_xy newpos; + newpos.x = GET_X_LPARAM(lparam) / debug_font_width; + newpos.y = GET_Y_LPARAM(lparam) / debug_font_height; + debug_view_set_cursor_position(info->view, newpos); SetFocus(wnd); } break; @@ -1491,19 +1432,18 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L // hscroll case WM_HSCROLL: { - UINT32 left_col = debug_view_process_scroll(info, LOWORD(wparam), (HWND)lparam); - debug_view_set_property_UINT32(info->view, DVP_LEFT_COL, left_col); + debug_view_xy topleft = debug_view_get_visible_position(info->view); + topleft.x = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam); + debug_view_set_visible_position(info->view, topleft); break; } // vscroll case WM_VSCROLL: { - UINT32 top_row = debug_view_process_scroll(info, LOWORD(wparam), (HWND)lparam); - if (info->is_textbuf) - debug_view_set_property_UINT32(info->view, DVP_TEXTBUF_LINE_LOCK, top_row); - else - debug_view_set_property_UINT32(info->view, DVP_TOP_ROW, top_row); + debug_view_xy topleft = debug_view_get_visible_position(info->view); + topleft.y = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam); + debug_view_set_visible_position(info->view, topleft); break; } @@ -1518,10 +1458,10 @@ static LRESULT CALLBACK debug_view_proc(HWND wnd, UINT message, WPARAM wparam, L //============================================================ -// debug_edit_proc +// debugwin_edit_proc //============================================================ -static LRESULT CALLBACK debug_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) +static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA); TCHAR buffer[MAX_EDIT_STRING]; @@ -1565,9 +1505,9 @@ static LRESULT CALLBACK debug_edit_proc(HWND wnd, UINT message, WPARAM wparam, L case VK_TAB: if (GetAsyncKeyState(VK_SHIFT) & 0x8000) - debug_view_prev_view(info, NULL); + debugwin_view_prev_view(info, NULL); else - debug_view_next_view(info, NULL); + debugwin_view_next_view(info, NULL); info->ignore_char_lparam = lparam >> 16; break; @@ -1660,8 +1600,8 @@ static void generic_create_window(running_machine *machine, int type) // create the window _snprintf(title, ARRAY_LENGTH(title), "Debug: %s [%s]", Machine->gamedrv->description, Machine->gamedrv->name); - info = debug_window_create(machine, title, NULL); - if (info == NULL || !debug_view_create(info, 0, type)) + info = debugwin_window_create(machine, title, NULL); + if (info == NULL || !debugwin_view_create(info, 0, type)) return; // set the child function @@ -1684,16 +1624,13 @@ static void generic_create_window(running_machine *machine, int type) static void generic_recompute_children(debugwin_info *info) { + debug_view_xy totalsize = debug_view_get_total_size(info->view[0].view); RECT parent; RECT bounds; - UINT32 width; - - // get the view width - width = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); // compute a client rect bounds.top = bounds.left = 0; - bounds.right = width * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; + bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; bounds.bottom = 200; AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX); @@ -1705,7 +1642,7 @@ static void generic_recompute_children(debugwin_info *info) // view gets the remaining space InflateRect(&parent, -EDGE_WIDTH, -EDGE_WIDTH); - debug_view_set_bounds(&info->view[0], info->wnd, &parent); + debugwin_view_set_bounds(&info->view[0], info->wnd, &parent); } @@ -1716,27 +1653,26 @@ static void generic_recompute_children(debugwin_info *info) static void log_create_window(running_machine *machine) { + debug_view_xy totalsize; debugwin_info *info; char title[256]; - UINT32 width; RECT bounds; // create the window _snprintf(title, ARRAY_LENGTH(title), "Errorlog: %s [%s]", machine->gamedrv->description, machine->gamedrv->name); - info = debug_window_create(machine, title, NULL); - if (info == NULL || !debug_view_create(info, 0, DVT_LOG)) + info = debugwin_window_create(machine, title, NULL); + if (info == NULL || !debugwin_view_create(info, 0, DVT_LOG)) return; - info->view->is_textbuf = TRUE; // set the child function info->recompute_children = generic_recompute_children; // get the view width - width = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); + totalsize = debug_view_get_total_size(info->view[0].view); // compute a client rect bounds.top = bounds.left = 0; - bounds.right = width * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; + bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; bounds.bottom = 200; AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX); @@ -1769,23 +1705,22 @@ static void memory_determine_combo_items(running_machine *machine) // first add all the CPUs' address spaces for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++) if (machine->cpu[cpunum] != NULL) - { - const cpu_debug_data *cpuinfo = cpu_get_debug_data(machine->cpu[cpunum]); for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) - if (cpuinfo->space[spacenum].databytes != 0) + { + const address_space *space = cpu_get_address_space(machine->cpu[cpunum], spacenum); + if (space != NULL) { memorycombo_item *ci = malloc_or_die(sizeof(*ci)); TCHAR *t_tag, *t_name, *t_space; memset(ci, 0, sizeof(*ci)); - ci->cpunum = cpunum; - ci->spacenum = spacenum; - ci->prefsize = MIN(cpuinfo->space[spacenum].databytes, 8); + ci->space = space; + ci->prefsize = MIN(space->dbits / 8, 8); - t_tag = tstring_from_utf8(machine->config->cpu[cpunum].tag); - t_name = tstring_from_utf8(cpu_get_name(machine->cpu[cpunum])); - t_space = tstring_from_utf8(address_space_names[spacenum]); - _sntprintf(ci->name, ARRAY_LENGTH(ci->name), TEXT("CPU #%d \"%s\" (%s) %s memory"), cpunum, t_tag, t_name, t_space); + t_tag = tstring_from_utf8(space->cpu->tag); + t_name = tstring_from_utf8(cpu_get_name(space->cpu)); + t_space = tstring_from_utf8(space->name); + _sntprintf(ci->name, ARRAY_LENGTH(ci->name), TEXT("CPU '%s' (%s) %s memory"), t_tag, t_name, t_space); free(t_space), free(t_name); free(t_tag); @@ -1805,14 +1740,14 @@ static void memory_determine_combo_items(running_machine *machine) TCHAR *t_tag; memset(ci, 0, sizeof(*ci)); - ci->base = memory_region(machine, rgntag); - ci->length = memory_region_length(machine, rgntag); + ci->raw.base = memory_region(machine, rgntag); + ci->raw.length = memory_region_length(machine, rgntag); + ci->raw.offsetxor = width - 1; + ci->raw.endianness = little_endian ? CPU_IS_LE : CPU_IS_BE; ci->prefsize = MIN(width, 8); - ci->offset_xor = width - 1; - ci->little_endian = little_endian; t_tag = tstring_from_utf8(rgntag); - _sntprintf(ci->name, ARRAY_LENGTH(ci->name), TEXT("Region \"%s\""), t_tag); + _sntprintf(ci->name, ARRAY_LENGTH(ci->name), TEXT("Region '%s'"), t_tag); free(t_tag); *tail = ci; @@ -1838,10 +1773,10 @@ static void memory_determine_combo_items(running_machine *machine) TCHAR *t_name; memset(ci, 0, sizeof(*ci)); - ci->base = base; - ci->length = valcount * valsize; + ci->raw.base = base; + ci->raw.length = valcount * valsize; + ci->raw.endianness = CPU_IS_LE; ci->prefsize = MIN(valsize, 8); - ci->little_endian = TRUE; t_name = tstring_from_utf8(name); _tcscpy(ci->name, _tcsrchr(t_name, TEXT('/')) + 1); @@ -1860,13 +1795,13 @@ static void memory_determine_combo_items(running_machine *machine) static void memory_update_selection(debugwin_info *info, memorycombo_item *ci) { - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_CPUNUM, ci->cpunum); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_SPACENUM, ci->spacenum); - debug_view_set_property_ptr(info->view[0].view, DVP_MEM_RAW_BASE, ci->base); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_RAW_LENGTH, ci->length); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_RAW_OFFSET_XOR, ci->offset_xor); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_RAW_LITTLE_ENDIAN, ci->little_endian); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK, ci->prefsize); + debug_view_begin_update(info->view[0].view); + if (ci->space != NULL) + memory_view_set_address_space(info->view[0].view, ci->space); + else + memory_view_set_raw(info->view[0].view, &ci->raw); + memory_view_set_bytes_per_chunk(info->view[0].view, ci->prefsize); + debug_view_end_update(info->view[0].view); SetWindowText(info->wnd, ci->name); } @@ -1877,14 +1812,15 @@ static void memory_update_selection(debugwin_info *info, memorycombo_item *ci) static void memory_create_window(running_machine *machine) { - int curcpu = cpunum_get_active(), cursel = 0; + const device_config *curcpu = debug_cpu_get_visible_cpu(machine); memorycombo_item *ci, *selci = NULL; debugwin_info *info; HMENU optionsmenu; + int cursel = 0; // create the window - info = debug_window_create(machine, "Memory", NULL); - if (info == NULL || !debug_view_create(info, 0, DVT_MEMORY)) + info = debugwin_window_create(machine, "Memory", NULL); + if (info == NULL || !debugwin_view_create(info, 0, DVT_MEMORY)) return; // set the handlers @@ -1909,18 +1845,15 @@ static void memory_create_window(running_machine *machine) AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // set up the view to track the initial expression - debug_view_begin_update(info->view[0].view); - debug_view_set_property_string(info->view[0].view, DVP_MEM_EXPRESSION, "0"); + memory_view_set_expression(info->view[0].view, "0"); strcpy(info->edit_defstr, "0"); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_TRACK_LIVE, 1); - debug_view_end_update(info->view[0].view); // create an edit box and override its key handling info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE, 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL); info->original_editproc = (void *)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC); SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info); - SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debug_edit_proc); + SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc); SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE); SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("0")); SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0); @@ -1935,10 +1868,10 @@ static void memory_create_window(running_machine *machine) // populate the combobox if (memorycombo == NULL) memory_determine_combo_items(machine); - for (ci = memorycombo; ci; ci = ci->next) + for (ci = memorycombo; ci != NULL; ci = ci->next) { int item = SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)ci->name); - if (ci->base == NULL && ci->cpunum == curcpu && ci->spacenum == ADDRESS_SPACE_PROGRAM) + if (selci == NULL && ci->space != NULL && ci->space->cpu == curcpu) { cursel = item; selci = ci; @@ -1975,16 +1908,13 @@ static void memory_create_window(running_machine *machine) static void memory_recompute_children(debugwin_info *info) { + debug_view_xy totalsize = debug_view_get_total_size(info->view[0].view); RECT parent, memrect, editrect, comborect; RECT bounds; - UINT32 width; - - // get the view width - width = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); // compute a client rect bounds.top = bounds.left = 0; - bounds.right = width * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; + bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; bounds.bottom = 200; AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX); @@ -2013,7 +1943,7 @@ static void memory_recompute_children(debugwin_info *info) memrect.right = parent.right - EDGE_WIDTH; // set the bounds of things - debug_view_set_bounds(&info->view[0], info->wnd, &memrect); + debugwin_view_set_bounds(&info->view[0], info->wnd, &memrect); smart_set_window_bounds(info->editwnd, info->wnd, &editrect); smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect); } @@ -2027,7 +1957,7 @@ static void memory_recompute_children(debugwin_info *info) static void memory_process_string(debugwin_info *info, const char *string) { // set the string to the memory view - debug_view_set_property_string(info->view[0].view, DVP_MEM_EXPRESSION, string); + memory_view_set_expression(info->view[0].view, string); // select everything in the edit text box SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1); @@ -2044,13 +1974,13 @@ static void memory_process_string(debugwin_info *info, const char *string) static void memory_update_menu(debugwin_info *info) { - CheckMenuItem(GetMenu(info->wnd), ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK) == 1? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK) == 2 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK) == 4 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK) == 8 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_NO_TRANSLATION) ? MF_UNCHECKED : MF_CHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_NO_TRANSLATION) ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_REVERSE_VIEW, MF_BYCOMMAND | (debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_REVERSE_VIEW) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memory_view_get_bytes_per_chunk(info->view[0].view) == 1 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memory_view_get_bytes_per_chunk(info->view[0].view) == 2 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memory_view_get_bytes_per_chunk(info->view[0].view) == 4 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memory_view_get_bytes_per_chunk(info->view[0].view) == 8 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memory_view_get_physical(info->view[0].view) ? MF_UNCHECKED : MF_CHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memory_view_get_physical(info->view[0].view) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_REVERSE_VIEW, MF_BYCOMMAND | (memory_view_get_reverse(info->view[0].view) ? MF_CHECKED : MF_UNCHECKED)); } @@ -2073,11 +2003,7 @@ static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lpar memorycombo_item *ci; for (ci = memorycombo; ci; ci = ci->next) if (sel-- == 0) - { - debug_view_begin_update(info->view[0].view); memory_update_selection(info, ci); - debug_view_end_update(info->view[0].view); - } // reset the focus SetFocus(info->focuswnd); @@ -2091,57 +2017,39 @@ static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lpar switch (LOWORD(wparam)) { case ID_1_BYTE_CHUNKS: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK, 1); - debug_view_end_update(info->view[0].view); + memory_view_set_bytes_per_chunk(info->view[0].view, 1); return 1; case ID_2_BYTE_CHUNKS: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK, 2); - debug_view_end_update(info->view[0].view); + memory_view_set_bytes_per_chunk(info->view[0].view, 2); return 1; case ID_4_BYTE_CHUNKS: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK, 4); - debug_view_end_update(info->view[0].view); + memory_view_set_bytes_per_chunk(info->view[0].view, 4); return 1; case ID_8_BYTE_CHUNKS: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_BYTES_PER_CHUNK, 8); - debug_view_end_update(info->view[0].view); + memory_view_set_bytes_per_chunk(info->view[0].view, 8); return 1; case ID_LOGICAL_ADDRESSES: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_NO_TRANSLATION, FALSE); - debug_view_end_update(info->view[0].view); + memory_view_set_physical(info->view[0].view, FALSE); return 1; case ID_PHYSICAL_ADDRESSES: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_NO_TRANSLATION, TRUE); - debug_view_end_update(info->view[0].view); + memory_view_set_physical(info->view[0].view, TRUE); return 1; case ID_REVERSE_VIEW: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_REVERSE_VIEW, !debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_REVERSE_VIEW)); - debug_view_end_update(info->view[0].view); + memory_view_set_reverse(info->view[0].view, !memory_view_get_reverse(info->view[0].view)); return 1; case ID_INCREASE_MEM_WIDTH: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_WIDTH, debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_WIDTH) + 1); - debug_view_end_update(info->view[0].view); + memory_view_set_chunks_per_row(info->view[0].view, memory_view_get_chunks_per_row(info->view[0].view) + 1); return 1; case ID_DECREASE_MEM_WIDTH: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_MEM_WIDTH, debug_view_get_property_UINT32(info->view[0].view, DVP_MEM_WIDTH) - 1); - debug_view_end_update(info->view[0].view); + memory_view_set_chunks_per_row(info->view[0].view, memory_view_get_chunks_per_row(info->view[0].view) - 1); return 1; } break; @@ -2209,14 +2117,15 @@ static int memory_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam) static void disasm_create_window(running_machine *machine) { - int curcpu = cpunum_get_active(), cursel = 0; + const address_space *selspace = NULL, *fallbackspace = NULL; + int selindex = 0, fallbackindex = 0; debugwin_info *info; HMENU optionsmenu; UINT32 cpunum; // create the window - info = debug_window_create(machine, "Disassembly", NULL); - if (info == NULL || !debug_view_create(info, 0, DVT_DISASSEMBLY)) + info = debugwin_window_create(machine, "Disassembly", NULL); + if (info == NULL || !debugwin_view_create(info, 0, DVT_DISASSEMBLY)) return; // create the options menu @@ -2235,18 +2144,15 @@ static void disasm_create_window(running_machine *machine) info->update_menu = disasm_update_menu; // set up the view to track the initial expression - debug_view_begin_update(info->view[0].view); - debug_view_set_property_string(info->view[0].view, DVP_DASM_EXPRESSION, "curpc"); + disasm_view_set_expression(info->view[0].view, "curpc"); strcpy(info->edit_defstr, "curpc"); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_TRACK_LIVE, 1); - debug_view_end_update(info->view[0].view); // create an edit box and override its key handling info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE, 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL); info->original_editproc = (void *)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC); SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info); - SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debug_edit_proc); + SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc); SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE); SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("curpc")); SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0); @@ -2262,29 +2168,38 @@ static void disasm_create_window(running_machine *machine) for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++) if (machine->cpu[cpunum] != NULL) { - TCHAR* t_cpunum_name; - const cpu_debug_data *cpuinfo = cpu_get_debug_data(machine->cpu[cpunum]); - if (cpuinfo->space[ADDRESS_SPACE_PROGRAM].databytes) + const address_space *space = cpu_get_address_space(machine->cpu[cpunum], ADDRESS_SPACE_PROGRAM); + if (space != NULL) { + TCHAR *t_cpu_name = tstring_from_utf8(cpu_get_name(space->cpu)); + TCHAR *t_cpu_tag = tstring_from_utf8(space->cpu->tag); TCHAR name[100]; int item; - t_cpunum_name = tstring_from_utf8(cpu_get_name(machine->cpu[cpunum])); - _sntprintf(name, ARRAY_LENGTH(name), TEXT("CPU #%d (%s)"), cpunum, t_cpunum_name); - free(t_cpunum_name); - t_cpunum_name = NULL; + + _sntprintf(name, ARRAY_LENGTH(name), TEXT("CPU '%s' (%s)"), t_cpu_tag, t_cpu_name); + free(t_cpu_tag); + free(t_cpu_name); item = SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)name); - if (cpunum == curcpu) - cursel = item; + if (space->cpu == debug_cpu_get_visible_cpu(machine)) + { + selspace = space; + selindex = item; + } + else if (fallbackspace == NULL) + { + fallbackspace = space; + fallbackindex = item; + } } } - SendMessage(info->otherwnd[0], CB_SETCURSEL, cursel, 0); + SendMessage(info->otherwnd[0], CB_SETCURSEL, (selspace != NULL) ? selindex : fallbackindex, 0); // set the child functions info->recompute_children = disasm_recompute_children; info->process_string = disasm_process_string; - // set the CPUnum and spacenum properties - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM, (curcpu == -1) ? 0 : curcpu); + // set the target space + disasm_view_set_address_space(info->view[0].view, (selspace != NULL) ? selspace : fallbackspace); // set the caption disasm_update_caption(machine, info->wnd); @@ -2309,16 +2224,13 @@ static void disasm_create_window(running_machine *machine) static void disasm_recompute_children(debugwin_info *info) { + debug_view_xy totalsize = debug_view_get_total_size(info->view[0].view); RECT parent, dasmrect, editrect, comborect; RECT bounds; - UINT32 width; - - // get the view width - width = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); // compute a client rect bounds.top = bounds.left = 0; - bounds.right = width * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; + bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH; bounds.bottom = 200; AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX); @@ -2347,7 +2259,7 @@ static void disasm_recompute_children(debugwin_info *info) dasmrect.right = parent.right - EDGE_WIDTH; // set the bounds of things - debug_view_set_bounds(&info->view[0], info->wnd, &dasmrect); + debugwin_view_set_bounds(&info->view[0], info->wnd, &dasmrect); smart_set_window_bounds(info->editwnd, info->wnd, &editrect); smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect); } @@ -2361,7 +2273,7 @@ static void disasm_recompute_children(debugwin_info *info) static void disasm_process_string(debugwin_info *info, const char *string) { // set the string to the disasm view - debug_view_set_property_string(info->view[0].view, DVP_DASM_EXPRESSION, string); + disasm_view_set_expression(info->view[0].view, string); // select everything in the edit text box SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1); @@ -2378,10 +2290,10 @@ static void disasm_process_string(debugwin_info *info, const char *string) static void disasm_update_menu(debugwin_info *info) { - int rightcol = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_RIGHT_COLUMN); - CheckMenuItem(GetMenu(info->wnd), ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DVP_DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DVP_DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(GetMenu(info->wnd), ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DVP_DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED)); + disasm_right_column rightcol = disasm_view_get_right_column(info->view[0].view); + CheckMenuItem(GetMenu(info->wnd), ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(GetMenu(info->wnd), ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED)); } @@ -2393,7 +2305,6 @@ static void disasm_update_menu(debugwin_info *info) static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam) { char command[64]; - UINT32 active_address = 0x00; switch (HIWORD(wparam)) { @@ -2408,15 +2319,12 @@ static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lpar for (cpunum = 0; cpunum < ARRAY_LENGTH(info->machine->cpu); cpunum++) if (info->machine->cpu[cpunum] != NULL) { - const cpu_debug_data *cpuinfo = cpu_get_debug_data(info->machine->cpu[cpunum]); - if (cpuinfo->space[ADDRESS_SPACE_PROGRAM].databytes) - if (sel-- == 0) - { - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM, cpunum); - debug_view_end_update(info->view[0].view); - disasm_update_caption(info->machine, info->wnd); - } + const address_space *space = cpu_get_address_space(info->machine->cpu[cpunum], ADDRESS_SPACE_PROGRAM); + if (space != NULL && sel-- == 0) + { + disasm_view_set_address_space(info->view[0].view, space); + disasm_update_caption(info->machine, info->wnd); + } } // reset the focus @@ -2431,73 +2339,59 @@ static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lpar switch (LOWORD(wparam)) { case ID_SHOW_RAW: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_RIGHT_COLUMN, DVP_DASM_RIGHTCOL_RAW); - debug_view_end_update(info->view[0].view); + disasm_view_set_right_column(info->view[0].view, DASM_RIGHTCOL_RAW); (*info->recompute_children)(info); return 1; case ID_SHOW_ENCRYPTED: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_RIGHT_COLUMN, DVP_DASM_RIGHTCOL_ENCRYPTED); - debug_view_end_update(info->view[0].view); + disasm_view_set_right_column(info->view[0].view, DASM_RIGHTCOL_ENCRYPTED); (*info->recompute_children)(info); return 1; case ID_SHOW_COMMENTS: - debug_view_begin_update(info->view[0].view); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_RIGHT_COLUMN, DVP_DASM_RIGHTCOL_COMMENTS); - debug_view_end_update(info->view[0].view); + disasm_view_set_right_column(info->view[0].view, DASM_RIGHTCOL_COMMENTS); (*info->recompute_children)(info); return 1; case ID_RUN_TO_CURSOR: - if (debug_view_get_property_UINT32(info->view[0].view, DVP_CURSOR_VISIBLE)) + if (debug_view_get_cursor_visible(info->view[0].view)) { - UINT32 cpu_num = 0; - cpu_debug_data *cpuinfo ; - - /* for BYTE2ADDR */ - cpu_num = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM); - cpuinfo = (cpu_debug_data *)cpu_get_debug_data(info->machine->cpu[cpu_num]); - - active_address = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_ACTIVE_ADDRESS); - sprintf(command, "go %X", BYTE2ADDR(active_address, cpuinfo, ADDRESS_SPACE_PROGRAM)); - debug_console_execute_command(info->machine, command, 1); + const address_space *space = disasm_view_get_address_space(info->view[0].view); + if (debug_cpu_get_visible_cpu(info->machine) == space->cpu) + { + offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(info->view[0].view)); + sprintf(command, "go %X", address); + debug_console_execute_command(info->machine, command, 1); + } } return 1; case ID_TOGGLE_BREAKPOINT: - if (debug_view_get_property_UINT32(info->view[0].view, DVP_CURSOR_VISIBLE)) + if (debug_view_get_cursor_visible(info->view[0].view)) { - UINT32 cpu_num = 0; - cpu_debug_data *cpuinfo ; - debug_cpu_breakpoint *bp; - INT8 bp_exists = 0; - UINT32 bp_num = 0; - - /* what address are we dealing with? */ - active_address = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_ACTIVE_ADDRESS); - - /* is there already a breakpoint there? */ - cpu_num = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM); - cpuinfo = cpu_get_debug_data(info->machine->cpu[cpu_num]); - - for (bp = cpuinfo->bplist; bp != NULL; bp = bp->next) + const address_space *space = disasm_view_get_address_space(info->view[0].view); + if (debug_cpu_get_visible_cpu(info->machine) == space->cpu) { - if (BYTE2ADDR(active_address, cpuinfo, ADDRESS_SPACE_PROGRAM) == bp->address) - { - bp_exists = 1; - bp_num = bp->index; - } + offs_t address = memory_byte_to_address(space, disasm_view_get_selected_address(info->view[0].view)); + cpu_debug_data *cpuinfo = cpu_get_debug_data(space->cpu); + debug_cpu_breakpoint *bp; + INT32 bpindex = -1; + + /* first find an existing breakpoint at this address */ + for (bp = cpuinfo->bplist; bp != NULL; bp = bp->next) + if (address == bp->address) + { + bpindex = bp->index; + break; + } + + /* if it doesn't exist, add a new one */ + if (bpindex == -1) + sprintf(command, "bpset %X", address); + else + sprintf(command, "bpclear %X", bpindex); + debug_console_execute_command(info->machine, command, 1); } - - /* Toggle */ - if (!bp_exists) - sprintf(command, "bpset %X", BYTE2ADDR(active_address, cpuinfo, ADDRESS_SPACE_PROGRAM)); - else - sprintf(command, "bpclear %X", bp_num); - debug_console_execute_command(info->machine, command, 1); } return 1; } @@ -2544,7 +2438,7 @@ static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam) return 1; case VK_RETURN: - if (debug_view_get_property_UINT32(info->view[0].view, DVP_CURSOR_VISIBLE)) + if (debug_view_get_cursor_visible(info->view[0].view)) { SendMessage(info->wnd, WM_COMMAND, ID_STEP, 0); return 1; @@ -2564,14 +2458,11 @@ static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam) static void disasm_update_caption(running_machine *machine, HWND wnd) { debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA); + const address_space *space = disasm_view_get_address_space(info->view[0].view); char title[100]; - UINT32 cpunum; - - // get the properties - cpunum = debug_view_get_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM); // then update the caption - sprintf(title, "Disassembly: CPU #%d \"%s\" (%s)", cpunum, info->machine->config->cpu[cpunum].tag, cpu_get_name(machine->cpu[cpunum])); + sprintf(title, "Disassembly: CPU '%s' (%s)", space->cpu->tag, cpu_get_name(space->cpu)); win_set_window_text_utf8(wnd, title); } @@ -2590,18 +2481,18 @@ void console_create_window(running_machine *machine) UINT32 cpunum; // create the window - info = debug_window_create(machine, "Debug", NULL); + info = debugwin_window_create(machine, "Debug", NULL); if (info == NULL) return; main_console = info; - console_set_cpunum(machine, 0); + console_set_cpu(machine->cpu[0]); // create the views - if (!debug_view_create(info, 0, DVT_DISASSEMBLY)) + if (!debugwin_view_create(info, 0, DVT_DISASSEMBLY)) goto cleanup; - if (!debug_view_create(info, 1, DVT_REGISTERS)) + if (!debugwin_view_create(info, 1, DVT_REGISTERS)) goto cleanup; - if (!debug_view_create(info, 2, DVT_CONSOLE)) + if (!debugwin_view_create(info, 2, DVT_CONSOLE)) goto cleanup; // create the options menu @@ -2618,21 +2509,15 @@ void console_create_window(running_machine *machine) info->handle_command = disasm_handle_command; info->handle_key = disasm_handle_key; - // lock us to the bottom of the console by default - info->view[2].is_textbuf = TRUE; - // set up the disassembly view to track the current pc - debug_view_begin_update(info->view[0].view); - debug_view_set_property_string(info->view[0].view, DVP_DASM_EXPRESSION, "curpc"); - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_TRACK_LIVE, 1); - debug_view_end_update(info->view[0].view); + disasm_view_set_expression(info->view[0].view, "curpc"); // create an edit box and override its key handling info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE, 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL); info->original_editproc = (void *)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC); SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info); - SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debug_edit_proc); + SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc); SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE); SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0); @@ -2644,19 +2529,20 @@ void console_create_window(running_machine *machine) info->minwidth = 0; info->maxwidth = 0; for (cpunum = MAX_CPU - 1; (INT32)cpunum >= 0; cpunum--) - if (machine->config->cpu[cpunum].type != CPU_DUMMY) + if (machine->cpu[cpunum] != NULL) { + const address_space *program = cpu_get_address_space(machine->cpu[cpunum], ADDRESS_SPACE_PROGRAM); UINT32 regchars, dischars, conchars; UINT32 minwidth, maxwidth; // point all views to the new CPU number - debug_view_set_property_UINT32(info->view[0].view, DVP_DASM_CPUNUM, cpunum); - debug_view_set_property_UINT32(info->view[1].view, DVP_REGS_CPUNUM, cpunum); + disasm_view_set_address_space(info->view[0].view, program); + registers_view_set_cpu(info->view[1].view, program->cpu); // get the total width of all three children - dischars = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); - regchars = debug_view_get_property_UINT32(info->view[1].view, DVP_TOTAL_COLS); - conchars = debug_view_get_property_UINT32(info->view[2].view, DVP_TOTAL_COLS); + dischars = debug_view_get_total_size(info->view[0].view).x; + regchars = debug_view_get_total_size(info->view[1].view).x; + conchars = debug_view_get_total_size(info->view[2].view).x; // compute the preferred width minwidth = EDGE_WIDTH + regchars * debug_font_width + vscroll_width + 2 * EDGE_WIDTH + 100 + EDGE_WIDTH; @@ -2721,9 +2607,9 @@ static void console_recompute_children(debugwin_info *info) GetClientRect(info->wnd, &parent); // get the total width of all three children - dischars = debug_view_get_property_UINT32(info->view[0].view, DVP_TOTAL_COLS); - regchars = debug_view_get_property_UINT32(info->view[1].view, DVP_TOTAL_COLS); - conchars = debug_view_get_property_UINT32(info->view[2].view, DVP_TOTAL_COLS); + dischars = debug_view_get_total_size(info->view[0].view).x; + regchars = debug_view_get_total_size(info->view[1].view).x; + conchars = debug_view_get_total_size(info->view[2].view).x; // registers always get their desired width, and span the entire height regrect.top = parent.top + EDGE_WIDTH; @@ -2749,9 +2635,9 @@ static void console_recompute_children(debugwin_info *info) conrect.right = parent.right - EDGE_WIDTH; // set the bounds of things - debug_view_set_bounds(&info->view[0], info->wnd, &disrect); - debug_view_set_bounds(&info->view[1], info->wnd, ®rect); - debug_view_set_bounds(&info->view[2], info->wnd, &conrect); + debugwin_view_set_bounds(&info->view[0], info->wnd, &disrect); + debugwin_view_set_bounds(&info->view[1], info->wnd, ®rect); + debugwin_view_set_bounds(&info->view[2], info->wnd, &conrect); smart_set_window_bounds(info->editwnd, info->wnd, &editrect); } @@ -2780,23 +2666,23 @@ static void console_process_string(debugwin_info *info, const char *string) //============================================================ -// console_set_cpunum +// console_set_cpu //============================================================ -static void console_set_cpunum(running_machine *machine, int cpunum) +static void console_set_cpu(const device_config *device) { char title[256], curtitle[256]; // first set all the views to the new cpu number - if (main_console->view[0].view) - debug_view_set_property_UINT32(main_console->view[0].view, DVP_DASM_CPUNUM, cpunum); - if (main_console->view[1].view) - debug_view_set_property_UINT32(main_console->view[1].view, DVP_REGS_CPUNUM, cpunum); + if (main_console->view[0].view != NULL) + disasm_view_set_address_space(main_console->view[0].view, cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM)); + if (main_console->view[1].view != NULL) + registers_view_set_cpu(main_console->view[1].view, device); // then update the caption - snprintf(title, ARRAY_LENGTH(title), "Debug: %s - CPU #%d \"%s\" (%s)", machine->gamedrv->name, cpunum_get_active(), machine->config->cpu[cpunum_get_active()].tag, cpu_get_name(machine->activecpu)); + snprintf(title, ARRAY_LENGTH(title), "Debug: %s - CPU '%s' (%s)", device->machine->gamedrv->name, device->tag, cpu_get_name(device)); win_get_window_text_utf8(main_console->wnd, curtitle, ARRAY_LENGTH(curtitle)); - if (strcmp(title, curtitle)) + if (strcmp(title, curtitle) != 0) win_set_window_text_utf8(main_console->wnd, title); }