/ MCUME_teensy / teensyspeccy / ConDebug.c
ConDebug.c
  1  /** Z80: portable Z80 emulator *******************************/
  2  /**                                                         **/
  3  /**                       ConDebug.c                        **/
  4  /**                                                         **/
  5  /** This file contains a console version of the built-in    **/
  6  /** debugger, using EMULib's Console.c. When -DCONDEBUG is  **/
  7  /** ommitted, ConDebug.c just includes the default command  **/
  8  /** line based debugger (Debug.c).                          **/
  9  /**                                                         **/
 10  /** Copyright (C) Marat Fayzullin 2005-2007                 **/
 11  /**     You are not allowed to distribute this software     **/
 12  /**     commercially. Please, notify me, if you make any    **/
 13  /**     changes to this file.                               **/
 14  /*************************************************************/
 15  #ifdef DEBUG
 16  
 17  #ifndef CONDEBUG
 18  /** Normal DebugZ80() ****************************************/
 19  /** When CONDEBUG #undefined, we use plain command line.    **/
 20  /*************************************************************/
 21  #include "Debug.c"
 22  
 23  #else
 24  /** Console DebugZ80() ***************************************/
 25  /** When CONDEBUG #defined, we use EMULib console.          **/
 26  /*************************************************************/
 27  
 28  #include "Z80.h"
 29  #include "Console.h"
 30  #include <stdlib.h>
 31  
 32  #define DebugZ80 OriginalDebugZ80
 33  #include "Debug.c"
 34  #undef DebugZ80
 35  
 36  #define CLR_BACK   PIXEL(255,255,255)
 37  #define CLR_TEXT   PIXEL(0,0,0)
 38  #define CLR_DIALOG PIXEL(0,100,0)
 39  #define CLR_PC     PIXEL(255,0,0)
 40  #define CLR_SP     PIXEL(0,0,100)
 41  
 42  static byte ChrDump(byte C)
 43  {
 44    return((C>=32)&&(C<128)? C:'.');
 45  }
 46   
 47  /** DebugZ80() ***********************************************/
 48  /** This function should exist if DEBUG is #defined. When   **/
 49  /** Trace!=0, it is called after each command executed by   **/
 50  /** the CPU, and given the Z80 registers.                   **/
 51  /*************************************************************/
 52  byte DebugZ80(Z80 *R)
 53  {
 54    char S[1024];
 55    word A,Addr,ABuf[20];
 56    int J,I,K,X,Y,MemoryDump,DrawWindow,ExitNow;
 57  
 58    /* If we don't have enough screen estate... */
 59    if((VideoW<32*8)||(VideoH<23*8))
 60    {
 61      /* Show warning message */
 62      CONMsg(
 63        -1,-1,-1,-1,PIXEL(255,255,255),PIXEL(255,0,0),
 64        "Error","Screen is\0too small!\0\0"
 65      );
 66      /* Continue emulation */
 67      R->Trace=0;
 68      return(1);
 69    }
 70  
 71    X    = ((VideoW>>3)-32)>>1;
 72    Y    = ((VideoH>>3)-23)>>1;
 73    Addr = R->PC.W;
 74    A    = ~Addr;
 75    K    = 0;
 76    
 77    for(DrawWindow=1,MemoryDump=ExitNow=0;!ExitNow&&VideoImg;)
 78    {
 79      if(DrawWindow)
 80      {
 81        CONWindow(X,Y,32,23,CLR_TEXT,CLR_BACK,"Z80 Debugger");
 82  
 83        sprintf(S,"PC %04X",R->PC.W);
 84        CONSetColor(CLR_BACK,CLR_PC);
 85        CONPrint(X+24,Y+18,S);
 86        sprintf(S,"SP %04X",R->SP.W);
 87        CONSetColor(CLR_BACK,CLR_SP);
 88        CONPrint(X+24,Y+19,S);
 89  
 90        CONSetColor(CLR_TEXT,CLR_BACK);
 91        sprintf(S,
 92          " %c%c%c%c%c%c\n\n"
 93          "AF %04X\nBC %04X\nDE %04X\nHL %04X\nIX %04X\nIY %04X\n\n"
 94          "AF'%04X\nBC'%04X\nDE'%04X\nHL'%04X\n\n"
 95          "IR %02X%02X",
 96          R->AF.B.l&0x80? 'S':'.',R->AF.B.l&0x40? 'Z':'.',R->AF.B.l&0x10? 'H':'.',
 97          R->AF.B.l&0x04? 'P':'.',R->AF.B.l&0x02? 'N':'.',R->AF.B.l&0x01? 'C':'.',
 98          R->AF.W,R->BC.W,R->DE.W,R->HL.W,
 99          R->IX.W,R->IY.W,
100          R->AF1.W,R->BC1.W,R->DE1.W,R->HL1.W,
101          R->I,R->R
102        );
103        CONPrint(X+24,Y+2,S);
104        sprintf(S,
105          "%s %s",
106          R->IFF&0x04? "IM2":R->IFF&0x02? "IM1":"IM0",
107          R->IFF&0x01? "EI":"DI"
108        );
109        CONPrint(X+25,Y+21,S);
110        DrawWindow=0;
111        A=~Addr;
112      }
113  
114      /* If top address has changed... */
115      if(A!=Addr)
116      {
117        /* Clear display */
118        CONBox((X+1)<<3,(Y+2)<<3,23*8,20*8,CLR_BACK);
119  
120        if(MemoryDump)
121        {
122          /* Draw memory dump */
123          for(J=0,A=Addr;J<20;J++,A+=4)
124          {
125            if(A==R->PC.W)      CONSetColor(CLR_BACK,CLR_PC);
126            else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
127            else                CONSetColor(CLR_TEXT,CLR_BACK);
128            sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
129            CONPrint(X+1,Y+J+2,S);
130  
131            CONSetColor(CLR_TEXT,CLR_BACK);
132            sprintf(S,
133              "%02X %02X %02X %02X %c%c%c%c",
134              RdZ80(A),RdZ80(A+1),RdZ80(A+2),RdZ80(A+3),
135              ChrDump(RdZ80(A)),ChrDump(RdZ80(A+1)),
136              ChrDump(RdZ80(A+2)),ChrDump(RdZ80(A+3))
137            );
138            CONPrint(X+7,Y+J+2,S);
139          }
140        }
141        else
142        {
143          /* Draw listing */
144          for(J=0,A=Addr;J<20;J++)
145          {
146            if(A==R->PC.W)      CONSetColor(CLR_BACK,CLR_PC);
147            else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
148            else                CONSetColor(CLR_TEXT,CLR_BACK);
149            sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
150            CONPrint(X+1,Y+J+2,S);
151  
152            ABuf[J]=A;
153            A+=DAsm(S,A);
154  
155            CONSetColor(CLR_TEXT,CLR_BACK);
156            CONPrintN(X+7,Y+J+2,S,23);
157          }
158        }
159  
160        /* Display redrawn */
161        A=Addr;
162      }
163  
164      /* Draw pointer */
165      CONChar(X+6,Y+K+2,CON_ARROW);
166  
167      /* Show screen buffer */
168      ShowVideo();
169  
170      /* Get key code */
171      I=WaitKey();
172  
173      /* Clear pointer */
174      CONChar(X+6,Y+K+2,' ');
175  
176      /* Get and process key code */
177      switch(I)
178      {
179        case 'H':
180          CONMsg(
181            -1,-1,-1,-1,
182            CLR_BACK,CLR_DIALOG,
183            "Debugger Help",
184            "ENTER - Execute next opcode\0"
185            "   UP - Previous opcode\0"
186            " DOWN - Next opcode\0"
187            " LEFT - Page up\0"
188            "RIGHT - Page down\0"
189            "    H - This help page\0"
190            "    G - Go to address\0"
191            "    D - Disassembler view\0"
192            "    M - Memory dump view\0"
193            "    S - Show stack\0"
194            "    J - Jump to cursor\0"
195            "    R - Run to cursor\0"
196            "    C - Continue execution\0"
197            "    Q - Quit emulator\0"
198          );
199          DrawWindow=1;
200          break;
201        case CON_UP:
202          if(K) --K;
203          else
204            if(MemoryDump) Addr-=4;
205            else for(--Addr;Addr+DAsm(S,Addr)>A;--Addr);
206          break;
207        case CON_DOWN:
208          if(K<19) ++K;
209          else
210            if(MemoryDump) Addr+=4;
211            else Addr+=DAsm(S,Addr);
212          break;
213        case CON_LEFT:
214          if(MemoryDump)
215            Addr-=4*20;
216          else
217          {
218            for(I=20,Addr=~A;(Addr>A)||((A^Addr)&~Addr&0x8000);++I)
219              for(J=0,Addr=A-I;J<20;++J) Addr+=DAsm(S,Addr);
220            Addr=A-I+1;
221          }
222          break; 
223        case CON_RIGHT:
224          if(MemoryDump)
225            Addr+=4*20;
226          else
227            for(J=0;J<20;++J) Addr+=DAsm(S,Addr);
228          break;
229        case CON_OK:
230          ExitNow=1;
231          break;
232        case 'Q':
233          return(0);
234        case CON_EXIT:
235        case 'C':
236          R->Trap=0xFFFF;
237          R->Trace=0;
238          ExitNow=1;
239          break;
240        case 'R':
241          R->Trap=ABuf[K];
242          R->Trace=0;
243          ExitNow=1;
244          break;
245        case 'M':
246          MemoryDump=1;
247          A=~Addr;
248          break;
249        case 'S':
250          MemoryDump=1;
251          Addr=R->SP.W;
252          K=0;
253          A=~Addr;
254          break;
255        case 'D':
256          MemoryDump=0;
257          A=~Addr;
258          break;        
259        case 'G':
260          if(CONInput(-1,-1,CLR_BACK,CLR_DIALOG,"Go to Address:",S,5|CON_HEX))
261          { Addr=strtol(S,0,16);K=0; }
262          DrawWindow=1;
263          break;
264        case 'J':
265          R->PC.W=ABuf[K];
266          A=~Addr;
267          break;
268      }
269    }
270  
271    /* Continue emulation */
272    return(1);
273  }
274  
275  #endif /* CONDEBUG */
276  #endif /* DEBUG */