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(®s);
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