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 TO8D
16  *
17  *  Copyright (C) 1997-2017 Gilles F�tis, Eric Botcazou, Alexandre Pukall,
18  *                          J�r�mie Guillaume
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     : dos/memmng.c
37  *  Version    : 1.8.4
38  *  Cr�� par   : Eric Botcazou 1998
39  *  Modifi� par: Eric Botcazou 23/11/2000
40  *               Fran�ois Mouret 08/2011 20/09/2013 02/06/2014
41  *
42  *  Gestionnaire de m�moire du TO8.
43  *   Ce module est ind�pendant du reste de l'�mulateur et vient se greffer
44  *   sur le d�bogueur. Il permet de naviguer dans la m�moire du TO8 sans
45  *   influer sur son fonctionnement.
46  */
47 
48 
49 #ifndef SCAN_DEPEND
50    #include <stdio.h>
51    #include <conio.h>
52 #endif
53 
54 #include "defs.h"
55 #include "mc68xx/dasm6809.h"
56 #include "mc68xx/mc6809.h"
57 #include "debug.h"
58 #include "teo.h"
59 
60 
61 /* param�tres de disposition des modules � l'�cran */
62 #define MENU_NLINE      7
63 #define MENU_POS_X      4
64 #define MENU_POS_Y     28
65 #define DASM_POS_X     48
66 #define DASM_POS_Y     13
67 #define   DUMP_POS_X    3
68 #define   DUMP_POS_Y   13
69 #define   DUMP_NBYTES   8
70 #define   DUMP_NLINES  10
71 #define DIALOG_POS_X    6
72 #define DIALOG_POS_Y   39
73 
74 static char map_line[11][81]={
75 #ifdef FRENCH_LANGUAGE
76 "                          Gestionnaire de m�moire du TO8                        ",
77 #else
78 "                               TO8 memory manager                               ",
79 #endif
80 "������������������������������������������������������������������������������Ŀ",
81 "�                  �         �                   �                   �         �",
82 "�0                3�4       5�6                 9�A                 D�E       F�",
83 "�0     BASICs     F�0 Video F�0     System      F�0      User       F�0  I/O  F�",
84 "�0      ROM       F�0  RAM  F�0      RAM        F�0      RAM        F�0  ROM  F�",
85 "�0                F�0       F�0                 F�0                 F�0       F�",
86 "�                  �         �                   �                   �         �",
87 "������������������������������������������������������������������������������Ĵ",
88 "�     bank   /3    �bank   /1�                   �     bank   /31    �bank   /1�",
89 "������������������������������                   �������������������������������"
90 };
91 
92 #ifdef FRENCH_LANGUAGE
93 static char menu_line[MENU_NLINE][30]={ "Commandes:",
94                                         " c: charger un bloc m�moire",
95                                         " s: sauver un bloc m�moire",
96                                         " a: aller � l'<adresse>",
97                                         " e: �diter un octet",
98                                         " TAB,+,-: naviguer",
99                                         " q: quitter le gestionnaire"};
100 #else
101 static char menu_line[MENU_NLINE][30]={ "Commands:",
102                                         " c: load a memory block",
103                                         " s: save a memory block",
104                                         " a: go to <address>",
105                                         " e: editing a byte",
106                                         " TAB,+,-: navigating",
107                                         " q: quit the manager"};
108 #endif
109 
110 static struct P2D {
111     int x;
112     int y;
113 } hotspot_loc[5]={{12,10},{26,10},{61,10},{76,10},{45,50}};
114 static int   current_bank[4];
115 static int       max_bank[4]={  3,   1,  31,   1};
116 static int       bank_loc[4]={  0,   4, 0xA, 0xE};
117 static int      bank_size[4]={  4,   2,   4,   2};
118 static unsigned char *VRAM[2];
119 static unsigned char **mapper_table[4]={mem.rom.bank, VRAM, mem.ram.bank, mem.mon.bank};
120 
121 
122 
123 /* Helper routines:
124  */
ReadFileName(char * file_name,int pos_x,int pos_y,const char * mesg)125 static void ReadFileName(char *file_name,int pos_x, int pos_y, const char *mesg)
126 {
127     textbackground(BLACK);
128     textcolor(WHITE);
129     gotoxy(pos_x,pos_y);
130     cputs(mesg);
131     _setcursortype(_NORMALCURSOR);
132     cscanf("%s",file_name);
133     _setcursortype(_NOCURSOR);
134 }
135 
136 
ReadAddress(int * addr,int pos_x,int pos_y,const char * mesg)137 static void ReadAddress(int *addr, int pos_x, int pos_y, const char *mesg)
138 {
139     textbackground(BLACK);
140     textcolor(WHITE);
141     gotoxy(pos_x,pos_y);
142     cputs(mesg);
143     _setcursortype(_NORMALCURSOR);
144     cscanf("%4X",addr);
145     *addr&=0xFFFF;
146     _setcursortype(_NOCURSOR);
147 }
148 
149 
ReadByte(int * val,int pos_x,int pos_y,const char * mesg)150 static void ReadByte(int *val, int pos_x, int pos_y, const char *mesg)
151 {
152     textbackground(BLACK);
153     textcolor(WHITE);
154     gotoxy(pos_x,pos_y);
155     cputs(mesg);
156     _setcursortype(_NORMALCURSOR);
157     cscanf("%2x",val);
158     *val&=0xFF;
159     _setcursortype(_NOCURSOR);
160 }
161 
162 
DeleteBox(int left,int top,int right,int bottom)163 static void DeleteBox(int left, int top, int right, int bottom)
164 {
165     register int i,j;
166 
167     for (i=top; i<=bottom; i++)
168     {
169         gotoxy(left,i);
170         for (j=left; j<=right; j++)
171             putch(32);
172     }
173 }
174 
175 
176 
177 /* SetHotspot:
178  *  D�place le curseur de s�lection � l'emplacement voulu.
179  */
SetHotspot(int hotspot)180 static void SetHotspot(int hotspot)
181 {
182     static int prev_hotspot;
183 
184     /* on �teint l'emplacement pr�c�dent du curseur */
185     gotoxy(hotspot_loc[prev_hotspot].x,hotspot_loc[prev_hotspot].y);
186 
187     if (prev_hotspot == 4)
188     {
189         textbackground(BLACK);
190         textcolor(WHITE);
191         cprintf("->");
192     }
193     else
194     {
195         textbackground(BLACK);
196         textcolor(LIGHTGREEN);
197         cprintf("%2d",current_bank[prev_hotspot]);
198     }
199 
200     /* on allume le nouveau */
201     gotoxy(hotspot_loc[hotspot].x,hotspot_loc[hotspot].y);
202 
203     if (hotspot == 4)
204     {
205         textbackground(WHITE);
206         textcolor(BLACK);
207         cprintf("->");
208     }
209     else
210     {
211         textbackground(LIGHTGREEN);
212         textcolor(BLACK);
213         cprintf("%2d",current_bank[hotspot]);
214     }
215 
216     prev_hotspot=hotspot;
217 }
218 
219 
220 
221 /* DumpMemory:
222  *  Transcrit un bloc m�moire au format ASCII.
223  */
DumpMemory(char * out_str,int addr,int nbytes)224 static void DumpMemory(char *out_str, int addr, int nbytes)
225 {
226     register int i;
227     int c;
228 
229     sprintf(out_str, "%04X ", addr);  /* affiche l'adresse */
230     out_str+=5;
231 
232     for (i=0; i<nbytes; i++)
233     {
234         sprintf(out_str, "%02X ", LOAD_BYTE(addr+i));
235         out_str+=3;
236     }
237 
238     sprintf(out_str++, " ");
239 
240     for (i=0; i<nbytes; i++)
241     {
242         c=LOAD_BYTE(addr+i);
243 
244         if ((c>=32) && (c<=125))
245             sprintf(out_str++, "%c", c);
246         else
247             sprintf(out_str++, ".");
248     }
249 }
250 
251 
252 
253 /* UpdateDasmAndDump:
254  *  D�sassemble l'instruction suivante et met � jour
255  *  si n�cessaire le dump m�moire.
256  */
UpdateDasmAndDump(int * pc)257 static void UpdateDasmAndDump(int *pc)
258 {
259     int i, q=*pc/DUMP_NBYTES;
260     struct MC6809_DASM mc6809_dasm;
261 
262     textbackground(BLACK);
263     textcolor(WHITE);
264 
265     /* on d�cale l'�cran de d�sassemblage d'une ligne vers le haut */
266     movetext(DASM_POS_X,DASM_POS_Y+2,80,50,DASM_POS_X,DASM_POS_Y+1);
267     DeleteBox(DASM_POS_X,50,79,50);
268 
269     for (i=0; i<MC6809_DASM_FETCH_SIZE; i++)
270         mc6809_dasm.fetch[i]=LOAD_BYTE(*pc+i);
271 
272     mc6809_dasm.addr = *pc;
273     mc6809_dasm.mode = MC6809_DASM_ASM_MODE;
274     *pc+=dasm6809_Disassemble(&mc6809_dasm);
275 
276     if (*pc>0xFFFF)
277         *pc&=0xFFFF;
278 
279     gotoxy(DASM_POS_X,50);
280     cputs(mc6809_dasm.str);
281 
282     if ((*pc/DUMP_NBYTES) != q)
283     {
284         /* on d�cale l'�cran de dump d'une ligne vers le haut */
285         movetext(DUMP_POS_X,DUMP_POS_Y+2,40,DUMP_POS_Y+DUMP_NLINES,DUMP_POS_X,DUMP_POS_Y+1);
286         DeleteBox(DUMP_POS_X,DUMP_POS_Y+DUMP_NLINES,40,DUMP_POS_Y+DUMP_NLINES);
287 
288         DumpMemory(mc6809_dasm.str, q*DUMP_NBYTES, DUMP_NBYTES);
289         gotoxy(DUMP_POS_X,DUMP_POS_Y+DUMP_NLINES);
290         cputs(mc6809_dasm.str);
291     }
292 }
293 
294 
295 
296 /* EditMemory:
297  *  Edite un octet de m�moire.
298  */
EditMemory(void)299 static int EditMemory(void)
300 {
301     int addr, val;
302 
303     ReadAddress(&addr,DIALOG_POS_X,DIALOG_POS_Y,is_fr?"Adresse: ":"Address: ");
304     ReadByte(&val,DIALOG_POS_X,DIALOG_POS_Y+1,is_fr?"Nouvelle valeur : ":"New value : ");
305     DeleteBox(DIALOG_POS_X,DIALOG_POS_Y,40,DIALOG_POS_Y+1);
306 
307     STORE_BYTE(addr, val);
308     UpdateDasmAndDump(&addr);
309     return addr;
310 }
311 
312 
313 
314 /* LoadMemory:
315  *  Lit une portion de la m�moire.
316  */
LoadMemory(void)317 static int LoadMemory(void)
318 {
319     char file_name[32];
320     int  addr, addr_orig, d;
321     FILE *file;
322 
323     ReadFileName(file_name,DIALOG_POS_X,DIALOG_POS_Y,is_fr?"Nom du fichier: ":"File name: ");
324     ReadAddress(&addr,DIALOG_POS_X,DIALOG_POS_Y+1,is_fr?"Adresse de d�but: ":"Start address: ");
325 
326     addr_orig=addr;
327 
328     if ((file=fopen(file_name,"rb")) == NULL)
329     {
330         gotoxy(DIALOG_POS_X,DIALOG_POS_Y+2);
331         cprintf(is_fr?"Erreur !!!":"Error !!!");
332     }
333     else
334     {
335         while ((addr<0x10000) && ((d=fgetc(file))!=EOF))
336         {
337             STORE_BYTE(addr, d);
338             addr++;
339         }
340 
341         fclose(file);
342         gotoxy(DIALOG_POS_X,DIALOG_POS_Y+2);
343         cprintf(is_fr?"Termin�":"Finished");
344     }
345 
346     gotoxy(DIALOG_POS_X,DIALOG_POS_Y+3);
347     cprintf(is_fr?"Appuyer sur <espace>":"Press <space bar>");
348 
349     while (getch() != 32)
350         ;
351 
352     DeleteBox(DIALOG_POS_X,DIALOG_POS_Y,40,DIALOG_POS_Y+3);
353 
354     UpdateDasmAndDump(&addr_orig);
355     return addr_orig;
356 }
357 
358 
359 
360 /* SaveMemory:
361  *  Sauvegarde une portion de la m�moire.
362  */
SaveMemory(void)363 static void SaveMemory(void)
364 {
365     char file_name[32];
366     struct MC6809_DASM mc6809_dasm;
367     int addr1,addr2,c,i;
368     FILE *file;
369 
370     ReadFileName(file_name,DIALOG_POS_X,DIALOG_POS_Y,is_fr?"Nom du fichier: ":"File name: ");
371     ReadAddress(&addr1,DIALOG_POS_X,DIALOG_POS_Y+1,is_fr?"Adresse de d�but: ":"Start address: ");
372     ReadAddress(&addr2,DIALOG_POS_X,DIALOG_POS_Y+2,is_fr?"Adresse de fin: ":"End address: ");
373 
374     gotoxy(DIALOG_POS_X, DIALOG_POS_Y+3);
375     cprintf(is_fr?"Format: 1.binaire":"Format: 1.binary");
376     gotoxy(DIALOG_POS_X, DIALOG_POS_Y+4);
377     cprintf("        2.ASCII");
378     gotoxy(DIALOG_POS_X, DIALOG_POS_Y+5);
379     cprintf(is_fr?"        3.assembleur":"        3.assembler");
380 
381     do
382         c=getch();
383     while ((c<'1') || (c>'3'));
384 
385     if ((file=fopen(file_name,"wb")) == NULL)
386     {
387         gotoxy(DIALOG_POS_X,DIALOG_POS_Y+6);
388         cprintf(is_fr?"Erreur !!!":"Error !!!");
389     }
390     else
391     {
392         switch(c)
393         {
394             case '1':
395                 for (i=addr1; i<=addr2; i++)
396                     fputc(LOAD_BYTE(i)&0xFF, file);
397                 break;
398 
399             case '2':
400                 do
401                 {
402                     DumpMemory(mc6809_dasm.str, addr1, 8);
403                     addr1+=8;
404                     fprintf(file, "%s\r\n", mc6809_dasm.str);
405                 }
406                 while (addr1 < addr2);
407                 break;
408 
409             case '3':
410                 do
411                 {
412                     for (i=0; i<MC6809_DASM_FETCH_SIZE; i++)
413                         mc6809_dasm.fetch[i]=LOAD_BYTE(addr1+i);
414 
415                     mc6809_dasm.addr = addr1;
416                     mc6809_dasm.mode = MC6809_DASM_BINASM_MODE;
417                     addr1 += dasm6809_Disassemble(&mc6809_dasm);
418                     fprintf(file, "%s\r\n", mc6809_dasm.str);
419                 }
420                 while (addr1 < addr2);
421                 break;
422         }
423 
424         fclose(file);
425         gotoxy(DIALOG_POS_X,DIALOG_POS_Y+6);
426         cprintf(is_fr?"Termin�":"Finished");
427     }
428 
429     gotoxy(DIALOG_POS_X,DIALOG_POS_Y+7);
430     cprintf(is_fr?"Appuyer sur <espace>":"Press <space bar>");
431 
432     while (getch() != 32)
433         ;
434 
435     DeleteBox(DIALOG_POS_X,DIALOG_POS_Y,40,DIALOG_POS_Y+7);
436 }
437 
438 
439 
440 /* MemoryManager:
441  *  Point d'entr�e du module; affiche l'�cran du gestionnaire
442  *  de m�moire et lance la boucle principale.
443  */
MemoryManager(void)444 void MemoryManager(void)
445 {
446     register int i;
447              int c=0,hotspot=4,pc;
448     struct MC6809_REGS regs;
449     unsigned char *mapper_orig[16];
450 
451     /* on sauvegarde d'abord l'�tat du mapper */
452     for (i=0; i<16; i++)
453         mapper_orig[i]=mempager.segment[i];
454 
455     /* on lit ensuite l'�tat des banques de m�moire et du PC */
456     VRAM[0]=mem.ram.bank[0]+0x2000;
457     VRAM[1]=mem.ram.bank[0];
458     current_bank[0]=mempager.cart.rom_page;
459     current_bank[1]=mempager.screen.page;
460     current_bank[2]=mempager.data.page;
461     current_bank[3]=mempager.mon.page;
462     mc6809_GetRegs(&regs);
463     pc=regs.pc;
464 
465     /* on construit l'�cran du gestionnaire */
466     clrscr();
467 
468     /* les trois barres de titres */
469     textbackground(BLUE);
470     textcolor(LIGHTGRAY);
471     cputs(map_line[0]);
472     gotoxy(DUMP_POS_X-2,DUMP_POS_Y);
473     cprintf(is_fr?"          Contenu de la m�moire           ":"          Content of the memory           ");
474     gotoxy(DASM_POS_X-2,DASM_POS_Y);
475     cprintf(is_fr?"       D�sassembleur MC6809E       ":"       MC6809E disassembler        ");
476 
477     /* la carte de la m�moire */
478     textbackground(BLACK);
479     textcolor(WHITE);
480     gotoxy(1,2);
481     for (i=1; i<9; i++)
482         cputs(map_line[i]);
483 
484     /* le d�sassembleur */
485     for (i=0; i<50-DASM_POS_Y; i++)
486         UpdateDasmAndDump(&pc);
487 
488     /* les volets des banques */
489     textcolor(LIGHTGREEN);
490     gotoxy(1,10);
491     cputs(map_line[9]);
492     cputs(map_line[10]);
493     for (i=0; i<4; i++)
494     {
495         gotoxy(hotspot_loc[i].x,hotspot_loc[i].y);
496         cprintf("%2d",current_bank[i]);
497     }
498 
499     /* le menu */
500     textcolor(LIGHTCYAN);
501     for (i=0; i<MENU_NLINE; i++)
502     {
503         gotoxy(MENU_POS_X,MENU_POS_Y+i);
504         cputs(menu_line[i]);
505     }
506 
507     SetHotspot(hotspot);
508 
509     while ((c != 'q') && (c != 'Q'))  /* boucle principale */
510     {
511         switch (c=getch())
512         {
513             case 9: /* TAB: circulation du curseur */
514                 if (++hotspot == 5)
515                     hotspot=0;
516                 SetHotspot(hotspot);
517                 break;
518 
519             case '+': /* banque suivante ou instruction suivante */
520                 if (hotspot == 4)
521                     UpdateDasmAndDump(&pc);
522                 else
523                 {
524                     if (current_bank[hotspot] < max_bank[hotspot])
525                     {
526                         int mod=0;
527 
528                         if (hotspot==2)  /* espace donn�es */
529                             mod=2;
530 
531                         current_bank[hotspot]++;
532 
533                         for (i=0; i<bank_size[hotspot]; i++)
534                             mempager.segment[bank_loc[hotspot]+i]=
535                              mapper_table[hotspot][current_bank[hotspot]]+(i^mod)*0x1000;
536 
537                         SetHotspot(hotspot);
538                     }
539                 }
540                 break;
541 
542             case '-': /* banque pr�c�dente */
543                 if (hotspot != 4)
544                 {
545                     if (current_bank[hotspot] > 0)
546                     {
547                         int mod=0;
548 
549                         if (hotspot==2)  /* espace donn�es */
550                             mod=2;
551 
552                         current_bank[hotspot]--;
553 
554                         for (i=0; i<bank_size[hotspot]; i++)
555                             mempager.segment[bank_loc[hotspot]+i]=
556                              mapper_table[hotspot][current_bank[hotspot]]+(i^mod)*0x1000;
557 
558                         SetHotspot(hotspot);
559                     }
560                 }
561                 break;
562 
563             case 'e': /* �dition d'un octet de m�moire */
564             case 'E':
565                 pc=EditMemory();
566                 hotspot=4;
567                 SetHotspot(hotspot);
568                 break;
569 
570             case 'a': /* saut � l'adresse voulue */
571             case 'A':
572                 ReadAddress(&pc,DIALOG_POS_X,DIALOG_POS_Y,is_fr?"Nouvelle adresse: ":"New address: ");
573                 DeleteBox(DIALOG_POS_X,DIALOG_POS_Y,40,DIALOG_POS_Y);
574                 UpdateDasmAndDump(&pc);
575                 hotspot=4;
576                 SetHotspot(hotspot);
577                 break;
578 
579             case 'c': /* chargement d'une portion m�moire */
580             case 'C':
581                 pc=LoadMemory();
582                 hotspot=4;
583                 SetHotspot(hotspot);
584                 break;
585 
586             case 's': /* sauvegarde d'une portion m�moire */
587             case 'S':
588                 SaveMemory();
589                 break;
590         } /* end of switch */
591     }
592 
593     /* on restaure l'ancien mapper */
594     for (i=0; i<16; i++)
595         mempager.segment[i]=mapper_orig[i];
596 }
597 
598