Integrated comments into debugcpu.c, and removed debugcmt.c. Modernized

the code and updated so it actually works with the modern debug classes.
This commit is contained in:
Aaron Giles 2010-09-05 06:12:47 +00:00
parent d5f94fa913
commit 6fe9fe53f4
12 changed files with 423 additions and 582 deletions

2
.gitattributes vendored
View File

@ -550,8 +550,6 @@ src/emu/crsshair.c svneol=native#text/plain
src/emu/crsshair.h svneol=native#text/plain
src/emu/debug/debugcmd.c svneol=native#text/plain
src/emu/debug/debugcmd.h svneol=native#text/plain
src/emu/debug/debugcmt.c svneol=native#text/plain
src/emu/debug/debugcmt.h svneol=native#text/plain
src/emu/debug/debugcon.c svneol=native#text/plain
src/emu/debug/debugcon.h svneol=native#text/plain
src/emu/debug/debugcpu.c svneol=native#text/plain

View File

@ -12,7 +12,6 @@
#include "emu.h"
#include "emuopts.h"
#include "debugcmd.h"
#include "debugcmt.h"
#include "debugcon.h"
#include "debugcpu.h"
#include "express.h"
@ -1117,7 +1116,7 @@ static void execute_comment(running_machine *machine, int ref, int params, const
}
/* Now try adding the comment */
debug_comment_add(cpu, address, param[1], 0x00ff0000, debug_comment_get_opcode_crc32(cpu, address));
cpu->debug()->comment_add(address, param[1], 0x00ff0000);
cpu->machine->m_debug_view->update_all(DVT_DISASSEMBLY);
}
@ -1141,7 +1140,7 @@ static void execute_comment_del(running_machine *machine, int ref, int params, c
/* If it's a number, it must be an address */
/* The bankoff and cbn will be pulled from what's currently active */
debug_comment_remove(cpu, address, debug_comment_get_opcode_crc32(cpu, address));
cpu->debug()->comment_remove(address);
cpu->machine->m_debug_view->update_all(DVT_DISASSEMBLY);
}
@ -2216,7 +2215,7 @@ static void execute_dasm(running_machine *machine, int ref, int params, const ch
for (i = 0; i < length; )
{
int pcbyte = space->address_to_byte(offset + i) & space->bytemask();
char output[200+DEBUG_COMMENT_MAX_LINE_LENGTH], disasm[200];
char output[512], disasm[200];
const char *comment;
offs_t tempaddr;
int outdex = 0;
@ -2258,7 +2257,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(space->cpu, tempaddr, debug_comment_get_opcode_crc32(space->cpu, tempaddr));
comment = space->cpu->debug()->comment_text(tempaddr);
if (comment != NULL)
{
/* somewhat arbitrary guess as to how long most disassembly lines will be [column 60] */

View File

@ -1,507 +0,0 @@
/***************************************************************************
debugcmt.c
Debugger code-comment management functions.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
****************************************************************************
Debugger comment file format:
(from comment struct - assuming (MAX_COMMENT_LINE_LENGTH == 128))
0 - valid byte
1:4 - address
5:133 - comment
134:138 - color
139:142 - instruction crc
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "xmlfile.h"
#include "debugcmt.h"
#include "debugcpu.h"
#include "debugvw.h"
#include "info.h"
#include <zlib.h>
/***************************************************************************
DEBUGGING
***************************************************************************/
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/***************************************************************************
CONSTANTS
***************************************************************************/
#define COMMENT_VERSION (1)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
class debug_comment
{
public:
bool is_valid;
UINT32 address;
char text[DEBUG_COMMENT_MAX_LINE_LENGTH];
rgb_t color;
UINT32 crc;
};
class debug_cpu_comment_group
{
public:
int comment_count;
UINT32 change_count;
debug_comment * comment_info[DEBUG_COMMENT_MAX_NUM];
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static int debug_comment_load_xml(running_machine *machine, mame_file *file);
/***************************************************************************
INITIALIZATION
***************************************************************************/
/*-------------------------------------------------------------------------
debug_comment_init - initializes the comment memory and
loads any existing comment file
-------------------------------------------------------------------------*/
int debug_comment_init(device_t &device, device_debug &devdebug)
{
/* allocate memory for the comments */
devdebug.m_comments = auto_alloc_clear(device.machine, debug_cpu_comment_group);
return 1;
}
/*-------------------------------------------------------------------------
debug_comment_add - adds a comment to the list at the given address.
use debug_comment_get_opcode_crc32(addr) to get
the proper crc32
-------------------------------------------------------------------------*/
int debug_comment_add(device_t *device, offs_t addr, const char *comment, rgb_t color, UINT32 c_crc)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
int insert_point = comments->comment_count;
int match = 0;
int i = 0;
/* Create a new item to insert into the list */
debug_comment *insert_me = auto_alloc(device->machine, debug_comment);
insert_me->color = color;
insert_me->is_valid = 1;
insert_me->address = addr;
insert_me->crc = c_crc;
strcpy(insert_me->text, comment);
/* Find the insert point */
for (i = 0; i < comments->comment_count; i++)
{
if (insert_me->address < comments->comment_info[i]->address)
{
insert_point = i;
break;
}
else if (insert_me->address == comments->comment_info[i]->address &&
insert_me->crc == comments->comment_info[i]->crc)
{
insert_point = i;
match = 1;
break;
}
}
/* Got an exact match? Just replace */
if (match == 1)
{
auto_free(device->machine, comments->comment_info[insert_point]);
comments->comment_info[insert_point] = insert_me;
comments->change_count++;
/* force an update of disassembly views */
device->machine->m_debug_view->update_all(DVT_DISASSEMBLY);
return 1;
}
/* Otherwise insert */
/* First, shift the list down */
for (i = comments->comment_count; i >= insert_point; i--)
comments->comment_info[i] = comments->comment_info[i-1];
/* do the insertion */
comments->comment_info[insert_point] = insert_me;
comments->comment_count++;
comments->change_count++;
/* force an update of disassembly views */
device->machine->m_debug_view->update_all(DVT_DISASSEMBLY);
return 1;
}
/*-------------------------------------------------------------------------
debug_comment_remove - removes a comment at a given address
use debug_comment_get_opcode_crc32(addr) to get
the proper crc32
-------------------------------------------------------------------------*/
int debug_comment_remove(device_t *device, offs_t addr, UINT32 c_crc)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
int remove_index = -1;
int i;
for (i = 0; i < comments->comment_count; i++)
if (comments->comment_info[i]->address == addr) /* got an address match */
if (comments->comment_info[i]->crc == c_crc)
remove_index = i;
/* The comment doesn't exist? */
if (remove_index == -1)
return 0;
/* Okay, it's there, now remove it */
auto_free(device->machine, comments->comment_info[remove_index]);
for (i = remove_index; i < comments->comment_count-1; i++)
comments->comment_info[i] = comments->comment_info[i+1];
comments->comment_count--;
comments->change_count++;
/* force an update of disassembly views */
device->machine->m_debug_view->update_all(DVT_DISASSEMBLY);
return 1;
}
/*-------------------------------------------------------------------------
debug_comment_get_text - returns the comment for a given addresses
use debug_comment_get_opcode_crc32(addr) to get
the proper crc32
-------------------------------------------------------------------------*/
const char *debug_comment_get_text(device_t *device, offs_t addr, UINT32 c_crc)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
int i;
/* inefficient - should use bsearch - but will be a little tricky with multiple comments per addr */
for (i = 0; i < comments->comment_count; i++)
if (comments->comment_info[i]->address == addr) /* got an address match */
{
/* now check the bank information to be sure */
if (comments->comment_info[i]->crc == c_crc)
return comments->comment_info[i]->text;
}
return 0x00;
}
/*-------------------------------------------------------------------------
debug_comment_get_count - returns the number of comments
for a given cpu number
-------------------------------------------------------------------------*/
int debug_comment_get_count(device_t *device)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
return comments->comment_count;
}
/*-------------------------------------------------------------------------
debug_comment_get_change_count - returns the change counter
for a given cpu number
-------------------------------------------------------------------------*/
UINT32 debug_comment_get_change_count(device_t *device)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
return comments->change_count;
}
/*-------------------------------------------------------------------------
debug_comment_all_change_count - returns the change counter
for all cpu's
-------------------------------------------------------------------------*/
UINT32 debug_comment_all_change_count(running_machine *machine)
{
UINT32 retVal = 0;
for (device_t *device = machine->m_devicelist.first(); device != NULL; device = device->next())
if (device->debug()->m_comments != NULL)
retVal += device->debug()->m_comments->change_count;
return retVal;
}
/*-------------------------------------------------------------------------
debug_comment_get_opcode_crc32 - magic function that takes all the
current state of the debugger and returns a crc32
for the opcode at the requested address.
-------------------------------------------------------------------------*/
UINT32 debug_comment_get_opcode_crc32(device_t *device, offs_t address)
{
address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM);
int i;
UINT32 crc;
UINT8 opbuf[64], argbuf[64];
char buff[256];
offs_t numbytes;
cpu_device *cpudevice = downcast<cpu_device *>(device);
int maxbytes = cpudevice->max_opcode_bytes();
UINT32 addrmask = space->logaddrmask();
memset(opbuf, 0x00, sizeof(opbuf));
memset(argbuf, 0x00, sizeof(argbuf));
// fetch the bytes up to the maximum
for (i = 0; i < maxbytes; i++)
{
opbuf[i] = debug_read_opcode(space, address + i, 1, FALSE);
argbuf[i] = debug_read_opcode(space, address + i, 1, TRUE);
}
numbytes = device->debug()->disassemble(buff, address & addrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK;
numbytes = space->address_to_byte(numbytes);
crc = crc32(0, argbuf, numbytes);
return crc;
}
/*-------------------------------------------------------------------------
debug_comment_dump - debugging function to dump junk to the command line
-------------------------------------------------------------------------*/
void debug_comment_dump(device_t *device, offs_t addr)
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
int i;
int ff = 0;
if (addr == -1)
{
for (i = 0; i < comments->comment_count; i++)
if (comments->comment_info[i]->is_valid)
logerror("%d : %s (%d %d)\n", i, comments->comment_info[i]->text,
comments->comment_info[i]->address,
comments->comment_info[i]->crc);
}
else
{
UINT32 c_crc = debug_comment_get_opcode_crc32(device, addr);
for (i = 0; i < comments->comment_count; i++)
if (comments->comment_info[i]->address == addr) /* got an address match */
{
/* now check the bank information to be sure */
if (comments->comment_info[i]->crc == c_crc)
{
logerror("%d : %s (%d %d)\n", addr,
comments->comment_info[addr]->text,
comments->comment_info[addr]->address,
comments->comment_info[addr]->crc);
ff = 1;
}
}
if (!ff) logerror("No comment exists for address : 0x%x\n", addr);
}
}
/*-------------------------------------------------------------------------
debug_comment_save - comment file saving
-------------------------------------------------------------------------*/
int debug_comment_save(running_machine *machine)
{
int j;
char crc_buf[20];
xml_data_node *root = xml_file_create();
xml_data_node *commentnode, *systemnode;
int total_comments = 0;
/* if we don't have a root, bail */
if (root == NULL)
return 0;
/* create a comment node */
commentnode = xml_add_child(root, "mamecommentfile", NULL);
if (commentnode == NULL)
goto error;
xml_set_attribute_int(commentnode, "version", COMMENT_VERSION);
/* create a system node */
systemnode = xml_add_child(commentnode, "system", NULL);
if (systemnode == NULL)
goto error;
xml_set_attribute(systemnode, "name", machine->gamedrv->name);
/* for each cpu */
for (device_t *device = machine->m_devicelist.first(); device != NULL; device = device->next())
{
debug_cpu_comment_group *comments = device->debug()->m_comments;
if (comments != NULL)
{
xml_data_node *curnode = xml_add_child(systemnode, "cpu", NULL);
if (curnode == NULL)
goto error;
xml_set_attribute(curnode, "tag", device->tag());
for (j = 0; j < comments->comment_count; j++)
{
xml_data_node *datanode = xml_add_child(curnode, "comment", xml_normalize_string(comments->comment_info[j]->text));
if (datanode == NULL)
goto error;
xml_set_attribute_int(datanode, "address", comments->comment_info[j]->address);
xml_set_attribute_int(datanode, "color", comments->comment_info[j]->color);
sprintf(crc_buf, "%08X", comments->comment_info[j]->crc);
xml_set_attribute(datanode, "crc", crc_buf);
total_comments++;
}
}
}
/* flush the file */
if (total_comments > 0)
{
file_error filerr;
mame_file *fp;
astring fname(machine->basename(), ".cmt");
filerr = mame_fopen(SEARCHPATH_COMMENT, fname, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &fp);
if (filerr == FILERR_NONE)
{
xml_file_write(root, mame_core_file(fp));
mame_fclose(fp);
}
}
/* free and get out of here */
xml_file_free(root);
return 1;
error:
xml_file_free(root);
return 0;
}
/*-------------------------------------------------------------------------
debug_comment_load(_xml) - comment file loading
-------------------------------------------------------------------------*/
int debug_comment_load(running_machine *machine)
{
file_error filerr;
mame_file *fp;
astring fname(machine->basename(), ".cmt");
filerr = mame_fopen(SEARCHPATH_COMMENT, fname, OPEN_FLAG_READ, &fp);
if (filerr != FILERR_NONE) return 0;
debug_comment_load_xml(machine, fp);
mame_fclose(fp);
return 1;
}
static int debug_comment_load_xml(running_machine *machine, mame_file *fp)
{
int j;
xml_data_node *root, *commentnode, *systemnode, *cpunode, *datanode;
const char *name;
int version;
/* read the file */
root = xml_file_read(mame_core_file(fp), NULL);
if (root == NULL)
goto error;
/* find the config node */
commentnode = xml_get_sibling(root->child, "mamecommentfile");
if (commentnode == NULL)
goto error;
/* validate the config data version */
version = xml_get_attribute_int(commentnode, "version", 0);
if (version != COMMENT_VERSION)
goto error;
/* check to make sure the file is applicable */
systemnode = xml_get_sibling(commentnode->child, "system");
name = xml_get_attribute_string(systemnode, "name", "");
if (strcmp(name, machine->gamedrv->name) != 0)
goto error;
for (cpunode = xml_get_sibling(systemnode->child, "cpu"); cpunode; cpunode = xml_get_sibling(cpunode->next, "cpu"))
{
device_t *cpu = machine->device(xml_get_attribute_string(cpunode, "tag", ""));
if (cpu != NULL)
{
debug_cpu_comment_group *comments = cpu->debug()->m_comments;
j = 0;
for (datanode = xml_get_sibling(cpunode->child, "comment"); datanode; datanode = xml_get_sibling(datanode->next, "comment"))
{
/* Malloc the comment */
comments->comment_info[j] = auto_alloc(machine, debug_comment);
comments->comment_info[j]->address = xml_get_attribute_int(datanode, "address", 0);
comments->comment_info[j]->color = xml_get_attribute_int(datanode, "color", 0);
sscanf(xml_get_attribute_string(datanode, "crc", 0), "%08X", &comments->comment_info[j]->crc);
strcpy(comments->comment_info[j]->text, datanode->value);
comments->comment_info[j]->is_valid = 1;
j++;
}
comments->comment_count = j;
}
}
/* free the parser */
xml_file_free(root);
return 1;
error:
if (root)
xml_file_free(root);
return 0;
}

View File

@ -1,40 +0,0 @@
/***************************************************************************
debugcmt.h
Debugger code-comment management functions.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#pragma once
#ifndef __DEBUGCMT_H__
#define __DEBUGCMT_H__
#define DEBUG_COMMENT_MAX_LINE_LENGTH (128) /* 128 characters per comment - 50 are displayed at once */
#define DEBUG_COMMENT_MAX_NUM (0x10000) /* 64k comments should be good for awhile */
/* init and exit */
int debug_comment_init(device_t &device, device_debug &devdebug);
/* load and save */
int debug_comment_save(running_machine *machine);
int debug_comment_load(running_machine *machine);
/* comment interface functions */
int debug_comment_add(device_t *device, offs_t addr, const char *comment, rgb_t color, UINT32 c_crc);
int debug_comment_remove(device_t *device, offs_t addr, UINT32 c_crc);
const char *debug_comment_get_text(device_t *device, offs_t addr, UINT32 c_crc);
int debug_comment_get_count(device_t *device);
UINT32 debug_comment_get_change_count(device_t *device);
UINT32 debug_comment_all_change_count(running_machine *machine);
/* local functionality */
UINT32 debug_comment_get_opcode_crc32(device_t *device, offs_t address); /* pull a crc for the opcode at a given address */
void debug_comment_dump(device_t *device, offs_t addr); /* dump all (or a single) comment to the command line */
#endif

View File

@ -38,17 +38,19 @@
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "osdepend.h"
#include "debugcpu.h"
#include "debugcmd.h"
#include "debugcmt.h"
#include "debugcon.h"
#include "express.h"
#include "debugvw.h"
#include "debugger.h"
#include "debugint/debugint.h"
#include "uiinput.h"
#include "xmlfile.h"
#include <ctype.h>
#include <zlib.h>
@ -311,6 +313,146 @@ void debug_cpu_source_script(running_machine *machine, const char *file)
//**************************************************************************
// MEMORY AND DISASSEMBLY HELPERS
//**************************************************************************
//-------------------------------------------------
// debug_comment_save - save all comments for
// the given machine
//-------------------------------------------------
bool debug_comment_save(running_machine *machine)
{
// if we don't have a root, bail
xml_data_node *root = xml_file_create();
if (root == NULL)
return false;
// wrap in a try/catch to handle errors
try
{
// create a comment node
xml_data_node *commentnode = xml_add_child(root, "mamecommentfile", NULL);
if (commentnode == NULL)
throw emu_exception();
xml_set_attribute_int(commentnode, "version", COMMENT_VERSION);
// create a system node
xml_data_node *systemnode = xml_add_child(commentnode, "system", NULL);
if (systemnode == NULL)
throw emu_exception();
xml_set_attribute(systemnode, "name", machine->gamedrv->name);
// for each device
bool found_comments = false;
for (device_t *device = machine->m_devicelist.first(); device != NULL; device = device->next())
if (device->debug()->comment_count() > 0)
{
// create a node for this device
xml_data_node *curnode = xml_add_child(systemnode, "cpu", NULL);
if (curnode == NULL)
throw emu_exception();
xml_set_attribute(curnode, "tag", device->tag());
// export the comments
if (!device->debug()->comment_export(*curnode))
throw emu_exception();
found_comments = true;
}
// flush the file
if (found_comments)
{
astring fname(machine->basename(), ".cmt");
mame_file *fp;
file_error filerr = mame_fopen(SEARCHPATH_COMMENT, fname, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &fp);
if (filerr == FILERR_NONE)
{
xml_file_write(root, mame_core_file(fp));
mame_fclose(fp);
}
}
}
catch (emu_exception &)
{
xml_file_free(root);
return false;
}
// free and get out of here
xml_file_free(root);
return true;
}
//-------------------------------------------------
// debug_comment_load - load all comments for
// the given machine
//-------------------------------------------------
bool debug_comment_load(running_machine *machine)
{
// open the file
astring fname(machine->basename(), ".cmt");
mame_file *fp;
file_error filerr = mame_fopen(SEARCHPATH_COMMENT, fname, OPEN_FLAG_READ, &fp);
// if an error, just return false
if (filerr != FILERR_NONE)
return false;
// wrap in a try/catch to handle errors
xml_data_node *root = xml_file_read(mame_core_file(fp), NULL);
try
{
// read the file
if (root == NULL)
throw emu_exception();
// find the config node
xml_data_node *commentnode = xml_get_sibling(root->child, "mamecommentfile");
if (commentnode == NULL)
throw emu_exception();
// validate the config data version
int version = xml_get_attribute_int(commentnode, "version", 0);
if (version != COMMENT_VERSION)
throw emu_exception();
// check to make sure the file is applicable
xml_data_node *systemnode = xml_get_sibling(commentnode->child, "system");
const char *name = xml_get_attribute_string(systemnode, "name", "");
if (strcmp(name, machine->gamedrv->name) != 0)
throw emu_exception();
// iterate over devices
for (xml_data_node *cpunode = xml_get_sibling(systemnode->child, "cpu"); cpunode; cpunode = xml_get_sibling(cpunode->next, "cpu"))
{
device_t *device = machine->device(xml_get_attribute_string(cpunode, "tag", ""));
if (device != NULL)
if (!device->debug()->comment_import(*cpunode))
throw emu_exception();
}
}
catch (emu_exception &)
{
// clean up in case of error
if (root != NULL)
xml_file_free(root);
mame_fclose(fp);
return false;
}
// free the parser
xml_file_free(root);
mame_fclose(fp);
return true;
}
/***************************************************************************
MEMORY AND DISASSEMBLY HELPERS
***************************************************************************/
@ -1583,8 +1725,7 @@ device_debug::device_debug(device_t &device)
m_trace(NULL),
m_hotspots(NULL),
m_hotspot_count(0),
m_hotspot_threshhold(0),
m_comments(NULL)
m_hotspot_threshhold(0)
{
memset(m_pc_history, 0, sizeof(m_pc_history));
memset(m_wplist, 0, sizeof(m_wplist));
@ -1629,10 +1770,6 @@ device_debug::device_debug(device_t &device)
if (m_state != NULL && symtable_find(m_symtable, "curpc") == NULL)
symtable_add_register(m_symtable, "curpc", NULL, get_current_pc, 0);
}
// initialize coments
if (m_disasm != NULL)
debug_comment_init(device, *this);
}
@ -1958,7 +2095,7 @@ void device_debug::set_instruction_hook(debug_instruction_hook_func hook)
// PC on a given device
//-------------------------------------------------
offs_t device_debug::disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
offs_t device_debug::disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) const
{
offs_t result = 0;
@ -2423,6 +2560,212 @@ offs_t device_debug::history_pc(int index) const
}
//-------------------------------------------------
// comment_add - adds a comment to the list at
// the given address
//-------------------------------------------------
void device_debug::comment_add(offs_t addr, const char *comment, rgb_t color)
{
// create a new item for the list
UINT32 crc = compute_opcode_crc32(addr);
dasm_comment *newcomment = auto_alloc(m_device.machine, dasm_comment(comment, addr, color, crc));
// figure out where to insert it
dasm_comment *prev = NULL;
dasm_comment *curr;
for (curr = m_comment_list.first(); curr != NULL; prev = curr, curr = curr->next())
if (curr->m_address >= addr)
break;
// we could be the new head
if (prev == NULL)
m_comment_list.prepend(*newcomment);
// or else we just insert ourselves here
else
{
newcomment->m_next = prev->m_next;
prev->m_next = newcomment;
}
// scan forward from here to delete any exact matches
for ( ; curr != NULL && curr->m_address == addr; curr = curr->next())
if (curr->m_crc == crc)
{
m_comment_list.remove(*curr);
break;
}
// force an update
m_comment_change++;
}
//-------------------------------------------------
// comment_remove - removes a comment at the
// given address with a matching CRC
//-------------------------------------------------
bool device_debug::comment_remove(offs_t addr)
{
// scan the list for a match
UINT32 crc = compute_opcode_crc32(addr);
for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
{
// if we're past the address, we failed
if (curr->m_address > addr)
break;
// find an exact match
if (curr->m_address == addr && curr->m_crc == crc)
{
// remove it and force an update
m_comment_list.remove(*curr);
m_comment_change++;
return true;
}
}
// failure is an option
return false;
}
//-------------------------------------------------
// comment_text - return the text of a comment
//-------------------------------------------------
const char *device_debug::comment_text(offs_t addr) const
{
// scan the list for a match
UINT32 crc = compute_opcode_crc32(addr);
for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
{
// if we're past the address, we failed
if (curr->m_address > addr)
break;
// find an exact match
if (curr->m_address == addr && curr->m_crc == crc)
return curr->m_text;
}
// failure is an option
return NULL;
}
//-------------------------------------------------
// comment_export - export the comments to the
// given XML data node
//-------------------------------------------------
bool device_debug::comment_export(xml_data_node &curnode)
{
// iterate through the comments
astring crc_buf;
for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
{
xml_data_node *datanode = xml_add_child(&curnode, "comment", xml_normalize_string(curr->m_text));
if (datanode == NULL)
return false;
xml_set_attribute_int(datanode, "address", curr->m_address);
xml_set_attribute_int(datanode, "color", curr->m_color);
crc_buf.printf("%08X", curr->m_crc);
xml_set_attribute(datanode, "crc", crc_buf);
}
return true;
}
//-------------------------------------------------
// comment_import - import the comments from the
// given XML data node
//-------------------------------------------------
bool device_debug::comment_import(xml_data_node &cpunode)
{
// iterate through nodes
for (xml_data_node *datanode = xml_get_sibling(cpunode.child, "comment"); datanode; datanode = xml_get_sibling(datanode->next, "comment"))
{
// extract attributes
offs_t address = xml_get_attribute_int(datanode, "address", 0);
rgb_t color = xml_get_attribute_int(datanode, "color", 0);
UINT32 crc;
sscanf(xml_get_attribute_string(datanode, "crc", 0), "%08X", &crc);
// add the new comment; we assume they were saved ordered
m_comment_list.append(*auto_alloc(m_device.machine, dasm_comment(datanode->value, address, color, crc)));
}
return true;
}
//-------------------------------------------------
// comment_dump - logs comments to the error.log
// at a given address
//-------------------------------------------------
void device_debug::comment_dump(offs_t addr)
{
// determine the CRC at the given address (if valid)
UINT32 crc = (addr == ~0) ? 0 : compute_opcode_crc32(addr);
// dump everything that matches
bool found = false;
for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
if (addr == ~0 || (curr->m_address == addr && curr->m_crc == crc))
{
found = true;
logerror("%08X %08X - %s\n", curr->m_address, curr->m_crc, curr->m_text.cstr());
}
// if nothing found, indicate as much
if (!found)
logerror("No comment exists for address : 0x%x\n", addr);
}
//-------------------------------------------------
// compute_opcode_crc32 - determine the CRC of
// the opcode bytes at the given address
//-------------------------------------------------
UINT32 device_debug::compute_opcode_crc32(offs_t address) const
{
// no memory interface, just fail
if (m_memory == NULL)
return 0;
// no program interface, just fail
address_space *space = m_memory->space(AS_PROGRAM);
if (space == NULL)
return 0;
// zero out the buffers
UINT8 opbuf[64], argbuf[64];
memset(opbuf, 0x00, sizeof(opbuf));
memset(argbuf, 0x00, sizeof(argbuf));
// fetch the bytes up to the maximum
int maxbytes = m_disasm->max_opcode_bytes();
for (int index = 0; index < maxbytes; index++)
{
opbuf[index] = debug_read_opcode(space, address + index, 1, false);
argbuf[index] = debug_read_opcode(space, address + index, 1, true);
}
// disassemble and then convert to bytes
char buff[256];
int numbytes = disassemble(buff, address & space->logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK;
numbytes = space->address_to_byte(numbytes);
// return a CRC of the resulting bytes
return crc32(0, argbuf, numbytes);
}
//-------------------------------------------------
// trace - trace execution of a given device
//-------------------------------------------------
@ -3076,3 +3419,16 @@ void device_debug::tracer::flush()
fflush(&m_file);
}
//-------------------------------------------------
// dasm_comment - constructor
//-------------------------------------------------
device_debug::dasm_comment::dasm_comment(const char *text, offs_t address, rgb_t color, UINT32 crc)
: m_next(NULL),
m_address(address),
m_color(color),
m_crc(crc),
m_text(text)
{
}

View File

@ -53,6 +53,8 @@ const UINT8 WATCHPOINT_READ = 1;
const UINT8 WATCHPOINT_WRITE = 2;
const UINT8 WATCHPOINT_READWRITE = WATCHPOINT_READ | WATCHPOINT_WRITE;
const int COMMENT_VERSION = 1;
//**************************************************************************
@ -62,7 +64,7 @@ const UINT8 WATCHPOINT_READWRITE = WATCHPOINT_READ | WATCHPOINT_WRITE;
typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
class debug_cpu_comment_group;
typedef struct _xml_data_node xml_data_node;
class device_debug
@ -126,7 +128,7 @@ public:
bool hit(int type, offs_t address, int size);
watchpoint * m_next; // next in the list
address_space &m_space; // address space
address_space & m_space; // address space
int m_index; // user reported index
bool m_enabled; // enabled?
UINT8 m_type; // type (read/write)
@ -164,7 +166,7 @@ public:
void set_dasm_override(dasm_override_func dasm_override) { m_dasm_override = dasm_override; }
// disassembly
offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) const;
// debugger focus
void ignore(bool ignore = true);
@ -203,6 +205,17 @@ public:
// hotspots
bool hotspot_tracking_enabled() const { return (m_hotspots != NULL); }
void hotspot_track(int numspots, int threshhold);
// comments
void comment_add(offs_t address, const char *comment, rgb_t color);
bool comment_remove(offs_t addr);
const char *comment_text(offs_t addr) const;
UINT32 comment_count() const { return m_comment_list.count(); }
UINT32 comment_change_count() const { return m_comment_change; }
bool comment_export(xml_data_node &node);
bool comment_import(xml_data_node &node);
void comment_dump(offs_t addr = ~0);
UINT32 compute_opcode_crc32(offs_t address) const;
// history
offs_t history_pc(int index) const;
@ -304,13 +317,30 @@ private:
{
offs_t m_access; // access address
offs_t m_pc; // PC of the access
address_space *m_space; // space where the access occurred
address_space * m_space; // space where the access occurred
UINT32 m_count; // number of hits
};
hotspot_entry * m_hotspots; // hotspot list
int m_hotspot_count; // number of hotspots
int m_hotspot_threshhold; // threshhold for the number of hits to print
// comments
class dasm_comment
{
public:
dasm_comment(const char *text, offs_t address, rgb_t color, UINT32 crc);
dasm_comment *next() const { return m_next; }
dasm_comment * m_next; // next comment in the list
offs_t m_address; // address in question
rgb_t m_color; // color to use
UINT32 m_crc; // CRC of code
astring m_text; // text
};
simple_list<dasm_comment> m_comment_list; // list of comments
UINT32 m_comment_change; // change counter for comments
// internal flag values
static const UINT32 DEBUG_FLAG_OBSERVING = 0x00000001; // observing this CPU
static const UINT32 DEBUG_FLAG_HISTORY = 0x00000002; // tracking this CPU's history
@ -332,9 +362,6 @@ private:
static const UINT32 DEBUG_FLAG_TRACING_ANY = DEBUG_FLAG_TRACING | DEBUG_FLAG_TRACING_OVER;
static const UINT32 DEBUG_FLAG_TRANSIENT = DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_STOP_CONTEXT |
DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK | DEBUG_FLAG_STOP_TIME;
public: // until comments get folded in
debug_cpu_comment_group *m_comments; // disassembly comments
};
@ -391,6 +418,16 @@ void debug_cpu_source_script(running_machine *machine, const char *file);
/* ----- debugger comment helpers ----- */
// save all comments for a given machine
bool debug_comment_save(running_machine *machine);
// load all comments for a given machine
bool debug_comment_load(running_machine *machine);
/* ----- debugger memory accessors ----- */
/* return the physical address corresponding to the given logical address */

View File

@ -44,7 +44,6 @@
#include "dvdisasm.h"
#include "dvmemory.h"
#include "debugcmd.h"
#include "debugcmt.h"
#include "debugcpu.h"
#include "debugcon.h"
#include "express.h"

View File

@ -40,7 +40,6 @@
#include "emu.h"
#include "debugvw.h"
#include "dvdisasm.h"
#include "debugcmt.h"
#include "debugcpu.h"
@ -98,7 +97,7 @@ debug_view_disasm::debug_view_disasm(running_machine &machine, debug_view_osd_up
for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next())
{
const debug_view_disasm_source &dasmsource = downcast<const debug_view_disasm_source &>(*source);
total_comments += debug_comment_get_count(&dasmsource.m_device);
total_comments += dasmsource.m_device.debug()->comment_count();
}
// initialize
@ -438,7 +437,7 @@ bool debug_view_disasm::recompute(offs_t pc, int startline, int lines)
{
// get and add the comment, if present
offs_t comment_address = source.m_space->byte_to_address(m_byteaddress[instr]);
const char *text = debug_comment_get_text(&source.m_device, comment_address, debug_comment_get_opcode_crc32(&source.m_device, comment_address));
const char *text = source.m_device.debug()->comment_text(comment_address);
if (text != NULL)
sprintf(&destbuf[m_divider2], "// %.*s", m_allocated.x - m_divider2 - 1, text);
}
@ -451,7 +450,7 @@ bool debug_view_disasm::recompute(offs_t pc, int startline, int lines)
// update opcode base information
m_last_direct_decrypted = source.m_space->direct().decrypted();
m_last_direct_raw = source.m_space->direct().raw();
m_last_change_count = debug_comment_all_change_count(&m_machine);
m_last_change_count = source.m_device.debug()->comment_change_count();
// now longer need to recompute
m_recompute = false;
@ -502,7 +501,7 @@ void debug_view_disasm::view_update()
m_recompute = true;
// if the comments have changed, redo it
if (m_last_change_count != debug_comment_all_change_count(&m_machine))
if (m_last_change_count != source.m_device.debug()->comment_change_count())
m_recompute = true;
// if we need to recompute, do it
@ -511,7 +510,7 @@ recompute:
if (m_recompute)
{
// recompute the view
if (m_byteaddress != NULL && m_last_change_count != debug_comment_all_change_count(&m_machine))
if (m_byteaddress != NULL && m_last_change_count != source.m_device.debug()->comment_change_count())
{
// smoosh us against the left column, but not the top row
m_topleft.x = 0;

View File

@ -79,7 +79,7 @@ private:
// internal state
device_t & m_device; // underlying device
device_disasm_interface *m_disasmintf; // disassembly interface
address_space *m_space; // address space to display
address_space * m_space; // address space to display
};

View File

@ -13,7 +13,6 @@
#include "debugger.h"
#include "debug/debugcpu.h"
#include "debug/debugcmd.h"
#include "debug/debugcmt.h"
#include "debug/debugcon.h"
#include "debug/express.h"
#include "debug/debugvw.h"
@ -114,9 +113,6 @@ static void debugger_exit(running_machine &machine)
{
machine_entry **entryptr;
// save any comments
debug_comment_save(&machine);
/* remove this machine from the list; it came down cleanly */
for (entryptr = &machine_list; *entryptr != NULL; entryptr = &(*entryptr)->next)
if ((*entryptr)->machine == &machine)

View File

@ -200,6 +200,11 @@ void device_list::static_reset(running_machine &machine)
void device_list::static_exit(running_machine &machine)
{
// first let the debugger save comments
if ((machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
debug_comment_save(&machine);
// then nuke the devices
machine.m_devicelist.reset();
}

View File

@ -99,7 +99,6 @@ EMUOBJS = \
$(EMUOBJ)/video.o \
$(EMUOBJ)/watchdog.o \
$(EMUOBJ)/debug/debugcmd.o \
$(EMUOBJ)/debug/debugcmt.o \
$(EMUOBJ)/debug/debugcon.o \
$(EMUOBJ)/debug/debugcpu.o \
$(EMUOBJ)/debug/debughlp.o \