nkeynes@1 | 1 | #include <stdlib.h>
|
nkeynes@1 | 2 | #include <stdarg.h>
|
nkeynes@1 | 3 | #include <gnome.h>
|
nkeynes@1 | 4 | #include <math.h>
|
nkeynes@1 | 5 | #include "gui.h"
|
nkeynes@1 | 6 | #include "mem.h"
|
nkeynes@1 | 7 | #include "sh4dasm.h"
|
nkeynes@1 | 8 | #include "sh4core.h"
|
nkeynes@1 | 9 |
|
nkeynes@1 | 10 | #define REGISTER_FONT "-*-fixed-medium-r-normal--12-*-*-*-*-*-iso8859-1"
|
nkeynes@1 | 11 |
|
nkeynes@1 | 12 | #define REG_INT 0
|
nkeynes@1 | 13 | #define REG_FLT 1
|
nkeynes@1 | 14 | #define REG_SPECIAL 2
|
nkeynes@1 | 15 |
|
nkeynes@1 | 16 | struct reg_map_struct {
|
nkeynes@1 | 17 | char *name;
|
nkeynes@1 | 18 | int type;
|
nkeynes@1 | 19 | void *value;
|
nkeynes@1 | 20 | } reg_map[] = { {"R0", REG_INT, &sh4r.r[0]}, {"R1", REG_INT, &sh4r.r[1]},
|
nkeynes@1 | 21 | {"R2", REG_INT, &sh4r.r[2]}, {"R3", REG_INT, &sh4r.r[3]},
|
nkeynes@1 | 22 | {"R4", REG_INT, &sh4r.r[4]}, {"R5", REG_INT, &sh4r.r[5]},
|
nkeynes@1 | 23 | {"R6", REG_INT, &sh4r.r[6]}, {"R7", REG_INT, &sh4r.r[7]},
|
nkeynes@1 | 24 | {"R8", REG_INT, &sh4r.r[8]}, {"R9", REG_INT, &sh4r.r[9]},
|
nkeynes@1 | 25 | {"R10",REG_INT, &sh4r.r[10]}, {"R11",REG_INT, &sh4r.r[11]},
|
nkeynes@1 | 26 | {"R12",REG_INT, &sh4r.r[12]}, {"R13",REG_INT, &sh4r.r[13]},
|
nkeynes@1 | 27 | {"R14",REG_INT, &sh4r.r[14]}, {"R15",REG_INT, &sh4r.r[15]},
|
nkeynes@1 | 28 | {"SR", REG_INT, &sh4r.sr}, {"GBR", REG_INT, &sh4r.gbr},
|
nkeynes@1 | 29 | {"SSR",REG_INT, &sh4r.ssr}, {"SPC", REG_INT, &sh4r.spc},
|
nkeynes@1 | 30 | {"SGR",REG_INT, &sh4r.sgr}, {"DBR", REG_INT, &sh4r.dbr},
|
nkeynes@1 | 31 | {"VBR",REG_INT, &sh4r.vbr},
|
nkeynes@1 | 32 | {"PC", REG_INT, &sh4r.pc}, {"PR", REG_INT, &sh4r.pr},
|
nkeynes@1 | 33 | {"MACL",REG_INT, &sh4r.mac},{"MACH",REG_INT, ((uint32_t *)&sh4r.mac)+1},
|
nkeynes@1 | 34 | {"FPUL", REG_INT, &sh4r.fpul}, {"FPSCR", REG_INT, &sh4r.fpscr},
|
nkeynes@1 | 35 | {NULL, 0, NULL} };
|
nkeynes@1 | 36 |
|
nkeynes@1 | 37 | GtkCList *msgs, *regs, *disasm;
|
nkeynes@1 | 38 | GdkColor clrNormal, clrChanged, clrError, clrWarn, clrPC, clrDebug, clrTrace;
|
nkeynes@1 | 39 | GtkEntry *page_field;
|
nkeynes@1 | 40 | GnomeAppBar *appbar;
|
nkeynes@1 | 41 | GtkProgressBar *icounter;
|
nkeynes@1 | 42 | char icounter_text[16];
|
nkeynes@1 | 43 | GtkStyle *fixed_list_style;
|
nkeynes@1 | 44 | PangoFontDescription *fixed_list_font;
|
nkeynes@1 | 45 | GdkColor *msg_colors[] = { &clrError, &clrError, &clrWarn, &clrNormal,
|
nkeynes@1 | 46 | &clrDebug, &clrTrace };
|
nkeynes@1 | 47 |
|
nkeynes@1 | 48 | struct sh4_registers sh4r_s;
|
nkeynes@1 | 49 | int disasm_from = -1, disasm_to = -1;
|
nkeynes@1 | 50 | int disasm_pc = -1;
|
nkeynes@1 | 51 |
|
nkeynes@1 | 52 | void open_file_callback(GtkWidget *btn, gpointer user_data);
|
nkeynes@1 | 53 | void open_file_canceled(GtkWidget *btn, gpointer user_data);
|
nkeynes@1 | 54 | void open_file( char *filename );
|
nkeynes@1 | 55 |
|
nkeynes@1 | 56 | /*
|
nkeynes@1 | 57 | * Check for changed registers and update the display
|
nkeynes@1 | 58 | */
|
nkeynes@1 | 59 | void update_registers( void )
|
nkeynes@1 | 60 | {
|
nkeynes@1 | 61 | int i;
|
nkeynes@1 | 62 | for( i=0; reg_map[i].name != NULL; i++ ) {
|
nkeynes@1 | 63 | if( reg_map[i].type == REG_INT ) {
|
nkeynes@1 | 64 | /* Yes this _is_ probably fairly evil */
|
nkeynes@1 | 65 | if( *((uint32_t *)reg_map[i].value) !=
|
nkeynes@1 | 66 | *((uint32_t *)((char *)&sh4r_s + ((char *)reg_map[i].value - (char *)&sh4r))) ) {
|
nkeynes@1 | 67 | char buf[20];
|
nkeynes@1 | 68 | sprintf( buf, "%08X", *((uint32_t *)reg_map[i].value) );
|
nkeynes@1 | 69 | gtk_clist_set_text( regs, i, 1, buf );
|
nkeynes@1 | 70 | gtk_clist_set_foreground( regs, i, &clrChanged );
|
nkeynes@1 | 71 | } else {
|
nkeynes@1 | 72 | gtk_clist_set_foreground( regs, i, &clrNormal );
|
nkeynes@1 | 73 | }
|
nkeynes@1 | 74 | } else {
|
nkeynes@1 | 75 | if( *((float *)reg_map[i].value) !=
|
nkeynes@1 | 76 | *((float *)((char *)&sh4r_s + ((char *)reg_map[i].value - (char *)&sh4r))) ) {
|
nkeynes@1 | 77 | char buf[20];
|
nkeynes@1 | 78 | sprintf( buf, "%f", *((float *)reg_map[i].value) );
|
nkeynes@1 | 79 | gtk_clist_set_text( regs, i, 1, buf );
|
nkeynes@1 | 80 | gtk_clist_set_foreground( regs, i, &clrChanged );
|
nkeynes@1 | 81 | } else {
|
nkeynes@1 | 82 | gtk_clist_set_foreground( regs, i, &clrNormal );
|
nkeynes@1 | 83 | }
|
nkeynes@1 | 84 | }
|
nkeynes@1 | 85 | }
|
nkeynes@1 | 86 | if( sh4r.pc != sh4r_s.pc )
|
nkeynes@1 | 87 | set_disassembly_pc( sh4r.pc, FALSE );
|
nkeynes@1 | 88 | memcpy( &sh4r_s, &sh4r, sizeof(sh4r) );
|
nkeynes@1 | 89 |
|
nkeynes@1 | 90 | update_icount();
|
nkeynes@1 | 91 | update_mmr_win();
|
nkeynes@1 | 92 | }
|
nkeynes@1 | 93 |
|
nkeynes@1 | 94 | void update_icount( void )
|
nkeynes@1 | 95 | {
|
nkeynes@1 | 96 | sprintf( icounter_text, "%d", sh4r.icount );
|
nkeynes@1 | 97 | gtk_progress_bar_set_text( icounter, icounter_text );
|
nkeynes@1 | 98 | }
|
nkeynes@1 | 99 |
|
nkeynes@1 | 100 | void set_disassembly_region( unsigned int page )
|
nkeynes@1 | 101 | {
|
nkeynes@1 | 102 | uint32_t i, posn;
|
nkeynes@1 | 103 | uint16_t op;
|
nkeynes@1 | 104 | char buf[80];
|
nkeynes@1 | 105 | char addr[10];
|
nkeynes@1 | 106 | char opcode[6] = "";
|
nkeynes@1 | 107 | char *arr[4] = { addr, " ", opcode, buf };
|
nkeynes@1 | 108 | unsigned int from = page & 0xFFFFF000;
|
nkeynes@1 | 109 | unsigned int to = from + 4096;
|
nkeynes@1 | 110 |
|
nkeynes@1 | 111 | gtk_clist_clear(disasm);
|
nkeynes@1 | 112 |
|
nkeynes@1 | 113 | sprintf( addr, "%08X", from );
|
nkeynes@1 | 114 | gtk_entry_set_text( page_field, addr );
|
nkeynes@1 | 115 |
|
nkeynes@1 | 116 | if( !mem_has_page( from ) ) {
|
nkeynes@1 | 117 | arr[3] = "This page is currently unmapped";
|
nkeynes@1 | 118 | gtk_clist_append( disasm, arr );
|
nkeynes@1 | 119 | gtk_clist_set_foreground( disasm, 0, &clrError );
|
nkeynes@1 | 120 | } else {
|
nkeynes@1 | 121 | for( i=from; i<to; i+=2 ) {
|
nkeynes@1 | 122 | sh4_disasm_instruction( i, buf, sizeof(buf) );
|
nkeynes@1 | 123 | sprintf( addr, "%08X", i );
|
nkeynes@1 | 124 | op = mem_read_phys_word(i);
|
nkeynes@1 | 125 | sprintf( opcode, "%02X %02X", op&0xFF, op>>8 );
|
nkeynes@1 | 126 | posn = gtk_clist_append( disasm, arr );
|
nkeynes@1 | 127 | if( buf[0] == '?' )
|
nkeynes@1 | 128 | gtk_clist_set_foreground( disasm, posn, &clrWarn );
|
nkeynes@1 | 129 | }
|
nkeynes@1 | 130 | if( disasm_pc != -1 && disasm_pc >= from && disasm_pc < to )
|
nkeynes@1 | 131 | gtk_clist_set_foreground( disasm, (disasm_pc - from)>>1,
|
nkeynes@1 | 132 | &clrPC );
|
nkeynes@1 | 133 | }
|
nkeynes@1 | 134 |
|
nkeynes@1 | 135 | if( page != from ) { /* not a page boundary */
|
nkeynes@1 | 136 | gtk_clist_moveto( disasm, (page-from)>>1, 0, 0.5, 0.0 );
|
nkeynes@1 | 137 | }
|
nkeynes@1 | 138 | disasm_from = from;
|
nkeynes@1 | 139 | disasm_to = to;
|
nkeynes@1 | 140 | }
|
nkeynes@1 | 141 |
|
nkeynes@1 | 142 | void jump_to_disassembly( unsigned int addr, gboolean select )
|
nkeynes@1 | 143 | {
|
nkeynes@1 | 144 | int row;
|
nkeynes@1 | 145 |
|
nkeynes@1 | 146 | if( addr < disasm_from || addr >= disasm_to )
|
nkeynes@1 | 147 | set_disassembly_region(addr);
|
nkeynes@1 | 148 |
|
nkeynes@1 | 149 | row = (addr-disasm_from)>>1;
|
nkeynes@1 | 150 | if(select) {
|
nkeynes@1 | 151 | gtk_clist_select_row( disasm, row, 0 );
|
nkeynes@1 | 152 | }
|
nkeynes@1 | 153 | if( gtk_clist_row_is_visible( disasm, row ) != GTK_VISIBILITY_FULL ){
|
nkeynes@1 | 154 | gtk_clist_moveto( disasm, row, 0, 0.5, 0.0 );
|
nkeynes@1 | 155 | }
|
nkeynes@1 | 156 | }
|
nkeynes@1 | 157 |
|
nkeynes@1 | 158 | void set_disassembly_pc( unsigned int pc, gboolean select )
|
nkeynes@1 | 159 | {
|
nkeynes@1 | 160 | int row;
|
nkeynes@1 | 161 |
|
nkeynes@1 | 162 | jump_to_disassembly( pc, select );
|
nkeynes@1 | 163 | if( disasm_pc != -1 && disasm_pc >= disasm_from && disasm_pc < disasm_to )
|
nkeynes@1 | 164 | gtk_clist_set_foreground( disasm, (disasm_pc - disasm_from)>>1,
|
nkeynes@1 | 165 | &clrNormal );
|
nkeynes@1 | 166 | row = (pc - disasm_from)>>1;
|
nkeynes@1 | 167 | gtk_clist_set_foreground( disasm, row, &clrPC );
|
nkeynes@1 | 168 | disasm_pc = pc;
|
nkeynes@1 | 169 | }
|
nkeynes@1 | 170 |
|
nkeynes@1 | 171 | void open_file_callback(GtkWidget *btn, gpointer user_data) {
|
nkeynes@1 | 172 | GtkFileSelection *file = GTK_FILE_SELECTION(user_data);
|
nkeynes@1 | 173 | gchar *filename = strdup( gtk_file_selection_get_filename(
|
nkeynes@1 | 174 | GTK_FILE_SELECTION(file) ) );
|
nkeynes@1 | 175 | gtk_widget_destroy(GTK_WIDGET(file));
|
nkeynes@1 | 176 | open_file( filename );
|
nkeynes@1 | 177 | free(filename);
|
nkeynes@1 | 178 | }
|
nkeynes@1 | 179 |
|
nkeynes@1 | 180 | void open_file_canceled(GtkWidget *btn, gpointer user_data) {
|
nkeynes@1 | 181 | gtk_widget_destroy(GTK_WIDGET(user_data));
|
nkeynes@1 | 182 | }
|
nkeynes@1 | 183 |
|
nkeynes@1 | 184 | void open_file_dialog( void )
|
nkeynes@1 | 185 | {
|
nkeynes@1 | 186 | GtkWidget *file;
|
nkeynes@1 | 187 |
|
nkeynes@1 | 188 | file = gtk_file_selection_new( "Open..." );
|
nkeynes@1 | 189 | gtk_signal_connect( GTK_OBJECT(GTK_FILE_SELECTION(file)->ok_button),
|
nkeynes@1 | 190 | "clicked", GTK_SIGNAL_FUNC(open_file_callback), file );
|
nkeynes@1 | 191 | gtk_signal_connect( GTK_OBJECT(GTK_FILE_SELECTION(file)->cancel_button),
|
nkeynes@1 | 192 | "clicked", GTK_SIGNAL_FUNC(open_file_canceled), file );
|
nkeynes@1 | 193 | gtk_widget_show( file );
|
nkeynes@1 | 194 | }
|
nkeynes@1 | 195 |
|
nkeynes@1 | 196 | void emit( int level, int source, char *msg, ... )
|
nkeynes@1 | 197 | {
|
nkeynes@1 | 198 | char buf[20], addr[10] = "", *p;
|
nkeynes@1 | 199 | char *arr[3] = {buf, addr};
|
nkeynes@1 | 200 | int posn;
|
nkeynes@1 | 201 | time_t tm = time(NULL);
|
nkeynes@1 | 202 | va_list ap;
|
nkeynes@1 | 203 |
|
nkeynes@1 | 204 | va_start(ap, msg);
|
nkeynes@1 | 205 | p = g_strdup_vprintf( msg, ap );
|
nkeynes@1 | 206 | strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
|
nkeynes@1 | 207 | if( source != -1 )
|
nkeynes@1 | 208 | sprintf( addr, "%08X", sh4r.pc );
|
nkeynes@1 | 209 | arr[2] = p;
|
nkeynes@1 | 210 | posn = gtk_clist_append(msgs, arr);
|
nkeynes@1 | 211 | free(p);
|
nkeynes@1 | 212 | va_end(ap);
|
nkeynes@1 | 213 |
|
nkeynes@1 | 214 | gtk_clist_set_foreground( msgs, posn, msg_colors[level] );
|
nkeynes@1 | 215 | gtk_clist_moveto( msgs, posn, 0, 1.0, 0.0 );
|
nkeynes@1 | 216 |
|
nkeynes@1 | 217 | /* emit _really_ slows down the emu, to the point where the gui can be
|
nkeynes@1 | 218 | * completely unresponsive if I don't include this:
|
nkeynes@1 | 219 | */
|
nkeynes@1 | 220 | while( gtk_events_pending() )
|
nkeynes@1 | 221 | gtk_main_iteration();
|
nkeynes@1 | 222 | }
|
nkeynes@1 | 223 |
|
nkeynes@1 | 224 | void init_debug_win(GtkWidget *win)
|
nkeynes@1 | 225 | {
|
nkeynes@1 | 226 | GdkColormap *map;
|
nkeynes@1 | 227 | GdkFont *regfont;
|
nkeynes@1 | 228 | GtkAdjustment *adj;
|
nkeynes@1 | 229 | int i;
|
nkeynes@1 | 230 | char buf[20];
|
nkeynes@1 | 231 | char *arr[2];
|
nkeynes@1 | 232 |
|
nkeynes@1 | 233 | clrNormal.red = clrNormal.green = clrNormal.blue = 0;
|
nkeynes@1 | 234 | clrChanged.red = clrChanged.green = 64*256;
|
nkeynes@1 | 235 | clrChanged.blue = 154*256;
|
nkeynes@1 | 236 | clrError.red = 65535;
|
nkeynes@1 | 237 | clrError.green = clrError.blue = 64*256;
|
nkeynes@1 | 238 | clrPC.red = 32*256;
|
nkeynes@1 | 239 | clrPC.green = 170*256;
|
nkeynes@1 | 240 | clrPC.blue = 52*256;
|
nkeynes@1 | 241 | clrWarn = clrChanged;
|
nkeynes@1 | 242 | clrTrace.red = 156*256;
|
nkeynes@1 | 243 | clrTrace.green = 78*256;
|
nkeynes@1 | 244 | clrTrace.blue = 201*256;
|
nkeynes@1 | 245 | clrDebug = clrPC;
|
nkeynes@1 | 246 |
|
nkeynes@1 | 247 | map = gdk_colormap_new(gdk_visual_get_best(), TRUE);
|
nkeynes@1 | 248 | gdk_colormap_alloc_color(map, &clrNormal, TRUE, TRUE);
|
nkeynes@1 | 249 | gdk_colormap_alloc_color(map, &clrChanged, TRUE, TRUE);
|
nkeynes@1 | 250 | gdk_colormap_alloc_color(map, &clrError, TRUE, TRUE);
|
nkeynes@1 | 251 | gdk_colormap_alloc_color(map, &clrWarn, TRUE, TRUE);
|
nkeynes@1 | 252 | gdk_colormap_alloc_color(map, &clrPC, TRUE, TRUE);
|
nkeynes@1 | 253 | gdk_colormap_alloc_color(map, &clrDebug, TRUE, TRUE);
|
nkeynes@1 | 254 | gdk_colormap_alloc_color(map, &clrTrace, TRUE, TRUE);
|
nkeynes@1 | 255 |
|
nkeynes@1 | 256 | fixed_list_font = pango_font_description_from_string("Courier 10");
|
nkeynes@1 | 257 | regs = gtk_object_get_data(GTK_OBJECT(win), "reg_list");
|
nkeynes@1 | 258 | arr[1] = buf;
|
nkeynes@1 | 259 | for( i=0; reg_map[i].name != NULL; i++ ) {
|
nkeynes@1 | 260 | arr[0] = reg_map[i].name;
|
nkeynes@1 | 261 | if( reg_map[i].type == REG_INT )
|
nkeynes@1 | 262 | sprintf( buf, "%08X", *((uint32_t *)reg_map[i].value) );
|
nkeynes@1 | 263 | else
|
nkeynes@1 | 264 | sprintf( buf, "%f", *((float *)reg_map[i].value) );
|
nkeynes@1 | 265 | gtk_clist_append( regs, arr );
|
nkeynes@1 | 266 | }
|
nkeynes@1 | 267 |
|
nkeynes@1 | 268 | fixed_list_style = gtk_style_copy( gtk_rc_get_style( GTK_WIDGET(regs) ) );
|
nkeynes@1 | 269 | if( fixed_list_style != NULL ) {
|
nkeynes@1 | 270 | fixed_list_style->font_desc = fixed_list_font;
|
nkeynes@1 | 271 | gtk_widget_set_style( GTK_WIDGET(regs), fixed_list_style );
|
nkeynes@1 | 272 | }
|
nkeynes@1 | 273 |
|
nkeynes@1 | 274 | msgs = gtk_object_get_data(GTK_OBJECT(win), "output_list");
|
nkeynes@1 | 275 | disasm = gtk_object_get_data(GTK_OBJECT(win), "disasm_list");
|
nkeynes@1 | 276 | gtk_clist_set_column_width( disasm, 1, 16 );
|
nkeynes@1 | 277 | page_field = gtk_object_get_data(GTK_OBJECT(win), "page_field");
|
nkeynes@1 | 278 |
|
nkeynes@1 | 279 | appbar = gtk_object_get_data(GTK_OBJECT(win), "debug_appbar");
|
nkeynes@1 | 280 | icounter = gnome_appbar_get_progress( appbar );
|
nkeynes@1 | 281 | gtk_progress_bar_set_text(icounter, "1");
|
nkeynes@1 | 282 | }
|