1 /*
2 * TTTTTTTTTTTTTT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
3 * TTTTTTTTTTTTTT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
4 * TT EE OO OO
5 * TT EE OO OO
6 * TT EE OO OO
7 * TT EEEEEEEEEE OO OO
8 * TT EEEEEEEEEE OO OO
9 * TT EE OO OO
10 * TT EE OO OO
11 * TT EE OO OO
12 * TT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
13 * TT EEEEEEEEEEEEEE OOOOOOOOOOOOOO
14 *
15 * L'�mulateur Thomson TO8
16 *
17 * Copyright (C) 1997-2017 Gilles F�tis, Eric Botcazou, Alexandre Pukall,
18 * J�r�mie Guillaume, Fran�ois Mouret
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 */
34
35 /*
36 * Module : linux/udebug/udmem.c
37 * Version : 1.8.4
38 * Cr�� par : Fran�ois Mouret 14/07/2016
39 * Modifi� par:
40 *
41 * D�bogueur 6809 - Affichage de la m�moire.
42 */
43
44
45 #ifndef SCAN_DEPEND
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <gtk/gtk.h>
50 #endif
51
52 #include "defs.h"
53 #include "teo.h"
54 #include "std.h"
55 #include "hardware.h"
56 #include "mc68xx/dasm6809.h"
57 #include "debug.h"
58 #include "debug/debug.h"
59 #include "linux/gui.h"
60
61 #define HIGHLIGHT_NAME "teo_dmem_highlight"
62
63 static GtkWidget *address_combo;
64 static GtkWidget *ram_combo;
65 static GtkWidget *video_combo;
66 static GtkWidget *cart_combo;
67 static GtkWidget *monitor_combo;
68
69 static GtkWidget *text_view;
70 static GtkTextBuffer *text_buffer;
71 static GtkTextMark *mark_first;
72 static GtkTextMark *mark_last;
73
74 static char *old_text = NULL;
75
76 static int prev_address = -1;
77
78
79
80 /* set_text:
81 * Set the text in the textview.
82 */
set_text(int address,uint8 * addr_ptr)83 static void set_text (int address, uint8 *addr_ptr)
84 {
85 char *text = NULL;
86
87 /* display the new text */
88 text = dmem_GetText (address&0xe000, addr_ptr, "\n");
89
90 /* Set the new text if different */
91 if (text != NULL)
92 {
93 if ((old_text == NULL) || (memcmp (text, old_text, strlen(text)) != 0))
94 {
95 gtk_text_buffer_set_text (
96 GTK_TEXT_BUFFER (text_buffer),
97 text,
98 -1);
99 }
100 }
101 /* Keep new text as old text */
102 if (old_text != NULL)
103 free (old_text);
104 old_text = text;
105 }
106
107
108
get_first_visible_line_number(void)109 static int get_first_visible_line_number (void)
110 {
111 int y;
112 int y_next;
113 int height;
114 int height_next;
115 GdkRectangle rect;
116 GtkTextIter iter;
117 GtkTextIter iter_next;
118 GtkTextView *view = GTK_TEXT_VIEW (text_view);
119
120 gtk_text_view_get_visible_rect (view, &rect);
121 gtk_text_view_get_iter_at_location (view, &iter, 0, rect.y);
122 gtk_text_view_get_line_yrange (view, &iter, &y, &height);
123 gtk_text_view_get_iter_at_location (view, &iter_next, 0, rect.y+height);
124 gtk_text_view_get_line_yrange (view, &iter_next, &y_next, &height_next);
125
126 if (y < y_next)
127 y = y_next;
128
129 return (height != 0) ? y/height : y;
130 }
131
132
133 /* do_combo_changed:
134 * Update the combo row value
135 */
do_combo_changed(GtkComboBox * combo_box,gpointer user_data)136 static void do_combo_changed (GtkComboBox *combo_box, gpointer user_data)
137 {
138 int *combo_row = user_data;
139
140 *combo_row = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
141 teo.debug.ram_number = gtk_combo_box_get_active (
142 GTK_COMBO_BOX (ram_combo));
143 teo.debug.mon_number = gtk_combo_box_get_active (
144 GTK_COMBO_BOX (monitor_combo));
145 teo.debug.video_number = gtk_combo_box_get_active (
146 GTK_COMBO_BOX (video_combo));
147 teo.debug.cart_number = gtk_combo_box_get_active (
148 GTK_COMBO_BOX (cart_combo));
149 teo.debug.memory_address = gtk_combo_box_get_active (
150 GTK_COMBO_BOX (address_combo))*0x2000;
151 teo.debug.memory_address += get_first_visible_line_number() * 8;
152 set_text (teo.debug.memory_address, dmem_GetDisplayPointer());
153 gtk_widget_show (GTK_WIDGET (text_view));
154
155 }
156
157
158
159 /* create_address:
160 * Create address label and combo
161 */
create_address_widgets(GtkWidget * grid)162 static void create_address_widgets (GtkWidget *grid)
163 {
164 int i;
165 char addr[20] = "";
166 GtkWidget *label = gtk_label_new (is_fr?"Adresse:":"Address:");
167
168 gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
169
170 address_combo = gtk_combo_box_text_new ();
171 for (i=0; i<8; i++)
172 {
173 *addr = '\0';
174 sprintf (addr, "$%04X", i*0x2000);
175 gtk_combo_box_text_append_text (
176 GTK_COMBO_BOX_TEXT (address_combo),
177 addr);
178 }
179 gtk_combo_box_set_active (
180 GTK_COMBO_BOX (address_combo),
181 (teo.debug.memory_address >> 13) & 0x7);
182 gtk_grid_attach (GTK_GRID (grid), address_combo, 0, 1, 1, 1);
183 g_signal_connect(
184 G_OBJECT(address_combo),
185 "changed",
186 G_CALLBACK (do_combo_changed),
187 (gpointer) &teo.debug.memory_address);
188 }
189
190
191
192 /* create_cartridge_widgets:
193 * Create cartridge label and combo
194 */
create_cartridge_widgets(GtkWidget * grid)195 static void create_cartridge_widgets (GtkWidget *grid)
196 {
197 int i;
198 char addr[20] = "";
199 GtkWidget *label = gtk_label_new (is_fr?"Cartouche:":"Cartridge:");
200
201 gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
202
203 cart_combo = gtk_combo_box_text_new ();
204 for (i=0; i<4; i++)
205 {
206 *addr = '\0';
207 sprintf (addr, "%d", i);
208 gtk_combo_box_text_append_text (
209 GTK_COMBO_BOX_TEXT (cart_combo),
210 addr);
211 }
212 gtk_combo_box_text_append_text (
213 GTK_COMBO_BOX_TEXT (cart_combo),
214 is_fr?"Memo":"Memo");
215
216 for (i=0; i<teo.setting.bank_range; i++)
217 {
218 *addr = '\0';
219 sprintf (addr, is_fr?"Banque %d":"Bank %d", i);
220 gtk_combo_box_text_append_text (
221 GTK_COMBO_BOX_TEXT (cart_combo),
222 addr);
223 }
224 gtk_combo_box_set_active (
225 GTK_COMBO_BOX (cart_combo),
226 teo.debug.cart_number);
227 gtk_grid_attach (GTK_GRID (grid), cart_combo, 1, 1, 1, 1);
228 g_signal_connect(
229 G_OBJECT(cart_combo),
230 "changed",
231 G_CALLBACK (do_combo_changed),
232 (gpointer) &teo.debug.cart_number);
233 }
234
235
236
237 /* create_video_widgets:
238 * Create video label and combo
239 */
create_video_widgets(GtkWidget * grid)240 static void create_video_widgets (GtkWidget *grid)
241 {
242 GtkWidget *label = gtk_label_new (is_fr?"Vidéo:":"Video:");
243
244 gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
245
246 video_combo = gtk_combo_box_text_new ();
247 gtk_combo_box_text_append_text (
248 GTK_COMBO_BOX_TEXT (video_combo),
249 is_fr?"Forme":"Form");
250 gtk_combo_box_text_append_text (
251 GTK_COMBO_BOX_TEXT (video_combo),
252 is_fr?"Couleur":"Colour");
253 gtk_combo_box_set_active (
254 GTK_COMBO_BOX (video_combo),
255 teo.debug.video_number);
256 gtk_grid_attach (GTK_GRID (grid), video_combo, 2, 1, 1, 1);
257 g_signal_connect(
258 G_OBJECT(video_combo),
259 "changed",
260 G_CALLBACK (do_combo_changed),
261 (gpointer) &teo.debug.video_number);
262 }
263
264
265
266 /* create_ram_widgets:
267 * Create ram label and combo
268 */
create_ram_widgets(GtkWidget * grid)269 static void create_ram_widgets (GtkWidget *grid)
270 {
271 int i;
272 char addr[20] = "";
273 GtkWidget *label = gtk_label_new (is_fr?"RAM:":"RAM:");
274
275 gtk_grid_attach (GTK_GRID (grid), label, 3, 0, 1, 1);
276
277 ram_combo = gtk_combo_box_text_new ();
278 for (i=0; i<teo.setting.bank_range; i++)
279 {
280 *addr = '\0';
281 sprintf (addr, "%d", i);
282 gtk_combo_box_text_append_text (
283 GTK_COMBO_BOX_TEXT (ram_combo),
284 addr);
285 }
286 gtk_combo_box_set_active (
287 GTK_COMBO_BOX (ram_combo),
288 teo.debug.ram_number);
289 gtk_grid_attach (GTK_GRID (grid), ram_combo, 3, 1, 1, 1);
290 g_signal_connect(
291 G_OBJECT(ram_combo),
292 "changed",
293 G_CALLBACK (do_combo_changed),
294 (gpointer) &teo.debug.ram_number);
295 }
296
297
298
299 /* create_monitor_widgets:
300 * Create monitor label and combo
301 */
create_monitor_widgets(GtkWidget * grid)302 static void create_monitor_widgets (GtkWidget *grid)
303 {
304 int i;
305 char addr[20] = "";
306 GtkWidget *label = gtk_label_new (is_fr?"Moniteur:":"Monitor:");
307
308 gtk_grid_attach (GTK_GRID (grid), label, 4, 0, 1, 1);
309
310 monitor_combo = gtk_combo_box_text_new ();
311 for (i=0; i<2; i++)
312 {
313 *addr = '\0';
314 sprintf (addr, "%d", i);
315 gtk_combo_box_text_append_text (
316 GTK_COMBO_BOX_TEXT (monitor_combo),
317 addr);
318 }
319 gtk_combo_box_set_active (
320 GTK_COMBO_BOX (monitor_combo),
321 teo.debug.mon_number);
322 gtk_grid_attach (GTK_GRID (grid), monitor_combo, 4, 1, 1, 1);
323 g_signal_connect(
324 G_OBJECT(monitor_combo),
325 "changed",
326 G_CALLBACK (do_combo_changed),
327 (gpointer) &teo.debug.mon_number);
328 }
329
330
331
332 /* init_combos:
333 * Initialization of the combobox.
334 */
init_combos(void)335 static GtkWidget *init_combos (void)
336 {
337 int i;
338 GtkWidget *box;
339 GtkWidget *grid;
340
341 /* Create combo grid */
342 grid = gtk_grid_new ();
343 for (i=0; i<3; i++)
344 gtk_grid_insert_row (GTK_GRID (grid), 0);
345 for (i=0; i<5; i++)
346 gtk_grid_insert_column (GTK_GRID (grid), 0);
347
348 /* Create widgets */
349 create_address_widgets (grid);
350 create_cartridge_widgets (grid);
351 create_video_widgets (grid);
352 create_ram_widgets (grid);
353 create_monitor_widgets (grid);
354
355 /* initialize the combo line */
356 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
357 gtk_box_pack_start( GTK_BOX(box), GTK_WIDGET(grid), FALSE, FALSE, 0);
358
359 return box;
360 }
361
362
363
364 /* scroll_to_mark :
365 * Scroll to the mark in the textview
366 */
scroll_to_mark(GtkTextView * view)367 static void scroll_to_mark (GtkTextView *view)
368 {
369 GtkTextIter iter;
370 GdkRectangle rect_view;
371 GdkRectangle rect_iter;
372 GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
373
374 do
375 {
376 gtk_text_view_scroll_to_mark (view, mark_first, 0.0, TRUE, 0.0, 0.5);
377
378 /* Wait for end of GTK work */
379 while (gtk_events_pending ())
380 gtk_main_iteration ();
381
382 gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark_first);
383 gtk_text_view_get_iter_location (view, &iter, &rect_iter);
384 gtk_text_view_get_visible_rect (view, &rect_view);
385
386 } while (((rect_view.y + rect_view.height) < (rect_iter.y+rect_iter.height))
387 || (rect_view.y > rect_iter.y));
388
389 }
390
391
392
393 /* add_mark:
394 * Add/Move a mark in the textview.
395 */
add_mark(GtkTextMark * mark,int line,int char_pos)396 static void add_mark (GtkTextMark *mark, int line, int char_pos)
397 {
398 GtkTextIter iter;
399 GtkTextBuffer *buff = GTK_TEXT_BUFFER (text_buffer);
400
401 gtk_text_buffer_get_iter_at_line_offset (buff, &iter, line, char_pos);
402 if (gtk_text_mark_get_deleted (mark) == TRUE)
403 {
404 gtk_text_buffer_add_mark (buff, mark, &iter);
405 }
406 else
407 {
408 gtk_text_buffer_move_mark (buff, mark, &iter);
409 }
410 }
411
412
413
414 /* scroll_text:
415 * Scroll the text in the textview.
416 */
scroll_text(int value_line,int address)417 static void scroll_text (int value_line, int address)
418 {
419 int count;
420
421 count = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (text_buffer));
422 if (count > 0)
423 {
424 add_mark (mark_first, value_line, 6+(address&0x07)*3);
425 add_mark (mark_last, value_line, 6+(address&0x07)*3+2);
426 scroll_to_mark (GTK_TEXT_VIEW (text_view));
427 }
428 }
429
430
431
432 /* unselect_range :
433 * Unselect the text
434 */
unselect_range(GtkTextBuffer * buf)435 static void unselect_range (GtkTextBuffer *buf)
436 {
437 GtkTextIter start;
438 GtkTextIter end;
439
440 gtk_text_buffer_get_start_iter (buf, &start);
441 gtk_text_buffer_get_end_iter (buf, &end);
442 gtk_text_buffer_remove_tag_by_name (buf, HIGHLIGHT_NAME, &start, &end);
443
444 /* Wait for end of GTK work */
445 while (gtk_events_pending ())
446 gtk_main_iteration ();
447 }
448
449
450
451 /* select_range :
452 * Select and highlight the current value
453 */
select_range(GtkTextBuffer * buf)454 static void select_range (GtkTextBuffer *buf)
455 {
456 GtkTextIter start;
457 GtkTextIter end;
458
459 gtk_text_buffer_get_iter_at_mark (buf, &start, mark_first);
460 gtk_text_buffer_get_iter_at_mark (buf, &end, mark_last);
461 gtk_text_buffer_apply_tag_by_name (buf, HIGHLIGHT_NAME, &start, &end);
462
463 /* Wait for end of GTK work */
464 while (gtk_events_pending ())
465 gtk_main_iteration ();
466 }
467
468
469
470 /* display:
471 * Display the memory dump.
472 */
display(int address,uint8 * addr_ptr)473 static void display (int address, uint8 *addr_ptr)
474 {
475 int value_line = (address & 0x1fff) >> 3;
476
477 /* Set and scroll text */
478 unselect_range (GTK_TEXT_BUFFER (text_buffer));
479 set_text (address, addr_ptr);
480 scroll_text (value_line, address);
481 select_range (GTK_TEXT_BUFFER (text_buffer));
482 }
483
484
485
486 /* init_source_text:
487 * Initialization of the source text.
488 */
init_source_text(void)489 static GtkWidget *init_source_text (void)
490 {
491 GtkWidget *box;
492 GtkWidget *scrolled_window;
493 GtkTextTagTable *tag_table;
494 GtkTextTag *tag_highlight;
495
496 /* Create source buffer */
497 tag_table = gtk_text_tag_table_new ();
498 text_buffer = gtk_text_buffer_new (tag_table);
499 tag_highlight = gtk_text_tag_new (HIGHLIGHT_NAME);
500 g_object_set (
501 (gpointer)tag_highlight,
502 "foreground", "white",
503 "background", "crimson",
504 "weight", PANGO_WEIGHT_BOLD,
505 NULL);
506 gtk_text_tag_table_add (tag_table, tag_highlight);
507 mark_first = gtk_text_mark_new ("teo_dmem_mark_first", FALSE);
508 mark_last = gtk_text_mark_new ("teo_dmem_mark_last", FALSE);
509
510 /* Create source view */
511 text_view = gtk_text_view_new_with_buffer (text_buffer);
512 gtk_text_view_set_editable (GTK_TEXT_VIEW(text_view), FALSE);
513 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW(text_view), FALSE);
514
515 /* Create scroll window */
516 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
517 gtk_scrolled_window_set_policy (
518 GTK_SCROLLED_WINDOW (scrolled_window),
519 GTK_POLICY_AUTOMATIC,
520 GTK_POLICY_AUTOMATIC);
521 gtk_scrolled_window_set_min_content_height (
522 GTK_SCROLLED_WINDOW (scrolled_window),
523 80);
524
525 /* Pack text view */
526 gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
527
528 /* Set Courier font */
529 gtk_widget_set_name (scrolled_window, COURIER_DEBUG);
530
531 /* Pack everything in box */
532 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
533 gtk_box_pack_start (GTK_BOX(box), scrolled_window, TRUE, TRUE, 0);
534
535 return box;
536 }
537
538
539 /* ------------------------------------------------------------------------- */
540
541
542 /* udmem_Free:
543 * Free the memory used by the memory area.
544 */
udmem_Free(void)545 void udmem_Free(void)
546 {
547 /* Free old text memory */
548 if (old_text != NULL)
549 {
550 free (old_text);
551 old_text = NULL;
552 }
553 }
554
555
556
557 /* udmem_Init:
558 * Create widgets.
559 */
udmem_Init(void)560 GtkWidget *udmem_Init(void)
561 {
562 GtkWidget *box;
563
564 prev_address = -1;
565
566 /* initialize the source box */
567 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
568 gtk_box_pack_start( GTK_BOX(box), init_combos (), FALSE, FALSE, 0);
569 gtk_box_pack_start( GTK_BOX(box), init_source_text (), TRUE, TRUE, 0);
570
571 return box;
572 }
573
574
575
576 /* udmem_GetStepAddress:
577 * Get the jump address in step mode.
578 */
udmem_GetStepAddress(void)579 int udmem_GetStepAddress(void)
580 {
581 return dmem_GetJumpAddress();
582 }
583
584
585
586 /* udmem_StepDisplay:
587 * Display memory for disassembling.
588 */
udmem_StepDisplay(int address)589 void udmem_StepDisplay(int address)
590 {
591 int index = 0;
592
593 if (address == -1)
594 address = prev_address;
595
596 if (address != -1)
597 {
598 gtk_combo_box_set_active (
599 GTK_COMBO_BOX (address_combo),
600 (address >> 13) & 0x0f);
601
602 gtk_combo_box_set_active (
603 GTK_COMBO_BOX (ram_combo),
604 mempager.data.reg_page);
605
606 gtk_combo_box_set_active (
607 GTK_COMBO_BOX (video_combo),
608 1-mempager.screen.page);
609
610 gtk_combo_box_set_active (
611 GTK_COMBO_BOX (monitor_combo),
612 mempager.mon.page);
613
614 if (mode_page.cart&0x20)
615 index = 5+mempager.cart.ram_page;
616 else
617 if (mc6846.prc&4)
618 index = mempager.cart.rom_page;
619 else
620 index = 4;
621
622 gtk_combo_box_set_active (GTK_COMBO_BOX (cart_combo),index);
623
624 display(address, NULL);
625 }
626 }
627
628
629
630 /* udmem_Display:
631 * Display choosen memory slice.
632 */
udmem_Display(void)633 void udmem_Display(void)
634 {
635 uint8 *addr_ptr = NULL;
636
637 addr_ptr = dmem_GetDisplayPointer();
638 set_text (teo.debug.memory_address, addr_ptr);
639 scroll_text (
640 (teo.debug.memory_address&0x1fff)>>3,
641 teo.debug.memory_address);
642
643 }
644