What's new

New Debugger branch - Functional

ebenblues

Mupen64Plus Dev.
And I'm still seeing that "interface freezes up" issue. Seems like it happens the second time a breakpoint hits.
I haven't looked at your code at all, but generally interface freeze-up's can be gtk threading issues. Have you tried running mupen64plus using gdb and doing a "bt" when the gui hangs to see where it's stuck? If it's stuck trying to get some lock, then that would be your issue. The way I setup gui multi-threading support for mupen64plus, you have to take the gdk lock before you make any gtk calls from threads outside of the main gui thread only. If you're on the main gui thread, you will already have the lock and attempting to take it again will result in a deadlock which can look like a hang.

Also, with this design I found that making calls like this from the main gui thread

Code:
while(g_main_context_iteration(NULL, FALSE));

to tell gtk to process any queued events also causes a deadlock. You may want to check if you put something like that in any of your debugger gtk code. I created a macro called GUI_PROCESS_QUEUED_EVENTS in main/gui_gtk/main_gtk.h that does this, but prevents the deadlock.

Hope that helps.
 
Last edited:

Tillin9

Mupen64Plus Dev.
I concur. I ran into this issue trying to update the Gtk statusbar from the core. If you need to manipulate Gtk widgets from other threads you need to use a lock like in the info_message() function ebenblues added.
 
OP
D

DarkJezter

New member
The only functions that should be getting called to update the debugger is update_debugger_frontend, which last I worked on it had the locks added to it which resolved the issues I was seeing. I'll be taking a closer look at this in a bit to see if I can pin down what's going on here.

P.S. The memory editing system includes a call:
get_memory_flags(addr)

This function detmines in advance what operations can be performed on memory. I was thinking it may be nice if we use for example, a color-coded scheme for determining what kind of memory we're looking at, (virtual vs physical, readable/writable vs read-only or unreadable)
 
Last edited:
OP
D

DarkJezter

New member
Actually that's a good point

Our update debugger routine should probably be changed so that it pushes a message into the queue of the GUI thread, and that thread can then go ahead and update the frontend. One slight issue with that though, right now the debugger code assumes the emulator is NOT running when it accesses the parts of the emulator to show it's state.

To keep this assumption, we would have to make sure that the emulator blocks at pushing the message into the GUI's queue, until the debugger has successfully updated the display.
 

HyperHacker

Raving Lunatic
I verified the problem occurs every time a second breakpoint hits. The interface keeps working, but stops redrawing. However if I don't call switch_button_to_run() when a breakpoint hits, it seems to work fine. As a temporary solution I'm just going to dummy out that function and change the button label to "> \ ||". :p

Also it looks like the displayed register values aren't always correct. For example set a breakpoint for writes to 0x8033B21E in Mario 64 and get hit by a Goomba. The instruction shown at 0x80254208 is SH reg25, 0x00AE(reg14), and it should be storing Mario's health back to the aforementioned address. The hex at 0x80254208 is 0xA5D900AE, and another disassembler confirms this is the correct instruction, but I see Mario's health in reg27, and the address to store it at (minus 0xAE) in regs 4, 11, 15, and 26.
Comparing to Nemu, I see SH $T9, 0x00AE($T6); T6 (reg14) = 0x8033B170 (address), T9 (reg25) = 0x840 (new health value). (Why don't we have real register names? <_<) So looks like the order of the registers is mixed up.

[edit] Wait, no, durr. The labels just aren't lining up with the rows. The reg24 box lines up with the reg26 label.
 
Last edited:

MIO0

New member
I recently tried to make the labels line up by turning the GtkCList into a bunch of labels or entry boxes and then packing them into a GtkTable with the labels. This ended up making the window bigger, and attempts to fiddle with the widget sizes ended up looking ugly. I guess the easiest way to make the labels line up is to put them into their own column in the CList. (or two, one for the numeric and one for the symbolic names)

EDIT: I tried that idea. It is working rather well.
 
Last edited:
OP
D

DarkJezter

New member
Mio0, please feel free to either check in the changes you've made or if you prefer, post a patch and I can apply them for you :) I'm ecstatic that someone's been playing with lining up the labels... I wasn't looking forward to playing with that myself.
 

MIO0

New member
I'm already doing that as I go along. Not only am I using a monospace font, I'm also trying different font sizes. So far I have the GP, cop0, cop1, AI, and PI registers' appearance changed.

Does anyone think that it would a good idea to move the cop0 viewer into the notebook? I'm trying to find ways to make the register window smaller, and for what I think most users are going to use the debugger for, I don't think that the cop0 registers are very important.
 

HyperHacker

Raving Lunatic
As I mentioned before, having those 3 pieces of info each on their own tab would be great. Being able to split the tabs off into their own window would be even cooler, but first things first. :p

Speaking of which, actual register names and float/double views (at least for the FPU) would be nice too.
 

MIO0

New member
Summary of changes:
  • Register labels are now cells inside of the CList widgets used to display register values. This guarantees that the labels will line up.
  • Widgets used to display lists of register values now use a 9pt monospace font.
  • The highlight color is now a lighter shade of blue for better contrast.
  • GPRs are now also labeled with their symbolic names.
  • COP0 and hardware registers are displayed as 32 bit values like they really are.
  • The big long update sequences for the hardware register displays are now rolled up into loops.
  • Some code reformatting in edited areas.

This patch was made with a week old checkout, but applies correctly to the current debugger branch.

patch: (had to compress it to fit -- use uudecode | gunzip -c)
Code:
begin-base64 644 /dev/stdout
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
AHNbugAA
====
 
OP
D

DarkJezter

New member
Right now, my biggest priority is to get the treeview in the disassembler all fixed up. Once the scrolling issues are resolved and we can jump to specific addresses, I'm planning a temporary merge back into the trunk. Lets get what we have working, and as rock solid as possible for a public release. It won't be pretty, but it will be functional.

After the remerge, we'll be looking at a complete revamp of the debugger GUI. I want to see a single main window, with dockable subwindows that can be detached, or disabled. Having 5 seperate windows to juggle with the main window, the n64 display and possibly the console is simply ridiculous. People who want it to work that way can detach any of the windows they need, should they be so inclined. (multiple monitors perhaps) But so far, it seems this approach should be very flexible, and fully handled by GTK.

Once the GUI is rewritten, we will do what should be our final remerge to the trunk. If we keep this up, we may just have the finished debugger in before the next major release.

[EDIT] Looked at your code Mio0, and had no problems including it in the branch. Great work, although I may play with the font sizes for the registers a bit. I'd like to keep everything relatively consistent if possible.
 
Last edited:

HyperHacker

Raving Lunatic
I hope not too much of this code will have to be rewritten for the GUI update. :p It's a bit rough around the edges, disassembler could use some work, but for the most part I think the only major issue right now is having so many windows, with no way to reopen them if closed, and I'm guessing no real defined behaviour if some are closed.

Anyway, here's my latest work on the memory editor, based on today's revision with MIO0's patch.

-Added right-click menu to memory editor.
-Fixed incorrect display of breakpoint ranges ('$c').
-Workaround for GUI deadlock when breakpoints hit.
-Disassembly columns are resizable.
-General code improvements in memory editor (replacing magic numbers, etc).

Code:
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' : '-',
 

HyperHacker

Raving Lunatic
So if this is all being merged into the trunk at some point, if I want to change other things not related to the debugger (thinking remembering your filter in the ROM selector would be nice), should I just do it in the debugger branch?

Also, when I'm adding files, should I be changing the "Copyright (C) 2002 DavFr" in the comments?
 
Last edited:

ebenblues

Mupen64Plus Dev.
So if this is all being merged into the trunk at some point, if I want to change other things not related to the debugger (thinking remembering your filter in the ROM selector would be nice), should I just do it in the debugger branch?
No, only changes for the debugger should go in that branch. For the rom filter change, I would submit a patch against trunk.

Also, when I'm adding files, should I be changing the "Copyright (C) 2002 DavFr" in the comments?
Yeah, for new files, I change the copyright year to 2008 and put ebenblues.
 

okaygo

Mupen64Plus Dev.
When I try to build or compile the branch:

make DBG=1 mupen64plus
I get this error:
debugger/memory.c:23:21: error: dis-asm.h: No such file or directory

Edit: I was missing a dependency :cat:
 
Last edited:

HyperHacker

Raving Lunatic
Where did ui_clist_edit come from? From the header it looks like it was copied from another open-source project, but I can't find anything about it on Google, only copies of the file. I need similar for a treeview and was hoping it already existed. :p

[edit] Or GtkCellRenderer has such a thing built in. v¯v;
 
Last edited:
OP
D

DarkJezter

New member
It's a template I found on the GTK webpage. They lay out in example how to create a simple treemodel, which I gutted and rewrote. :-$ In fact, a lot of the comments are still incorrect. I'll be going through and cleaning that before it goes in the trunk.
 

Top