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