Index: debugger/breakpoints.c
===================================================================
--- debugger/breakpoints.c (revision 426)
+++ debugger/breakpoints.c (working copy)
@@ -96,8 +96,8 @@
{
if((address >= g_Breakpoints[i].address) && (address <= g_Breakpoints[i].endaddr) && (!flags || ((g_Breakpoints[i].flags & flags) == flags)))
{
- printf("Bpt %d (0x%08X - 0x%08X) matches 0x%08X\n", i, g_Breakpoints[i].address,
- g_Breakpoints[i].endaddr, address);
+ //printf("Bpt %d (0x%08X - 0x%08X) matches 0x%08X\n", i, g_Breakpoints[i].address,
+ // g_Breakpoints[i].endaddr, address);
return i;
}
else
Index: main/gui_gtk/debugger/desasm.c
===================================================================
--- main/gui_gtk/debugger/desasm.c (revision 426)
+++ main/gui_gtk/debugger/desasm.c (working copy)
@@ -115,11 +115,15 @@
renderer = gtk_cell_renderer_text_new();
col = gtk_tree_view_column_new_with_attributes("Address", renderer, "text", 0, NULL);
gtk_tree_view_column_set_cell_data_func(col, renderer, disasm_set_color, NULL, NULL);
-
+ gtk_tree_view_column_set_resizable(col, TRUE);
gtk_tree_view_append_column( GTK_TREE_VIEW( clDesasm ), col);
+
col = gtk_tree_view_column_new_with_attributes("Opcode", renderer, "text", 1, NULL);
+ gtk_tree_view_column_set_resizable(col, TRUE);
gtk_tree_view_append_column( GTK_TREE_VIEW( clDesasm ), col);
+
col = gtk_tree_view_column_new_with_attributes("Args", renderer, "text", 2, NULL);
+ gtk_tree_view_column_set_resizable(col, TRUE);
gtk_tree_view_append_column( GTK_TREE_VIEW( clDesasm ), col);
adj = gtk_adjustment_new(0, -500, 500, 1, max_row, max_row);
@@ -137,7 +141,8 @@
boxV1 = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_end( GTK_BOX(boxH1), boxV1, FALSE, FALSE, 0 );
- buRun = gtk_button_new_with_label( "Run" );
+ //buRun = gtk_button_new_with_label( "Run" );
+ buRun = gtk_button_new_with_label( "> \\ ||" );
gtk_box_pack_start( GTK_BOX(boxV1), buRun, FALSE, FALSE, 5 );
buStep = gtk_button_new_with_label( "Next" );
gtk_box_pack_start( GTK_BOX(boxV1), buStep, FALSE, FALSE, 0 );
@@ -198,7 +203,10 @@
void switch_button_to_run()
{ //Is called from debugger.c, when a breakpoint is reached.
- gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run");
+ //gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run");
+ //todo: this causes a deadlock or something the second time a
+ //breakpoint hits, breaking the interface. The other lines changing
+ //this label have been commented with the note "avoid deadlock".
}
@@ -208,10 +216,10 @@
{
if(run == 2) {
run = 0;
- gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run");
+ //gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run"); //avoid deadlock
} else {
run = 2;
- gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child),"Pause");
+ //gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child),"Pause"); //avoid deadlock
pthread_cond_signal(&debugger_done_cond);
}
}
@@ -220,7 +228,7 @@
static void on_step()
{
if(run == 2) {
- gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run");
+ //gtk_label_set_text( GTK_LABEL (GTK_BIN (buRun)->child), "Run"); //avoid deadlock
} else {
pthread_cond_signal(&debugger_done_cond);
}
Index: main/gui_gtk/debugger/memedit.c
===================================================================
--- main/gui_gtk/debugger/memedit.c (revision 426)
+++ main/gui_gtk/debugger/memedit.c (working copy)
@@ -28,24 +28,39 @@
#include "memedit.h"
+#include <math.h>
#include <gdk/gdkkeysyms.h>
GtkTextBuffer *textbuf;
GtkTextTag *textfont;
-GtkTextIter textstart, textend;
+//note: just changing these constants is not (yet) enough to properly change the display.
+const uint32 num_menu_items = 6;
+const int bytesperline = 16;
+const int hexstartpos = 9;
+//apparently the compiler isn't smart enough to figure out that these equations are constant. -_-
+const int linelen = 74; //hexstartpos + (bytesperline * 3) + bytesperline + 1; //address, separator, hex, text, line break (hex/text separator included in hex)
+const int textstartpos = 57; //hexstartpos + (bytesperline * 3); //address, separator, hex
uint32 memedit_address, memedit_numlines;
+GtkWidget *menu;
+GtkWidget* menuitem[6]; //DO NOT FORGET TO UPDATE THIS WHEN YOU ADD ITEMS
+GtkClipboard* clipboard;
+
static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
+static gboolean on_mouse_down(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
+static void on_menu_select(GtkMenuItem *menuitem, gpointer user_data);
static void on_close();
+static int GetSelectionRange(uint32* StartAddr, int AllowEmpty);
void update_memory_editor()
{
int i, j, k;
- char line[75];
+ char line[linelen + 1];
char* buf;
uint32 addr;
- uint8 byte[16];
+ uint8 byte[bytesperline];
+ GtkTextIter textstart, textend;
buf = (char*)malloc(memedit_numlines * sizeof(line) * sizeof(char));
if(!buf)
@@ -62,7 +77,7 @@
buf[0] = 0;
for(i=0; i<memedit_numlines; i++)
{
- for(j=0; j<16; j++)
+ for(j=0; j<bytesperline; j++)
byte[j] = read_memory_8(addr + j);
sprintf(line, "%08X|%02X %02X %02X %02X|%02X %02X %02X %02X|%02X %02X %02X %02X|%02X %02X %02X %02X|",
@@ -70,7 +85,7 @@
byte[8], byte[9], byte[10], byte[11], byte[12], byte[13], byte[14], byte[15]);
strcat(buf, line);
- for(j=0; j<16; j++)
+ for(j=0; j<bytesperline; j++)
{
if((byte[j] >= 0x20) && (byte[j] <= 0x7E))
line[j] = byte[j];
@@ -79,12 +94,12 @@
if(i < (memedit_numlines - 1))
{
- line[16] = '\n';
- line[17] = 0;
+ line[bytesperline] = '\n';
+ line[bytesperline + 1] = 0;
}
- else line[16] = 0;
+ else line[bytesperline] = 0;
strcat(buf, line);
- addr += 16;
+ addr += bytesperline;
}
//Update textbox
@@ -106,7 +121,7 @@
*textbox;
memedit_opened = 1;
- memedit_address = 0x800F6A10; //0x800EB5D0;
+ memedit_address = 0x80000000;
memedit_numlines = 16;
//=== Creation of Memory Editor ===========/
@@ -120,20 +135,42 @@
textfont = gtk_text_buffer_create_tag(textbuf, "font", "font", "monospace", NULL);
update_memory_editor();
+ gtk_container_add(GTK_CONTAINER(winMemEdit), textbox);
- gtk_container_add(GTK_CONTAINER(winMemEdit), textbox);
+ clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD );
+
+ //Create right-click menu
+ menu = gtk_menu_new();
+ menuitem[0] = gtk_menu_item_new_with_mnemonic("_Copy");
+ menuitem[1] = gtk_menu_item_new_with_mnemonic("Copy as _Binary");
+ menuitem[2] = gtk_menu_item_new_with_mnemonic("Copy as _ASCII");
+ menuitem[3] = gtk_menu_item_new_with_mnemonic("Add _Read Breakpoint");
+ menuitem[4] = gtk_menu_item_new_with_mnemonic("Add _Write Breakpoint");
+ menuitem[5] = gtk_menu_item_new_with_mnemonic("_Disable Breakpoints");
+
+ for(i=0; i<num_menu_items; i++)
+ {
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem[i]);
+ gtk_widget_show(menuitem[i]);
+ }
+
gtk_widget_show_all(winMemEdit);
+ gtk_widget_show(menu);
//=== Signal Connections ===========================/
gtk_signal_connect( GTK_OBJECT(winMemEdit), "destroy", on_close, NULL );
gtk_signal_connect( GTK_OBJECT(textbox), "key-press-event", on_key_press, NULL );
+ gtk_signal_connect( GTK_OBJECT(textbox), "button-press-event", on_mouse_down, NULL );
+
+ for(i=0; i<num_menu_items; i++)
+ gtk_signal_connect( GTK_OBJECT(menuitem[i]), "activate", on_menu_select, (gpointer)i);
}
static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
GtkTextMark* cursor;
GtkTextIter cursor_iter;
- int cursorpos, linepos, linenum, linelen = 74;
+ int cursorpos, linepos, linenum;
uint32 key, addr;
uint8 byte;
@@ -141,47 +178,27 @@
//todo: make this not suck
switch(event->keyval)
{
- case GDK_0:
- case GDK_1:
- case GDK_2:
- case GDK_3:
- case GDK_4:
- case GDK_5:
- case GDK_6:
- case GDK_7:
- case GDK_8:
+ case GDK_0: case GDK_1: case GDK_2:
+ case GDK_3: case GDK_4: case GDK_5:
+ case GDK_6: case GDK_7: case GDK_8:
case GDK_9:
key = event->keyval - GDK_0;
break;
- case GDK_KP_0:
- case GDK_KP_1:
- case GDK_KP_2:
- case GDK_KP_3:
- case GDK_KP_4:
- case GDK_KP_5:
- case GDK_KP_6:
- case GDK_KP_7:
- case GDK_KP_8:
+ case GDK_KP_0: case GDK_KP_1: case GDK_KP_2:
+ case GDK_KP_3: case GDK_KP_4: case GDK_KP_5:
+ case GDK_KP_6: case GDK_KP_7: case GDK_KP_8:
case GDK_KP_9:
key = event->keyval - GDK_KP_0;
break;
- case GDK_A:
- case GDK_B:
- case GDK_C:
- case GDK_D:
- case GDK_E:
- case GDK_F:
+ case GDK_A: case GDK_B: case GDK_C:
+ case GDK_D: case GDK_E: case GDK_F:
key = (event->keyval - GDK_A) + 10;
break;
- case GDK_a:
- case GDK_b:
- case GDK_c:
- case GDK_d:
- case GDK_e:
- case GDK_f:
+ case GDK_a: case GDK_b: case GDK_c:
+ case GDK_d: case GDK_e: case GDK_f:
key = (event->keyval - GDK_a) + 10;
break;
@@ -204,7 +221,7 @@
cursorpos -= linelen;
if(cursorpos < 0)
{
- memedit_address -= 16;
+ memedit_address -= bytesperline;
cursorpos += linelen;
}
}
@@ -213,7 +230,7 @@
cursorpos += linelen;
if(cursorpos >= (linelen * memedit_numlines))
{
- memedit_address += 16;
+ memedit_address += bytesperline;
cursorpos -= linelen;
}
}
@@ -223,7 +240,7 @@
}
else if(key == GDK_Right)
{
- if(cursorpos) cursorpos++;
+ if(cursorpos < (linelen * memedit_numlines)) cursorpos++;
}
else
{
@@ -231,7 +248,7 @@
linenum = cursorpos / linelen;
linepos = cursorpos % linelen;
- if((linepos == 8) || (linepos == 56)) //address/hex or hex/text separators
+ if((event->keyval != GDK_BackSpace) && ((linepos == (hexstartpos - 1)) || (linepos == (textstartpos - 1)))) //address/hex or hex/text separators
{
linepos++;
cursorpos++;
@@ -241,38 +258,47 @@
if(linepos >= (linelen - 1)); //end of line; do nothing
//If cursor is in address
- else if(linepos < 8)
+ else if(linepos < (hexstartpos - 1))
{
if(key < 16) //hex number entered
{
//yes, I probably _could_ have made this line uglier.
memedit_address = (memedit_address & ~(0xF << (4 * (7 - linepos)))) | (key << (4 * (7 - linepos)));
cursorpos++;
- if((cursorpos % linelen) == 8) cursorpos++; //skip address/hex separator
+ if((cursorpos % linelen) == (hexstartpos - 1)) cursorpos++; //skip address/hex separator
}
+ else if(linepos && (event->keyval == GDK_BackSpace)) //back one character
+ {
+ cursorpos--;
+ if(cursorpos < 0)
+ {
+ memedit_address -= bytesperline;
+ cursorpos++;
+ }
+ }
//todo: else, beep or something
}
//If cursor is in text
- else if(linepos >= 56)
+ else if(linepos >= (textstartpos - 1))
{
//If a non-special key, except Enter, was pressed
if((event->keyval <= 0xFF) || (event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))
{
- linepos -= 57; //Character index
- addr = memedit_address + (linenum * 16) + linepos; //Address to edit
+ linepos -= textstartpos; //Character index
+ addr = memedit_address + (linenum * bytesperline) + linepos; //Address to edit
if(event->keyval <= 0xFF) byte = event->keyval;
else if((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter)) byte = 0x0A; //Enter inserts line break
write_memory_8(addr, byte);
cursorpos++;
- if((cursorpos % linelen) == 73) //wrote past last character
+ if((cursorpos % linelen) == (linelen - 1)) //wrote past last character
{
- cursorpos += 58; //to first char on next line
+ cursorpos += (textstartpos + 1); //to first char on next line (+1 for line break)
if(cursorpos >= (linelen * memedit_numlines)) //past end of box
{
- memedit_address += 16;
+ memedit_address += bytesperline;
cursorpos -= linelen;
}
}
@@ -280,12 +306,12 @@
else if(event->keyval == GDK_BackSpace) //back one character
{
cursorpos--;
- if((cursorpos % linelen) < 57) //before first character
+ if((cursorpos % linelen) < textstartpos) //before first character
{
- cursorpos -= 58; //to last char on prev line
+ cursorpos -= (textstartpos + 1); //to last char on prev line
if(cursorpos < 0)
{
- memedit_address -= 16;
+ memedit_address -= bytesperline;
cursorpos += linelen;
}
}
@@ -295,14 +321,14 @@
//If cursor is in hex
else
{
- linepos -= 8;
- if(!(linepos % 3)) //between bytes
+ linepos -= (hexstartpos - 1);
+ if((event->keyval != GDK_BackSpace) && !(linepos % 3)) //between bytes
{
cursorpos++;
linepos++;
}
- addr = memedit_address + (linenum * 16) + (linepos / 3);
+ addr = memedit_address + (linenum * bytesperline) + (linepos / 3);
//printf("byte %u (%08X) nybble %u, ", linepos / 3, addr, (linepos % 3) - 1);
if(key < 16) //hex number entered
@@ -319,9 +345,9 @@
write_memory_8(addr, byte);
cursorpos++;
- if((cursorpos % linelen) == 57) //wrote past last byte
+ if((cursorpos % linelen) == textstartpos) //wrote past last byte
{
- cursorpos += 26; //to first byte on next line
+ cursorpos += bytesperline + 10; //to first byte on next line - skip text (bytesperline chars), line break, address (8 chars), separator
if(cursorpos >= (linelen * memedit_numlines)) //past end of box
{
memedit_address += 16;
@@ -329,6 +355,25 @@
}
}
} //if hex number entered
+ else if(event->keyval == GDK_BackSpace) //back one character
+ {
+ if(linepos < 2) cursorpos -= linepos + 1; //end of address (before/after separator)
+ else
+ {
+ cursorpos--;
+ if(!(((cursorpos % linelen) - (hexstartpos - 1)) % 3)) cursorpos--; //between bytes
+
+ if((cursorpos % linelen) < hexstartpos) //before first character
+ {
+ cursorpos -= (hexstartpos + bytesperline + 1); //to last char on prev line
+ if(cursorpos < 0)
+ {
+ memedit_address -= bytesperline;
+ cursorpos += linelen;
+ }
+ }
+ }
+ } //if backspace
} //if in hex
}
@@ -346,7 +391,179 @@
}
+static gboolean on_mouse_down(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ if(event->button != 3) return FALSE;
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, 0, event->button, event->time);
+ return TRUE;
+}
+
+
+static void on_menu_select(GtkMenuItem *menuitem, gpointer user_data)
+{
+ gchar* text;
+ GtkTextIter start, end;
+ uint32 startaddr, endaddr, numbytes;
+ uint8 byte;
+ int i;
+ breakpoint newbp;
+
+ switch((int)user_data)
+ {
+ case 0: //Copy
+ if(!gtk_text_buffer_get_selection_bounds(textbuf, &start, &end)) break; //nothing selected if false
+ text = gtk_text_iter_get_text(&start, &end);
+ gtk_clipboard_set_text(clipboard, text, -1);
+ break;
+
+ case 1: //Copy as Binary
+ //TODO - not sure how to put raw binary data on clipboard <_<
+ gtk_clipboard_set_text(clipboard, "not implemented yet", i);
+ printf("Copy as Binary not implemented yet\n");
+ break;
+
+ case 2: //Copy as ASCII
+ numbytes = GetSelectionRange(&startaddr, 0);
+ if(!numbytes) break;
+ text = (gchar*)malloc((numbytes + 1) * sizeof(gchar));
+ if(!text) break;
+
+ for(i=0; i<numbytes; i++)
+ {
+ byte = read_memory_8(startaddr);
+ if((byte >= 0x20) && (byte <= 0x7E)) text[i] = byte;
+ else text[i] = '.';
+ startaddr++;
+ }
+ text[i] = 0;
+
+ gtk_clipboard_set_text(clipboard, text, i);
+ free(text);
+ break;
+
+ case 3: //Break on read
+ case 4: //Break on write
+ numbytes = GetSelectionRange(&startaddr, 1);
+ if(!numbytes) break;
+ endaddr = startaddr + (numbytes - 1);
+
+ //see if there's already a breakpoint for this range,
+ //and if so, just add the read/write flag.
+ for(i=0; i<g_NumBreakpoints; i++)
+ {
+ if((g_Breakpoints[i].address == startaddr)
+ && (g_Breakpoints[i].endaddr == endaddr))
+ {
+ g_Breakpoints[i].flags |= ((int)user_data == 3) ? BPT_FLAG_READ : BPT_FLAG_WRITE;
+ printf("Added %s flag to breakpoint %d.\n", ((int)user_data == 3) ? "read" : "write", i);
+ update_breakpoints();
+ numbytes = 0;
+ break;
+ }
+ }
+
+ if(!numbytes) break; //already found a breakpoint
+
+ newbp.address = startaddr;
+ newbp.endaddr = endaddr;
+ newbp.flags = BPT_FLAG_ENABLED | (((int)user_data == 3) ? BPT_FLAG_READ : BPT_FLAG_WRITE);
+ add_breakpoint_struct(&newbp);
+ printf("Added breakpoint.\n");
+ update_breakpoints();
+ break;
+
+ case 5: //Clear breakpoints
+ numbytes = GetSelectionRange(&startaddr, 1);
+ if(!numbytes)
+ {
+ //todo: prompt to clear all memory breakpoints
+ break;
+ }
+
+ for(i=0; i<g_NumBreakpoints; i++)
+ {
+ //if breakpoint overlaps this range
+ if(((g_Breakpoints[i].address <= startaddr) && (g_Breakpoints[i].endaddr >= startaddr))
+ || ((g_Breakpoints[i].address <= endaddr) && (g_Breakpoints[i].endaddr >= endaddr)))
+ {
+ g_Breakpoints[i].flags &= ~BPT_FLAG_ENABLED;
+ printf("Disabled breakpoint %d.\n", i);
+ }
+ }
+ update_breakpoints();
+ break;
+ }
+}
+
+
static void on_close()
{
memedit_opened = 0;
}
+
+
+//Determines range of bytes selected.
+//Returns # of bytes selected, sets StartAddr to address of first byte if any.
+//A byte is considered selected if the selection covers either the hex OR text view of it.
+//In the hex view, a byte is considered selected if either nybble and/or the space/pipe
+//after it is selected. I consider this a good thing, as it means if you accidentally don't
+//select an entire byte, it still gets copied.
+//When AllowEmpty is set, if there is no selection, but the cursor is in the hex or text,
+//the byte next to it is considered selected.
+static int GetSelectionRange(uint32* StartAddr, int AllowEmpty)
+{
+ GtkTextIter start, end;
+ GtkTextMark* cursor;
+ int startpos, endpos, startline, endline, startlinepos, endlinepos, numbytes;
+
+ //Determine what byte range is selected.
+ if(gtk_text_buffer_get_selection_bounds(textbuf, &start, &end))
+ {
+ startpos = gtk_text_iter_get_offset(&start);
+ endpos = gtk_text_iter_get_offset(&end);
+ }
+ else //nothing selected
+ {
+ if(!AllowEmpty) return 0;
+ cursor = gtk_text_buffer_get_insert(textbuf);
+ gtk_text_buffer_get_iter_at_mark(textbuf, &start, cursor);
+ startpos = gtk_text_iter_get_offset(&start);
+ endpos = startpos + 1;
+ }
+ //printf("selected %d - %d\n", startpos, endpos);
+
+ startline = startpos / linelen;
+ startlinepos = startpos % linelen;
+ endline = endpos / linelen;
+ endlinepos = endpos % linelen;
+
+ if((startlinepos == (textstartpos - 1)) && ((endpos - startpos) == 1)) return 0; //Only hex/text separator selected
+
+ if(startlinepos >= (linelen - 1)) //past end of line
+ {
+ startline++;
+ startlinepos = hexstartpos;
+ }
+
+ if(endlinepos <= hexstartpos) //before hex
+ {
+ endline--;
+ endlinepos = textstartpos - 1;
+ }
+
+ //It works.
+ if(startline > endline) return 0; //no actual hex/text selected
+ //else if((startline == endline) && ((endlinepos - startlinepos) < 2) && (startlinepos < (textstartpos - 1))) return 0; //no entire bytes
+
+ if(startlinepos >= textstartpos) //selection begins in text
+ (*StartAddr) = (startline * bytesperline) + (startlinepos - textstartpos);
+ else (*StartAddr) = (startline * bytesperline) + ((startlinepos - hexstartpos) / 3);
+
+ if(endlinepos >= textstartpos) //selection ends in text
+ numbytes = ((endline * bytesperline) + (endlinepos - textstartpos)) - (*StartAddr);
+ else numbytes = ((endline * bytesperline) + (int)ceil((float)(endlinepos - hexstartpos) / 3.0)) - (*StartAddr);
+
+ (*StartAddr) += memedit_address;
+ //printf("%u bytes from %08X\n", numbytes, (*StartAddr));
+ return numbytes;
+}
Index: main/gui_gtk/debugger/breakpoints.c
===================================================================
--- main/gui_gtk/debugger/breakpoints.c (revision 426)
+++ main/gui_gtk/debugger/breakpoints.c (working copy)
@@ -155,7 +155,7 @@
}
else
{
- sprintf(buf, "%c%c%c$c 0x%08X - 0x%08X",
+ sprintf(buf, "%c%c%c%c 0x%08X - 0x%08X",
(bpt->flags & BPT_FLAG_READ) ? 'R' : '-',
(bpt->flags & BPT_FLAG_WRITE) ? 'W' : '-',
(bpt->flags & BPT_FLAG_EXEC) ? 'X' : '-',