nkeynes@2: /** nkeynes@2: * Implements the memory dump window. nkeynes@2: */ nkeynes@2: #include nkeynes@2: #include nkeynes@2: #include nkeynes@2: #include "gui.h" nkeynes@2: #include "interface.h" nkeynes@2: #include "mem.h" nkeynes@2: nkeynes@2: #define MAX_DUMP_SIZE 4096 nkeynes@2: nkeynes@2: #define DUMP_DATA_TAG 0xD4B9DA7A nkeynes@2: nkeynes@2: typedef struct dump_data { nkeynes@2: uint32_t _tag; nkeynes@2: uint32_t start; nkeynes@2: uint32_t end; nkeynes@2: int flags; nkeynes@2: char *data; nkeynes@2: nkeynes@2: GtkEntry *fromInput, *toInput; nkeynes@2: GtkTextView *textArea; nkeynes@2: GtkTextTag *changedTag; nkeynes@2: GtkTextBuffer *textBuffer; nkeynes@2: struct dump_data *next; nkeynes@2: } *dump_data_t; nkeynes@2: nkeynes@2: static dump_data_t dump_list_head = NULL; nkeynes@2: nkeynes@2: gboolean on_dump_win_delete_event( GtkWidget *widget, GdkEvent *event, nkeynes@2: gpointer user_data ); nkeynes@2: void on_dump_win_button_view_clicked( GtkWidget *widget, gpointer user_data ); nkeynes@2: void dump_win_set_text( dump_data_t data, char *old_data, char *new_data ); nkeynes@2: nkeynes@2: nkeynes@2: void dump_window_new( void ) { nkeynes@2: GtkWidget *win = create_dump_win(); nkeynes@2: GtkWidget *dump_view_button = (GtkWidget *)g_object_get_data(G_OBJECT(win), "dump_view_button"); nkeynes@2: dump_data_t data = malloc( sizeof(struct dump_data) ); nkeynes@2: data->_tag = DUMP_DATA_TAG; nkeynes@2: data->fromInput = (GtkEntry *)g_object_get_data(G_OBJECT(win), "dump_from"); nkeynes@2: data->toInput = (GtkEntry *)g_object_get_data(G_OBJECT(win), "dump_to"); nkeynes@2: data->textArea = (GtkTextView *)g_object_get_data(G_OBJECT(win), "dump_text"); nkeynes@2: data->next = dump_list_head; nkeynes@2: dump_list_head = data; nkeynes@2: data->data = NULL; nkeynes@2: data->start = 0; nkeynes@2: data->end = 0; nkeynes@2: gtk_entry_set_text( data->fromInput, "" ); nkeynes@2: gtk_entry_set_text( data->toInput, "" ); nkeynes@2: data->textBuffer = gtk_text_buffer_new(NULL); nkeynes@2: data->changedTag = gtk_text_buffer_create_tag(data->textBuffer, "changed", nkeynes@2: "foreground", "blue", nkeynes@2: NULL); nkeynes@2: gtk_text_view_set_buffer(data->textArea, data->textBuffer); nkeynes@2: gtk_text_view_set_editable(data->textArea, FALSE); nkeynes@2: gtk_widget_modify_font(GTK_WIDGET(data->textArea),fixed_list_font); nkeynes@2: nkeynes@2: g_signal_connect ((gpointer) win, "delete_event", nkeynes@2: G_CALLBACK (on_dump_win_delete_event), nkeynes@2: data); nkeynes@2: g_signal_connect ((gpointer) dump_view_button, "clicked", nkeynes@2: G_CALLBACK (on_dump_win_button_view_clicked), nkeynes@2: data); nkeynes@2: gtk_widget_show( GTK_WIDGET(win) ); nkeynes@2: } nkeynes@2: nkeynes@2: nkeynes@2: nkeynes@2: gboolean on_dump_win_delete_event( GtkWidget *widget, GdkEvent *event, nkeynes@2: gpointer user_data ) nkeynes@2: { nkeynes@2: dump_data_t data = (dump_data_t)user_data; nkeynes@2: if( data->data != NULL ) nkeynes@2: free( data->data ); nkeynes@2: dump_data_t node = dump_list_head; nkeynes@2: if( node == data ) nkeynes@2: dump_list_head = data->next; nkeynes@2: else { nkeynes@2: while( node->next != data ) { nkeynes@2: node = node->next; nkeynes@2: assert( node != NULL ); nkeynes@2: } nkeynes@2: node->next = data->next; nkeynes@2: } nkeynes@2: free( data ); nkeynes@2: return FALSE; nkeynes@2: } nkeynes@2: nkeynes@2: void on_dump_win_button_view_clicked( GtkWidget *widget, gpointer user_data ) nkeynes@2: { nkeynes@2: dump_data_t data = (dump_data_t)user_data; nkeynes@2: uint32_t startVal, endVal; nkeynes@2: nkeynes@2: assert( data != NULL ); nkeynes@2: assert( data->_tag == DUMP_DATA_TAG ); nkeynes@2: nkeynes@2: startVal = gtk_entry_get_hex_value(data->fromInput, data->start); nkeynes@2: endVal = gtk_entry_get_hex_value(data->toInput, data->end); nkeynes@2: if( startVal != data->start || endVal != data->end ) { nkeynes@2: if( startVal > endVal ) { nkeynes@2: int tmp = endVal; nkeynes@2: endVal = startVal; nkeynes@2: startVal = tmp; nkeynes@2: } nkeynes@2: if( endVal > startVal + MAX_DUMP_SIZE ) nkeynes@2: endVal = startVal + MAX_DUMP_SIZE; nkeynes@2: nkeynes@2: gtk_entry_set_hex_value(data->fromInput,startVal); nkeynes@2: gtk_entry_set_hex_value(data->toInput,endVal); nkeynes@2: data->start = startVal; nkeynes@2: data->end = endVal; nkeynes@2: nkeynes@2: if( data->data != NULL ) { nkeynes@2: free( data->data ); nkeynes@2: data->data = NULL; nkeynes@2: } nkeynes@2: if( startVal != endVal ) { nkeynes@2: data->data = malloc( endVal - startVal ); nkeynes@2: mem_copy_from_sh4( data->data, startVal, endVal-startVal ); nkeynes@2: dump_win_set_text( data, data->data, data->data ); nkeynes@2: } nkeynes@2: } nkeynes@2: } nkeynes@2: nkeynes@2: void dump_win_update( dump_data_t data ) nkeynes@2: { nkeynes@2: if( data->data == NULL ) nkeynes@2: return; nkeynes@2: char tmp[data->end-data->start]; nkeynes@2: int length = data->end-data->start; nkeynes@2: memcpy( tmp, data->data, length ); nkeynes@2: mem_copy_from_sh4( data->data, data->start, length ); nkeynes@2: dump_win_set_text( data, tmp, data->data ); nkeynes@2: } nkeynes@2: nkeynes@2: void dump_win_update_all( ) nkeynes@2: { nkeynes@2: dump_data_t node = dump_list_head; nkeynes@2: while( node != NULL ) { nkeynes@2: dump_win_update(node); nkeynes@2: node = node->next; nkeynes@2: } nkeynes@2: } nkeynes@2: nkeynes@2: void dump_win_set_text( dump_data_t data, char *old_data, char *new_data ) nkeynes@2: { nkeynes@2: GtkTextBuffer *buf = data->textBuffer; nkeynes@2: GtkTextTag *changedTag = data->changedTag; nkeynes@2: GtkTextIter iter, endIter; nkeynes@2: int i, j, offset; nkeynes@2: /* Clear out the buffer */ nkeynes@2: gtk_text_buffer_get_start_iter(buf,&iter); nkeynes@2: gtk_text_buffer_get_end_iter(buf,&endIter); nkeynes@2: gtk_text_buffer_delete(buf,&iter,&endIter); nkeynes@2: gtk_text_buffer_get_start_iter(buf,&iter); nkeynes@2: nkeynes@2: for( offset = 0, i=data->start; iend; i+=16, offset+=16 ) { nkeynes@2: char text[80]; nkeynes@2: sprintf(text, "%08X:", i ); nkeynes@2: gtk_text_buffer_insert( buf, &iter, text, 9 ); nkeynes@2: for( j=0; j<16; j++ ) { nkeynes@2: if( j%4 == 0 ) nkeynes@2: gtk_text_buffer_insert( buf, &iter, " ", 1 ); nkeynes@2: if( i+j < data->end ) { nkeynes@2: int oldVal = ((int)old_data[offset+j])&0xFF; nkeynes@2: int newVal = ((int)new_data[offset+j])&0xFF; nkeynes@2: sprintf(text, "%02X ", newVal); nkeynes@2: if( oldVal == newVal ) nkeynes@2: gtk_text_buffer_insert( buf, &iter, text, 3 ); nkeynes@2: else nkeynes@2: gtk_text_buffer_insert_with_tags( buf, &iter, text, 3, nkeynes@2: changedTag, NULL ); nkeynes@2: } else { nkeynes@2: gtk_text_buffer_insert( buf, &iter, " ", 3 ); nkeynes@2: } nkeynes@2: } nkeynes@2: gtk_text_buffer_insert( buf, &iter, " ", 2 ); nkeynes@2: for( j=0; j<16 && i+j < data->end; j++ ) { nkeynes@2: int oldVal = ((int)old_data[offset+j])&0xFF; nkeynes@2: int newVal = ((int)new_data[offset+j])&0xFF; nkeynes@2: if( isprint(newVal) ) nkeynes@2: sprintf( text, "%c", newVal ); nkeynes@2: else strcpy( text, "." ); nkeynes@2: if( oldVal == newVal ) nkeynes@2: gtk_text_buffer_insert( buf, &iter, text, 1 ); nkeynes@2: else nkeynes@2: gtk_text_buffer_insert_with_tags( buf, &iter, text, 1, nkeynes@2: changedTag, NULL ); nkeynes@2: } nkeynes@2: gtk_text_buffer_insert( buf, &iter, "\n", 1 ); nkeynes@2: } nkeynes@2: }