Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/gtk/yuim68k.c
2 views
1
/* Copyright 2005-2006 Fabien Coulon
2
3
This file is part of Yabause.
4
5
Yabause is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
Yabause is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
#include <gtk/gtk.h>
21
#include <gdk/gdkkeysyms.h>
22
23
#include "yuim68k.h"
24
#include "../m68kd.h"
25
#include "../yabause.h"
26
#include "settings.h"
27
28
static void yui_m68k_class_init (YuiM68kClass * klass);
29
static void yui_m68k_init (YuiM68k * yfe);
30
static void yui_m68k_clear(YuiM68k * m68k);
31
static void yui_m68k_editedReg( GtkCellRendererText *cellrenderertext,
32
gchar *arg1,
33
gchar *arg2,
34
YuiM68k *m68k);
35
static void yui_m68k_editedBp( GtkCellRendererText *cellrenderertext,
36
gchar *arg1,
37
gchar *arg2,
38
YuiM68k *m68k);
39
static void yui_m68k_step( GtkWidget* widget, YuiM68k * m68k );
40
static void yui_m68k_breakpoint_handler(u32 addr);
41
42
static YuiM68k *yui_m68k;
43
static YuiWindow * yui;
44
45
GType yui_m68k_get_type (void) {
46
static GType yfe_type = 0;
47
48
if (!yfe_type)
49
{
50
static const GTypeInfo yfe_info =
51
{
52
sizeof (YuiM68kClass),
53
NULL, /* base_init */
54
NULL, /* base_finalize */
55
(GClassInitFunc) yui_m68k_class_init,
56
NULL, /* class_finalize */
57
NULL, /* class_data */
58
sizeof (YuiM68k),
59
0,
60
(GInstanceInitFunc) yui_m68k_init,
61
NULL,
62
};
63
64
yfe_type = g_type_register_static(GTK_TYPE_WINDOW, "YuiM68k", &yfe_info, 0);
65
}
66
67
return yfe_type;
68
}
69
70
static void yui_m68k_class_init (UNUSED YuiM68kClass * klass) {
71
}
72
73
static void yui_m68k_init (YuiM68k * m68k) {
74
gtk_window_set_title(GTK_WINDOW(m68k), "M68K");
75
gtk_window_set_resizable( GTK_WINDOW(m68k), FALSE );
76
77
m68k->vbox = gtk_vbox_new(FALSE, 2);
78
gtk_container_set_border_width( GTK_CONTAINER( m68k->vbox ),4 );
79
gtk_container_add (GTK_CONTAINER (m68k), m68k->vbox);
80
81
m68k->hboxmain = gtk_hbox_new(FALSE, 2);
82
gtk_container_set_border_width( GTK_CONTAINER( m68k->hboxmain ),4 );
83
gtk_box_pack_start( GTK_BOX( m68k->vbox ), m68k->hboxmain, FALSE, FALSE, 4 );
84
85
m68k->hbox = gtk_hbutton_box_new();
86
gtk_container_set_border_width( GTK_CONTAINER( m68k->hbox ),4 );
87
gtk_box_pack_start( GTK_BOX( m68k->vbox ), m68k->hbox, FALSE, FALSE, 4 );
88
89
m68k->vboxmain = gtk_vbox_new(FALSE, 2);
90
gtk_container_set_border_width( GTK_CONTAINER( m68k->vboxmain ),4 );
91
gtk_box_pack_start( GTK_BOX( m68k->hboxmain ), m68k->vboxmain, FALSE, FALSE, 4 );
92
93
/* unassembler frame */
94
95
m68k->uFrame = gtk_frame_new("Disassembled code");
96
gtk_box_pack_start( GTK_BOX( m68k->vboxmain ), m68k->uFrame, FALSE, FALSE, 4 );
97
98
m68k->uLabel = gtk_label_new(NULL);
99
gtk_container_add (GTK_CONTAINER (m68k->uFrame), m68k->uLabel );
100
101
/* Register list */
102
103
m68k->regListStore = gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_STRING);
104
m68k->regList = gtk_tree_view_new_with_model( GTK_TREE_MODEL(m68k->regListStore) );
105
m68k->regListRenderer1 = gtk_cell_renderer_text_new();
106
m68k->regListRenderer2 = gtk_cell_renderer_text_new();
107
g_object_set(G_OBJECT(m68k->regListRenderer2), "editable", TRUE, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL );
108
m68k->regListColumn1 = gtk_tree_view_column_new_with_attributes("Register", m68k->regListRenderer1, "text", 0, NULL);
109
gtk_tree_view_append_column(GTK_TREE_VIEW(m68k->regList), m68k->regListColumn1);
110
m68k->regListColumn2 = gtk_tree_view_column_new_with_attributes("Value", m68k->regListRenderer2, "text", 1, NULL);
111
gtk_tree_view_append_column(GTK_TREE_VIEW(m68k->regList), m68k->regListColumn2);
112
gtk_box_pack_start( GTK_BOX( m68k->hboxmain ), m68k->regList, FALSE, FALSE, 4 );
113
g_signal_connect(G_OBJECT(m68k->regListRenderer2), "edited", GTK_SIGNAL_FUNC(yui_m68k_editedReg), m68k );
114
115
/* breakpoint list */
116
117
m68k->bpListStore = gtk_list_store_new(1,G_TYPE_STRING);
118
m68k->bpList = gtk_tree_view_new_with_model( GTK_TREE_MODEL(m68k->bpListStore) );
119
m68k->bpListRenderer = gtk_cell_renderer_text_new();
120
g_object_set(G_OBJECT(m68k->bpListRenderer), "editable", TRUE, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL );
121
m68k->bpListColumn = gtk_tree_view_column_new_with_attributes("Breakpoints", m68k->bpListRenderer, "text", 0, NULL);
122
gtk_tree_view_append_column(GTK_TREE_VIEW(m68k->bpList), m68k->bpListColumn);
123
gtk_box_pack_start( GTK_BOX( m68k->hboxmain ), m68k->bpList, FALSE, FALSE, 4 );
124
g_signal_connect(G_OBJECT(m68k->bpListRenderer), "edited", GTK_SIGNAL_FUNC(yui_m68k_editedBp), m68k );
125
126
g_signal_connect(G_OBJECT(m68k), "delete-event", GTK_SIGNAL_FUNC(yui_m68k_destroy), NULL);
127
}
128
129
130
GtkWidget * yui_m68k_new(YuiWindow * y) {
131
GtkWidget * dialog;
132
GClosure *closureF7;
133
GtkAccelGroup *accelGroup;
134
const m68kcodebreakpoint_struct *cbp;
135
gint i;
136
yui = y;
137
138
if ( yui_m68k ) return GTK_WIDGET(yui_m68k);
139
140
dialog = GTK_WIDGET(g_object_new(yui_m68k_get_type(), NULL));
141
yui_m68k = YUI_M68K(dialog);
142
143
if (!( yui->state & YUI_IS_INIT )) {
144
yui_window_run(yui);
145
yui_window_pause(yui);
146
}
147
148
M68KSetBreakpointCallBack(&yui_m68k_breakpoint_handler);
149
150
for (i = 0; i < 23 ; i++) {
151
152
GtkTreeIter iter;
153
gtk_list_store_append( GTK_LIST_STORE( yui_m68k->regListStore ), &iter );
154
}
155
156
cbp = M68KGetBreakpointList();
157
158
for (i = 0; i < MAX_BREAKPOINTS ; i++) {
159
160
GtkTreeIter iter;
161
yui_m68k->cbp[i] = cbp[i].addr;
162
gtk_list_store_append( GTK_LIST_STORE( yui_m68k->bpListStore ), &iter );
163
if (cbp[i].addr != 0xFFFFFFFF) {
164
165
gchar tempstr[20];
166
sprintf(tempstr, "%08X", (int)cbp[i].addr);
167
gtk_list_store_set( GTK_LIST_STORE( yui_m68k->bpListStore ), &iter, 0, tempstr, -1 );
168
} else gtk_list_store_set( GTK_LIST_STORE( yui_m68k->bpListStore ), &iter, 0, "<empty>", -1 );
169
}
170
171
{
172
GtkWidget * but2, * but3, * but4;
173
174
yui_m68k->buttonStep = gtk_button_new_with_label( "Step [F7]" );
175
gtk_box_pack_start( GTK_BOX( yui_m68k->hbox ), yui_m68k->buttonStep, FALSE, FALSE, 2 );
176
g_signal_connect( yui_m68k->buttonStep, "clicked", G_CALLBACK(yui_m68k_step), yui_m68k );
177
178
but2 = gtk_button_new();
179
gtk_action_connect_proxy(gtk_action_group_get_action(yui->action_group, "run"), but2);
180
gtk_box_pack_start(GTK_BOX(yui_m68k->hbox), but2, FALSE, FALSE, 2);
181
182
but3 = gtk_button_new();
183
gtk_action_connect_proxy(gtk_action_group_get_action(yui->action_group, "pause"), but3);
184
gtk_box_pack_start(GTK_BOX(yui_m68k->hbox), but3, FALSE, FALSE, 2);
185
186
but4 = gtk_button_new_from_stock("gtk-close");
187
g_signal_connect_swapped(but4, "clicked", G_CALLBACK(yui_m68k_destroy), dialog);
188
gtk_box_pack_start(GTK_BOX(yui_m68k->hbox), but4, FALSE, FALSE, 2);
189
}
190
yui_m68k->paused_handler = g_signal_connect_swapped(yui, "paused", G_CALLBACK(yui_m68k_update), yui_m68k);
191
yui_m68k->running_handler = g_signal_connect_swapped(yui, "running", G_CALLBACK(yui_m68k_clear), yui_m68k);
192
accelGroup = gtk_accel_group_new ();
193
closureF7 = g_cclosure_new (G_CALLBACK (yui_m68k_step), yui_m68k, NULL);
194
gtk_accel_group_connect( accelGroup, GDK_F7, 0, 0, closureF7 );
195
gtk_window_add_accel_group( GTK_WINDOW( dialog ), accelGroup );
196
197
yui_m68k_update(yui_m68k);
198
if ( yui->state & YUI_IS_RUNNING ) yui_m68k_clear(yui_m68k);
199
200
gtk_widget_show_all(GTK_WIDGET(yui_m68k));
201
202
return dialog;
203
}
204
205
static void yui_m68k_update_reglist( YuiM68k *m68k, m68kregs_struct *regs) {
206
/* refresh the registery list */
207
208
GtkTreeIter iter;
209
char regstr[32];
210
char valuestr[32];
211
int i;
212
213
for ( i = 0 ; i < 8 ; i++ ) {
214
215
if ( i==0 ) gtk_tree_model_get_iter_first( GTK_TREE_MODEL( yui_m68k->regListStore ), &iter );
216
else gtk_tree_model_iter_next( GTK_TREE_MODEL( yui_m68k->regListStore ), &iter );
217
sprintf(regstr, "D%d", i );
218
sprintf(valuestr, "%08x", (int)regs->D[i]);
219
gtk_list_store_set( GTK_LIST_STORE( yui_m68k->regListStore ), &iter, 0, regstr, 1, valuestr, -1 );
220
}
221
for ( i = 0 ; i < 8 ; i++ ) {
222
223
gtk_tree_model_iter_next( GTK_TREE_MODEL( yui_m68k->regListStore ), &iter );
224
sprintf(regstr, "A%d", i );
225
sprintf(valuestr, "%08x", (int)regs->A[i]);
226
gtk_list_store_set( GTK_LIST_STORE( yui_m68k->regListStore ), &iter, 0, regstr, 1, valuestr, -1 );
227
}
228
229
gtk_tree_model_iter_next( GTK_TREE_MODEL( yui_m68k->regListStore ), &iter );
230
sprintf(valuestr, "%08x", (int)regs->SR);
231
gtk_list_store_set( GTK_LIST_STORE( yui_m68k->regListStore ), &iter, 0, "SR", 1, valuestr, -1 );
232
233
gtk_tree_model_iter_next( GTK_TREE_MODEL( yui_m68k->regListStore ), &iter );
234
sprintf(valuestr, "%08x", (int)regs->PC);
235
gtk_list_store_set( GTK_LIST_STORE( yui_m68k->regListStore ), &iter, 0, "PC", 1, valuestr, -1 );
236
}
237
238
static void m68ksetRegister( YuiM68k *m68k, int nReg, u32 value ) {
239
/* set register number <nReg> to value <value> in proc <m68k> */
240
241
m68kregs_struct m68kregs;
242
M68KGetRegisters(&m68kregs);
243
244
if ( nReg < 8 ) m68kregs.D[nReg] = value;
245
else if ( nReg < 16 ) m68kregs.A[nReg-8] = value;
246
if ( nReg == 16 ) m68kregs.SR = value;
247
if ( nReg == 17 ) m68kregs.PC = value;
248
249
M68KSetRegisters(&m68kregs);
250
}
251
252
static void yui_m68k_update_codelist( YuiM68k *m68k, u32 addr) {
253
/* refrem68k the assembler view. <addr> points the line to be highlighted. */
254
255
int i;
256
static char tagPC[] = "<span foreground=\"red\">";
257
static char tagEnd[] = "</span>\n";
258
char buf[64*24+40];
259
char *curs = buf;
260
char lineBuf[64];
261
u8 bOnPC = 0;
262
u32 offset;
263
264
if ( addr - m68k->lastCode >= 22 ) offset = addr;
265
else offset = m68k->lastCode;
266
m68k->lastCode = offset;
267
268
for (i=0; i < 24; i++) {
269
270
if ( offset == addr ) { bOnPC = 1; strcpy( curs, tagPC ); curs += strlen(tagPC); }
271
offset = M68KDisasm(offset, lineBuf);
272
strcpy( curs, lineBuf );
273
curs += strlen(lineBuf);
274
if ( bOnPC ) { bOnPC = 0; strcpy( curs, tagEnd ); curs += strlen(tagEnd); }
275
else { strcpy( curs, "\n" ); curs += 1;}
276
}
277
*curs = 0;
278
gtk_label_set_markup( GTK_LABEL(m68k->uLabel), buf );
279
}
280
281
static void yui_m68k_step( GtkWidget* widget, YuiM68k * m68k ) {
282
283
M68KStep();
284
yui_window_invalidate( yui ); /* update all dialogs, including us */
285
}
286
287
static void yui_m68k_editedReg( GtkCellRendererText *cellrenderertext,
288
gchar *arg1,
289
gchar *arg2,
290
YuiM68k *m68k) {
291
/* registry number <arg1> value has been set to <arg2> */
292
293
GtkTreeIter iter;
294
char bptext[10];
295
char *endptr;
296
int i = atoi(arg1);
297
u32 addr;
298
299
gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL( m68k->regListStore ), &iter, arg1 );
300
addr = strtoul(arg2, &endptr, 16 );
301
if ( endptr - arg2 == strlen(arg2) ) {
302
303
sprintf(bptext, "%08X", (int)addr);
304
m68ksetRegister( m68k, i, addr );
305
gtk_list_store_set( GTK_LIST_STORE( m68k->regListStore ), &iter, 1, bptext, -1 );
306
}
307
yui_window_invalidate( yui );
308
}
309
310
static void yui_m68k_editedBp( GtkCellRendererText *cellrenderertext,
311
gchar *arg1,
312
gchar *arg2,
313
YuiM68k *m68k) {
314
/* breakpoint <arg1> has been set to address <arg2> */
315
316
GtkTreeIter iter;
317
char bptext[10];
318
char *endptr;
319
int i = atoi(arg1);
320
u32 addr;
321
gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL( m68k->bpListStore ), &iter, arg1 );
322
addr = strtoul(arg2, &endptr, 16 );
323
if ((endptr - arg2 < strlen(arg2)) || (!addr)) addr = 0xFFFFFFFF;
324
if ( m68k->cbp[i] != 0xFFFFFFFF) M68KDelCodeBreakpoint(m68k->cbp[i]);
325
m68k->cbp[i] = 0xFFFFFFFF;
326
327
if ((addr!=0xFFFFFFFF)&&(M68KAddCodeBreakpoint(addr) == 0)) {
328
329
sprintf(bptext, "%08X", (int)addr);
330
m68k->cbp[i] = addr;
331
} else strcpy(bptext,"<empty>");
332
gtk_list_store_set( GTK_LIST_STORE( m68k->bpListStore ), &iter, 0, bptext, -1 );
333
}
334
335
static void debugPauseLoop(void) { /* secondary gtk event loop for the "breakpoint pause" state */
336
337
while ( !(yui->state & YUI_IS_RUNNING) )
338
if ( gtk_main_iteration() ) return;
339
}
340
341
static void yui_m68k_breakpoint_handler (u32 addr) {
342
343
yui_window_pause(yui);
344
{
345
m68kregs_struct regs;
346
YuiM68k* m68k = YUI_M68K(yui_m68k_new( yui ));
347
348
M68KGetRegisters(&regs);
349
yui_m68k_update_codelist(m68k,regs.PC);
350
yui_m68k_update_reglist(m68k,&regs);
351
}
352
debugPauseLoop(); /* execution is suspended inside a normal cycle - enter secondary gtk loop */
353
}
354
355
356
void yui_m68k_update(YuiM68k * m68k) {
357
m68kregs_struct m68kregs;
358
M68KGetRegisters(&m68kregs);
359
yui_m68k_update_codelist(m68k,m68kregs.PC);
360
yui_m68k_update_reglist(m68k, &m68kregs);
361
gtk_widget_set_sensitive(m68k->uLabel, TRUE);
362
gtk_widget_set_sensitive(m68k->bpList, TRUE);
363
gtk_widget_set_sensitive(m68k->regList, TRUE);
364
gtk_widget_set_sensitive(m68k->buttonStep, TRUE);
365
}
366
367
void yui_m68k_destroy(YuiM68k * m68k) {
368
g_signal_handler_disconnect(yui, m68k->running_handler);
369
g_signal_handler_disconnect(yui, m68k->paused_handler);
370
371
yui_m68k = NULL;
372
373
gtk_widget_destroy(GTK_WIDGET(m68k));
374
}
375
376
static void yui_m68k_clear(YuiM68k * m68k) {
377
378
gtk_widget_set_sensitive(m68k->uLabel, FALSE);
379
gtk_widget_set_sensitive(m68k->bpList, FALSE);
380
gtk_widget_set_sensitive(m68k->regList, FALSE);
381
gtk_widget_set_sensitive(m68k->buttonStep, FALSE);
382
}
383
384