1 /* MAIN PART OF MONITOR */
2 
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 #include "z80-cpu.h"
9 #include "execute.h"
10 #include "console_token"
11 #include "console.h"
12 #include "regs.h"
13 #include "file.h"
14 #include "asm.h"
15 #include "decode.h"
16 #include "memory.h"
17 #include "ports.h"
18 #include "interrupt.h"
19 #include "mini-display.h"
20 #include "keyboard.h"
21 #include "hash.h"
22 #include "expression.h"
23 #include "hardware/includes"
24 
25 static _ushort MEMP;
26 
27 static char *msg1="Z80 monitor V 2.3\n(c)1999-2004 Brainsoft\n";
28 static char *msg2="Z80 monitor (GPL)  " TIME_STAMP;
29 static char _string[257];
30 static char *string= _string+1;
31 static char load_name[256];
32 static char save_name[256];
33 static char proto_name[256];
34 static FILE *stream;
35 
36 static unsigned speed;
37 static int keyboard_disabled;
38 static int current_pc;
39 static int follow;
40 static int row;     /* row for printing next instruction */
41 static _uchar tmp_memory[64];
42 static unsigned long  last_ticks;
43 static unsigned long  breakpt[8];
44 
45 struct info{ char *label; int value; unsigned lineno; };
46 static struct info  *ele;
47 static unsigned  labels, next_label_index;
48 
49 enum
50 { DEFAULT,TOKEN,ADDR,  HOT,GARISH,WARN,  MEMORY,STATUS,HIDDEN };
51 static unsigned char color[] =
52 { WHITE,  GREEN,YELLOW,RED,BRIGHT,YELLOW,BLUE,  PURPLE,GRAY   };
53 
54 #define KEYBOARD_MAP_FILE "keyboard_map"
55 
56 
warning(char * message)57 static void warning(char* message)
58 {
59  static char txt[512];
60 /* c_bell(); */
61  c_goto(0,23);
62  c_setcolor(color[WARN]);
63  sprintf(txt,"%s",message);
64  c_print(txt);
65  usleep(2000000L);
66  c_setcolor(color[DEFAULT]);
67  c_clear(0,23,79,23);
68 }
69 
70 
error_msg(char * line,char * message)71 static void error_msg(char *line,char* message)
72 {
73  static char txt[512];
74  c_bell();
75  c_goto(0,23);
76  c_setcolor(color[HOT]);
77  sprintf(txt,"Error: %s %s",message,line);
78  c_print(txt);
79  usleep(1000000L);
80  c_setcolor(color[DEFAULT]);
81  c_clear(0,23,79,23);
82 }
83 
84 
85 /*** called e.g. from decode(...) in simul.c or compile() defined in asm.c ***/
error(int n,const char * line,char * message)86 void error(int n,const char *line,char* message)
87 {
88  static char txt[512];
89  unsigned char k;
90  n=n;
91  c_bell();
92  c_goto(0,22);
93  c_print(line);
94  c_goto(0,23);
95  c_setcolor(color[HOT]);
96  sprintf(txt,"Error: %s",message);
97  c_print(txt);
98  c_setcolor(color[DEFAULT]);
99  c_print(" hit any key");
100  k=c_getkey();
101  c_clear(0,22,39,22);
102  c_clear(0,23,79,23);
103 }
104 
105 
106 static char
__printable(char c)107 __printable(char c)
108 {
109  return (c>=32&&c<127)?c:'.';
110 }
111 
112 
113 /* prints instruction */
114 void
print(char * str)115 print(char *str)
116 {
117  if (row >= 0)
118  {
119   char txt[256];
120   sprintf(txt," %04x  ",current_pc);
121   c_goto(0,row);
122   c_setcolor(row==12?color[GARISH]:color[ADDR]);
123   c_print(txt);
124   c_setcolor(row==12?color[GARISH]:color[DEFAULT]);
125   c_print(str);
126  }
127  else if (row == -1)
128   fprintf(stream,"%04x %-14s",current_pc,str);
129  else if (row == -2 && (MODE&16))
130   ; /* first pass disassembling */
131  else if (row == -2)
132  { int i;
133    fprintf(stream,"%04x  ",current_pc);
134    for (i=0; i < (PC?PC:65536)-current_pc && i<4; i++)
135       fprintf(stream,"%02x ",(unsigned)memory_at((_ushort)(current_pc+i)));
136    for (;i<4;i++)
137       fprintf(stream,"   ");
138    for (i=0; i < (PC?PC:65536)-current_pc && i<4; i++)
139    {  unsigned char  m=memory_at((_ushort)(current_pc+i));
140       fprintf(stream,"%c",(m>=32&&m<127?m:' '));
141    }
142    for (;i<4;i++)
143       fprintf(stream," ");
144    if (MODE&8)  /* second pass disassembling */
145    {  while (next_label_index < labels && ele[next_label_index].value < current_pc)
146          next_label_index++;
147       if (next_label_index >= labels || ele[next_label_index].value > current_pc)
148          fprintf(stream,"        ");
149       else
150       {
151          fprintf(stream," %5s: ",ele[next_label_index].label);
152          ele[next_label_index].label[0]=0;
153          next_label_index += 1;
154          while (next_label_index < labels &&
155                 ele[next_label_index].value == ele[next_label_index-1].value)
156             ele[next_label_index].label[0]=0;
157       }
158    }
159    fprintf(stream," %-s",str);
160  }
161 }
162 
163 
164 static void
__print_r16(int x,int y,char * t,int R)165 __print_r16(int x,int y,char *t,int R)
166 {
167  char txt[256];
168  c_goto(x,y);
169  sprintf(txt,"%s=",t);
170  c_setcolor(color[TOKEN]);
171  c_print(txt);
172  sprintf(txt,"0x%04x %05u",R,R);
173  c_setcolor(color[DEFAULT]);
174  c_print(txt);
175 }
176 
177 
178 static void
__print_rr(int x,int y,char * t,int R)179 __print_rr(int x,int y,char *t,int R)
180 {
181  char txt[256];
182  c_goto(x,y);
183  sprintf(txt,"%s=",t);
184  c_setcolor(color[TOKEN]);
185  c_print(txt);
186  sprintf(txt,"x%02xx%02x %05u",R>>8&255,R&255,R);
187  c_setcolor(color[DEFAULT]);
188  c_print(txt);
189 }
190 
191 
192 static void
tobin(char * s,_uchar x)193 tobin(char *s,_uchar x)
194 {
195  int a;
196  for (a=0;a<8;a++)
197   s[7-a]=((x&(1<<a))>>a)?'1':'0';
198  s[8]=0;
199 }
200 
201 
202 static void
__print_x(int x,int y,char * t,_uchar R)203 __print_x(int x,int y,char *t,_uchar R)
204 {
205  char txt[256];
206  char b[256];
207  tobin(b,R);
208  c_goto(x,y);
209  sprintf(txt,"%s=",t);
210  c_setcolor(color[TOKEN]);
211  c_print(txt);
212  sprintf(txt,"x%02x (%s)",(unsigned)R,b);
213  c_setcolor(color[DEFAULT]);
214  c_print(txt);
215 }
216 
217 
218 static void
__print_r(int x,int y,char * t,_uchar R)219 __print_r(int x,int y,char *t,_uchar R)
220 {
221  char txt[256];
222  char b[256];
223  tobin(b,R);
224  c_goto(x,y);
225  c_setcolor(color[TOKEN]);
226  sprintf(txt,"%s=",t);
227  c_print(txt);
228  c_setcolor(color[DEFAULT]);
229  sprintf(txt,"%03d",R);
230  c_print(txt);
231  c_setcolor(color[MEMORY]);
232  sprintf(txt,"%c",__printable(R));
233  c_print(txt);
234  c_setcolor(color[DEFAULT]);
235  sprintf(txt,"(%s)",b);
236  c_print(txt);
237 }
238 
239 
240 static void
print_generell_regs(void)241 print_generell_regs(void)
242 {
243  __print_rr(46,2,"AF",(A<<8)+F);
244  __print_rr(46,3,"BC",(B<<8)+C);
245  __print_rr(46,4,"DE",(D<<8)+E);
246  __print_rr(46,5,"HL",(H<<8)+L);
247 
248  __print_rr(63,2,"AF'",(A_<<8)+F_);
249  __print_rr(63,3,"BC'",(B_<<8)+C_);
250  __print_rr(63,4,"DE'",(D_<<8)+E_);
251  __print_rr(63,5,"HL'",(H_<<8)+L_);
252 
253  __print_r(46,12,"A",A);
254  __print_r(46,13,"F",F);
255  __print_r(46,14,"B",B);
256  __print_r(46,15,"C",C);
257  __print_r(46,16,"D",D);
258  __print_r(46,17,"E",E);
259  __print_r(46,18,"H",H);
260  __print_r(46,19,"L",L);
261 
262  __print_r(63,12,"A'",A_);
263  __print_r(63,13,"F'",F_);
264  __print_r(63,14,"B'",B_);
265  __print_r(63,15,"C'",C_);
266  __print_r(63,16,"D'",D_);
267  __print_r(63,17,"E'",E_);
268  __print_r(63,18,"H'",H_);
269  __print_r(63,19,"L'",L_);
270 
271 }
272 
273 
274 static void
print_index_regs(void)275 print_index_regs(void)
276 {
277  __print_r16(56,7,"IX",IX);
278  __print_r16(56,8,"IY",IY);
279 }
280 
281 
282 static void
print_sp_and_pc(void)283 print_sp_and_pc(void)
284 {
285  __print_r16(56,9,"SP",SP);
286  __print_r16(56,10,"PC",PC);
287 }
288 
289 
290 static void
print_special_regs(void)291 print_special_regs(void)
292 {
293  __print_x(47,21,"I",I);
294  __print_x(64,21,"R",R);
295 }
296 
297 
298 static void
print_regs(void)299 print_regs(void)
300 {
301  print_generell_regs();
302  print_index_regs();
303  print_sp_and_pc();
304  print_special_regs();
305 }
306 
307 
308 static void
print_flags(void)309 print_flags(void)
310 {
311  char txt[256];
312 
313  c_goto(45,0);
314  c_setcolor(is_flag(F_C)?color[GARISH]:color[DEFAULT]);
315  c_print(is_flag(F_C)?" C ":"NC ");
316  c_setcolor(is_flag(F_Z)?color[GARISH]:color[DEFAULT]);
317  c_print(is_flag(F_Z)?" Z ":"NZ ");
318  c_setcolor(is_flag(F_M)?color[GARISH]:color[DEFAULT]);
319  c_print(is_flag(F_P)?" P ":" M ");
320  c_setcolor(is_flag(F_PE)?color[GARISH]:color[DEFAULT]);
321  c_print(is_flag(F_PE)?"PE ":"PO ");
322  c_setcolor(is_flag(F_H)?color[GARISH]:color[DEFAULT]);
323  c_print(is_flag(F_H)?" H ":"NH ");
324  c_setcolor(is_flag(F_N)?color[GARISH]:color[DEFAULT]);
325  c_print(is_flag(F_N)?" N ":"NN ");
326 
327  c_setcolor(color[TOKEN]);
328  c_goto(73,0);
329  c_print("IM=");
330  sprintf(txt,"%d",IM);
331  c_setcolor(color[DEFAULT]);
332  c_goto(76,0);
333  c_print(txt);
334 
335  c_setcolor(color[TOKEN]);
336  c_goto(65,0);
337  c_print("IFF=");
338  c_goto(69,0);
339  c_setcolor(IFF1?color[GARISH]:color[DEFAULT]);
340  c_print(IFF1?"EI":"DI");
341  c_setcolor(color[DEFAULT]);
342 
343 }
344 
345 
346 static void
print_instr(void)347 print_instr(void)
348 {
349  _ushort old_pc=PC;
350 
351  c_clear(7,12,22,22);
352  for (row=12;row<22;row++)
353  {
354   current_pc=PC;
355   decode(0,0);
356  }
357  c_goto(7,11);
358  c_setcolor(color[TOKEN]);
359  c_print("MNEMONIC");
360  c_setcolor(color[HIDDEN]);
361  if ((MODE&3)==1) c_print("d");
362  else if ((MODE&3)==2)  c_print("h");
363  else if ((MODE&3)==3)  c_print("x");
364  else c_print(" ");
365  if ((MODE&12)==4) c_print("a");
366  else if ((MODE&12)==8)  c_print("l");
367  else if ((MODE&12)==12)  c_print("L");
368  else c_print("r");
369  c_goto(0,12);
370  c_setcolor(color[GARISH]);
371  c_print(">");
372  c_setcolor(color[DEFAULT]);
373  PC=old_pc;
374 }
375 
376 
377 static void
print_stack(void)378 print_stack(void)
379 {
380  char txt[256];
381  _ushort b,c,d;
382  int r,a;
383 
384  c_goto(30,11);
385  c_setcolor(color[TOKEN]);
386  c_print("STACK");
387  c_setcolor(color[DEFAULT]);
388  for (r=12,a=SP+12;a>=SP-6;a-=2,r++)
389  {
390   c=a&65535;
391   d=(a+1)&65535;
392   b=memory_at(c)|(memory_at(d)<<8);
393   sprintf(txt,"%04x  ",c);
394   c_goto(24,r);
395   c_setcolor(r==18?color[GARISH]:color[ADDR]);
396   c_print(txt);
397   c_setcolor(r==18?color[GARISH]:color[DEFAULT]);
398   sprintf(txt,"%05d %04x ",b,b);
399   c_print(txt);
400   sprintf(txt,"%c%c",__printable(memory_at(d)),__printable(memory_at(c)));
401   c_setcolor(color[MEMORY]);
402   c_print(txt);
403   c_setcolor(color[DEFAULT]);
404  }
405  c_goto(23,18);
406  c_setcolor(color[GARISH]);
407  c_print(">");
408  c_setcolor(color[DEFAULT]);
409 }
410 
411 
412 static void
print_mem(void)413 print_mem(void)
414 {
415  char txt[256];
416  _ushort a;
417  int r,c;
418  _ushort memp;
419 
420  if (follow)memp=PC;
421  else memp=MEMP;
422 
423  c_goto(14,0);
424  c_setcolor(color[TOKEN]);
425  c_print("MEMORY");
426  for (r=0,c=memp;c<memp+80;c+=8,r++)
427  {_ushort b;
428   a=c&65535;
429   sprintf(txt,"%04x  ",a);
430   c_goto(0,1+r);
431   c_setcolor(color[ADDR]);
432   c_print(txt);
433   c_setcolor(color[DEFAULT]);
434   for (b=0;b<8;b++)
435      sprintf(txt+3*b,"%02x ",(unsigned)memory_at(a+b));
436   c_print(txt);
437   for (b=0;b<8;b++)
438      sprintf(txt+b,"%c", __printable(memory_at(a+b)) );
439   c_setcolor(color[MEMORY]);
440   c_print(txt);
441   c_setcolor(color[DEFAULT]);
442  }
443 }
444 
445 
446 static void
print_speed(void)447 print_speed(void)
448 {
449  c_setcolor(color[STATUS]);
450  c_goto(11,23);
451  if (speed)
452  {  char txt[12];
453     double  freq= speed*0.0025;
454     if (freq < 1.0)
455        sprintf(txt," %4.0f kHz ",speed*2.5);
456     else if (freq < 10.0)
457        sprintf(txt,"%5.3f MHz ",freq);
458     else
459        sprintf(txt,"%5.2f MHz ",freq);
460     c_print(txt);
461  }
462  else
463     c_print("      ");
464  c_setcolor(color[DEFAULT]);
465 }
466 
467 
468 static void
print_status(void)469 print_status(void)
470 {
471  c_goto(0,23);
472  c_setcolor(color[STATUS]);
473  c_print(follow?"FOLLOW ":"       ");
474  c_goto(7,23);
475  c_print(!cpu_is_in_disassemble?"RUN ":"    ");
476  print_speed();
477  c_setcolor(color[STATUS]);
478  c_goto(20,23);
479  c_print(stream?"PROTO ":"      ");
480  c_setcolor(color[HOT]);
481  c_goto(26,23);
482  c_print(keyboard_disabled?"NOKEYS":"      ");
483  c_setcolor(color[DEFAULT]);
484 }
485 
486 
487 void
print_ticks(void)488 print_ticks(void)
489 {
490  char txt[16];
491  sprintf(txt,"%10lu",ticks);
492  c_setcolor(color[DEFAULT]);
493  c_goto(41,10);
494  c_print(txt);
495  c_setcolor(cpu_pin[busack]?color[HOT]:color[TOKEN]);
496  c_print(" T");
497  last_ticks=ticks;
498  sprintf(txt,"%10lu",cycles);
499  c_setcolor(color[DEFAULT]);
500  c_goto(41,8);
501  c_print(txt);
502  c_setcolor(color[TOKEN]);
503  c_print(" M");
504 }
505 
506 
507 static void
print_breaks(void)508 print_breaks(void)
509 {
510  int i,j;
511  char txt[16];
512  for (j=i=0;i<8;i++)
513     if (breakpt[i]>>16)
514     {
515       sprintf(txt,"%4lu",breakpt[i]>>16);
516       c_setcolor(color[HOT]);
517       c_goto(10*j,22);
518       c_print(txt);
519       sprintf(txt,"%04x",(unsigned)breakpt[i]&65535);
520       c_setcolor(color[ADDR]);
521       c_print(txt);
522       j++;
523       c_setcolor(color[DEFAULT]);
524     }
525 }
526 
527 
print_halt(void)528 static void print_halt(void)
529 {
530    c_setcolor(color[HOT]);
531    c_goto(78,0);
532    c_print(cpu_pin[halt]?"H":" ");
533    c_setcolor(color[DEFAULT]);
534 }
535 
536 
537 /* draw screen */
538 static void
print_panel(void)539 print_panel(void)
540 {
541  print_regs();
542  print_flags();
543  print_instr();
544  print_stack();
545  print_mem();
546  print_status();
547  print_ticks();
548  print_breaks();
549  print_halt();
550 }
551 
552 
553 static void
show_keys(void)554 show_keys(void)
555 {
556  int i=0;
557  c_cls();
558 #include  "help_layout"
559  c_goto(0,23);
560  c_print("PRESS ANY KEY TO QUIT HELP.");
561  c_goto(79-strlen(msg2),23);
562  c_print(msg2);
563  c_getkey();
564  c_cls();
565 }
566 
567 
568 /* clear all general purpos registers and IX, IY, and SP */
569 static void
clear_user_regs(void)570 clear_user_regs(void)
571 {
572  A=0;B=0;C=0;D=0;E=0;F=0;H=0;L=0;
573  A_=0;B_=0;C_=0;D_=0;E_=0;F_=0;H_=0;L_=0;
574  SP=0;IX=0;IY=0;
575 }
576 
577 
578 /* put SP to 0xFFFC and store 4 bytes starting at 0xFFFC */
579 static void
stack_halt(void)580 stack_halt(void)
581 {
582  _ushort d;
583  SP=0xfffc;
584  d=SP+2;
585  write_memo(SP, d&255);
586  write_memo(SP+1, d>>8);
587  write_memo(SP+2,0xf3); /* DI */
588  write_memo(SP+3,0x76); /* HALT */
589 }
590 
591 
592 static void
ask_flag(void)593 ask_flag(void)
594 {
595  unsigned char c;
596  c_clear(0,23,79,23);
597  c_goto(0,23);
598  c_print("Toggle flag: Zero, Carry, Parity, Sign, H, N?");
599  c=c_getkey();
600  switch(c)
601  {
602   case 'z':
603   case 'Z':
604   set_flag(is_flag(F_Z)?F_NZ:F_Z);
605   break;
606 
607   case 'c':
608   case 'C':
609   set_flag(is_flag(F_C)?F_NC:F_C);
610   break;
611 
612   case 'p':
613   case 'P':
614   set_flag(is_flag(F_PE)?F_PO:F_PE);
615   break;
616 
617   case 's':
618   case 'S':
619   set_flag(is_flag(F_M)?F_P:F_M);
620   break;
621 
622   case 'h':
623   case 'H':
624   set_flag(is_flag(F_H)?F_NH:F_H);
625   break;
626 
627   case 'n':
628   case 'N':
629   set_flag(is_flag(F_N)?F_NN:F_N);
630   break;
631 
632   default:
633   c_bell();
634   break;
635  }
636  c_clear(0,23,79,23);
637 }
638 
639 
640 /* reads string from input (will be stored in pointer), writes prompt message */
641 /* string cannot be longer than max_len */
642 /* return value: 0=ok, 1=escape pressed */
643 static int
ask_str(char * pointer,char * message,int max_len)644 ask_str(char *pointer,char *message,int max_len)
645 {
646  unsigned char c;
647  int a=strlen(pointer),l=strlen(message);
648 
649  c_clear(0,23,79,23);
650  c_cursor(C_NORMAL);
651  c_goto(0,23);
652  c_setcolor(color[GARISH]);
653  c_print(message);
654  c_setcolor(color[DEFAULT]);
655  c_print(pointer);
656  while(1)
657  {
658   c=c_getkey();
659   if (c==K_ESCAPE)
660   {
661    pointer[0]=0;
662    c_clear(0,23,79,23);
663    c_cursor(C_HIDE);
664    return 1;
665   }
666   if (c==K_ENTER)
667   {
668    c_clear(0,23,79,23);
669    c_cursor(C_HIDE);
670    return 0;
671   }
672   if (c==K_BACKSPACE&&a)
673   {
674    a--;
675    pointer[a]=0;
676    c_clear(l+strlen(pointer),23,79,23);
677    c_goto(l+strlen(pointer),23);
678    continue;
679   }
680   if (c>=32&&a<max_len)
681   {
682    pointer[a]=c;   /* do charu se dava unsigned char */
683    a++;
684    pointer[a]=0;
685    c_goto(l,23);
686    c_print(pointer);
687    c_clear(l+strlen(pointer),23,79,23);
688    c_goto(l+strlen(pointer),23);
689   }
690  }
691 }
692 
693 
694 /* tries to convert a string to an unsigned number */
695 /* on error returns ~0 */
convert_to_uns(char * txt)696 static unsigned  convert_to_uns(char *txt)
697 {
698  unsigned  i, j, val;
699  for (i=0;txt[i]==' '||txt[i]=='\t';i++);
700  if (!txt[i] || txt[i]=='+' || txt[i]=='-')  return ~0;
701  j=test_number(txt+i,&val); /* Single character-representation '?' is allowed */
702  if (!j)  return ~0;
703  return val;
704 }
705 
706 
707 /* reads a non negative integer from input */
708 /* on escape or error returns ~0 */
709 static unsigned
ask(char * str,unsigned init_val)710 ask(char *str,unsigned init_val)
711 {
712  static char txt[256];
713 
714  if (init_val)sprintf(txt,"%u",init_val);
715  else txt[0]=0;
716  if (ask_str(txt,str,16))return ~0;
717  return  convert_to_uns(txt);
718 }
719 
720 
721 /* reads a non negative integer from input */
722 /* on escape or error returns ~0 */
723 static unsigned
ask_x(char * str,unsigned init_val)724 ask_x(char *str,unsigned init_val)
725 {
726  static char txt[256];
727 
728  if (init_val)sprintf(txt,"0x%x",init_val);
729  else txt[0]=0;
730  if (ask_str(txt,str,16))return ~0;
731  return  convert_to_uns(txt);
732 }
733 
734 
735 static void
ask_general_16_register(char * prompt,_uchar * high,_uchar * low)736 ask_general_16_register(char *prompt, _uchar *high, _uchar *low)
737 { unsigned x;
738   x=ask(prompt,*high<<8|*low);
739   if (x>65535)
740   { c_bell();print_status(); }
741   else
742   { *high= x>>8;
743     *low= x&255;
744     cpu_is_in_disassemble=1;
745   }
746 }
747 
748 
749 static void
ask_special_16_register(char * prompt,_ushort * reg16)750 ask_special_16_register(char *prompt, _ushort *reg16)
751 { unsigned x;
752   x=ask(prompt,*reg16);
753   if (x>65535)
754   { c_bell();print_status(); }
755   else
756   { *reg16= x;
757     cpu_is_in_disassemble=1;
758   }
759 }
760 
761 
762 static void
ask_16bit_register(void)763 ask_16bit_register(void)
764 {
765  unsigned char c;
766  c_clear(0,23,79,23);
767  do {
768     c_goto(0,23);
769     c_print("Toggle Register: bc, de, hl, BC, DE, HL, xX, yY, Sp");
770     c=c_getkey();
771     switch(c)
772     {
773        case 'b':  ask_general_16_register("BC=",&B,&C);
774                   break;
775 
776        case 'B':  ask_general_16_register("BC'=",&B_,&C_);
777                   break;
778 
779        case 'd':  ask_general_16_register("DE=",&D,&E);
780                   break;
781 
782        case 'D':  ask_general_16_register("DE'=",&D_,&E_);
783                   break;
784 
785        case 'h':  ask_general_16_register("HL=",&H,&L);
786                   break;
787 
788        case 'H':  ask_general_16_register("HL'=",&H_,&L_);
789                   break;
790 
791        case 'x': case 'X':
792                   ask_special_16_register("IX=",&IX);
793                   break;
794 
795        case 'y': case 'Y':
796                   ask_special_16_register("IY=",&IY);
797                   break;
798 
799        case 's': case 'S':
800                   ask_special_16_register("SP=",&SP);
801                   break;
802 
803        case K_ENTER:
804                   break;
805 
806        default:   c_bell();
807                   break;
808     }
809     print_regs();
810  } while (c != K_ENTER);
811  c_clear(0,23,79,23);
812 }
813 
814 
815 static void
ask_8bit_register(char * prompt,_uchar * reg8)816 ask_8bit_register(char *prompt, _uchar *reg8)
817 {
818   unsigned x=ask(prompt,*reg8);
819   if (x>255)
820   { c_bell();print_status(); }
821   else
822   { *reg8= x;
823     cpu_is_in_disassemble=1;
824   }
825 }
826 
827 
828 static void
ask_register(void)829 ask_register(void)
830 {
831  unsigned char c;
832  c_clear(0,23,79,23);
833  do {
834     c_goto(0,23);
835     c_print("Toggle Register: a, f, b, c, d, e, h, l, "
836                              "A, F, B, C, D, E, H, L, =, I, R");
837     c=c_getkey();
838     switch(c)
839     {
840        case '=':  ask_16bit_register();
841                   break;
842 
843        case 'a':  ask_8bit_register("A=",&A);
844                   break;
845 
846        case 'A':  ask_8bit_register("A'=",&A_);
847                   break;
848 
849        case 'f':  ask_8bit_register("F=",&F);
850                   print_flags();
851                   break;
852 
853        case 'F':  ask_8bit_register("F'=",&F_);
854                   print_flags();
855                   break;
856 
857        case 'b':  ask_8bit_register("B=",&B);
858                   break;
859 
860        case 'B':  ask_8bit_register("B'=",&B_);
861                   break;
862 
863        case 'c':  ask_8bit_register("C=",&C);
864                   break;
865 
866        case 'C':  ask_8bit_register("C'=",&C_);
867                   break;
868 
869        case 'd':  ask_8bit_register("D=",&D);
870                   break;
871 
872        case 'D':  ask_8bit_register("D'=",&D_);
873                   break;
874 
875        case 'e':  ask_8bit_register("E=",&E);
876                   break;
877 
878        case 'E':  ask_8bit_register("E'=",&E_);
879                   break;
880 
881        case 'h':  ask_8bit_register("H=",&H);
882                   break;
883 
884        case 'H':  ask_8bit_register("H'=",&H_);
885                   break;
886 
887        case 'l':  ask_8bit_register("L=",&L);
888                   break;
889 
890        case 'L':  ask_8bit_register("L'=",&L_);
891                   break;
892 
893        case 'I':  ask_8bit_register("I=",&I);
894                   break;
895 
896        case 'R':  ask_8bit_register("R=",&R);
897                   break;
898 
899        case K_ENTER:
900                   break;
901 
902        default:   c_bell();
903                   break;
904     }
905     print_regs();
906  } while (c != K_ENTER);
907  c_clear(0,23,79,23);
908 }
909 
910 
911 static void
protocol(void)912 protocol(void)
913 {
914   row = -1;
915   current_pc=PC;
916   decode(0,0);
917   fprintf(stream,"%c%c%c%c ",(is_flag(F_C)?'C':'.'),(is_flag(F_Z)?'Z':'.')
918                             ,(is_flag(F_M)?'-':'+'),(is_flag(F_PE)?'e':'o'));
919   fprintf(stream,"%02x %02x %02x %02x %02x %02x %02x ",A,B,C,D,E,H,L);
920   fprintf(stream,"%02x %02x %02x %02x %02x %02x %02x ",A_,B_,C_,D_,E_,H_,L_);
921   fprintf(stream,"%04x %04x %04x\n",IX,IY,SP);
922   fflush(stream);
923   PC=current_pc;
924 }
925 
926 
finish(int signo)927 void finish(int signo)
928 {
929    c_shutdown();
930    exit(-signo);
931 }
932 
933 
compare_addr(const struct info * left,const struct info * right)934 static int compare_addr(const struct info *left, const struct info *right)
935 {
936    return  left->value == right->value ? 0 : left->value < right->value ? -1:1;
937 }
938 
939 
940 /*-------------------------------MAIN-----------------------------------------*/
941 int
main(int argc,char ** argv)942 main(int argc,char **argv)
943 {
944  unsigned char c, rom_path[256], bank_mapping_descr[128], emu=0;
945  unsigned short old_pc;
946  int b,a,s;
947  unsigned short start;
948  unsigned x;
949 
950  string[-1]=' ';  /* that is ok! (prevents any label recognation in compile) */
951  strcpy(rom_path,".");
952  strcpy(bank_mapping_descr,"");
953 
954  for (b=s=1;s<argc && *argv[s]=='-';s++,b=1)
955  {
956     if (!*(argv[s]+b))
957        continue;
958     else if (*(argv[s]+b)=='E')
959        emu=1;
960     else if (*(argv[s]+b)=='B')
961     {  if (s+1>=argc || 1!=sscanf(argv[s+1],"%127s",bank_mapping_descr))
962           fprintf(stderr,"Error: option -B needs a filename argument\n");
963        else
964           b=0, s++;
965     }
966     else if (*(argv[s]+b)=='R')
967     {  if (s+1>=argc || 1!=sscanf(argv[s+1],"%255s",rom_path))
968           fprintf(stderr,"Error: option -R needs a path argument\n");
969        else
970           b=0, s++;
971     }
972     else if (*(argv[s]+b)=='h' || *(argv[s]+b)=='?')
973     {
974        printf("%s\n",msg1);
975        printf("Usage: z80-mon [-h] [-E] [-R path] [<filename> ...]\n");
976        return 0;
977     }
978  }
979  clear_memory();
980  MEMP=0;
981 
982  for (b=s;b<argc;b++)
983  {
984   stream=fopen(argv[b],"rb");
985   if (!stream){fprintf(stderr,"Error: Can't read file \"%s\".\n",argv[b]);return(1);}
986   if (read_header(stream,&start,&x)){fprintf(stderr,"Error: \"%s\" is not a Z80 ASM file.\n",argv[b]);return(1);}
987   dma_write(start,x,stream);
988   MEMP=start;
989   fclose(stream);
990   stream=0;
991  }
992 
993  c_init(BLACK); /** for DEBUG set it to WHITE **/
994  c_cursor(C_HIDE);
995  define_scroll_line(39,23,40);
996  init_keyboard_map(KEYBOARD_MAP_FILE);
997  if(init_ports())
998     warning("asynchron buffered CPU port access impossible");
999  else if (*bank_mapping_descr)
1000     init_banks(rom_path,bank_mapping_descr);
1001  if (emu)
1002  {  init_cpu(".CPU");
1003     cpu_is_in_disassemble=0;
1004     speed= 1<<12;
1005     keyboard_disabled=1;
1006     follow=0;
1007  }
1008  else
1009  {
1010 #ifdef Z80_CTC
1011     if (init_ctc())
1012        error_msg("asynchron CTC port access denied","system:");
1013 #endif
1014 #ifdef LOGIC_ANALYZER
1015     reset_analyzer(".bus_proto");
1016 #endif
1017     reset_cpu();
1018     follow=1;
1019  }
1020  last_ticks=0;
1021  io_address=NULL;
1022 
1023  disable_pseudo=0;
1024  init_interrupt_handling();
1025  print_panel();
1026 
1027  while (1)
1028  {
1029   if (cpu_pin[halt] && !IFF1)
1030   { if (!cpu_is_in_disassemble && emu)
1031     {  dump_cpu(".CPU");
1032        break;
1033     }
1034     else
1035        cpu_is_in_disassemble= 1;
1036   }
1037   if (cpu_pin[busrq])
1038      /* don't run CPU */ ;
1039   else if (cpu_is_in_disassemble)
1040      usleep(20000);
1041   else
1042   {
1043    for (a=0;a<8;a++)
1044       if ((breakpt[a]&65535) == PC)
1045          if (breakpt[a]>>16)
1046          {  breakpt[a] -= 65536;
1047             print_breaks();
1048             break;
1049          }
1050    if (a == 8 || breakpt[a]>>16)
1051    { if (stream)protocol();
1052      decode(0,1);  /* here we decode and execute the current opcode */
1053      if (cpu_is_in_disassemble || speed <= 1) print_panel();
1054      else if (speed==4)
1055      {print_regs();print_ticks();print_halt();print_flags();}
1056      else
1057      { if (ticks>=last_ticks+speed)
1058        print_sp_and_pc(),print_ticks(),print_halt();
1059      }
1060    }
1061    else
1062    { cpu_is_in_disassemble=1; print_panel();
1063    }
1064   }
1065   if (cpu_pin[busrq])
1066     c=no_key_code; /* no keyboard input possible */
1067   else
1068   {
1069     if (cpu_is_in_disassemble)  keyboard_disabled=0;
1070     c = !keyboard_disabled && c_kbhit() ? c_getkey() : no_key_code;
1071     if (cpu_is_in_disassemble && c != no_key_code)  set_cpu_pin(halt,0);
1072   }
1073   if (c != no_key_code)
1074   switch(c)
1075   {
1076    case '?':
1077    case 'h':
1078    case 'H':
1079    show_keys();
1080    print_panel();
1081    break;
1082 
1083    /* case 'q':  too dangerous */
1084    case 'Q': /* quit */
1085    c_shutdown();
1086    return 0;
1087 
1088    case 'x':
1089    case 'X':
1090    string[0]=0;
1091    ask_str(string,"Execute instruction: ",40);
1092    cpu_is_in_x_mode= 1;
1093    io_address=tmp_memory;
1094    set_cpu_pin(iorq,1);
1095    old_pc=PC;
1096    set_start_address(0);
1097    disable_pseudo=1;
1098    if (!compile(string-1))
1099    {  disable_pseudo=0;
1100       PC=0;
1101       decode(&old_pc,1);
1102    }
1103    else
1104       disable_pseudo=0;
1105    set_cpu_pin(iorq,0);
1106    io_address=NULL;
1107    cpu_is_in_x_mode= 0;
1108    print_panel();
1109    break;
1110 
1111    case ' ':  /* move to next instruction */
1112    decode(0,2);
1113    print_panel();
1114    break;
1115 
1116    case K_BACKSPACE:  /* exec one instruction */
1117    if (!cpu_is_in_disassemble) break;
1118    if (stream)protocol();
1119    decode(0,1);
1120    print_panel();
1121    break;
1122 
1123    case 'f': /* toggle flag */
1124    case 'F':
1125    ask_flag();
1126    print_panel();
1127    break;
1128 
1129    case '=':
1130    ask_register();
1131    break;
1132 
1133    case 's': /* change SP */
1134    x=ask_x("SP=",SP);
1135    if (x>65535){c_bell();print_status();break;}
1136    cpu_is_in_disassemble=1;
1137    SP=x;
1138    print_panel();
1139    break;
1140 
1141    case '+': /* speed */
1142    if (!speed)  speed = 1;
1143    else if (speed < 15000)  speed <<=2;
1144    print_speed();
1145    break;
1146 
1147    case '-': /* speed */
1148    if (speed > 1)  speed >>= 2;
1149    else if (cpu_is_in_disassemble) speed =0;
1150    print_speed();
1151    break;
1152 
1153    case 'r': /* toggle cpu_wait/run */
1154    case 'R':
1155    if (!cpu_pin[halt] || c=='R') cpu_is_in_disassemble= !cpu_is_in_disassemble;
1156    if (!cpu_is_in_disassemble && !speed) speed=1;
1157    print_panel();
1158    break;
1159 
1160    case 'i': /* change IM */
1161    case 'I':
1162    IM++;
1163    IM%=3;
1164    print_panel();
1165    break;
1166 
1167    case 't': /* toggle disassembling numbers */
1168    /* 0:  default,  1: decimal, 2: hexadecimal, 3: hexadecimal with prefix */
1169    MODE= (MODE&~3) | ((MODE&3)+1 &3);
1170    print_panel();
1171    break;
1172 
1173    case 'j': /* toggle disassembling of address displacements (jr/djnz) */
1174    /* 0:  relative, 4: absolute 4 digit hexadecimal, 8,12: K-labels,V-labels */
1175    MODE= (MODE&~12) | ((MODE&12)+4 &12);
1176    print_panel();
1177    break;
1178 
1179    case '.': /* enter instruction */
1180    set_start_address(MEMP);
1181    do {
1182    sprintf(string,"0x%04x: ",MEMP);
1183    if (ask_str(string,"Put instruction into memory: ",40))break;
1184    compile(string+7);
1185    MEMP=get_current_address();
1186    print_panel();
1187    } while (string[0]);
1188    break;
1189 
1190    case K_ENTER: /* enter instruction */
1191    string[0]=0;
1192    ask_str(string,"Put instruction at PC: ",40);
1193    set_start_address(PC);
1194    compile(string-1);
1195    print_panel();
1196    break;
1197 
1198    case '^': /* toggle EI/DI */
1199    IFF2=IFF1;
1200    IFF1^=1;
1201    print_panel();
1202    break;
1203 
1204    case '*':
1205    clear_user_regs();
1206    reset_banks();
1207 
1208    case '@':
1209 #ifdef Z80_CTC
1210    reset_ctc();
1211 #endif
1212    reset_cpu();
1213    last_ticks=0;
1214    print_panel();
1215    break;
1216 
1217    case '#':
1218    clear_memory();
1219    print_panel();
1220    break;
1221 
1222    case '&': /* init stack_halt */
1223    stack_halt();
1224    print_panel();
1225    break;
1226 
1227    case '$':
1228    last_ticks=0;
1229    set_tics(0);
1230    print_ticks();
1231    break;
1232 
1233    case 'p': /* ask about address */
1234    case 'P':
1235    x=ask_x("PC=",PC);
1236    if (x>65535){c_bell();print_status();break;}
1237    cpu_is_in_disassemble=1;
1238    PC=x;
1239    print_panel();
1240    break;
1241 
1242    case 'u':  /* defm */
1243    case 'U':
1244    sprintf(string,"0x%04x: defm \"",MEMP);
1245    if (ask_str(string+13,string,100))break;
1246    string[strlen(string)]='"';
1247    set_start_address(MEMP);
1248    compile(string+7);
1249    print_panel();
1250    break;
1251 
1252    case 'w':  /* defw */
1253    case 'W':
1254    sprintf(string,"0x%04x: defw ",MEMP);
1255    if (ask_str(string+12,string,64))break;
1256    set_start_address(MEMP);
1257    compile(string+7);
1258    print_panel();
1259    break;
1260 
1261    case 'v':  /* defb */
1262    case 'V':
1263    sprintf(string,"0x%04x: defb ",MEMP);
1264    if (ask_str(string+12,string,64))break;
1265    set_start_address(MEMP);
1266    compile(string+7);
1267    print_panel();
1268    break;
1269 
1270    case K_TAB:
1271    follow^=1;
1272    print_panel();
1273    break;
1274 
1275    case 'm': /* ask about start of memory dump */
1276    case 'M':
1277    follow=0;
1278    x=ask_x("Enter memory address: ",MEMP);
1279    if (x>65535){c_bell();break;}
1280    MEMP=x;
1281    print_panel();
1282    break;
1283 
1284    case 'L':   /* load */
1285    if (ask_str(load_name,"Load file: ",40)){c_bell();print_status();break;}
1286    stream=fopen(load_name,"rb");
1287    if (!stream){stream=0;error_msg(load_name,"Can't read file");print_status();break;}
1288    if (read_header(stream,&start,&x))
1289    {warning("Not a Z80 ASM file"); start=ask("Load to address: ",PC);}
1290    else
1291    { sprintf(string,"starting at 0x%x  %u bytes put",a,x); warning(string); }
1292    dma_write(start,x,stream);
1293    fclose(stream);
1294    stream=0;
1295    print_panel();
1296    break;
1297 
1298    case 'S':   /* save */
1299    if (ask_str(save_name,"Save as: ",40)){c_bell();break;}
1300    x=ask("Length: ",0);
1301    if (PC+x>65536)break;
1302    stream=fopen(save_name,"wb");
1303    if (!stream){stream=0;error_msg(save_name,"Can't write to file ");print_status();break;}
1304    write_header(stream,PC);
1305    dma_read(PC,x,stream);
1306    fclose(stream);
1307    stream=0;
1308    print_panel();
1309    break;
1310 
1311    case 'D': /* dump/disassemble */
1312    if (ask_str(save_name,"Disassemble to: ",40)){c_bell();break;}
1313    sprintf(string,"0x%04x - ",PC);
1314 
1315    x=ask_x(string,0);
1316    if (x>65536 || x < PC)
1317    {error_msg("","memory wrap_around");print_status();break;}
1318    stream=fopen(save_name,"a");
1319    if (!stream)
1320       {stream=0;error_msg(save_name,"Can't append to file");print_status();break;}
1321    row = -2;
1322    if (MODE&8)
1323    {  hash_table_init();
1324       MODE |= 16;
1325    }
1326    old_pc=PC;
1327    while (PC <= x)
1328    {
1329      current_pc=PC;
1330      decode(0,0);
1331      if (!(MODE&16))
1332        fprintf(stream,"\n");
1333      if (PC < current_pc)  break;
1334    }
1335    PC=old_pc;
1336    if (MODE&16)
1337    {  char blanks[32];
1338       for (a=0;a<31;a++)
1339          blanks[a]=' ';
1340       blanks[a]=0;
1341       MODE &= ~16;
1342       if (labels=table_entries())
1343       {  ele= malloc(labels*sizeof(struct info));
1344          for(a=0;next_table_entry(&ele[a].label,&ele[a].value,&ele[a].lineno);a++);
1345          qsort(ele,labels,sizeof(struct info),compare_addr);
1346       }
1347       next_label_index=0;
1348       old_pc=PC;
1349       fprintf(stream,"%sORG 0x%04x\n",blanks,old_pc);
1350       while (PC <= x)
1351       {
1352         current_pc=PC;
1353         decode(0,0);
1354         fprintf(stream,"\n");
1355         if (PC < current_pc)  break;
1356       }
1357       PC=old_pc;
1358    }
1359    if (MODE&8)
1360    {
1361      char blanks[23];
1362      b=0;
1363      for (a=0;(unsigned)a<labels;a++)
1364         if (ele[a].label[0]) b++;
1365      if (labels)
1366         fprintf(stream,";\n; %u Used Labels    %u Undefined Labels:\n",labels-b,b);
1367      if ((unsigned)b<labels)
1368      {  for (a=0;a<23;a++)
1369            blanks[a]=' ';
1370         blanks[a]=0;
1371      }
1372      for (a=0;(unsigned)a<labels;a++)
1373         if (ele[a].label[0])
1374            fprintf(stream,"%s%5s   EQU  0x%04hx\n",blanks,ele[a].label,ele[a].value);
1375      free(ele);
1376      free_hash_table();
1377    }
1378    fclose(stream);
1379    stream=0;
1380    print_panel();
1381    break;
1382 
1383    case '\"': /* protocol execution */
1384    if (ask_str(proto_name,"Protocol into: ",40)){c_bell();break;}
1385    stream=fopen(proto_name,"a");
1386    if (!stream){stream=0;error_msg(proto_name,"Can't append to file");print_status();break;}
1387    fprintf(stream," PC  mnemonic     flags A  B  C  D  E  H  L "
1388                   " A' B' C' D' E' H' L'  IX   IY   SP\n");
1389    print_status();
1390    break;
1391 
1392    case '!':  /* toggle keyboard interrupt */
1393    keyboard_disabled^=1;
1394    print_status();
1395    break;
1396 
1397    case K_ESCAPE:  /* NMI */
1398    nmi_handler();
1399    print_panel();
1400    break;
1401 
1402    case '%': /* ask about break point */
1403    for (a=0;a<8;a++)
1404       if ((breakpt[a] & 0xffff) == MEMP)
1405          break;
1406    if (a==8)
1407    for (a=0;a<8;a++)
1408       if ((breakpt[a]>>16 & 0xffff) == 0)
1409          break;
1410    if (a==8)  {c_bell();break;}
1411    x=ask_x("Enter breakpoint count: ",breakpt[a]>>16);
1412    if (x>65535){c_bell();break;}
1413    breakpt[a] = MEMP | x<<16;
1414    print_breaks();
1415    break;
1416 
1417    MEMP=x;
1418    print_panel();
1419    break;
1420 
1421    default:
1422    c_bell();
1423    break;
1424   }
1425   if (cpu_is_in_disassemble)  emu=0;  /* really finish emulation mode ?? */
1426   if (IFF0)
1427      IFF2=IFF1=1;
1428   else if (cpu_pin[reset])
1429      reset_cpu();
1430   else if (cpu_pin[busrq])
1431      /* don't serve interrupts */ ;
1432   else if (IFF3)
1433      nmi_handler();
1434   else
1435      check_pending_interrupts();
1436  }
1437  c_shutdown();
1438  return 0;
1439 }
1440