Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/gtk/yuiscudsp.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 "yuiscudsp.h"
24
#include "../scu.h"
25
#include "../yabause.h"
26
#include "settings.h"
27
28
static void yui_scudsp_class_init (YuiScudspClass * klass);
29
static void yui_scudsp_init (YuiScudsp * yfe);
30
static void yui_scudsp_clear(YuiScudsp * scudsp);
31
static void yui_scudsp_editedReg( GtkCellRendererText *cellrenderertext,
32
gchar *arg1,
33
gchar *arg2,
34
YuiScudsp *scudsp);
35
static void yui_scudsp_editedBp( GtkCellRendererText *cellrenderertext,
36
gchar *arg1,
37
gchar *arg2,
38
YuiScudsp *scudsp);
39
static void yui_scudsp_step( GtkWidget* widget, YuiScudsp * scudsp );
40
static void yui_scudsp_breakpoint_handler (u32 addr);
41
42
static YuiScudsp *yui_scudsp;
43
static YuiWindow * yui;
44
45
GType yui_scudsp_get_type (void) {
46
static GType yfe_type = 0;
47
48
if (!yfe_type)
49
{
50
static const GTypeInfo yfe_info =
51
{
52
sizeof (YuiScudspClass),
53
NULL, /* base_init */
54
NULL, /* base_finalize */
55
(GClassInitFunc) yui_scudsp_class_init,
56
NULL, /* class_finalize */
57
NULL, /* class_data */
58
sizeof (YuiScudsp),
59
0,
60
(GInstanceInitFunc) yui_scudsp_init,
61
NULL,
62
};
63
64
yfe_type = g_type_register_static(GTK_TYPE_WINDOW, "YuiScudsp", &yfe_info, 0);
65
}
66
67
return yfe_type;
68
}
69
70
static void yui_scudsp_class_init (UNUSED YuiScudspClass * klass) {
71
}
72
73
static void yui_scudsp_init (YuiScudsp * scudsp) {
74
gtk_window_set_title(GTK_WINDOW(scudsp), "SCU-DSP");
75
gtk_window_set_resizable( GTK_WINDOW(scudsp), FALSE );
76
77
scudsp->vbox = gtk_vbox_new(FALSE, 2);
78
gtk_container_set_border_width( GTK_CONTAINER( scudsp->vbox ),4 );
79
gtk_container_add (GTK_CONTAINER (scudsp), scudsp->vbox);
80
81
scudsp->hboxmain = gtk_hbox_new(FALSE, 2);
82
gtk_container_set_border_width( GTK_CONTAINER( scudsp->hboxmain ),4 );
83
gtk_box_pack_start( GTK_BOX( scudsp->vbox ), scudsp->hboxmain, FALSE, FALSE, 4 );
84
85
scudsp->hbox = gtk_hbutton_box_new();
86
gtk_container_set_border_width( GTK_CONTAINER( scudsp->hbox ),4 );
87
gtk_box_pack_start( GTK_BOX( scudsp->vbox ), scudsp->hbox, FALSE, FALSE, 4 );
88
89
scudsp->vboxmain = gtk_vbox_new(FALSE, 2);
90
gtk_container_set_border_width( GTK_CONTAINER( scudsp->vboxmain ),4 );
91
gtk_box_pack_start( GTK_BOX( scudsp->hboxmain ), scudsp->vboxmain, FALSE, FALSE, 4 );
92
93
/* unassembler frame */
94
95
scudsp->uFrame = gtk_frame_new("Disassembled code");
96
gtk_box_pack_start( GTK_BOX( scudsp->vboxmain ), scudsp->uFrame, FALSE, FALSE, 4 );
97
98
scudsp->uLabel = gtk_label_new(NULL);
99
gtk_container_add (GTK_CONTAINER (scudsp->uFrame), scudsp->uLabel );
100
101
/* Register list */
102
103
scudsp->regListStore = gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_STRING);
104
scudsp->regList = gtk_tree_view_new_with_model( GTK_TREE_MODEL(scudsp->regListStore) );
105
scudsp->regListRenderer1 = gtk_cell_renderer_text_new();
106
scudsp->regListRenderer2 = gtk_cell_renderer_text_new();
107
g_object_set(G_OBJECT(scudsp->regListRenderer2), "editable", TRUE, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL );
108
scudsp->regListColumn1 = gtk_tree_view_column_new_with_attributes("Register", scudsp->regListRenderer1, "text", 0, NULL);
109
gtk_tree_view_append_column(GTK_TREE_VIEW(scudsp->regList), scudsp->regListColumn1);
110
scudsp->regListColumn2 = gtk_tree_view_column_new_with_attributes("Value", scudsp->regListRenderer2, "text", 1, NULL);
111
gtk_tree_view_append_column(GTK_TREE_VIEW(scudsp->regList), scudsp->regListColumn2);
112
gtk_box_pack_start( GTK_BOX( scudsp->hboxmain ), scudsp->regList, FALSE, FALSE, 4 );
113
g_signal_connect(G_OBJECT(scudsp->regListRenderer2), "edited", GTK_SIGNAL_FUNC(yui_scudsp_editedReg), scudsp );
114
115
/* breakpoint list */
116
117
scudsp->bpListStore = gtk_list_store_new(1,G_TYPE_STRING);
118
scudsp->bpList = gtk_tree_view_new_with_model( GTK_TREE_MODEL(scudsp->bpListStore) );
119
scudsp->bpListRenderer = gtk_cell_renderer_text_new();
120
g_object_set(G_OBJECT(scudsp->bpListRenderer), "editable", TRUE, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL );
121
scudsp->bpListColumn = gtk_tree_view_column_new_with_attributes("Breakpoints", scudsp->bpListRenderer, "text", 0, NULL);
122
gtk_tree_view_append_column(GTK_TREE_VIEW(scudsp->bpList), scudsp->bpListColumn);
123
gtk_box_pack_start( GTK_BOX( scudsp->hboxmain ), scudsp->bpList, FALSE, FALSE, 4 );
124
g_signal_connect(G_OBJECT(scudsp->bpListRenderer), "edited", GTK_SIGNAL_FUNC(yui_scudsp_editedBp), scudsp );
125
126
g_signal_connect(G_OBJECT(scudsp), "delete-event", GTK_SIGNAL_FUNC(yui_scudsp_destroy), NULL);
127
}
128
129
130
GtkWidget * yui_scudsp_new(YuiWindow * y) {
131
GtkWidget * dialog;
132
GClosure *closureF7;
133
GtkAccelGroup *accelGroup;
134
const scucodebreakpoint_struct *cbp;
135
gint i;
136
yui = y;
137
138
if ( yui_scudsp ) return GTK_WIDGET(yui_scudsp);
139
140
dialog = GTK_WIDGET(g_object_new(yui_scudsp_get_type(), NULL));
141
yui_scudsp = YUI_SCUDSP(dialog);
142
143
if (!( yui->state & YUI_IS_INIT )) {
144
yui_window_run(yui);
145
yui_window_pause(yui);
146
}
147
148
ScuDspSetBreakpointCallBack(&yui_scudsp_breakpoint_handler);
149
150
for (i = 0; i < 23 ; i++) {
151
152
GtkTreeIter iter;
153
gtk_list_store_append( GTK_LIST_STORE( yui_scudsp->regListStore ), &iter );
154
}
155
156
cbp = ScuDspGetBreakpointList();
157
158
for (i = 0; i < MAX_BREAKPOINTS; i++) {
159
160
GtkTreeIter iter;
161
yui_scudsp->cbp[i] = cbp[i].addr;
162
gtk_list_store_append( GTK_LIST_STORE( yui_scudsp->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_scudsp->bpListStore ), &iter, 0, tempstr, -1 );
168
} else gtk_list_store_set( GTK_LIST_STORE( yui_scudsp->bpListStore ), &iter, 0, "<empty>", -1 );
169
}
170
171
{
172
GtkWidget * but2, * but3, * but4;
173
174
yui_scudsp->buttonStep = gtk_button_new_with_label( "Step [F7]" );
175
gtk_box_pack_start( GTK_BOX( yui_scudsp->hbox ), yui_scudsp->buttonStep, FALSE, FALSE, 2 );
176
g_signal_connect( yui_scudsp->buttonStep, "clicked", G_CALLBACK(yui_scudsp_step), yui_scudsp );
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_scudsp->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_scudsp->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_scudsp_destroy), dialog);
188
gtk_box_pack_start(GTK_BOX(yui_scudsp->hbox), but4, FALSE, FALSE, 2);
189
}
190
yui_scudsp->paused_handler = g_signal_connect_swapped(yui, "paused", G_CALLBACK(yui_scudsp_update), yui_scudsp);
191
yui_scudsp->running_handler = g_signal_connect_swapped(yui, "running", G_CALLBACK(yui_scudsp_clear), yui_scudsp);
192
accelGroup = gtk_accel_group_new ();
193
closureF7 = g_cclosure_new (G_CALLBACK (yui_scudsp_step), yui_scudsp, 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_scudsp_update(yui_scudsp);
198
if ( yui->state & YUI_IS_RUNNING ) yui_scudsp_clear(yui_scudsp);
199
200
gtk_widget_show_all(GTK_WIDGET(yui_scudsp));
201
202
return dialog;
203
}
204
205
206
static void yui_scudsp_update_reglist( YuiScudsp *scudsp, scudspregs_struct *regs) {
207
/* refrescudsp the registery list */
208
209
GtkTreeIter iter;
210
char valuestr[32];
211
212
gtk_tree_model_get_iter_first( GTK_TREE_MODEL( scudsp->regListStore ), &iter );
213
sprintf(valuestr, "%d", regs->ProgControlPort.part.PR);
214
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 0, "PR", 1, valuestr, -1 );
215
216
#define SCUDSPUPDATEREGLISTp(rreg,format) \
217
gtk_tree_model_iter_next( GTK_TREE_MODEL( scudsp->regListStore ), &iter ); \
218
sprintf(valuestr, #format, (int)regs->ProgControlPort.part.rreg); \
219
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 0, #rreg, 1, valuestr, -1 );
220
#define SCUDSPUPDATEREGLIST(rreg,format) \
221
gtk_tree_model_iter_next( GTK_TREE_MODEL( scudsp->regListStore ), &iter ); \
222
sprintf(valuestr, #format, (int)regs->rreg); \
223
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 0, #rreg, 1, valuestr, -1 );
224
#define SCUDSPUPDATEREGLISTx(rreg,vreg,format) \
225
gtk_tree_model_iter_next( GTK_TREE_MODEL( scudsp->regListStore ), &iter ); \
226
sprintf(valuestr, #format, (int)(vreg)); \
227
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 0, #rreg, 1, valuestr, -1 );
228
229
SCUDSPUPDATEREGLISTp(EP,%d);
230
SCUDSPUPDATEREGLISTp(T0,%d);
231
SCUDSPUPDATEREGLISTp(S,%d);
232
SCUDSPUPDATEREGLISTp(Z,%d);
233
SCUDSPUPDATEREGLISTp(C,%d);
234
SCUDSPUPDATEREGLISTp(V,%d);
235
SCUDSPUPDATEREGLISTp(E,%d);
236
SCUDSPUPDATEREGLISTp(ES,%d);
237
SCUDSPUPDATEREGLISTp(EX,%d);
238
SCUDSPUPDATEREGLISTp(LE,%d);
239
SCUDSPUPDATEREGLISTp(P,%02X);
240
SCUDSPUPDATEREGLIST(TOP,%02X);
241
SCUDSPUPDATEREGLIST(LOP,%02X);
242
gtk_tree_model_iter_next( GTK_TREE_MODEL( scudsp->regListStore ), &iter );
243
sprintf(valuestr, "%08X", (int)(((u32)(regs->CT[0]))<<24 | ((u32)(regs->CT[1]))<<16 | ((u32)(regs->CT[2]))<<8 | ((u32)(regs->CT[3]))) );
244
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 0, "CT", 1, valuestr, -1 );
245
SCUDSPUPDATEREGLISTx(RA,regs->RA0,%08X);
246
SCUDSPUPDATEREGLISTx(WA,regs->WA0,%08X);
247
SCUDSPUPDATEREGLIST(RX,%08X);
248
SCUDSPUPDATEREGLIST(RY,%08X);
249
SCUDSPUPDATEREGLISTx(PH,regs->P.part.H & 0xFFFF,%04X);
250
SCUDSPUPDATEREGLISTx(PL,regs->P.part.L & 0xFFFFFFFF,%08X);
251
SCUDSPUPDATEREGLISTx(ACH,regs->AC.part.H & 0xFFFF,%04X);
252
SCUDSPUPDATEREGLISTx(ACL,regs->AC.part.L & 0xFFFFFFFF,%08X);
253
}
254
255
static void scudspsetRegister( YuiScudsp *scudsp, int nReg, u32 value ) {
256
/* set register number <nReg> to value <value> in proc <scudsp> */
257
258
scudspregs_struct scudspregs;
259
ScuDspGetRegisters(&scudspregs);
260
261
switch ( nReg ) {
262
case 0: scudspregs.ProgControlPort.part.PR = value; break;
263
case 1: scudspregs.ProgControlPort.part.EP = value; break;
264
case 2: scudspregs.ProgControlPort.part.T0 = value; break;
265
case 3: scudspregs.ProgControlPort.part.S = value; break;
266
case 4: scudspregs.ProgControlPort.part.Z = value; break;
267
case 5: scudspregs.ProgControlPort.part.C = value; break;
268
case 6: scudspregs.ProgControlPort.part.V = value; break;
269
case 7: scudspregs.ProgControlPort.part.E = value; break;
270
case 8: scudspregs.ProgControlPort.part.ES = value; break;
271
case 9: scudspregs.ProgControlPort.part.EX = value; break;
272
case 10: scudspregs.ProgControlPort.part.LE = value; break;
273
case 11: scudspregs.ProgControlPort.part.P = value; break;
274
case 12: scudspregs.TOP = value; break;
275
case 13: scudspregs.LOP = value; break;
276
case 14:
277
scudspregs.CT[0] = (value>>24) & 0xff;
278
scudspregs.CT[1] = (value>>16) & 0xff;
279
scudspregs.CT[2] = (value>>8) & 0xff;
280
scudspregs.CT[3] = (value) & 0xff;
281
break;
282
case 15: scudspregs.RA0 = value; break;
283
case 16: scudspregs.WA0 = value; break;
284
case 17: scudspregs.RX = value; break;
285
case 18: scudspregs.RY = value; break;
286
case 19: scudspregs.P.part.H = value; break;
287
case 20: scudspregs.P.part.L = value; break;
288
case 21: scudspregs.AC.part.H = value; break;
289
case 22: scudspregs.AC.part.L = value; break;
290
}
291
292
ScuDspSetRegisters(&scudspregs);
293
}
294
295
static void yui_scudsp_update_codelist( YuiScudsp *scudsp, u32 addr) {
296
/* refresh the assembler view. <addr> points the line to be highlighted. */
297
298
int i;
299
static char tagPC[] = "<span foreground=\"red\">";
300
static char tagEnd[] = "</span>\n";
301
char buf[100*24+40];
302
char *curs = buf;
303
char lineBuf[100];
304
u32 offset;
305
306
if ( addr - scudsp->lastCode >= 20 ) offset = addr - 8;
307
else offset = scudsp->lastCode;
308
scudsp->lastCode = offset;
309
310
for (i=0; i < 24; i++) {
311
312
if ( offset + i == addr ) { strcpy( curs, tagPC ); curs += strlen(tagPC); }
313
ScuDspDisasm(offset+i, lineBuf);
314
strcpy( curs, lineBuf );
315
curs += strlen(lineBuf);
316
if ( offset + i == addr ) { strcpy( curs, tagEnd ); curs += strlen(tagEnd); }
317
else { strcpy( curs, "\n" ); curs += 1;}
318
}
319
*curs = 0;
320
321
gtk_label_set_markup( GTK_LABEL(scudsp->uLabel), buf );
322
}
323
324
static void yui_scudsp_step( GtkWidget* widget, YuiScudsp * scudsp ) {
325
326
ScuDspStep();
327
yui_window_invalidate( yui ); /* update all dialogs, including us */
328
}
329
330
static void yui_scudsp_editedReg( GtkCellRendererText *cellrenderertext,
331
gchar *arg1,
332
gchar *arg2,
333
YuiScudsp *scudsp) {
334
/* registry number <arg1> value has been set to <arg2> */
335
336
GtkTreeIter iter;
337
char bptext[10];
338
char *endptr;
339
int i = atoi(arg1);
340
u32 addr;
341
342
gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL( scudsp->regListStore ), &iter, arg1 );
343
addr = strtoul(arg2, &endptr, 16 );
344
if ( endptr - arg2 == strlen(arg2) ) {
345
346
sprintf(bptext, "%08X", (int)addr);
347
scudspsetRegister( scudsp, i, addr );
348
gtk_list_store_set( GTK_LIST_STORE( scudsp->regListStore ), &iter, 1, bptext, -1 );
349
}
350
yui_window_invalidate( yui );
351
}
352
353
static void yui_scudsp_editedBp( GtkCellRendererText *cellrenderertext,
354
gchar *arg1,
355
gchar *arg2,
356
YuiScudsp *scudsp) {
357
/* breakpoint <arg1> has been set to address <arg2> */
358
359
GtkTreeIter iter;
360
char bptext[10];
361
char *endptr;
362
int i = atoi(arg1);
363
u32 addr;
364
gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL( scudsp->bpListStore ), &iter, arg1 );
365
addr = strtoul(arg2, &endptr, 16 );
366
if ((endptr - arg2 < strlen(arg2)) || (!addr)) addr = 0xFFFFFFFF;
367
if ( scudsp->cbp[i] != 0xFFFFFFFF) ScuDspDelCodeBreakpoint(scudsp->cbp[i]);
368
scudsp->cbp[i] = 0xFFFFFFFF;
369
370
if ((addr!=0xFFFFFFFF)&&(ScuDspAddCodeBreakpoint(addr) == 0)) {
371
372
sprintf(bptext, "%08X", (int)addr);
373
scudsp->cbp[i] = addr;
374
} else strcpy(bptext,"<empty>");
375
gtk_list_store_set( GTK_LIST_STORE( scudsp->bpListStore ), &iter, 0, bptext, -1 );
376
}
377
378
static void debugPauseLoop(void) { /* secondary gtk event loop for the "breakpoint pause" state */
379
380
while ( !(yui->state & YUI_IS_RUNNING) )
381
if ( gtk_main_iteration() ) return;
382
}
383
384
static void yui_scudsp_breakpoint_handler (u32 addr) {
385
386
yui_window_pause(yui);
387
{
388
scudspregs_struct scudspregs;
389
YuiScudsp* scudsp = YUI_SCUDSP(yui_scudsp_new( yui ));
390
391
ScuDspGetRegisters(&scudspregs);
392
yui_scudsp_update_reglist(scudsp, &scudspregs);
393
yui_scudsp_update_codelist(scudsp, scudspregs.PC);
394
}
395
debugPauseLoop(); /* execution is suspended inside a normal cycle - enter secondary gtk loop */
396
}
397
398
399
void yui_scudsp_update(YuiScudsp * scudsp) {
400
scudspregs_struct scudspregs;
401
ScuDspGetRegisters(&scudspregs);
402
yui_scudsp_update_codelist(scudsp,scudspregs.PC);
403
yui_scudsp_update_reglist(scudsp, &scudspregs);
404
gtk_widget_set_sensitive(scudsp->uLabel, TRUE);
405
gtk_widget_set_sensitive(scudsp->bpList, TRUE);
406
gtk_widget_set_sensitive(scudsp->regList, TRUE);
407
gtk_widget_set_sensitive(scudsp->buttonStep, TRUE);
408
}
409
410
void yui_scudsp_destroy(YuiScudsp * scudsp) {
411
g_signal_handler_disconnect(yui, scudsp->running_handler);
412
g_signal_handler_disconnect(yui, scudsp->paused_handler);
413
414
yui_scudsp = NULL;
415
416
gtk_widget_destroy(GTK_WIDGET(scudsp));
417
}
418
419
static void yui_scudsp_clear(YuiScudsp * scudsp) {
420
421
gtk_widget_set_sensitive(scudsp->uLabel, FALSE);
422
gtk_widget_set_sensitive(scudsp->bpList, FALSE);
423
gtk_widget_set_sensitive(scudsp->regList, FALSE);
424
gtk_widget_set_sensitive(scudsp->buttonStep, FALSE);
425
}
426
427