nkeynes@2 | 1 |
|
nkeynes@2 | 2 | #include <stdlib.h>
|
nkeynes@2 | 3 | #include <stdarg.h>
|
nkeynes@2 | 4 | #include <gnome.h>
|
nkeynes@2 | 5 | #include <math.h>
|
nkeynes@2 | 6 | #include "gui.h"
|
nkeynes@2 | 7 | #include "mem.h"
|
nkeynes@2 | 8 | #include "sh4dasm.h"
|
nkeynes@2 | 9 | #include "sh4core.h"
|
nkeynes@2 | 10 |
|
nkeynes@2 | 11 | GdkColor *msg_colors[] = { &clrError, &clrError, &clrWarn, &clrNormal,
|
nkeynes@2 | 12 | &clrDebug, &clrTrace };
|
nkeynes@2 | 13 |
|
nkeynes@2 | 14 | #define REG_INT 0
|
nkeynes@2 | 15 | #define REG_FLT 1
|
nkeynes@2 | 16 | #define REG_SPECIAL 2
|
nkeynes@2 | 17 |
|
nkeynes@2 | 18 | struct reg_map_struct {
|
nkeynes@2 | 19 | char *name;
|
nkeynes@2 | 20 | int type;
|
nkeynes@2 | 21 | void *value;
|
nkeynes@8 | 22 | };
|
nkeynes@8 | 23 |
|
nkeynes@8 | 24 | struct reg_map_struct sh4_reg_map[] =
|
nkeynes@8 | 25 | { {"R0", REG_INT, &sh4r.r[0]}, {"R1", REG_INT, &sh4r.r[1]},
|
nkeynes@2 | 26 | {"R2", REG_INT, &sh4r.r[2]}, {"R3", REG_INT, &sh4r.r[3]},
|
nkeynes@2 | 27 | {"R4", REG_INT, &sh4r.r[4]}, {"R5", REG_INT, &sh4r.r[5]},
|
nkeynes@2 | 28 | {"R6", REG_INT, &sh4r.r[6]}, {"R7", REG_INT, &sh4r.r[7]},
|
nkeynes@2 | 29 | {"R8", REG_INT, &sh4r.r[8]}, {"R9", REG_INT, &sh4r.r[9]},
|
nkeynes@2 | 30 | {"R10",REG_INT, &sh4r.r[10]}, {"R11",REG_INT, &sh4r.r[11]},
|
nkeynes@2 | 31 | {"R12",REG_INT, &sh4r.r[12]}, {"R13",REG_INT, &sh4r.r[13]},
|
nkeynes@2 | 32 | {"R14",REG_INT, &sh4r.r[14]}, {"R15",REG_INT, &sh4r.r[15]},
|
nkeynes@2 | 33 | {"SR", REG_INT, &sh4r.sr}, {"GBR", REG_INT, &sh4r.gbr},
|
nkeynes@2 | 34 | {"SSR",REG_INT, &sh4r.ssr}, {"SPC", REG_INT, &sh4r.spc},
|
nkeynes@2 | 35 | {"SGR",REG_INT, &sh4r.sgr}, {"DBR", REG_INT, &sh4r.dbr},
|
nkeynes@2 | 36 | {"VBR",REG_INT, &sh4r.vbr},
|
nkeynes@2 | 37 | {"PC", REG_INT, &sh4r.pc}, {"PR", REG_INT, &sh4r.pr},
|
nkeynes@2 | 38 | {"MACL",REG_INT, &sh4r.mac},{"MACH",REG_INT, ((uint32_t *)&sh4r.mac)+1},
|
nkeynes@2 | 39 | {"FPUL", REG_INT, &sh4r.fpul}, {"FPSCR", REG_INT, &sh4r.fpscr},
|
nkeynes@2 | 40 | {NULL, 0, NULL} };
|
nkeynes@2 | 41 |
|
nkeynes@2 | 42 | GtkCList *msgs, *regs, *disasm;
|
nkeynes@2 | 43 | GtkEntry *page_field;
|
nkeynes@2 | 44 | GtkProgressBar *icounter;
|
nkeynes@2 | 45 | char icounter_text[16];
|
nkeynes@2 | 46 |
|
nkeynes@2 | 47 | struct sh4_registers sh4r_s;
|
nkeynes@2 | 48 | int disasm_from = -1, disasm_to = -1;
|
nkeynes@2 | 49 | int disasm_pc = -1;
|
nkeynes@2 | 50 |
|
nkeynes@2 | 51 |
|
nkeynes@2 | 52 | void init_debug_win(GtkWidget *win)
|
nkeynes@2 | 53 | {
|
nkeynes@2 | 54 | int i;
|
nkeynes@2 | 55 | char buf[20];
|
nkeynes@2 | 56 | char *arr[2];
|
nkeynes@2 | 57 | GnomeAppBar *appbar;
|
nkeynes@2 | 58 |
|
nkeynes@2 | 59 | regs = gtk_object_get_data(GTK_OBJECT(win), "reg_list");
|
nkeynes@2 | 60 | arr[1] = buf;
|
nkeynes@8 | 61 | for( i=0; sh4_reg_map[i].name != NULL; i++ ) {
|
nkeynes@8 | 62 | arr[0] = sh4_reg_map[i].name;
|
nkeynes@8 | 63 | if( sh4_reg_map[i].type == REG_INT )
|
nkeynes@8 | 64 | sprintf( buf, "%08X", *((uint32_t *)sh4_reg_map[i].value) );
|
nkeynes@2 | 65 | else
|
nkeynes@8 | 66 | sprintf( buf, "%f", *((float *)sh4_reg_map[i].value) );
|
nkeynes@2 | 67 | gtk_clist_append( regs, arr );
|
nkeynes@2 | 68 | }
|
nkeynes@2 | 69 | gtk_widget_modify_font( GTK_WIDGET(regs), fixed_list_font );
|
nkeynes@2 | 70 |
|
nkeynes@2 | 71 | msgs = gtk_object_get_data(GTK_OBJECT(win), "output_list");
|
nkeynes@2 | 72 | disasm = gtk_object_get_data(GTK_OBJECT(win), "disasm_list");
|
nkeynes@2 | 73 | gtk_clist_set_column_width( disasm, 1, 16 );
|
nkeynes@2 | 74 | page_field = gtk_object_get_data(GTK_OBJECT(win), "page_field");
|
nkeynes@2 | 75 |
|
nkeynes@2 | 76 | appbar = gtk_object_get_data(GTK_OBJECT(win), "debug_appbar");
|
nkeynes@2 | 77 | icounter = gnome_appbar_get_progress( appbar );
|
nkeynes@2 | 78 | gtk_progress_bar_set_text(icounter, "1");
|
nkeynes@2 | 79 | }
|
nkeynes@2 | 80 |
|
nkeynes@2 | 81 | /*
|
nkeynes@2 | 82 | * Check for changed registers and update the display
|
nkeynes@2 | 83 | */
|
nkeynes@2 | 84 | void update_registers( void )
|
nkeynes@2 | 85 | {
|
nkeynes@2 | 86 | int i;
|
nkeynes@8 | 87 | for( i=0; sh4_reg_map[i].name != NULL; i++ ) {
|
nkeynes@8 | 88 | if( sh4_reg_map[i].type == REG_INT ) {
|
nkeynes@2 | 89 | /* Yes this _is_ probably fairly evil */
|
nkeynes@8 | 90 | if( *((uint32_t *)sh4_reg_map[i].value) !=
|
nkeynes@8 | 91 | *((uint32_t *)((char *)&sh4r_s + ((char *)sh4_reg_map[i].value - (char *)&sh4r))) ) {
|
nkeynes@2 | 92 | char buf[20];
|
nkeynes@8 | 93 | sprintf( buf, "%08X", *((uint32_t *)sh4_reg_map[i].value) );
|
nkeynes@2 | 94 | gtk_clist_set_text( regs, i, 1, buf );
|
nkeynes@2 | 95 | gtk_clist_set_foreground( regs, i, &clrChanged );
|
nkeynes@2 | 96 | } else {
|
nkeynes@2 | 97 | gtk_clist_set_foreground( regs, i, &clrNormal );
|
nkeynes@2 | 98 | }
|
nkeynes@2 | 99 | } else {
|
nkeynes@8 | 100 | if( *((float *)sh4_reg_map[i].value) !=
|
nkeynes@8 | 101 | *((float *)((char *)&sh4r_s + ((char *)sh4_reg_map[i].value - (char *)&sh4r))) ) {
|
nkeynes@2 | 102 | char buf[20];
|
nkeynes@8 | 103 | sprintf( buf, "%f", *((float *)sh4_reg_map[i].value) );
|
nkeynes@2 | 104 | gtk_clist_set_text( regs, i, 1, buf );
|
nkeynes@2 | 105 | gtk_clist_set_foreground( regs, i, &clrChanged );
|
nkeynes@2 | 106 | } else {
|
nkeynes@2 | 107 | gtk_clist_set_foreground( regs, i, &clrNormal );
|
nkeynes@2 | 108 | }
|
nkeynes@2 | 109 | }
|
nkeynes@2 | 110 | }
|
nkeynes@2 | 111 | if( sh4r.pc != sh4r_s.pc )
|
nkeynes@2 | 112 | set_disassembly_pc( sh4r.pc, FALSE );
|
nkeynes@2 | 113 | memcpy( &sh4r_s, &sh4r, sizeof(sh4r) );
|
nkeynes@2 | 114 | }
|
nkeynes@2 | 115 |
|
nkeynes@2 | 116 | void update_icount( void )
|
nkeynes@2 | 117 | {
|
nkeynes@2 | 118 | sprintf( icounter_text, "%d", sh4r.icount );
|
nkeynes@2 | 119 | gtk_progress_bar_set_text( icounter, icounter_text );
|
nkeynes@2 | 120 | }
|
nkeynes@2 | 121 |
|
nkeynes@2 | 122 | void set_disassembly_region( unsigned int page )
|
nkeynes@2 | 123 | {
|
nkeynes@2 | 124 | uint32_t i, posn;
|
nkeynes@2 | 125 | uint16_t op;
|
nkeynes@2 | 126 | char buf[80];
|
nkeynes@2 | 127 | char addr[10];
|
nkeynes@2 | 128 | char opcode[6] = "";
|
nkeynes@2 | 129 | char *arr[4] = { addr, " ", opcode, buf };
|
nkeynes@2 | 130 | unsigned int from = page & 0xFFFFF000;
|
nkeynes@2 | 131 | unsigned int to = from + 4096;
|
nkeynes@2 | 132 |
|
nkeynes@2 | 133 | gtk_clist_clear(disasm);
|
nkeynes@2 | 134 |
|
nkeynes@2 | 135 | sprintf( addr, "%08X", from );
|
nkeynes@2 | 136 | gtk_entry_set_text( page_field, addr );
|
nkeynes@2 | 137 |
|
nkeynes@2 | 138 | if( !mem_has_page( from ) ) {
|
nkeynes@2 | 139 | arr[3] = "This page is currently unmapped";
|
nkeynes@2 | 140 | gtk_clist_append( disasm, arr );
|
nkeynes@2 | 141 | gtk_clist_set_foreground( disasm, 0, &clrError );
|
nkeynes@2 | 142 | } else {
|
nkeynes@2 | 143 | for( i=from; i<to; i+=2 ) {
|
nkeynes@2 | 144 | sh4_disasm_instruction( i, buf, sizeof(buf) );
|
nkeynes@2 | 145 | sprintf( addr, "%08X", i );
|
nkeynes@2 | 146 | op = mem_read_phys_word(i);
|
nkeynes@2 | 147 | sprintf( opcode, "%02X %02X", op&0xFF, op>>8 );
|
nkeynes@2 | 148 | posn = gtk_clist_append( disasm, arr );
|
nkeynes@2 | 149 | if( buf[0] == '?' )
|
nkeynes@2 | 150 | gtk_clist_set_foreground( disasm, posn, &clrWarn );
|
nkeynes@2 | 151 | }
|
nkeynes@2 | 152 | if( disasm_pc != -1 && disasm_pc >= from && disasm_pc < to )
|
nkeynes@2 | 153 | gtk_clist_set_foreground( disasm, (disasm_pc - from)>>1,
|
nkeynes@2 | 154 | &clrPC );
|
nkeynes@2 | 155 | }
|
nkeynes@2 | 156 |
|
nkeynes@2 | 157 | if( page != from ) { /* not a page boundary */
|
nkeynes@2 | 158 | gtk_clist_moveto( disasm, (page-from)>>1, 0, 0.5, 0.0 );
|
nkeynes@2 | 159 | }
|
nkeynes@2 | 160 | disasm_from = from;
|
nkeynes@2 | 161 | disasm_to = to;
|
nkeynes@2 | 162 | }
|
nkeynes@2 | 163 |
|
nkeynes@2 | 164 | void jump_to_disassembly( unsigned int addr, gboolean select )
|
nkeynes@2 | 165 | {
|
nkeynes@2 | 166 | int row;
|
nkeynes@2 | 167 |
|
nkeynes@2 | 168 | if( addr < disasm_from || addr >= disasm_to )
|
nkeynes@2 | 169 | set_disassembly_region(addr);
|
nkeynes@2 | 170 |
|
nkeynes@2 | 171 | row = (addr-disasm_from)>>1;
|
nkeynes@2 | 172 | if(select) {
|
nkeynes@2 | 173 | gtk_clist_select_row( disasm, row, 0 );
|
nkeynes@2 | 174 | }
|
nkeynes@2 | 175 | if( gtk_clist_row_is_visible( disasm, row ) != GTK_VISIBILITY_FULL ){
|
nkeynes@2 | 176 | gtk_clist_moveto( disasm, row, 0, 0.5, 0.0 );
|
nkeynes@2 | 177 | }
|
nkeynes@2 | 178 | }
|
nkeynes@2 | 179 |
|
nkeynes@2 | 180 | void set_disassembly_pc( unsigned int pc, gboolean select )
|
nkeynes@2 | 181 | {
|
nkeynes@2 | 182 | int row;
|
nkeynes@2 | 183 |
|
nkeynes@2 | 184 | jump_to_disassembly( pc, select );
|
nkeynes@2 | 185 | if( disasm_pc != -1 && disasm_pc >= disasm_from && disasm_pc < disasm_to )
|
nkeynes@2 | 186 | gtk_clist_set_foreground( disasm, (disasm_pc - disasm_from)>>1,
|
nkeynes@2 | 187 | &clrNormal );
|
nkeynes@2 | 188 | row = (pc - disasm_from)>>1;
|
nkeynes@2 | 189 | gtk_clist_set_foreground( disasm, row, &clrPC );
|
nkeynes@2 | 190 | disasm_pc = pc;
|
nkeynes@2 | 191 | }
|
nkeynes@2 | 192 |
|
nkeynes@2 | 193 |
|
nkeynes@2 | 194 | void emit( int level, int source, char *msg, ... )
|
nkeynes@2 | 195 | {
|
nkeynes@2 | 196 | char buf[20], addr[10] = "", *p;
|
nkeynes@2 | 197 | char *arr[3] = {buf, addr};
|
nkeynes@2 | 198 | int posn;
|
nkeynes@2 | 199 | time_t tm = time(NULL);
|
nkeynes@2 | 200 | va_list ap;
|
nkeynes@2 | 201 |
|
nkeynes@2 | 202 | va_start(ap, msg);
|
nkeynes@2 | 203 | p = g_strdup_vprintf( msg, ap );
|
nkeynes@2 | 204 | strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
|
nkeynes@2 | 205 | if( source != -1 )
|
nkeynes@2 | 206 | sprintf( addr, "%08X", sh4r.pc );
|
nkeynes@2 | 207 | arr[2] = p;
|
nkeynes@2 | 208 | posn = gtk_clist_append(msgs, arr);
|
nkeynes@2 | 209 | free(p);
|
nkeynes@2 | 210 | va_end(ap);
|
nkeynes@2 | 211 |
|
nkeynes@2 | 212 | gtk_clist_set_foreground( msgs, posn, msg_colors[level] );
|
nkeynes@2 | 213 | gtk_clist_moveto( msgs, posn, 0, 1.0, 0.0 );
|
nkeynes@2 | 214 |
|
nkeynes@2 | 215 | /* emit _really_ slows down the emu, to the point where the gui can be
|
nkeynes@2 | 216 | * completely unresponsive if I don't include this:
|
nkeynes@2 | 217 | */
|
nkeynes@2 | 218 | while( gtk_events_pending() )
|
nkeynes@2 | 219 | gtk_main_iteration();
|
nkeynes@2 | 220 | }
|