1 /***************************************************************************/
2 /*                                                                         */
3 /*                       Debugging Source File                             */
4 /*                                                                         */
5 /*  Functions are here to help developpers making cool games and/or help   */
6 /*  hackers modifying (i.e. changing sprites, fonts, translating, putting  */
7 /*  training, ...) existing games                                          */
8 /*                                                                         */
9 /*  First intended to help Dave Shadoff with his open source game          */
10 /*  Now helps me and others to emulate CDs                                 */
11 /*                                                                         */
12 /***************************************************************************/
13 #include "debug.h"
14 
15 UInt16 Bp_pos_to_restore;
16 
17 // Used in RESTORE_BP to know where we must restore a BP
18 
19 Breakpoint Bp_list[MAX_BP];
20 
21 // Set of breakpoints
22 
23 UChar save_background = 1;
24 
25 
26 #ifdef ALLEGRO
27 
28 // If set, means we got to preserve the true display
29 // If not, we just go ahead e.g. for stepping
30 
31 PALETTE save_pal;
32 
33 // The true palette
34 
35 BITMAP *save_bg;
36 
37 // The true display
38 
39 
40 #endif
41 
42 /* Way to accedate to the PC Engine memory */
43 /*
44 #if defined(MSDOS) || defined(WIN32)
45 
46 unsigned char
47 Op6502 (register unsigned A)
48 {
49   register char __AUX;
50 
51   __asm__ __volatile__ ("movl _PageR (, %%eax, 4), %%ecx "
52 			"movb (%%edx, %%ecx), %%al "
53                         :"=a" (__AUX)
54                         :"d" (A),
55 			"a" (A >> 13):"%ebx", "%ecx");
56 
57   return __AUX;
58 };
59 
60 #else
61        */
62 
63 unsigned char
Op6502(unsigned int A)64 Op6502 (unsigned int A)
65 {
66   return (PageR[A >> 13][A]);
67 }
68 
69 /*
70 #endif
71         */
72 
73 void
disass_menu()74 disass_menu ()
75 {
76 
77 #ifdef ALLEGRO
78   if (save_background)
79 
80     {
81 
82       save_bg = create_bitmap (vwidth, vheight);
83 
84       blit (screen, save_bg, 0, 0, 0, 0, vwidth, vheight);
85 
86       get_palette (save_pal);
87 
88     }
89 #endif
90 
91 #ifndef KERNEL_DS
92   disassemble (M.PC.W);
93 #else
94   disassemble (reg_pc);
95 #endif
96 
97 #ifdef ALLEGRO
98   if (save_background)
99 
100     {
101 
102       set_palette (save_pal);
103 
104       blit (save_bg, screen, 0, 0, 0, 0, vwidth, vheight);
105 
106       destroy_bitmap (save_bg);
107 
108     }
109 
110 #endif
111   return;
112 
113 };
114 
115 
116 /*****************************************************************************
117 
118     Function:  toggle_user_breakpoint
119 
120     Description: set a breakpoint at the specified address if don't exist
121 	              or unset it if existant
122     Parameters: unsigned short where, a PCE-style address
123     Return: 0 on error
124 	         1 on success
125 
126 *****************************************************************************/
127 
128 int
toggle_user_breakpoint(UInt16 where)129 toggle_user_breakpoint (UInt16 where)
130 {
131 
132   UChar dum;
133 
134   for (dum = 0; dum < MAX_USER_BP; dum++)
135 
136     {
137 
138 
139       if ((Bp_list[dum].position == where) && (Bp_list[dum].flag != NOT_USED))
140 
141 	{			//Already set, unset it and put the right opcode
142 
143 	  Bp_list[dum].flag = NOT_USED;
144 
145 	  Wr6502 (where, Bp_list[dum].original_op);
146 
147 	  return 1;
148 
149 	}
150 
151 
152       if (Bp_list[dum].flag == NOT_USED)
153 
154 	break;
155 
156 
157     }
158 
159   if (dum == MAX_USER_BP)
160 
161     return 0;
162 
163 
164   Bp_list[dum].flag = ENABLED;
165 
166   Bp_list[dum].position = where;
167 
168   Bp_list[dum].original_op = Op6502 (where);
169 
170 
171   Wr6502 (where, (UChar)(0xB + 0x10 * dum));
172 
173   // Put an invalid opcode
174 
175   return 1;
176 
177 }
178 
179 
180 /*****************************************************************************
181 
182     Function:  display_debug_help
183 
184     Description: display help on debugging
185     Parameters: none
186     Return: nothing
187 
188 *****************************************************************************/
189 
190 void
display_debug_help()191 display_debug_help ()
192 {
193 #ifdef ALLEGRO
194   UInt32 x;
195 
196   BITMAP *bg;
197 
198 
199   bg = create_bitmap (vwidth, vheight);
200 
201   blit (screen, bg, 0, 0, 0, 0, vwidth, vheight);
202 
203   clear (screen);
204 
205 
206   for (x = 0; x < help_debug_size; x++)
207 
208     textout_centre (screen, font, MESSAGE[language][help_debug + x],
209 		    vwidth / 2, blit_y + 10 * x, -1);
210 
211   while (osd_keypressed ())
212     osd_readkey ();
213 
214   osd_readkey ();
215 
216 
217   blit (bg, screen, 0, 0, 0, 0, vwidth, vheight);
218 
219   destroy_bitmap (bg);
220 
221   return;
222 #endif
223 }
224 
225 
226 
227 /*****************************************************************************
228 
229     Function:  cvt_num
230 
231     Description: convert a hexa string without prefix "0x" into a number
232     Parameters: char* string, the string to convert
233     Return: -1 on error else the given number
234 
235 	 directly taken from Dave Shadoff emulator TGSIM*
236 
237 *****************************************************************************/
cvtnum(char * string)238 UInt32 cvtnum (char *string)
239 {
240 
241   UInt32 value = 0;
242 
243   char *c = string;
244 
245 
246   while (*c != '\0')
247     {
248 
249 
250       value *= 16;
251 
252 
253       if ((*c >= '0') && (*c <= '9'))
254 	{
255 
256 	  value += (*c - '0');
257 
258 
259 	}
260       else if ((*c >= 'A') && (*c <= 'F'))
261 	{
262 
263 	  value += (*c - 'A' + 10);
264 
265 
266 	}
267       else if ((*c >= 'a') && (*c <= 'f'))
268 	{
269 
270 	  value += (*c - 'a' + 10);
271 
272 
273 	}
274       else
275 	{
276 
277 
278 	  return (-1);
279 
280 	}
281 
282 
283       c++;
284 
285     }
286 
287 
288   return (value);
289 
290 }
291 
292 
293 /*****************************************************************************
294 
295     Function: set_bp_following
296 
297     Description: very tricky function, set a bp to the next IP, must handle
298        correctly jump, ret,...
299                  Well, the trick isn't in a 10 line function ;)
300                  but in the optable.following_IP funcs
301     Parameters: UInt16 where, the current address
302                 UChar nb, the nb of the breakpoint to set
303     Return: nothing
304 
305 *****************************************************************************/
306 void
set_bp_following(UInt16 where,UChar nb)307 set_bp_following (UInt16 where, UChar nb)
308 {
309 
310   UInt16 next_pos;
311 
312   UChar op = Op6502 (where);
313 
314 
315   next_pos = (*optable_debug[op].following_IP) (where);
316 
317 
318   Bp_list[nb].position = next_pos;
319 
320 
321   Bp_list[nb].flag = ENABLED;
322 
323 
324   Bp_list[nb].original_op = Op6502 (next_pos);
325 
326 
327   Wr6502 (next_pos, (UChar)(0xB + 0x10 * nb));
328 
329 
330   return;
331 
332 }
333 
334 
335 /*****************************************************************************
336 
337     Function:  change_value
338 
339     Description: change the value
340     Parameters: int X, int Y : position on screen
341                 UChar lenght : # of characters allowed
342     Return: the new value in int pointed by result
343 
344 *****************************************************************************/
change_value(int X,int Y,UChar length,UInt32 * result)345 UChar change_value (int X, int Y, UChar length, UInt32 * result)
346 {
347 #ifdef ALLEGRO
348   char index = 0;
349 
350   char value[9] = "\0\0\0\0\0\0\0\0";
351 
352   int ch;
353 
354 
355   do
356     {
357       rectfill (screen, X, Y, X + 16, Y + 9, -15);
358       textout (screen, font, value, X, Y + 1, -1);
359       ch = osd_readkey ();
360 
361       // first switch by scancode
362       switch (ch >> 8)
363 	{
364 	case KEY_ESC:
365 	  return 0;
366 	case KEY_ENTER:
367 	  *result = cvtnum (value);
368 	  return 1;
369 	case KEY_BACKSPACE:
370 	  if (index)
371 	    value[--index] = 0;
372 	  break;
373 	}
374 
375       // Now by ascii code
376       switch (ch & 0xff)
377 	{
378 	case '0'...'9':
379 	case 'a'...'f':
380 	case 'A'...'F':
381 	  if (index < length)
382 	    value[index++] = toupper (ch & 0xff);
383 	  break;
384 	}
385     }
386   while (1);
387 #endif
388 
389   return 0;
390 }
391