Search
lxdream.org :: lxdream/src/gtkui/gtk_dump.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gtkui/gtk_dump.c
changeset 1065:bc1cc0c54917
prev561:533f6b478071
prev763:b3ce4448f200
author nkeynes
date Sun Jul 05 13:52:50 2009 +1000 (14 years ago)
permissions -rw-r--r--
last change No-op merge lxdream-mmu to remove head (actually merged long ago)
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/gtkui/gtk_dump.c Sun Jul 05 13:52:50 2009 +1000
1.3 @@ -0,0 +1,256 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Implements the memory dump window.
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include <ctype.h>
1.23 +#include <assert.h>
1.24 +#include <string.h>
1.25 +#include <stdlib.h>
1.26 +#include "mem.h"
1.27 +#include "gtkui/gtkui.h"
1.28 +
1.29 +#define MAX_DUMP_SIZE 4096
1.30 +
1.31 +#define DUMP_WINDOW_TAG 0xD4B9DA7A
1.32 +
1.33 +struct dump_window_info {
1.34 + uint32_t _tag;
1.35 + uint32_t start;
1.36 + uint32_t end;
1.37 + int flags;
1.38 + unsigned char *data;
1.39 +
1.40 + GtkWidget *window;
1.41 + GtkWidget *fromInput, *toInput;
1.42 + GtkWidget *textArea;
1.43 + GtkTextTag *changedTag;
1.44 + GtkTextBuffer *textBuffer;
1.45 + struct dump_window_info *next;
1.46 +};
1.47 +
1.48 +static dump_window_t dump_list_head = NULL;
1.49 +
1.50 +gboolean on_dump_window_delete_event( GtkWidget *widget, GdkEvent *event,
1.51 + gpointer user_data );
1.52 +void on_dump_window_button_view_clicked( GtkWidget *widget, gpointer user_data );
1.53 +void dump_window_set_text( dump_window_t data, unsigned char *old_data, unsigned char *new_data );
1.54 +
1.55 +
1.56 +dump_window_t dump_window_new( const gchar *title )
1.57 +{
1.58 + GtkWidget *vbox3;
1.59 + GtkWidget *hbox2;
1.60 + GtkWidget *dump_view_button;
1.61 + GtkWidget *scrolledwindow9;
1.62 +
1.63 + dump_window_t dump = g_malloc0( sizeof( struct dump_window_info ) );
1.64 +
1.65 + dump->_tag = DUMP_WINDOW_TAG;
1.66 + dump->next = dump_list_head;
1.67 + dump_list_head = dump;
1.68 + dump->data = NULL;
1.69 + dump->start = 0;
1.70 + dump->end = 0;
1.71 + dump->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1.72 + gtk_window_set_title (GTK_WINDOW (dump->window), _("Memory dump"));
1.73 +
1.74 + vbox3 = gtk_vbox_new (FALSE, 0);
1.75 + gtk_container_add (GTK_CONTAINER (dump->window), vbox3);
1.76 +
1.77 + hbox2 = gtk_hbox_new (FALSE, 0);
1.78 + dump->fromInput = gtk_entry_new ();
1.79 + gtk_entry_set_text( GTK_ENTRY(dump->fromInput), "" );
1.80 + dump->toInput = gtk_entry_new ();
1.81 + gtk_entry_set_text( GTK_ENTRY(dump->toInput), "" );
1.82 + dump_view_button = gtk_button_new_with_mnemonic (_("View"));
1.83 +
1.84 + gtk_box_pack_start (GTK_BOX (hbox2), gtk_label_new(_(" From ")), FALSE, FALSE, 0);
1.85 + gtk_box_pack_start (GTK_BOX (hbox2), dump->fromInput, FALSE, TRUE, 0);
1.86 + gtk_box_pack_start (GTK_BOX (hbox2), gtk_label_new(_(" To ")), FALSE, FALSE, 0);
1.87 + gtk_box_pack_start (GTK_BOX (hbox2), dump->toInput, FALSE, TRUE, 0);
1.88 + gtk_box_pack_start (GTK_BOX (hbox2), dump_view_button, FALSE, FALSE, 0);
1.89 + gtk_box_pack_start (GTK_BOX (hbox2), gtk_label_new (_(" ")), TRUE, TRUE, 0);
1.90 + gtk_box_pack_start (GTK_BOX (vbox3), hbox2, FALSE, TRUE, 3);
1.91 +
1.92 + dump->textArea = gtk_text_view_new ();
1.93 + dump->textBuffer = gtk_text_buffer_new(NULL);
1.94 + dump->changedTag = gtk_text_buffer_create_tag(dump->textBuffer, "changed",
1.95 + "foreground", "blue", NULL);
1.96 + gtk_widget_modify_font(GTK_WIDGET(dump->textArea),gui_fixed_font);
1.97 + gtk_text_view_set_editable(GTK_TEXT_VIEW(dump->textArea), FALSE);
1.98 + gtk_text_view_set_buffer(GTK_TEXT_VIEW(dump->textArea), dump->textBuffer);
1.99 + scrolledwindow9 = gtk_scrolled_window_new (NULL, NULL);
1.100 + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow9), GTK_SHADOW_IN);
1.101 + gtk_container_add (GTK_CONTAINER (scrolledwindow9), dump->textArea);
1.102 + gtk_box_pack_start (GTK_BOX (vbox3), scrolledwindow9, TRUE, TRUE, 0);
1.103 +
1.104 + g_signal_connect (dump->window, "delete_event",
1.105 + G_CALLBACK (on_dump_window_delete_event),
1.106 + dump);
1.107 + g_signal_connect (dump_view_button, "clicked",
1.108 + G_CALLBACK (on_dump_window_button_view_clicked),
1.109 + dump);
1.110 + gtk_widget_show_all( dump->window );
1.111 +
1.112 + return dump;
1.113 +}
1.114 +
1.115 +void gtk_entry_set_hex_value( GtkEntry *entry, uint32_t value )
1.116 +{
1.117 + char buf[10];
1.118 + sprintf( buf, "%08X", value );
1.119 + gtk_entry_set_text( entry, buf );
1.120 +}
1.121 +
1.122 +uint32_t gtk_entry_get_hex_value( GtkEntry *entry, uint32_t defaultValue )
1.123 +{
1.124 + const gchar *text = gtk_entry_get_text(entry);
1.125 + if( text == NULL )
1.126 + return defaultValue;
1.127 + gchar *endptr;
1.128 + uint32_t value = strtoul( text, &endptr, 16 );
1.129 + if( text == endptr ) { /* invalid input */
1.130 + value = defaultValue;
1.131 + gtk_entry_set_hex_value( entry, value );
1.132 + }
1.133 + return value;
1.134 +}
1.135 +
1.136 +gboolean on_dump_window_delete_event( GtkWidget *widget, GdkEvent *event,
1.137 + gpointer user_data )
1.138 +{
1.139 + dump_window_t data = (dump_window_t)user_data;
1.140 + if( data->data != NULL )
1.141 + free( data->data );
1.142 + dump_window_t node = dump_list_head;
1.143 + if( node == data )
1.144 + dump_list_head = data->next;
1.145 + else {
1.146 + while( node->next != data ) {
1.147 + node = node->next;
1.148 + assert( node != NULL );
1.149 + }
1.150 + node->next = data->next;
1.151 + }
1.152 + free( data );
1.153 + return FALSE;
1.154 +}
1.155 +
1.156 +void on_dump_window_button_view_clicked( GtkWidget *widget, gpointer user_data )
1.157 +{
1.158 + dump_window_t data = (dump_window_t)user_data;
1.159 + uint32_t startVal, endVal;
1.160 +
1.161 + assert( data != NULL );
1.162 + assert( data->_tag == DUMP_WINDOW_TAG );
1.163 +
1.164 + startVal = gtk_entry_get_hex_value(GTK_ENTRY(data->fromInput), data->start);
1.165 + endVal = gtk_entry_get_hex_value(GTK_ENTRY(data->toInput), data->end);
1.166 + if( startVal != data->start || endVal != data->end ) {
1.167 + if( startVal > endVal ) {
1.168 + int tmp = endVal;
1.169 + endVal = startVal;
1.170 + startVal = tmp;
1.171 + }
1.172 + if( endVal > startVal + MAX_DUMP_SIZE )
1.173 + endVal = startVal + MAX_DUMP_SIZE;
1.174 +
1.175 + gtk_entry_set_hex_value(GTK_ENTRY(data->fromInput),startVal);
1.176 + gtk_entry_set_hex_value(GTK_ENTRY(data->toInput),endVal);
1.177 + data->start = startVal;
1.178 + data->end = endVal;
1.179 +
1.180 + if( data->data != NULL ) {
1.181 + free( data->data );
1.182 + data->data = NULL;
1.183 + }
1.184 + if( startVal != endVal ) {
1.185 + data->data = malloc( endVal - startVal );
1.186 + mem_copy_from_sh4( data->data, startVal, endVal-startVal );
1.187 + dump_window_set_text( data, data->data, data->data );
1.188 + }
1.189 + }
1.190 +}
1.191 +
1.192 +void dump_window_update( dump_window_t data )
1.193 +{
1.194 + if( data->data == NULL )
1.195 + return;
1.196 + unsigned char tmp[data->end-data->start];
1.197 + int length = data->end-data->start;
1.198 + memcpy( tmp, data->data, length );
1.199 + mem_copy_from_sh4( data->data, data->start, length );
1.200 + dump_window_set_text( data, tmp, data->data );
1.201 +}
1.202 +
1.203 +void dump_window_update_all( )
1.204 +{
1.205 + dump_window_t node = dump_list_head;
1.206 + while( node != NULL ) {
1.207 + dump_window_update(node);
1.208 + node = node->next;
1.209 + }
1.210 +}
1.211 +
1.212 +void dump_window_set_text( dump_window_t data, unsigned char *old_data, unsigned char *new_data )
1.213 +{
1.214 + GtkTextBuffer *buf = data->textBuffer;
1.215 + GtkTextTag *changedTag = data->changedTag;
1.216 + GtkTextIter iter, endIter;
1.217 + int i, j, offset;
1.218 + /* Clear out the buffer */
1.219 + gtk_text_buffer_get_start_iter(buf,&iter);
1.220 + gtk_text_buffer_get_end_iter(buf,&endIter);
1.221 + gtk_text_buffer_delete(buf,&iter,&endIter);
1.222 + gtk_text_buffer_get_start_iter(buf,&iter);
1.223 +
1.224 + for( offset = 0, i=data->start; i<data->end; i+=16, offset+=16 ) {
1.225 + char text[80];
1.226 + sprintf(text, "%08X:", i );
1.227 + gtk_text_buffer_insert( buf, &iter, text, 9 );
1.228 + for( j=0; j<16; j++ ) {
1.229 + if( j%4 == 0 )
1.230 + gtk_text_buffer_insert( buf, &iter, " ", 1 );
1.231 + if( i+j < data->end ) {
1.232 + int oldVal = ((int)old_data[offset+j])&0xFF;
1.233 + int newVal = ((int)new_data[offset+j])&0xFF;
1.234 + sprintf(text, "%02X ", newVal);
1.235 + if( oldVal == newVal )
1.236 + gtk_text_buffer_insert( buf, &iter, text, 3 );
1.237 + else
1.238 + gtk_text_buffer_insert_with_tags( buf, &iter, text, 3,
1.239 + changedTag, NULL );
1.240 + } else {
1.241 + gtk_text_buffer_insert( buf, &iter, " ", 3 );
1.242 + }
1.243 + }
1.244 + gtk_text_buffer_insert( buf, &iter, " ", 2 );
1.245 + for( j=0; j<16 && i+j < data->end; j++ ) {
1.246 + int oldVal = ((int)old_data[offset+j])&0xFF;
1.247 + int newVal = ((int)new_data[offset+j])&0xFF;
1.248 + if( isprint(newVal) )
1.249 + sprintf( text, "%c", newVal );
1.250 + else strcpy( text, "." );
1.251 + if( oldVal == newVal )
1.252 + gtk_text_buffer_insert( buf, &iter, text, 1 );
1.253 + else
1.254 + gtk_text_buffer_insert_with_tags( buf, &iter, text, 1,
1.255 + changedTag, NULL );
1.256 + }
1.257 + gtk_text_buffer_insert( buf, &iter, "\n", 1 );
1.258 + }
1.259 +}
.