/[VRac]/M6502/Debug.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /M6502/Debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Mon Jul 30 10:49:26 2007 UTC (16 years, 9 months ago) by dpavlin
File MIME type: text/plain
File size: 10729 byte(s)
import upstream M6502-010807.zip from http://fms.komkon.org/EMUL8/
1 /** M6502: portable 6502 emulator ****************************/
2 /** **/
3 /** Debug.c **/
4 /** **/
5 /** This file contains the built-in debugging routine for **/
6 /** the 6502 emulator which is called on each 6502 step **/
7 /** when Trap!=0. Some NES-dependent features are also **/
8 /** included under #ifdef INES. **/
9 /** **/
10 /** Copyright (C) Marat Fayzullin 1996-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 #include <stdio.h>
18 #include <string.h>
19 #include <ctype.h>
20
21 #ifdef INES
22 #include "NES.h"
23 extern word VAddr;
24 extern byte CURLINE;
25 #endif
26
27 #define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
28
29 enum AddressingModes { Ac=0,Il,Im,Ab,Zp,Zx,Zy,Ax,Ay,Rl,Ix,Iy,In,No };
30
31 static const byte *Ops[]=
32 {
33 "adc","and","asl","bcc","bcs","beq","bit","bmi",
34 "bne","bpl","brk","bvc","bvs","clc","cld","cli",
35 "clv","cmp","cpx","cpy","dec","dex","dey","inx",
36 "iny","eor","inc","jmp","jsr","lda","nop","ldx",
37 "ldy","lsr","ora","pha","php","pla","plp","rol",
38 "ror","rti","rts","sbc","sta","stx","sty","sec",
39 "sed","sei","tax","tay","txa","tya","tsx","txs"
40 };
41
42 static const byte Ads[512]=
43 {
44 10,Il, 34,Ix, No,No, No,No, No,No, 34,Zp, 2,Zp, No,No,
45 36,Il, 34,Im, 2,Ac, No,No, No,No, 34,Ab, 2,Ab, No,No,
46 9,Rl, 34,Iy, No,No, No,No, No,No, 34,Zx, 2,Zx, No,No,
47 13,Il, 34,Ay, No,No, No,No, No,No, 34,Ax, 2,Ax, No,No,
48 28,Ab, 1,Ix, No,No, No,No, 6,Zp, 1,Zp, 39,Zp, No,No,
49 38,Il, 1,Im, 39,Ac, No,No, 6,Ab, 1,Ab, 39,Ab, No,No,
50 7,Rl, 1,Iy, No,No, No,No, No,No, 1,Zx, 39,Zx, No,No,
51 47,Il, 1,Ay, No,No, No,No, No,No, 1,Ax, 39,Ax, No,No,
52 41,Il, 25,Ix, No,No, No,No, No,No, 25,Zp, 33,Zp, No,No,
53 35,Il, 25,Im, 33,Ac, No,No, 27,Ab, 25,Ab, 33,Ab, No,No,
54 11,Rl, 25,Iy, No,No, No,No, No,No, 25,Zx, 33,Zx, No,No,
55 15,Il, 25,Ay, No,No, No,No, No,No, 25,Ax, 33,Ax, No,No,
56 42,Il, 0,Ix, No,No, No,No, No,No, 0,Zp, 40,Zp, No,No,
57 37,Il, 0,Im, 40,Ac, No,No, 27,In, 0,Ab, 40,Ab, No,No,
58 12,Rl, 0,Iy, No,No, No,No, No,No, 0,Zx, 40,Zx, No,No,
59 49,Il, 0,Ay, No,No, No,No, No,No, 0,Ax, 40,Ax, No,No,
60 No,No, 44,Ix, No,No, No,No, 46,Zp, 44,Zp, 45,Zp, No,No,
61 22,Il, No,No, 52,Il, No,No, 46,Ab, 44,Ab, 45,Ab, No,No,
62 3,Rl, 44,Iy, No,No, No,No, 46,Zx, 44,Zx, 45,Zy, No,No,
63 53,Il, 44,Ay, 55,Il, No,No, No,No, 44,Ax, No,No, No,No,
64 32,Im, 29,Ix, 31,Im, No,No, 32,Zp, 29,Zp, 31,Zp, No,No,
65 51,Il, 29,Im, 50,Il, No,No, 32,Ab, 29,Ab, 31,Ab, No,No,
66 4,Rl, 29,Iy, No,No, No,No, 32,Zx, 29,Zx, 31,Zy, No,No,
67 16,Il, 29,Ay, 54,Il, No,No, 32,Ax, 29,Ax, 31,Ay, No,No,
68 19,Im, 17,Ix, No,No, No,No, 19,Zp, 17,Zp, 20,Zp, No,No,
69 24,Il, 17,Im, 21,Il, No,No, 19,Ab, 17,Ab, 20,Ab, No,No,
70 8,Rl, 17,Iy, No,No, No,No, No,No, 17,Zx, 20,Zx, No,No,
71 14,Il, 17,Ay, No,No, No,No, No,No, 17,Ax, 20,Ax, No,No,
72 18,Im, 43,Ix, No,No, No,No, 18,Zp, 43,Zp, 26,Zp, No,No,
73 23,Il, 43,Im, 30,Il, No,No, 18,Ab, 43,Ab, 26,Ab, No,No,
74 5,Rl, 43,Iy, No,No, No,No, No,No, 43,Zx, 26,Zx, No,No,
75 48,Il, 43,Ay, No,No, No,No, No,No, 43,Ax, 26,Ax, No,No
76 };
77
78 /** DAsm() ****************************************************/
79 /** This function will disassemble a single command and **/
80 /** return the number of bytes disassembled. **/
81 /**************************************************************/
82 static int DAsm(char *S,word A)
83 {
84 byte J;
85 word B,OP,TO;
86
87 B=A;OP=Rd6502(B++)*2;
88
89 switch(Ads[OP+1])
90 {
91 case Ac: sprintf(S,"%s a",Ops[Ads[OP]]);break;
92 case Il: sprintf(S,"%s",Ops[Ads[OP]]);break;
93
94 case Rl: J=Rd6502(B++);TO=A+2+((J<0x80)? J:(J-256));
95 sprintf(S,"%s $%04X",Ops[Ads[OP]],TO);break;
96
97 case Im: sprintf(S,"%s #$%02X",Ops[Ads[OP]],Rd6502(B++));break;
98 case Zp: sprintf(S,"%s $%02X",Ops[Ads[OP]],Rd6502(B++));break;
99 case Zx: sprintf(S,"%s $%02X,x",Ops[Ads[OP]],Rd6502(B++));break;
100 case Zy: sprintf(S,"%s $%02X,y",Ops[Ads[OP]],Rd6502(B++));break;
101 case Ix: sprintf(S,"%s ($%02X,x)",Ops[Ads[OP]],Rd6502(B++));break;
102 case Iy: sprintf(S,"%s ($%02X),y",Ops[Ads[OP]],Rd6502(B++));break;
103
104 case Ab: sprintf(S,"%s $%04X",Ops[Ads[OP]],RDWORD(B));B+=2;break;
105 case Ax: sprintf(S,"%s $%04X,x",Ops[Ads[OP]],RDWORD(B));B+=2;break;
106 case Ay: sprintf(S,"%s $%04X,y",Ops[Ads[OP]],RDWORD(B));B+=2;break;
107 case In: sprintf(S,"%s ($%04X)",Ops[Ads[OP]],RDWORD(B));B+=2;break;
108
109 default: sprintf(S,".db $%02X",OP/2);
110 }
111 return(B-A);
112 }
113
114 /** Debug6502() **********************************************/
115 /** This function should exist if DEBUG is #defined. When **/
116 /** Trace!=0, it is called after each command executed by **/
117 /** the CPU, and given the 6502 registers. Emulation exits **/
118 /** if Debug6502() returns 0. **/
119 /*************************************************************/
120 byte Debug6502(M6502 *R)
121 {
122 static char FA[9]="NVRBDIZC";
123 char S[128];
124 byte *P,F;
125 int J,I,K;
126
127 DAsm(S,R->PC.W);
128
129 printf
130 (
131 "A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
132 R->A,R->P,R->X,R->Y,R->S+0x0100,R->PC.W
133 );
134
135 for(J=0,F=R->P;J<8;J++,F<<=1)
136 printf("%c",F&0x80? FA[J]:'.');
137 printf("]\n");
138
139 printf
140 (
141 "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
142 Rd6502(R->PC.W),S,
143 Rd6502(0x0100+(byte)(R->S+1)),
144 Rd6502(0x0100+(byte)(R->S+2)),
145 Rd6502(0x0100+(byte)(R->S+3))
146 );
147
148 while(1)
149 {
150 printf("\n[Command,'?']-> ");
151 fflush(stdout);fflush(stdin);
152
153 fgets(S,50,stdin);
154 for(J=0;S[J]>=' ';J++)
155 S[J]=toupper(S[J]);
156 S[J]='\0';
157
158 switch(S[0])
159 {
160 case 'H':
161 case '?':
162 printf("\n***** Built-in 6502 Debugger Commands *****\n");
163 printf("<CR> : Break at the next instruction\n");
164 printf("= <addr> : Break at addr\n");
165 printf("+ <offset> : Break at PC + offset\n");
166 printf("c : Continue without break\n");
167 printf("j <addr> : Continue from addr\n");
168 printf("m <addr> : Memory dump at addr\n");
169 printf("d <addr> : Disassembly at addr\n");
170 printf("v : Show interrupt vectors\n");
171 #ifdef INES
172 printf("p : Show NES palette\n");
173 printf("r : Show NES hardware registers\n");
174 printf("s : Show sprite attributes\n");
175 printf("s <number> : Show sprite pattern\n");
176 #endif /* INES */
177 printf("?,h : Show this help text\n");
178 printf("q : Exit emulation\n");
179 break;
180
181 case '\0': return(1);
182 case '=': if(strlen(S)>=2)
183 { sscanf(S+1,"%hX",&(R->Trap));R->Trace=0;return(1); }
184 break;
185 case '+': if(strlen(S)>=2)
186 {
187 sscanf(S+1,"%hX",&(R->Trap));
188 R->Trap+=R->PC.W;R->Trace=0;
189 return(1);
190 }
191 break;
192 case 'J': if(strlen(S)>=2)
193 { sscanf(S+1,"%hX",&(R->PC.W));R->Trace=0;return(1); }
194 break;
195 case 'C': R->Trap=0xFFFF;R->Trace=0;return(1);
196 case 'Q': return(0);
197
198 case 'V':
199 printf("\n6502 Interrupt Vectors:\n");
200 printf("[$FFFC] INIT: $%04X\n",Rd6502(0xFFFC)+256*Rd6502(0xFFFD));
201 printf("[$FFFE] IRQ: $%04X\n",Rd6502(0xFFFE)+256*Rd6502(0xFFFF));
202 printf("[$FFFA] NMI: $%04X\n",Rd6502(0xFFFA)+256*Rd6502(0xFFFB));
203 break;
204
205 case 'M':
206 {
207 word Addr;
208
209 if(sscanf(S+1,"%hX",&Addr)!=1) Addr=R->PC.W;
210 printf("\n");
211 for(J=0;J<16;J++)
212 {
213 printf("%04X: ",Addr);
214 for(I=0;I<16;I++,Addr++)
215 printf("%02X ",Rd6502(Addr));
216 printf(" | ");Addr-=16;
217 for(I=0;I<16;I++,Addr++)
218 printf("%c",isprint(Rd6502(Addr))? Rd6502(Addr):'.');
219 printf("\n");
220 }
221 }
222 break;
223
224 case 'D':
225 {
226 word Addr;
227
228 if(sscanf(S+1,"%hX",&Addr)!=1) Addr=R->PC.W;
229 printf("\n");
230 for(J=0;J<16;J++)
231 {
232 printf("%04X: ",Addr);
233 Addr+=DAsm(S,Addr);
234 printf("%s\n",S);
235 }
236 }
237 break;
238
239 #ifdef INES
240 case 'P':
241 printf("\nNo | Picture | Sprites\n");
242 for(J=0;J<16;J++)
243 {
244 byte B1,B2;
245 B1=*(VRAM+0x3F00+J);B2=*(VRAM+0x3F10+J);
246 printf
247 (
248 "%2d | %02X (%02X,%02X,%02X) | %02X (%02X,%02X,%02X)\n",J,
249 B1,Palette[B1][0],Palette[B1][1],Palette[B1][2],
250 B2,Palette[B2][0],Palette[B2][1],Palette[B2][2]
251 );
252 }
253 break;
254
255 case 'R':
256 printf
257 (
258 "\n[$2000] PPUCONT1 = $%02X\n[$2001] PPUCONT2 = $%02X\n[$2002] PPUSTAT = $%02X\n",
259 PPU[0],PPU[1],PPU[2]
260 );
261 printf
262 (
263 "POSITION = %d,%d\nVADDR = $%04X\nSCANLINE = %d\n",
264 SCROLLX,SCROLLY,VAddr,CURLINE
265 );
266 break;
267
268 case 'S':
269 if(sscanf(S+1,"%d",&J)==1)
270 {
271 K=SRAM[J*4+1];
272 P=SPRITES16?
273 VPage[(K&0x01? 4:0)+(K>>6)]+((K&0x3E)<<4)
274 :SprGen[K>>6]+((K&0x3F)<<4);
275 printf("Sprite #%d (pattern $%02X)\n--------\n",J,K);
276 for(I=SPRITES16? 16:8;I>0;I--,P++)
277 {
278 for(K=0x80;K;K>>=1)
279 printf("%c",P[0]&K? (P[8]&K? '#':'o'):(P[8]&K? 'O':'.'));
280 printf("\n");
281 if(I==9) P+=8;
282 }
283 printf("--------\n");
284 }
285 else
286 {
287 printf("\nNo| Position | Pat | Att |No| Position | Pat | Att |No| Position | Pat | Att\n");
288 for(J=I=0;J<64*4;J+=4)
289 if(!J||(SRAM[J]&&SRAM[J+3]&&(SRAM[J]<240)))
290 {
291 printf
292 (
293 "%2d| %3d,%3d | $%02X | $%02X %s",
294 J/4,SRAM[J+3],SRAM[J],SRAM[J+1],SRAM[J+2],
295 I%3==2? "\n":"|"
296 );
297 I++;
298 }
299 }
300 break;
301 #endif /* INES */
302 }
303 }
304
305 /* Continue with emulation */
306 return(1);
307 }
308
309 #endif /* DEBUG */

  ViewVC Help
Powered by ViewVC 1.1.26