1 /*
2 * TilEm II
3 *
4 * Copyright (c) 2011 Benjamin Moody
5 *
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <gtk/gtk.h>
28 #include <ticalcs.h>
29 #include <tilem.h>
30 #include <tilemdb.h>
31
32 #include "gui.h"
33
tilem_format_addr(TilemDebugger * dbg,dword addr,gboolean physical)34 char * tilem_format_addr(TilemDebugger *dbg, dword addr, gboolean physical)
35 {
36 dword page, addr_l;
37
38 g_return_val_if_fail(dbg != NULL, NULL);
39 g_return_val_if_fail(dbg->emu != NULL, NULL);
40 g_return_val_if_fail(dbg->emu->calc != NULL, NULL);
41
42 if (!physical)
43 return g_strdup_printf("%04X", addr);
44
45 if (addr >= dbg->emu->calc->hw.romsize)
46 page = (((addr - dbg->emu->calc->hw.romsize) >> 14)
47 + dbg->emu->calc->hw.rampagemask);
48 else
49 page = addr >> 14;
50
51 addr_l = (*dbg->emu->calc->hw.mem_ptol)(dbg->emu->calc, addr);
52 if (addr_l == 0xffffffff)
53 addr_l = (addr & 0x3fff) | 0x4000;
54
55 return g_strdup_printf("%02X:%04X", page, addr_l);
56 }
57
parse_hex(const char * string,dword * value)58 static gboolean parse_hex(const char *string, dword *value)
59 {
60 const char *n;
61 char *e;
62 dword a;
63
64 if (string[0] == '$')
65 n = string + 1;
66 else if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
67 n = string + 2;
68 else
69 n = string;
70
71 a = strtol(n, &e, 16);
72 if (value)
73 *value = a;
74
75 if (e == n)
76 return FALSE;
77
78 if (*e == 'h' || *e == 'H')
79 e++;
80
81 return (*e == 0);
82 }
83
tilem_parse_paged_addr(TilemDebugger * dbg,const char * pagestr,const char * offsstr,dword * value)84 gboolean tilem_parse_paged_addr(TilemDebugger *dbg, const char *pagestr,
85 const char *offsstr, dword *value)
86 {
87 dword page, offs;
88
89 g_return_val_if_fail(dbg != NULL, FALSE);
90 g_return_val_if_fail(dbg->emu != NULL, FALSE);
91 g_return_val_if_fail(dbg->emu->calc != NULL, FALSE);
92
93 if (!parse_hex(pagestr, &page))
94 return FALSE;
95 if (!tilem_parse_addr(dbg, offsstr, &offs, NULL))
96 return FALSE;
97
98 offs &= 0x3fff;
99 if (page & dbg->emu->calc->hw.rampagemask) {
100 page &= ~dbg->emu->calc->hw.rampagemask;
101 offs += (offs << 14);
102 if (offs > dbg->emu->calc->hw.ramsize)
103 return FALSE;
104 offs += dbg->emu->calc->hw.romsize;
105 }
106 else {
107 offs += (page << 14);
108 if (offs > dbg->emu->calc->hw.romsize)
109 return FALSE;
110 }
111
112 if (value) *value = offs;
113 return TRUE;
114 }
115
tilem_parse_addr(TilemDebugger * dbg,const char * string,dword * value,gboolean * physical)116 gboolean tilem_parse_addr(TilemDebugger *dbg, const char *string,
117 dword *value, gboolean *physical)
118 {
119 const char *offstr;
120 char *pagestr;
121
122 g_return_val_if_fail(dbg != NULL, FALSE);
123 g_return_val_if_fail(dbg->emu != NULL, FALSE);
124 g_return_val_if_fail(dbg->emu->calc != NULL, FALSE);
125
126 if (parse_hex(string, value)) {
127 if (physical) *physical = FALSE;
128 return TRUE;
129 }
130
131 if (physical && (offstr = strchr(string, ':'))) {
132 pagestr = g_strndup(string, offstr - string);
133 offstr++;
134 if (tilem_parse_paged_addr(dbg, pagestr, offstr, value)) {
135 *physical = TRUE;
136 return TRUE;
137 }
138 }
139
140 if (dbg->dasm && tilem_disasm_get_label(dbg->dasm, string, value)) {
141 if (physical) *physical = FALSE;
142 return TRUE;
143 }
144
145 return FALSE;
146 }
147
148 struct addrdlg {
149 GtkWidget *dlg;
150 TilemDebugger *dbg;
151 gboolean physical;
152 };
153
edited(GtkEntry * entry,gpointer data)154 static void edited(GtkEntry *entry, gpointer data)
155 {
156 struct addrdlg *adlg = data;
157 const char *text;
158 gboolean valid, phys;
159
160 text = gtk_entry_get_text(entry);
161 valid = tilem_parse_addr(adlg->dbg, text, NULL,
162 adlg->physical ? &phys : NULL);
163 gtk_dialog_set_response_sensitive(GTK_DIALOG(adlg->dlg),
164 GTK_RESPONSE_OK,
165 valid);
166 }
167
tilem_prompt_address(TilemDebugger * dbg,GtkWindow * parent,const char * title,const char * prompt,dword * value,gboolean physical,gboolean usedefault)168 gboolean tilem_prompt_address(TilemDebugger *dbg, GtkWindow *parent,
169 const char *title, const char *prompt,
170 dword *value, gboolean physical,
171 gboolean usedefault)
172 {
173 GtkWidget *dlg, *hbox, *vbox, *lbl, *ent;
174 struct addrdlg adlg;
175 const char *text;
176 gboolean phys;
177 char *s;
178
179 g_return_val_if_fail(dbg != NULL, FALSE);
180 g_return_val_if_fail(dbg->emu != NULL, FALSE);
181 g_return_val_if_fail(dbg->emu->calc != NULL, FALSE);
182
183 dlg = gtk_dialog_new_with_buttons(title, parent, GTK_DIALOG_MODAL,
184 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
185 GTK_STOCK_OK, GTK_RESPONSE_OK,
186 NULL);
187 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dlg),
188 GTK_RESPONSE_OK,
189 GTK_RESPONSE_CANCEL,
190 -1);
191 gtk_dialog_set_default_response(GTK_DIALOG(dlg),
192 GTK_RESPONSE_OK);
193
194 hbox = gtk_hbox_new(FALSE, 6);
195 gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
196
197 lbl = gtk_label_new(prompt);
198 gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
199
200 ent = gtk_entry_new();
201 gtk_entry_set_activates_default(GTK_ENTRY(ent), TRUE);
202 gtk_box_pack_start(GTK_BOX(hbox), ent, TRUE, TRUE, 0);
203
204 if (usedefault) {
205 s = tilem_format_addr(dbg, *value, physical);
206 gtk_entry_set_text(GTK_ENTRY(ent), s);
207 g_free(s);
208 }
209
210 adlg.dlg = dlg;
211 adlg.dbg = dbg;
212 adlg.physical = physical;
213
214 g_signal_connect(ent, "changed",
215 G_CALLBACK(edited), &adlg);
216 edited(GTK_ENTRY(ent), &adlg);
217
218 gtk_widget_show_all(hbox);
219 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
220 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
221
222 if (gtk_dialog_run(GTK_DIALOG(dlg)) != GTK_RESPONSE_OK) {
223 gtk_widget_destroy(dlg);
224 return FALSE;
225 }
226
227 text = gtk_entry_get_text(GTK_ENTRY(ent));
228 if (!tilem_parse_addr(dbg, text, value, physical ? &phys : NULL)) {
229 gtk_widget_destroy(dlg);
230 return FALSE;
231 }
232
233 if (physical && !phys) {
234 tilem_calc_emulator_lock(dbg->emu);
235 *value &= 0xffff;
236 *value = (*dbg->emu->calc->hw.mem_ltop)(dbg->emu->calc, *value);
237 tilem_calc_emulator_unlock(dbg->emu);
238 }
239
240 gtk_widget_destroy(dlg);
241 return TRUE;
242 }
243