|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Debugger
5: *
6: * (c) 1995 Bernd Schmidt
7: * (c) 2006 Toni Wilen
8: *
9: */
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include "main.h"
15: #include "hatari-glue.h"
16:
17: #include <ctype.h>
18: #include <signal.h>
19:
20: #include "options_cpu.h"
21: //#include "uae.h"
22: #include "memory.h"
23: #include "custom.h"
24: #include "newcpu.h"
25: #include "cpu_prefetch.h"
26: #include "debug.h"
27: //#include "cia.h"
28: //#include "xwin.h"
29: //#include "identify.h"
30: //#include "audio.h"
31: //#include "sound.h"
32: //#include "disk.h"
33: #include "savestate.h"
34: //#include "autoconf.h"
35: //#include "akiko.h"
36: //#include "inputdevice.h"
37: //#include "crc32.h"
38: //#include "rommgr.h"
39: //#include "inputrecord.h"
40: #include "cpummu.h"
41: #include "cpummu030.h"
42: //#include "ppc/ppcd.h"
43: //#include "uae/ppc.h"
44:
45: #ifdef WINUAE_FOR_HATARI
46: #include "stMemory.h"
47: static int debug_mmu_mode;
48:
49: #else
50: int debugger_active;
51: static uaecptr skipaddr_start, skipaddr_end;
52: static int skipaddr_doskip;
53: static uae_u32 skipins;
54: static int do_skip;
55: static int debug_rewind;
56: static int memwatch_triggered;
57: int memwatch_enabled;
58: static uae_u16 sr_bpmask, sr_bpvalue;
59: int debugging;
60: int exception_debugging;
61: int no_trace_exceptions;
62: int debug_copper = 0;
63: int debug_dma = 0;
64: int debug_sprite_mask = 0xff;
65: int debug_illegal = 0;
66: uae_u64 debug_illegal_mask;
67: static int debug_mmu_mode;
68: static bool break_if_enforcer;
69:
70: static uaecptr processptr;
71: static uae_char *processname;
72:
73: static uaecptr debug_copper_pc;
74:
75: extern int audio_channel_mask;
76: extern int inputdevice_logging;
77:
78: void deactivate_debugger (void)
79: {
80: debugger_active = 0;
81: debugging = 0;
82: exception_debugging = 0;
83: processptr = 0;
84: xfree (processname);
85: processname = NULL;
86: }
87:
88: void activate_debugger (void)
89: {
90: do_skip = 0;
91: if (debugger_active)
92: return;
93: debugger_active = 1;
94: set_special (SPCFLAG_BRK);
95: debugging = 1;
96: mmu_triggered = 0;
97: }
98:
99: bool debug_enforcer(void)
100: {
101: if (!break_if_enforcer)
102: return false;
103: activate_debugger();
104: return true;
105: }
106:
107: int firsthist = 0;
108: int lasthist = 0;
109: static struct regstruct history[MAX_HIST];
110:
111: static TCHAR help[] = {
112: _T(" HELP for UAE Debugger\n")
113: _T(" -----------------------\n\n")
114: _T(" g [<address>] Start execution at the current address or <address>.\n")
115: _T(" c Dump state of the CIA, disk drives and custom registers.\n")
116: _T(" r Dump state of the CPU.\n")
117: _T(" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n")
118: _T(" m <address> [<lines>] Memory dump starting at <address>.\n")
119: _T(" d <address> [<lines>] Disassembly starting at <address>.\n")
120: _T(" t [instructions] Step one or more instructions.\n")
121: _T(" z Step through one instruction - useful for JSR, DBRA etc.\n")
122: _T(" f Step forward until PC in RAM (\"boot block finder\").\n")
123: _T(" f <address> Add/remove breakpoint.\n")
124: _T(" fa <address> [<start>] [<end>]\n")
125: _T(" Find effective address <address>.\n")
126: _T(" fi Step forward until PC points to RTS, RTD or RTE.\n")
127: _T(" fi <opcode> Step forward until PC points to <opcode>.\n")
128: _T(" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active.\n")
129: _T(" fl List breakpoints.\n")
130: _T(" fd Remove all breakpoints.\n")
131: _T(" fs <lines to wait> | <vpos> <hpos> Wait n scanlines/position.\n")
132: _T(" fc <CCKs to wait> Wait n color clocks.\n")
133: _T(" fS <val> <mask> Break when (SR & mask) = val.\n")
134: _T(" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>.\n")
135: _T(" e Dump contents of all custom registers, ea = AGA colors.\n")
136: _T(" i [<addr>] Dump contents of interrupt and trap vectors.\n")
137: _T(" il [<mask>] Exception breakpoint.\n")
138: _T(" o <0-2|addr> [<lines>]View memory as Copper instructions.\n")
139: _T(" od Enable/disable Copper vpos/hpos tracing.\n")
140: _T(" ot Copper single step trace.\n")
141: _T(" ob <addr> Copper breakpoint.\n")
142: _T(" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions.\n")
143: _T(" C <value> Search for values like energy or lifes in games.\n")
144: _T(" Cl List currently found trainer addresses.\n")
145: _T(" D[idxzs <[max diff]>] Deep trainer. i=new value must be larger, d=smaller,\n")
146: _T(" x = must be same, z = must be different, s = restart.\n")
147: _T(" W <address> <values[.x] separated by space> Write into Amiga memory.\n")
148: _T(" W <address> 'string' Write into Amiga memory.\n")
149: _T(" w <num> <address> <length> <R/W/I/F/C> [<value>[.x]] (read/write/opcode/freeze/mustchange).\n")
150: _T(" Add/remove memory watchpoints.\n")
151: _T(" wd [<0-1>] Enable illegal access logger. 1 = enable break.\n")
152: _T(" S <file> <addr> <n> Save a block of Amiga memory.\n")
153: _T(" s \"<string>\"/<values> [<addr>] [<length>]\n")
154: _T(" Search for string/bytes.\n")
155: _T(" T or Tt Show exec tasks and their PCs.\n")
156: _T(" Td,Tl,Tr,Tp,Ts,TS,Ti,TO,TM Show devs, libs, resources, ports, semaphores,\n")
157: _T(" residents, interrupts, doslist and memorylist.\n")
158: _T(" b Step to previous state capture position.\n")
159: _T(" M<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites.\n")
160: _T(" sp <addr> [<addr2][<size>] Dump sprite information.\n")
161: _T(" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n")
162: _T(" Also enables level 1 disk logging.\n")
163: _T(" did <log level> Enable disk logging.\n")
164: _T(" dj [<level bitmask>] Enable joystick/mouse input debugging.\n")
165: _T(" smc [<0-1>] Enable self-modifying code detector. 1 = enable break.\n")
166: _T(" dm Dump current address space map.\n")
167: _T(" v <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode).\n")
168: _T(" v [-1 to -4] = enable visual DMA debugger.\n")
169: _T(" ?<value> Hex ($ and 0x)/Bin (%)/Dec (!) converter.\n")
170: #ifdef _WIN32
171: _T(" x Close debugger.\n")
172: _T(" xx Switch between console and GUI debugger.\n")
173: _T(" mg <address> Memory dump starting at <address> in GUI.\n")
174: _T(" dg <address> Disassembly starting at <address> in GUI.\n")
175: #endif
176: _T(" q Quit the emulator. You don't want to use this command.\n\n")
177: };
178:
179: void debug_help (void)
180: {
181: console_out (help);
182: }
183:
184: static int debug_linecounter;
185: #define MAX_LINECOUNTER 1000
186:
187: static int debug_out (const TCHAR *format, ...)
188: {
189: va_list parms;
190: TCHAR buffer[4000];
191:
192: va_start (parms, format);
193: _vsntprintf (buffer, 4000 - 1, format, parms);
194: va_end (parms);
195:
196: console_out (buffer);
197: if (debug_linecounter < MAX_LINECOUNTER)
198: debug_linecounter++;
199: if (debug_linecounter >= MAX_LINECOUNTER)
200: return 0;
201: return 1;
202: }
203:
204: #endif /* ! WINUAE_FOR_HATARI */
205:
206: uae_u32 get_byte_debug (uaecptr addr)
207: {
208: uae_u32 v = 0xff;
209: if (debug_mmu_mode) {
210: flagtype olds = regs.s;
211: regs.s = (debug_mmu_mode & 4) != 0;
212: TRY(p) {
213: if (currprefs.mmu_model == 68030) {
214: v = mmu030_get_generic (addr, debug_mmu_mode, sz_byte, sz_byte, 0);
215: } else {
216: v = mmu_get_user_byte (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_byte);
217: }
218: } CATCH(p) {
219: } ENDTRY
220: regs.s = olds;
221: } else {
222: #ifndef WINUAE_FOR_HATARI
223: v = get_byte (addr);
224: #else
225: v = STMemory_ReadByte ( addr );
226: #endif
227: }
228: return v;
229: }
230: uae_u32 get_word_debug (uaecptr addr)
231: {
232: uae_u32 v = 0xffff;
233: if (debug_mmu_mode) {
234: flagtype olds = regs.s;
235: regs.s = (debug_mmu_mode & 4) != 0;
236: TRY(p) {
237: if (currprefs.mmu_model == 68030) {
238: v = mmu030_get_generic (addr, debug_mmu_mode, sz_word, sz_word, 0);
239: } else {
240: v = mmu_get_user_word (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_word);
241: }
242: } CATCH(p) {
243: } ENDTRY
244: regs.s = olds;
245: } else {
246: #ifndef WINUAE_FOR_HATARI
247: v = get_word (addr);
248: #else
249: v = STMemory_ReadWord ( addr );
250: #endif
251: }
252: return v;
253: }
254: uae_u32 get_long_debug (uaecptr addr)
255: {
256: uae_u32 v = 0xffffffff;
257: if (debug_mmu_mode) {
258: flagtype olds = regs.s;
259: regs.s = (debug_mmu_mode & 4) != 0;
260: TRY(p) {
261: if (currprefs.mmu_model == 68030) {
262: v = mmu030_get_generic (addr, debug_mmu_mode, sz_long, sz_long, 0);
263: } else {
264: v = mmu_get_user_long (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_long);
265: }
266: } CATCH(p) {
267: } ENDTRY
268: regs.s = olds;
269: } else {
270: #ifndef WINUAE_FOR_HATARI
271: v = get_long (addr);
272: #else
273: v = STMemory_ReadLong ( addr );
274: #endif
275: }
276: return v;
277: }
278: uae_u32 get_iword_debug (uaecptr addr)
279: {
280: if (debug_mmu_mode) {
281: return get_word_debug (addr);
282: } else {
283: #ifndef WINUAE_FOR_HATARI
284: if (valid_address (addr, 2))
285: return get_word (addr);
286: return 0xffff;
287: #else
288: return get_word_debug (addr);
289: #endif
290: }
291: }
292: uae_u32 get_ilong_debug (uaecptr addr)
293: {
294: if (debug_mmu_mode) {
295: return get_long_debug (addr);
296: } else {
297: #ifndef WINUAE_FOR_HATARI
298: if (valid_address (addr, 4))
299: return get_long (addr);
300: return 0xffffffff;
301: #else
302: return get_long_debug (addr);
303: #endif
304: }
305: }
306:
307: #ifndef WINUAE_FOR_HATARI
308: int safe_addr (uaecptr addr, int size)
309: {
310: if (debug_mmu_mode) {
311: flagtype olds = regs.s;
312: regs.s = (debug_mmu_mode & 4) != 0;
313: TRY(p) {
314: if (currprefs.mmu_model >= 68040)
315: addr = mmu_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
316: else
317: addr = mmu030_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
318: } CATCH(p) {
319: return 0;
320: } ENDTRY
321: regs.s = olds;
322: }
323: addrbank *ab = &get_mem_bank (addr);
324: if (!ab)
325: return 0;
326: if (ab->flags & ABFLAG_SAFE)
327: return 1;
328: if (!ab->check (addr, size))
329: return 0;
330: if (ab->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
331: return 1;
332: return 0;
333: }
334:
335: static bool iscancel (int counter)
336: {
337: static int cnt;
338:
339: cnt++;
340: if (cnt < counter)
341: return false;
342: cnt = 0;
343: if (!console_isch ())
344: return false;
345: console_getch ();
346: return true;
347: }
348:
349: static bool isoperator(TCHAR **cp)
350: {
351: TCHAR c = **cp;
352: return c == '+' || c == '-' || c == '/' || c == '*' || c == '(' || c == ')';
353: }
354:
355: static void ignore_ws (TCHAR **c)
356: {
357: while (**c && _istspace(**c))
358: (*c)++;
359: }
360: static TCHAR peekchar (TCHAR **c)
361: {
362: return **c;
363: }
364: static TCHAR readchar (TCHAR **c)
365: {
366: TCHAR cc = **c;
367: (*c)++;
368: return cc;
369: }
370: static TCHAR next_char (TCHAR **c)
371: {
372: ignore_ws (c);
373: return *(*c)++;
374: }
375: static TCHAR peek_next_char (TCHAR **c)
376: {
377: TCHAR *pc = *c;
378: return pc[1];
379: }
380: static int more_params (TCHAR **c)
381: {
382: ignore_ws (c);
383: return (**c) != 0;
384: }
385:
386: static uae_u32 readint (TCHAR **c);
387: static uae_u32 readbin (TCHAR **c);
388: static uae_u32 readhex (TCHAR **c);
389:
390: static int readregx (TCHAR **c, uae_u32 *valp)
391: {
392: int i;
393: uae_u32 addr;
394: TCHAR *p = *c;
395: TCHAR tmp[10];
396: int extra = 0;
397:
398: addr = 0;
399: i = 0;
400: while (p[i]) {
401: tmp[i] = _totupper (p[i]);
402: if (i >= sizeof (tmp) / sizeof (TCHAR) - 1)
403: break;
404: i++;
405: }
406: tmp[i] = 0;
407: if (_totupper (tmp[0]) == 'R') {
408: memmove (tmp, tmp + 1, sizeof (tmp) - sizeof (TCHAR));
409: extra = 1;
410: }
411: if (!_tcsncmp (tmp, _T("USP"), 3)) {
412: addr = regs.usp;
413: (*c) += 3;
414: } else if (!_tcsncmp (tmp, _T("VBR"), 3)) {
415: addr = regs.vbr;
416: (*c) += 3;
417: } else if (!_tcsncmp (tmp, _T("MSP"), 3)) {
418: addr = regs.msp;
419: (*c) += 3;
420: } else if (!_tcsncmp (tmp, _T("ISP"), 3)) {
421: addr = regs.isp;
422: (*c) += 3;
423: } else if (!_tcsncmp (tmp, _T("PC"), 2)) {
424: addr = regs.pc;
425: (*c) += 2;
426: } else if (tmp[0] == 'A' || tmp[0] == 'D') {
427: int reg = 0;
428: if (tmp[0] == 'A')
429: reg += 8;
430: reg += tmp[1] - '0';
431: if (reg < 0 || reg > 15)
432: return 0;
433: addr = regs.regs[reg];
434: (*c) += 2;
435: } else {
436: return 0;
437: }
438: *valp = addr;
439: (*c) += extra;
440: return 1;
441: }
442:
443: static bool readbinx (TCHAR **c, uae_u32 *valp)
444: {
445: uae_u32 val = 0;
446: bool first = true;
447:
448: ignore_ws (c);
449: for (;;) {
450: TCHAR nc = **c;
451: if (nc != '1' && nc != '0') {
452: if (first)
453: return false;
454: break;
455: }
456: first = false;
457: (*c)++;
458: val <<= 1;
459: if (nc == '1')
460: val |= 1;
461: }
462: *valp = val;
463: return true;
464: }
465:
466: static bool readhexx (TCHAR **c, uae_u32 *valp)
467: {
468: uae_u32 val = 0;
469: TCHAR nc;
470:
471: ignore_ws (c);
472: if (!isxdigit (peekchar (c)))
473: return false;
474: while (isxdigit (nc = **c)) {
475: (*c)++;
476: val *= 16;
477: nc = _totupper (nc);
478: if (isdigit (nc)) {
479: val += nc - '0';
480: } else {
481: val += nc - 'A' + 10;
482: }
483: }
484: *valp = val;
485: return true;
486: }
487:
488: static bool readintx (TCHAR **c, uae_u32 *valp)
489: {
490: uae_u32 val = 0;
491: TCHAR nc;
492: int negative = 0;
493:
494: ignore_ws (c);
495: if (**c == '-')
496: negative = 1, (*c)++;
497: if (!isdigit (peekchar (c)))
498: return false;
499: while (isdigit (nc = **c)) {
500: (*c)++;
501: val *= 10;
502: val += nc - '0';
503: }
504: *valp = val * (negative ? -1 : 1);
505: return true;
506: }
507:
508:
509: static int checkvaltype2 (TCHAR **c, uae_u32 *val, TCHAR def)
510: {
511: TCHAR nc;
512:
513: ignore_ws (c);
514: nc = _totupper (**c);
515: if (nc == '!') {
516: (*c)++;
517: return readintx (c, val) ? 1 : 0;
518: }
519: if (nc == '$') {
520: (*c)++;
521: return readhexx (c, val) ? 1 : 0;
522: }
523: if (nc == '0' && _totupper ((*c)[1]) == 'X') {
524: (*c)+= 2;
525: return readhexx (c, val) ? 1 : 0;
526: }
527: if (nc == '%') {
528: (*c)++;
529: return readbinx (c, val) ? 1: 0;
530: }
531: if (nc >= 'A' && nc <= 'Z' && nc != 'A' && nc != 'D') {
532: if (readregx (c, val))
533: return 1;
534: }
535: if (def == '!') {
536: return readintx (c, val) ? -1 : 0;
537: return -1;
538: } else if (def == '$') {
539: return readhexx (c, val) ? -1 : 0;
540: } else if (def == '%') {
541: return readbinx (c, val) ? -1 : 0;
542: }
543: return 0;
544: }
545:
546: static int readsize (int val, TCHAR **c)
547: {
548: TCHAR cc = _totupper (readchar(c));
549: if (cc == 'B')
550: return 1;
551: if (cc == 'W')
552: return 2;
553: if (cc == '3')
554: return 3;
555: if (cc == 'L')
556: return 4;
557: return 0;
558: }
559:
560: static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
561: {
562: TCHAR form[256], *p;
563: bool gotop = false;
564: double out;
565:
566: form[0] = 0;
567: *size = 0;
568: p = form;
569: for (;;) {
570: uae_u32 v;
571: if (!checkvaltype2 (cp, &v, def))
572: return 0;
573: *val = v;
574: // stupid but works!
575: _stprintf(p, _T("%u"), v);
576: p += _tcslen (p);
577: if (peekchar (cp) == '.') {
578: readchar (cp);
579: *size = readsize (v, cp);
580: }
581: if (!isoperator (cp))
582: break;
583: gotop = true;
584: *p++= readchar (cp);
585: *p = 0;
586: }
587: if (!gotop) {
588: if (*size == 0) {
589: uae_s32 v = (uae_s32)(*val);
590: if (v > 255 || v < -127) {
591: *size = 2;
592: } else if (v > 65535 || v < -32767) {
593: *size = 4;
594: } else {
595: *size = 1;
596: }
597: }
598: return 1;
599: }
600: if (calc (form, &out)) {
601: *val = (uae_u32)out;
602: if (*size == 0) {
603: uae_s32 v = (uae_s32)(*val);
604: if (v > 255 || v < -127) {
605: *size = 2;
606: } else if (v > 65535 || v < -32767) {
607: *size = 4;
608: } else {
609: *size = 1;
610: }
611: }
612: return 1;
613: }
614: return 0;
615: }
616:
617:
618: static uae_u32 readnum (TCHAR **c, int *size, TCHAR def)
619: {
620: uae_u32 val;
621: if (checkvaltype (c, &val, size, def))
622: return val;
623: return 0;
624: }
625:
626: static uae_u32 readint (TCHAR **c)
627: {
628: int size;
629: return readnum (c, &size, '!');
630: }
631: static uae_u32 readhex (TCHAR **c)
632: {
633: int size;
634: return readnum (c, &size, '$');
635: }
636: static uae_u32 readbin (TCHAR **c)
637: {
638: int size;
639: return readnum (c, &size, '%');
640: }
641: static uae_u32 readint (TCHAR **c, int *size)
642: {
643: return readnum (c, size, '!');
644: }
645: static uae_u32 readhex (TCHAR **c, int *size)
646: {
647: return readnum (c, size, '$');
648: }
649:
650: static int next_string (TCHAR **c, TCHAR *out, int max, int forceupper)
651: {
652: TCHAR *p = out;
653: int startmarker = 0;
654:
655: if (**c == '\"') {
656: startmarker = 1;
657: (*c)++;
658: }
659: *p = 0;
660: while (**c != 0) {
661: if (**c == '\"' && startmarker)
662: break;
663: if (**c == 32 && !startmarker) {
664: ignore_ws (c);
665: break;
666: }
667: *p = next_char (c);
668: if (forceupper)
669: *p = _totupper(*p);
670: *++p = 0;
671: max--;
672: if (max <= 1)
673: break;
674: }
675: return _tcslen (out);
676: }
677:
678: static void converter (TCHAR **c)
679: {
680: uae_u32 v = readint (c);
681: TCHAR s[100];
682: TCHAR *p = s;
683: int i;
684:
685: for (i = 0; i < 32; i++)
686: s[i] = (v & (1 << (31 - i))) ? '1' : '0';
687: s[i] = 0;
688: console_out_f (_T("0x%08X = %%%s = %u = %d\n"), v, s, v, (uae_s32)v);
689: }
690:
691: int notinrom (void)
692: {
693: uaecptr pc = munge24 (m68k_getpc ());
694: if (pc < 0x00e00000 || pc > 0x00ffffff)
695: return 1;
696: return 0;
697: }
698:
699: static uae_u32 lastaddr (void)
700: {
701: if (currprefs.z3fastmem2_size)
702: return z3fastmem2_bank.start + currprefs.z3fastmem2_size;
703: if (currprefs.z3fastmem_size)
704: return z3fastmem_bank.start + currprefs.z3fastmem_size;
705: if (currprefs.z3chipmem_size)
706: return z3chipmem_bank.start + currprefs.z3chipmem_size;
707: if (currprefs.mbresmem_high_size)
708: return a3000hmem_bank.start + currprefs.mbresmem_high_size;
709: if (currprefs.mbresmem_low_size)
710: return a3000lmem_bank.start + currprefs.mbresmem_low_size;
711: if (currprefs.bogomem_size)
712: return bogomem_bank.start + currprefs.bogomem_size;
713: if (currprefs.fastmem_size)
714: return fastmem_bank.start + currprefs.fastmem_size;
715: return currprefs.chipmem_size;
716: }
717:
718: static uaecptr nextaddr2 (uaecptr addr, int *next)
719: {
720: uaecptr prev, prevx;
721: int size, sizex;
722:
723: if (addr >= lastaddr ()) {
724: *next = -1;
725: return 0xffffffff;
726: }
727: prev = currprefs.z3autoconfig_start + currprefs.z3fastmem_size;
728: size = currprefs.z3fastmem2_size;
729:
730: if (currprefs.z3fastmem_size) {
731: prevx = prev;
732: sizex = size;
733: size = currprefs.z3fastmem_size;
734: prev = z3fastmem_bank.start;
735: if (addr == prev + size) {
736: *next = prevx + sizex;
737: return prevx;
738: }
739: }
740: if (currprefs.z3chipmem_size) {
741: prevx = prev;
742: sizex = size;
743: size = currprefs.z3chipmem_size;
744: prev = z3chipmem_bank.start;
745: if (addr == prev + size) {
746: *next = prevx + sizex;
747: return prevx;
748: }
749: }
750: if (currprefs.mbresmem_high_size) {
751: sizex = size;
752: prevx = prev;
753: size = currprefs.mbresmem_high_size;
754: prev = a3000hmem_bank.start;
755: if (addr == prev + size) {
756: *next = prevx + sizex;
757: return prevx;
758: }
759: }
760: if (currprefs.mbresmem_low_size) {
761: prevx = prev;
762: sizex = size;
763: size = currprefs.mbresmem_low_size;
764: prev = a3000lmem_bank.start;
765: if (addr == prev + size) {
766: *next = prevx + sizex;
767: return prevx;
768: }
769: }
770: if (currprefs.bogomem_size) {
771: sizex = size;
772: prevx = prev;
773: size = currprefs.bogomem_size;
774: prev = bogomem_bank.start;
775: if (addr == prev + size) {
776: *next = prevx + sizex;
777: return prevx;
778: }
779: }
780: if (currprefs.fastmem_size) {
781: sizex = size;
782: prevx = prev;
783: size = currprefs.fastmem_size;
784: prev = fastmem_bank.start;
785: if (addr == prev + size) {
786: *next = prevx + sizex;
787: return prevx;
788: }
789: }
790: sizex = size;
791: prevx = prev;
792: size = currprefs.chipmem_size;
793: if (addr == size) {
794: *next = prevx + sizex;
795: return prevx;
796: }
797: if (addr == 1)
798: *next = size;
799: return addr;
800: }
801:
802: static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *end)
803: {
804: static uaecptr old;
805: uaecptr paddr = addr;
806: int next = last;
807: if (last && 0) {
808: if (addr >= last)
809: return 0xffffffff;
810: return addr + 1;
811: }
812: if (addr == 0xffffffff) {
813: if (end)
814: *end = currprefs.chipmem_size;
815: return 0;
816: }
817: if (end)
818: next = *end;
819: addr = nextaddr2 (addr + 1, &next);
820: if (end)
821: *end = next;
822: if (old != next) {
823: if (addr != 0xffffffff)
824: console_out_f (_T("Scanning.. %08x - %08x (%s)\n"), addr & 0xffffff00, next, get_mem_bank (addr).name);
825: old = next;
826: }
827: #if 0
828: if (next && addr != 0xffffffff) {
829: uaecptr xa = addr;
830: if (xa == 1)
831: xa = 0;
832: console_out_f ("%08X -> %08X (%08X)...\n", xa, xa + next - 1, next);
833: }
834: #endif
835: return addr;
836: }
837:
838: uaecptr dumpmem2 (uaecptr addr, TCHAR *out, int osize)
839: {
840: int i, cols = 8;
841: int nonsafe = 0;
842:
843: if (osize <= (9 + cols * 5 + 1 + 2 * cols))
844: return addr;
845: _stprintf (out, _T("%08X "), addr);
846: for (i = 0; i < cols; i++) {
847: uae_u8 b1, b2;
848: b1 = b2 = 0;
849: if (safe_addr (addr, 1)) {
850: b1 = get_byte_debug (addr + 0);
851: b2 = get_byte_debug (addr + 1);
852: _stprintf (out + 9 + i * 5, _T("%02X%02X "), b1, b2);
853: out[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
854: out[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
855: } else {
856: nonsafe++;
857: _tcscpy (out + 9 + i * 5, _T("**** "));
858: out[9 + cols * 5 + 1 + i * 2 + 0] = '*';
859: out[9 + cols * 5 + 1 + i * 2 + 1] = '*';
860: }
861: addr += 2;
862: }
863: out[9 + cols * 5] = ' ';
864: out[9 + cols * 5 + 1 + 2 * cols] = 0;
865: if (nonsafe == cols) {
866: addrbank *ab = &get_mem_bank (addr);
867: if (ab->name)
868: memcpy (out + (9 + 4 + 1) * sizeof (TCHAR), ab->name, _tcslen (ab->name) * sizeof (TCHAR));
869: }
870: return addr;
871: }
872:
873: static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
874: {
875: TCHAR line[MAX_LINEWIDTH + 1];
876: for (;lines--;) {
877: addr = dumpmem2 (addr, line, sizeof(line));
878: debug_out (_T("%s"), line);
879: if (!debug_out (_T("\n")))
880: break;
881: }
882: *nxmem = addr;
883: }
884:
885: static void dump_custom_regs (int aga)
886: {
887: int len, i, j, end;
888: uae_u8 *p1, *p2, *p3, *p4;
889:
890: if (aga) {
891: dump_aga_custom();
892: return;
893: }
894:
895: p1 = p2 = save_custom (&len, 0, 1);
896: p1 += 4; // skip chipset type
897: for (i = 0; i < 4; i++) {
898: p4 = p1 + 0xa0 + i * 16;
899: p3 = save_audio (i, &len, 0);
900: p4[0] = p3[12];
901: p4[1] = p3[13];
902: p4[2] = p3[14];
903: p4[3] = p3[15];
904: p4[4] = p3[4];
905: p4[5] = p3[5];
906: p4[6] = p3[8];
907: p4[7] = p3[9];
908: p4[8] = 0;
909: p4[9] = p3[1];
910: p4[10] = p3[10];
911: p4[11] = p3[11];
912: free (p3);
913: }
914: end = 0;
915: while (custd[end].name)
916: end++;
917: end++;
918: end /= 2;
919: for (i = 0; i < end; i++) {
920: uae_u16 v1, v2;
921: int addr1, addr2;
922: j = end + i;
923: addr1 = custd[i].adr & 0x1ff;
924: addr2 = custd[j].adr & 0x1ff;
925: v1 = (p1[addr1 + 0] << 8) | p1[addr1 + 1];
926: v2 = (p1[addr2 + 0] << 8) | p1[addr2 + 1];
927: console_out_f (_T("%03X %s\t%04X\t%03X %s\t%04X\n"),
928: addr1, custd[i].name, v1,
929: addr2, custd[j].name, v2);
930: }
931: free (p2);
932: }
933:
934: static void dump_vectors (uaecptr addr)
935: {
936: int i = 0, j = 0;
937:
938: if (addr == 0xffffffff)
939: addr = regs.vbr;
940:
941: while (int_labels[i].name || trap_labels[j].name) {
942: if (int_labels[i].name) {
943: console_out_f (_T("$%08X %02d: %12s $%08X "), int_labels[i].adr + addr, int_labels[i].adr / 4,
944: int_labels[i].name, get_long_debug (int_labels[i].adr + addr));
945: i++;
946: }
947: if (trap_labels[j].name) {
948: console_out_f (_T("$%08X %02d: %12s $%08X"), trap_labels[j].adr + addr, trap_labels[j].adr / 4,
949: trap_labels[j].name, get_long_debug (trap_labels[j].adr + addr));
950: j++;
951: }
952: console_out (_T("\n"));
953: }
954: }
955:
956: static void disassemble_wait (FILE *file, unsigned long insn)
957: {
958: int vp, hp, ve, he, bfd, v_mask, h_mask;
959: int doout = 0;
960:
961: vp = (insn & 0xff000000) >> 24;
962: hp = (insn & 0x00fe0000) >> 16;
963: ve = (insn & 0x00007f00) >> 8;
964: he = (insn & 0x000000fe);
965: bfd = (insn & 0x00008000) >> 15;
966:
967: /* bit15 can never be masked out*/
968: v_mask = vp & (ve | 0x80);
969: h_mask = hp & he;
970: if (v_mask > 0) {
971: doout = 1;
972: console_out (_T("vpos "));
973: if (ve != 0x7f) {
974: console_out_f (_T("& 0x%02x "), ve);
975: }
976: console_out_f (_T(">= 0x%02x"), v_mask);
977: }
978: if (he > 0) {
979: if (v_mask > 0) {
980: console_out (_T(" and"));
981: }
982: console_out (_T(" hpos "));
983: if (he != 0xfe) {
984: console_out_f (_T("& 0x%02x "), he);
985: }
986: console_out_f (_T(">= 0x%02x"), h_mask);
987: } else {
988: if (doout)
989: console_out (_T(", "));
990: console_out (_T(", ignore horizontal"));
991: }
992:
993: console_out_f (_T("\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n"),
994: vp, ve, hp, he, bfd);
995: }
996:
997: #define NR_COPPER_RECORDS 100000
998: /* Record copper activity for the debugger. */
999: struct cop_rec
1000: {
1001: uae_u16 w1, w2;
1002: int hpos, vpos;
1003: int bhpos, bvpos;
1004: uaecptr addr;
1005: };
1006: static struct cop_rec *cop_record[2];
1007: static int nr_cop_records[2], curr_cop_set;
1008:
1009: #define NR_DMA_REC_HPOS 256
1010: #define NR_DMA_REC_VPOS 1000
1011: static struct dma_rec *dma_record[2];
1012: static int dma_record_toggle;
1013:
1014: void record_dma_reset (void)
1015: {
1016: int v, h;
1017: struct dma_rec *dr, *dr2;
1018:
1019: if (!dma_record[0])
1020: return;
1021: dma_record_toggle ^= 1;
1022: dr = dma_record[dma_record_toggle];
1023: for (v = 0; v < NR_DMA_REC_VPOS; v++) {
1024: for (h = 0; h < NR_DMA_REC_HPOS; h++) {
1025: dr2 = &dr[v * NR_DMA_REC_HPOS + h];
1026: memset (dr2, 0, sizeof (struct dma_rec));
1027: dr2->reg = 0xffff;
1028: dr2->addr = 0xffffffff;
1029: }
1030: }
1031: }
1032:
1033: void record_copper_reset (void)
1034: {
1035: /* Start a new set of copper records. */
1036: curr_cop_set ^= 1;
1037: nr_cop_records[curr_cop_set] = 0;
1038: }
1039:
1040: STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a)
1041: {
1042: uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff];
1043: if (a)
1044: v |= a[255 - ((c >> 24) & 0xff)];
1045: return v;
1046: }
1047:
1048: STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8)
1049: {
1050: if (x <= 0)
1051: return;
1052:
1053: switch (bpp) {
1054: case 1:
1055: buf[x] = (uae_u8)c8;
1056: break;
1057: case 2:
1058: {
1059: uae_u16 *p = (uae_u16*)buf + x;
1060: *p = (uae_u16)c8;
1061: break;
1062: }
1063: case 3:
1064: /* no 24 bit yet */
1065: break;
1066: case 4:
1067: {
1068: uae_u32 *p = (uae_u32*)buf + x;
1069: *p = c8;
1070: break;
1071: }
1072: }
1073: }
1074:
1075: #define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL)
1076:
1077: static uae_u32 intlevc[] = { 0x000000, 0x444444, 0x008800, 0xffff00, 0x000088, 0x880000, 0xff0000, 0xffffff };
1078:
1079: void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
1080: {
1081: int y, x, xx, dx, xplus, yplus;
1082: struct dma_rec *dr;
1083: int t;
1084: uae_u32 cc[DMARECORD_MAX];
1085:
1086: if (debug_dma >= 4)
1087: yplus = 2;
1088: else
1089: yplus = 1;
1090: if (debug_dma >= 3)
1091: xplus = 2;
1092: else
1093: xplus = 1;
1094:
1095: t = dma_record_toggle ^ 1;
1096: y = line / yplus - 8;
1097:
1098: if (y < 0)
1099: return;
1100: if (y > maxvpos)
1101: return;
1102: if (y >= height)
1103: return;
1104:
1105: dx = width - xplus * ((maxhpos + 1) & ~1) - 16;
1106:
1107: cc[0] = lc(0x222222);
1108: cc[DMARECORD_REFRESH] = lc(0x444444);
1109: cc[DMARECORD_CPU] = lc(0x888888);
1110: cc[DMARECORD_COPPER] = lc(0xeeee00);
1111: cc[DMARECORD_AUDIO] = lc(0xff0000);
1112: cc[DMARECORD_BLITTER] = lc(0x008888);
1113: cc[DMARECORD_BLITTER_FILL] = lc(0x0088ff);
1114: cc[DMARECORD_BLITTER_LINE] = lc(0x00ff00);
1115: cc[DMARECORD_BITPLANE] = lc(0x0000ff);
1116: cc[DMARECORD_SPRITE] = lc(0xff00ff);
1117: cc[DMARECORD_DISK] = lc(0xffffff);
1118:
1119: uae_s8 intlev = 0;
1120: for (x = 0; x < maxhpos; x++) {
1121: uae_u32 c = cc[0];
1122: xx = x * xplus + dx;
1123: dr = &dma_record[t][y * NR_DMA_REC_HPOS + x];
1124: if (dr->reg != 0xffff) {
1125: c = cc[dr->type];
1126: }
1127: if (dr->intlev > intlev)
1128: intlev = dr->intlev;
1129: putpixel (buf, bpp, xx + 4, c);
1130: if (xplus)
1131: putpixel (buf, bpp, xx + 4 + 1, c);
1132: }
1133: putpixel (buf, bpp, dx + 0, 0);
1134: putpixel (buf, bpp, dx + 1, lc(intlevc[intlev]));
1135: putpixel (buf, bpp, dx + 2, lc(intlevc[intlev]));
1136: putpixel (buf, bpp, dx + 3, 0);
1137: }
1138:
1139: #define HEATMAP_COUNT 50
1140: static struct memory_heatmap *heatmap;
1141: struct memory_heatmap
1142: {
1143: uae_u16 cnt;
1144: uae_u16 type;
1145: };
1146:
1147: static void memwatch_heatmap (uaecptr addr, int rwi, int size)
1148: {
1149: }
1150:
1151: static void record_dma_heatmap (uaecptr addr, int type)
1152: {
1153: if (addr >= 0x01000000 || !heatmap)
1154: return;
1155: struct memory_heatmap *hp = &heatmap[addr / 2];
1156: hp->cnt = HEATMAP_COUNT;
1157: hp->type = type;
1158: }
1159:
1160: void record_dma_event (int evt, int hpos, int vpos)
1161: {
1162: struct dma_rec *dr;
1163:
1164: if (!dma_record[0])
1165: return;
1166: if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
1167: return;
1168: dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
1169: dr->evt |= evt;
1170: }
1171:
1172: struct dma_rec *record_dma (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos, int vpos, int type)
1173: {
1174: struct dma_rec *dr;
1175:
1176: if (!heatmap)
1177: heatmap = xcalloc (struct memory_heatmap, 16 * 1024 * 1024 / 2);
1178: if (!dma_record[0]) {
1179: dma_record[0] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
1180: dma_record[1] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
1181: dma_record_toggle = 0;
1182: record_dma_reset ();
1183: }
1184: if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
1185: return NULL;
1186:
1187: record_dma_heatmap (addr, type);
1188:
1189: dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
1190: if (dr->reg != 0xffff) {
1191: write_log (_T("DMA conflict: v=%d h=%d OREG=%04X NREG=%04X\n"), vpos, hpos, dr->reg, reg);
1192: return dr;
1193: }
1194: dr->reg = reg;
1195: dr->dat = dat;
1196: dr->addr = addr;
1197: dr->type = type;
1198: dr->intlev = regs.intmask;
1199: return dr;
1200: }
1201:
1202: static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
1203: {
1204: struct dma_rec *dr;
1205: int h, i, maxh, cnt;
1206: uae_u32 cycles;
1207:
1208: if (!dma_record[0])
1209: return;
1210: dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS];
1211: if (logfile)
1212: write_dlog (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
1213: else
1214: console_out_f (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
1215: h = hpos;
1216: dr += hpos;
1217: maxh = hpos + 80;
1218: if (maxh > maxhpos)
1219: maxh = maxhpos;
1220: cycles = vsync_cycles;
1221: if (toggle)
1222: cycles -= maxvpos * maxhpos * CYCLE_UNIT;
1223: cnt = 0;
1224: while (h < maxh) {
1225: int col = 9;
1226: int cols = 8;
1227: TCHAR l1[81];
1228: TCHAR l2[81];
1229: TCHAR l3[81];
1230: TCHAR l4[81];
1231: TCHAR l5[81];
1232: for (i = 0; i < cols && h < maxh; i++, h++, dr++) {
1233: int cl = i * col, cl2;
1234: int r = dr->reg;
1235: bool longsize = false;
1236: TCHAR *sr;
1237:
1238: sr = _T(" ");
1239: if (dr->type == DMARECORD_COPPER)
1240: sr = _T("COP ");
1241: else if (dr->type == DMARECORD_BLITTER)
1242: sr = _T("BLT ");
1243: else if (dr->type == DMARECORD_BLITTER_LINE)
1244: sr = _T("BLL ");
1245: else if (dr->type == DMARECORD_REFRESH)
1246: sr = _T("RFS ");
1247: else if (dr->type == DMARECORD_AUDIO)
1248: sr = _T("AUD ");
1249: else if (dr->type == DMARECORD_DISK)
1250: sr = _T("DSK ");
1251: else if (dr->type == DMARECORD_SPRITE)
1252: sr = _T("SPR ");
1253: _stprintf (l1 + cl, _T("[%02X %3d]"), h, h);
1254: _tcscpy (l4 + cl, _T(" "));
1255: if (r != 0xffff) {
1256: if (r & 0x1000) {
1257: if ((r & 0x0100) == 0x0000)
1258: _tcscpy (l2 + cl, _T(" CPU-R "));
1259: else if ((r & 0x0100) == 0x0100)
1260: _tcscpy (l2 + cl, _T(" CPU-W "));
1261: if ((r & 0xff) == 4) {
1262: l2[cl + 7] = 'L';
1263: longsize = true;
1264: }
1265: if ((r & 0xff) == 2)
1266: l2[cl + 7] = 'W';
1267: if ((r & 0xff) == 1)
1268: l2[cl + 7] = 'B';
1269: } else {
1270: _stprintf (l2 + cl, _T("%4s %03X"), sr, r);
1271: }
1272: _stprintf (l3 + cl, longsize ? _T("%08X") : _T(" %04X"), dr->dat);
1273: if (dr->addr != 0xffffffff)
1274: _stprintf (l4 + cl, _T("%08X"), dr->addr & 0x00ffffff);
1275: } else {
1276: _tcscpy (l2 + cl, _T(" "));
1277: _tcscpy (l3 + cl, _T(" "));
1278: }
1279: cl2 = cl;
1280: if (dr->evt & DMA_EVENT_BLITNASTY)
1281: l3[cl2++] = 'N';
1282: if (dr->evt & DMA_EVENT_BLITSTARTFINISH)
1283: l3[cl2++] = 'B';
1284: if (dr->evt & DMA_EVENT_BLITIRQ)
1285: l3[cl2++] = 'b';
1286: if (dr->evt & DMA_EVENT_BPLFETCHUPDATE)
1287: l3[cl2++] = 'p';
1288: if (dr->evt & DMA_EVENT_COPPERWAKE)
1289: l3[cl2++] = 'W';
1290: if (dr->evt & DMA_EVENT_COPPERWANTED)
1291: l3[cl2++] = 'c';
1292: if (dr->evt & DMA_EVENT_CPUIRQ)
1293: l3[cl2++] = 'I';
1294: if (dr->evt & DMA_EVENT_INTREQ)
1295: l3[cl2++] = 'i';
1296: _stprintf (l5 + cl, _T("%08X"), cycles + (vpos * maxhpos + (hpos + cnt)) * CYCLE_UNIT);
1297: if (i < cols - 1 && h < maxh - 1) {
1298: l1[cl + col - 1] = 32;
1299: l2[cl + col - 1] = 32;
1300: l3[cl + col - 1] = 32;
1301: l4[cl + col - 1] = 32;
1302: l5[cl + col - 1] = 32;
1303: }
1304: cnt++;
1305: }
1306: if (logfile) {
1307: write_dlog (_T("%s\n"), l1);
1308: write_dlog (_T("%s\n"), l2);
1309: write_dlog (_T("%s\n"), l3);
1310: write_dlog (_T("%s\n"), l4);
1311: write_dlog (_T("%s\n"), l5);
1312: write_dlog (_T("\n"));
1313: } else {
1314: console_out_f (_T("%s\n"), l1);
1315: console_out_f (_T("%s\n"), l2);
1316: console_out_f (_T("%s\n"), l3);
1317: console_out_f (_T("%s\n"), l4);
1318: console_out_f (_T("%s\n"), l5);
1319: console_out_f (_T("\n"));
1320: }
1321: }
1322: }
1323: void log_dma_record (void)
1324: {
1325: if (!input_record && !input_play)
1326: return;
1327: if (!debug_dma)
1328: debug_dma = 1;
1329: decode_dma_record (0, 0, 0, true);
1330: }
1331:
1332: static void init_record_copper(void)
1333: {
1334: if (!cop_record[0]) {
1335: cop_record[0] = xmalloc(struct cop_rec, NR_COPPER_RECORDS);
1336: cop_record[1] = xmalloc(struct cop_rec, NR_COPPER_RECORDS);
1337: }
1338: }
1339:
1340: void record_copper_blitwait (uaecptr addr, int hpos, int vpos)
1341: {
1342: int t = nr_cop_records[curr_cop_set];
1343: init_record_copper();
1344: cop_record[curr_cop_set][t].bhpos = hpos;
1345: cop_record[curr_cop_set][t].bvpos = vpos;
1346: }
1347:
1348: void record_copper (uaecptr addr, uae_u16 word1, uae_u16 word2, int hpos, int vpos)
1349: {
1350: int t = nr_cop_records[curr_cop_set];
1351: init_record_copper();
1352: if (t < NR_COPPER_RECORDS) {
1353: cop_record[curr_cop_set][t].addr = addr;
1354: cop_record[curr_cop_set][t].w1 = word1;
1355: cop_record[curr_cop_set][t].w2 = word2;
1356: cop_record[curr_cop_set][t].hpos = hpos;
1357: cop_record[curr_cop_set][t].vpos = vpos;
1358: cop_record[curr_cop_set][t].bvpos = -1;
1359: nr_cop_records[curr_cop_set] = t + 1;
1360: }
1361: if (debug_copper & 2) { /* trace */
1362: debug_copper &= ~2;
1363: activate_debugger ();
1364: }
1365: if ((debug_copper & 4) && addr >= debug_copper_pc && addr <= debug_copper_pc + 3) {
1366: debug_copper &= ~4;
1367: activate_debugger ();
1368: }
1369: }
1370:
1371: static struct cop_rec *find_copper_records (uaecptr addr)
1372: {
1373: int s = curr_cop_set ^ 1;
1374: int t = nr_cop_records[s];
1375: int i;
1376: for (i = 0; i < t; i++) {
1377: if (cop_record[s][i].addr == addr)
1378: return &cop_record[s][i];
1379: }
1380: return 0;
1381: }
1382:
1383: /* simple decode copper by Mark Cox */
1384: static void decode_copper_insn (FILE* file, uae_u16 mword1, uae_u16 mword2, unsigned long addr)
1385: {
1386: struct cop_rec *cr = NULL;
1387: uae_u32 insn_type, insn;
1388: TCHAR here = ' ';
1389: TCHAR record[] = _T(" ");
1390:
1391: if ((cr = find_copper_records (addr))) {
1392: _stprintf (record, _T(" [%03x %03x]"), cr->vpos, cr->hpos);
1393: insn = (cr->w1 << 16) | cr->w2;
1394: } else {
1395: insn = (mword1 << 16) | mword2;
1396: }
1397:
1398: insn_type = insn & 0x00010001;
1399:
1400: if (get_copper_address (-1) >= addr && get_copper_address(-1) <= addr + 3)
1401: here = '*';
1402:
1403: console_out_f (_T("%c%08x: %04x %04x%s\t;%c "), here, addr, insn >> 16, insn & 0xFFFF, record, insn != ((mword1 << 16) | mword2) ? '!' : ' ');
1404:
1405: switch (insn_type) {
1406: case 0x00010000: /* WAIT insn */
1407: console_out (_T("Wait for "));
1408: disassemble_wait (file, insn);
1409:
1410: if (insn == 0xfffffffe)
1411: console_out (_T(" \t; End of Copperlist\n"));
1412:
1413: break;
1414:
1415: case 0x00010001: /* SKIP insn */
1416: console_out (_T("Skip if "));
1417: disassemble_wait (file, insn);
1418: break;
1419:
1420: case 0x00000000:
1421: case 0x00000001: /* MOVE insn */
1422: {
1423: int addr = (insn >> 16) & 0x1fe;
1424: int i = 0;
1425: while (custd[i].name) {
1426: if (custd[i].adr == addr + 0xdff000)
1427: break;
1428: i++;
1429: }
1430: if (custd[i].name)
1431: console_out_f (_T("%s := 0x%04x\n"), custd[i].name, insn & 0xffff);
1432: else
1433: console_out_f (_T("%04x := 0x%04x\n"), addr, insn & 0xffff);
1434: }
1435: break;
1436:
1437: default:
1438: abort ();
1439: }
1440:
1441: if (cr && cr->bvpos >= 0) {
1442: console_out_f (_T(" BLT [%03x %03x]\n"), cr->bvpos, cr->bhpos);
1443: }
1444: }
1445:
1446: static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
1447: {
1448: while (nolines-- > 0) {
1449: decode_copper_insn (file, chipmem_wget_indirect (address), chipmem_wget_indirect (address + 2), address);
1450: address += 4;
1451: }
1452: return address;
1453: /* You may wonder why I don't stop this at the end of the copperlist?
1454: * Well, often nice things are hidden at the end and it is debatable the actual
1455: * values that mean the end of the copperlist */
1456: }
1457:
1458: static int copper_debugger (TCHAR **c)
1459: {
1460: static uaecptr nxcopper;
1461: uae_u32 maddr;
1462: int lines;
1463:
1464: if (**c == 'd') {
1465: next_char (c);
1466: if (debug_copper)
1467: debug_copper = 0;
1468: else
1469: debug_copper = 1;
1470: console_out_f (_T("Copper debugger %s.\n"), debug_copper ? _T("enabled") : _T("disabled"));
1471: } else if (**c == 't') {
1472: debug_copper = 1|2;
1473: return 1;
1474: } else if (**c == 'b') {
1475: (*c)++;
1476: debug_copper = 1|4;
1477: if (more_params (c)) {
1478: debug_copper_pc = readhex (c);
1479: console_out_f (_T("Copper breakpoint @0x%08x\n"), debug_copper_pc);
1480: } else {
1481: debug_copper &= ~4;
1482: }
1483: } else {
1484: if (more_params (c)) {
1485: maddr = readhex (c);
1486: if (maddr == 1 || maddr == 2)
1487: maddr = get_copper_address (maddr);
1488: else if (maddr == 0)
1489: maddr = get_copper_address (-1);
1490: } else
1491: maddr = nxcopper;
1492:
1493: if (more_params (c))
1494: lines = readhex (c);
1495: else
1496: lines = 20;
1497:
1498: nxcopper = decode_copperlist (stdout, maddr, lines);
1499: }
1500: return 0;
1501: }
1502:
1503: #define MAX_CHEAT_VIEW 100
1504: struct trainerstruct {
1505: uaecptr addr;
1506: int size;
1507: };
1508:
1509: static struct trainerstruct *trainerdata;
1510: static int totaltrainers;
1511:
1512: static void clearcheater(void)
1513: {
1514: if (!trainerdata)
1515: trainerdata = xmalloc(struct trainerstruct, MAX_CHEAT_VIEW);
1516: memset(trainerdata, 0, sizeof (struct trainerstruct) * MAX_CHEAT_VIEW);
1517: totaltrainers = 0;
1518: }
1519: static int addcheater(uaecptr addr, int size)
1520: {
1521: if (totaltrainers >= MAX_CHEAT_VIEW)
1522: return 0;
1523: trainerdata[totaltrainers].addr = addr;
1524: trainerdata[totaltrainers].size = size;
1525: totaltrainers++;
1526: return 1;
1527: }
1528: static void listcheater(int mode, int size)
1529: {
1530: int i, skip;
1531:
1532: if (!trainerdata)
1533: return;
1534: if (mode)
1535: skip = 6;
1536: else
1537: skip = 8;
1538: for(i = 0; i < totaltrainers; i++) {
1539: struct trainerstruct *ts = &trainerdata[i];
1540: uae_u16 b;
1541:
1542: if (size) {
1543: b = get_byte_debug (ts->addr);
1544: } else {
1545: b = get_word_debug (ts->addr);
1546: }
1547: if (mode)
1548: console_out_f (_T("%08X=%04X "), ts->addr, b);
1549: else
1550: console_out_f (_T("%08X "), ts->addr);
1551: if ((i % skip) == skip)
1552: console_out (_T("\n"));
1553: }
1554: }
1555:
1556: static void deepcheatsearch (TCHAR **c)
1557: {
1558: static int first = 1;
1559: static uae_u8 *memtmp;
1560: static int memsize, memsize2;
1561: uae_u8 *p1, *p2;
1562: uaecptr addr, end;
1563: int i, wasmodified, nonmodified;
1564: static int size;
1565: static int inconly, deconly, maxdiff;
1566: int addrcnt, cnt;
1567: TCHAR v;
1568:
1569: v = _totupper (**c);
1570:
1571: if(!memtmp || v == 'S') {
1572: maxdiff = 0x10000;
1573: inconly = 0;
1574: deconly = 0;
1575: size = 1;
1576: }
1577:
1578: if (**c)
1579: (*c)++;
1580: ignore_ws (c);
1581: if ((**c) == '1' || (**c) == '2') {
1582: size = **c - '0';
1583: (*c)++;
1584: }
1585: if (more_params (c))
1586: maxdiff = readint (c);
1587:
1588: if (!memtmp || v == 'S') {
1589: first = 1;
1590: xfree (memtmp);
1591: memsize = 0;
1592: addr = 0xffffffff;
1593: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
1594: memsize += end - addr;
1595: addr = end - 1;
1596: }
1597: memsize2 = (memsize + 7) / 8;
1598: memtmp = xmalloc (uae_u8, memsize + memsize2);
1599: if (!memtmp)
1600: return;
1601: memset (memtmp + memsize, 0xff, memsize2);
1602: p1 = memtmp;
1603: addr = 0xffffffff;
1604: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
1605: for (i = addr; i < end; i++)
1606: *p1++ = get_byte_debug (i);
1607: addr = end - 1;
1608: }
1609: console_out (_T("Deep trainer first pass complete.\n"));
1610: return;
1611: }
1612: inconly = deconly = 0;
1613: wasmodified = v == 'X' ? 0 : 1;
1614: nonmodified = v == 'Z' ? 1 : 0;
1615: if (v == 'I')
1616: inconly = 1;
1617: if (v == 'D')
1618: deconly = 1;
1619: p1 = memtmp;
1620: p2 = memtmp + memsize;
1621: addrcnt = 0;
1622: cnt = 0;
1623: addr = 0xffffffff;
1624: while ((addr = nextaddr (addr, 0, NULL)) != 0xffffffff) {
1625: uae_s32 b, b2;
1626: int doremove = 0;
1627: int addroff = addrcnt >> 3;
1628: int addrmask ;
1629:
1630: if (size == 1) {
1631: b = (uae_s8)get_byte_debug (addr);
1632: b2 = (uae_s8)p1[addrcnt];
1633: addrmask = 1 << (addrcnt & 7);
1634: } else {
1635: b = (uae_s16)get_word_debug (addr);
1636: b2 = (uae_s16)((p1[addrcnt] << 8) | p1[addrcnt + 1]);
1637: addrmask = 3 << (addrcnt & 7);
1638: }
1639:
1640: if (p2[addroff] & addrmask) {
1641: if (wasmodified && !nonmodified) {
1642: int diff = b - b2;
1643: if (b == b2)
1644: doremove = 1;
1645: if (abs(diff) > maxdiff)
1646: doremove = 1;
1647: if (inconly && diff < 0)
1648: doremove = 1;
1649: if (deconly && diff > 0)
1650: doremove = 1;
1651: } else if (nonmodified && b == b2) {
1652: doremove = 1;
1653: } else if (!wasmodified && b != b2) {
1654: doremove = 1;
1655: }
1656: if (doremove)
1657: p2[addroff] &= ~addrmask;
1658: else
1659: cnt++;
1660: }
1661: if (size == 1) {
1662: p1[addrcnt] = b;
1663: addrcnt++;
1664: } else {
1665: p1[addrcnt] = b >> 8;
1666: p1[addrcnt + 1] = b >> 0;
1667: addr = nextaddr (addr, 0, NULL);
1668: if (addr == 0xffffffff)
1669: break;
1670: addrcnt += 2;
1671: }
1672: if (iscancel (65536)) {
1673: console_out_f (_T("Aborted at %08X\n"), addr);
1674: break;
1675: }
1676: }
1677:
1678: console_out_f (_T("%d addresses found\n"), cnt);
1679: if (cnt <= MAX_CHEAT_VIEW) {
1680: clearcheater ();
1681: cnt = 0;
1682: addrcnt = 0;
1683: addr = 0xffffffff;
1684: while ((addr = nextaddr(addr, 0, NULL)) != 0xffffffff) {
1685: int addroff = addrcnt >> 3;
1686: int addrmask = (size == 1 ? 1 : 3) << (addrcnt & 7);
1687: if (p2[addroff] & addrmask)
1688: addcheater (addr, size);
1689: addrcnt += size;
1690: cnt++;
1691: }
1692: if (cnt > 0)
1693: console_out (_T("\n"));
1694: listcheater (1, size);
1695: } else {
1696: console_out (_T("Now continue with 'g' and use 'D' again after you have lost another life\n"));
1697: }
1698: }
1699:
1700: /* cheat-search by Toni Wilen (originally by Holger Jakob) */
1701: static void cheatsearch (TCHAR **c)
1702: {
1703: static uae_u8 *vlist;
1704: static int listsize;
1705: static int first = 1;
1706: static int size = 1;
1707: uae_u32 val, memcnt, prevmemcnt;
1708: int i, count, vcnt, memsize;
1709: uaecptr addr, end;
1710:
1711: memsize = 0;
1712: addr = 0xffffffff;
1713: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
1714: memsize += end - addr;
1715: addr = end - 1;
1716: }
1717:
1718: if (_totupper (**c) == 'L') {
1719: listcheater (1, size);
1720: return;
1721: }
1722: ignore_ws (c);
1723: if (!more_params (c)) {
1724: first = 1;
1725: console_out (_T("Search reset\n"));
1726: xfree (vlist);
1727: listsize = memsize;
1728: vlist = xcalloc (uae_u8, listsize >> 3);
1729: return;
1730: }
1731: if (first)
1732: val = readint (c, &size);
1733: else
1734: val = readint (c);
1735:
1736: if (vlist == NULL) {
1737: listsize = memsize;
1738: vlist = xcalloc (uae_u8, listsize >> 3);
1739: }
1740:
1741: count = 0;
1742: vcnt = 0;
1743:
1744: clearcheater ();
1745: addr = 0xffffffff;
1746: prevmemcnt = memcnt = 0;
1747: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
1748: if (addr + size < end) {
1749: for (i = 0; i < size; i++) {
1750: int shift = (size - i - 1) * 8;
1751: if (get_byte_debug (addr + i) != ((val >> shift) & 0xff))
1752: break;
1753: }
1754: if (i == size) {
1755: int voffset = memcnt >> 3;
1756: int vmask = 1 << (memcnt & 7);
1757: if (!first) {
1758: while (prevmemcnt < memcnt) {
1759: vlist[prevmemcnt >> 3] &= ~(1 << (prevmemcnt & 7));
1760: prevmemcnt++;
1761: }
1762: if (vlist[voffset] & vmask) {
1763: count++;
1764: addcheater(addr, size);
1765: } else {
1766: vlist[voffset] &= ~vmask;
1767: }
1768: prevmemcnt = memcnt + 1;
1769: } else {
1770: vlist[voffset] |= vmask;
1771: count++;
1772: }
1773: }
1774: }
1775: memcnt++;
1776: if (iscancel (65536)) {
1777: console_out_f (_T("Aborted at %08X\n"), addr);
1778: break;
1779: }
1780: }
1781: if (!first) {
1782: while (prevmemcnt < memcnt) {
1783: vlist[prevmemcnt >> 3] &= ~(1 << (prevmemcnt & 7));
1784: prevmemcnt++;
1785: }
1786: listcheater (0, size);
1787: }
1788: console_out_f (_T("Found %d possible addresses with 0x%X (%u) (%d bytes)\n"), count, val, val, size);
1789: if (count > 0)
1790: console_out (_T("Now continue with 'g' and use 'C' with a different value\n"));
1791: first = 0;
1792: }
1793:
1794: struct breakpoint_node bpnodes[BREAKPOINT_TOTAL];
1795: static addrbank **debug_mem_banks;
1796: static addrbank *debug_mem_area;
1797: struct memwatch_node mwnodes[MEMWATCH_TOTAL];
1798: static struct memwatch_node mwhit;
1799: static int addressspaceheatmap;
1800:
1801: static uae_u8 *illgdebug, *illghdebug;
1802: static int illgdebug_break;
1803:
1804: static void illg_free (void)
1805: {
1806: xfree (illgdebug);
1807: illgdebug = NULL;
1808: xfree (illghdebug);
1809: illghdebug = NULL;
1810: }
1811:
1812: static void illg_init (void)
1813: {
1814: int i;
1815: uae_u8 c = 3;
1816: uaecptr addr, end;
1817:
1818: illgdebug = xcalloc (uae_u8, 0x01000000);
1819: illghdebug = xcalloc (uae_u8, 65536);
1820: if (!illgdebug || !illghdebug) {
1821: illg_free();
1822: return;
1823: }
1824: addr = 0xffffffff;
1825: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
1826: if (end < 0x01000000) {
1827: memset (illgdebug + addr, c, end - addr);
1828: } else {
1829: uae_u32 s = addr >> 16;
1830: uae_u32 e = end >> 16;
1831: memset (illghdebug + s, c, e - s);
1832: }
1833: addr = end - 1;
1834: }
1835: if (currprefs.rtgmem_size)
1836: memset (illghdebug + (gfxmem_bank.start >> 16), 3, currprefs.rtgmem_size >> 16);
1837:
1838: i = 0;
1839: while (custd[i].name) {
1840: int rw = custd[i].rw;
1841: illgdebug[custd[i].adr] = rw;
1842: illgdebug[custd[i].adr + 1] = rw;
1843: i++;
1844: }
1845: for (i = 0; i < 16; i++) { /* CIAs */
1846: if (i == 11)
1847: continue;
1848: illgdebug[0xbfe001 + i * 0x100] = c;
1849: illgdebug[0xbfd000 + i * 0x100] = c;
1850: }
1851: memset (illgdebug + 0xf80000, 1, 512 * 1024); /* KS ROM */
1852: memset (illgdebug + 0xdc0000, c, 0x3f); /* clock */
1853: #ifdef CDTV
1854: if (currprefs.cs_cdtvram) {
1855: memset (illgdebug + 0xdc8000, c, 4096); /* CDTV batt RAM */
1856: memset (illgdebug + 0xf00000, 1, 256 * 1024); /* CDTV ext ROM */
1857: }
1858: #endif
1859: #ifdef CD32
1860: if (currprefs.cs_cd32cd) {
1861: memset (illgdebug + AKIKO_BASE, c, AKIKO_BASE_END - AKIKO_BASE);
1862: memset (illgdebug + 0xe00000, 1, 512 * 1024); /* CD32 ext ROM */
1863: }
1864: #endif
1865: if (currprefs.cs_ksmirror_e0)
1866: memset (illgdebug + 0xe00000, 1, 512 * 1024);
1867: if (currprefs.cs_ksmirror_a8)
1868: memset (illgdebug + 0xa80000, 1, 2 * 512 * 1024);
1869: #ifdef FILESYS
1870: if (uae_boot_rom_type) /* filesys "rom" */
1871: memset (illgdebug + rtarea_base, 1, 0x10000);
1872: #endif
1873: if (currprefs.cs_ide > 0)
1874: memset (illgdebug + 0xdd0000, 3, 65536);
1875: }
1876:
1877: /* add special custom register check here */
1878: static void illg_debug_check (uaecptr addr, int rwi, int size, uae_u32 val)
1879: {
1880: return;
1881: }
1882:
1883: static void illg_debug_do (uaecptr addr, int rwi, int size, uae_u32 val)
1884: {
1885: uae_u8 mask;
1886: uae_u32 pc = m68k_getpc ();
1887: int i;
1888:
1889: for (i = size - 1; i >= 0; i--) {
1890: uae_u8 v = val >> (i * 8);
1891: uae_u32 ad = addr + i;
1892: if (ad >= 0x01000000)
1893: mask = illghdebug[ad >> 16];
1894: else
1895: mask = illgdebug[ad];
1896: if ((mask & 3) == 3)
1897: return;
1898: if (mask & 0x80) {
1899: illg_debug_check (ad, rwi, size, val);
1900: } else if ((mask & 3) == 0) {
1901: if (rwi & 2)
1902: console_out_f (_T("W: %08X=%02X PC=%08X\n"), ad, v, pc);
1903: else if (rwi & 1)
1904: console_out_f (_T("R: %08X PC=%08X\n"), ad, pc);
1905: if (illgdebug_break)
1906: activate_debugger ();
1907: } else if (!(mask & 1) && (rwi & 1)) {
1908: console_out_f (_T("RO: %08X=%02X PC=%08X\n"), ad, v, pc);
1909: if (illgdebug_break)
1910: activate_debugger ();
1911: } else if (!(mask & 2) && (rwi & 2)) {
1912: console_out_f (_T("WO: %08X PC=%08X\n"), ad, pc);
1913: if (illgdebug_break)
1914: activate_debugger ();
1915: }
1916: }
1917: }
1918:
1919: static int debug_mem_off (uaecptr *addrp)
1920: {
1921: uaecptr addr = *addrp;
1922: addrbank *ba;
1923: int offset = munge24 (addr) >> 16;
1924: if (!debug_mem_banks)
1925: return offset;
1926: ba = debug_mem_banks[offset];
1927: if (!ba)
1928: return offset;
1929: if (ba->mask || ba->startmask)
1930: addr = (addr & ba->mask) | ba->startmask;
1931: *addrp = addr;
1932: return offset;
1933: }
1934:
1935: struct smc_item {
1936: uae_u32 addr;
1937: uae_u8 cnt;
1938: };
1939:
1940: static int smc_size, smc_mode;
1941: static struct smc_item *smc_table;
1942:
1943: static void smc_free (void)
1944: {
1945: if (smc_table)
1946: console_out (_T("SMCD disabled\n"));
1947: xfree(smc_table);
1948: smc_mode = 0;
1949: smc_table = NULL;
1950: }
1951:
1952: static void initialize_memwatch (int mode);
1953: static void smc_detect_init (TCHAR **c)
1954: {
1955: int v, i;
1956:
1957: ignore_ws (c);
1958: v = readint (c);
1959: smc_free ();
1960: smc_size = 1 << 24;
1961: if (currprefs.z3fastmem_size)
1962: smc_size = currprefs.z3autoconfig_start + currprefs.z3fastmem_size;
1963: smc_size += 4;
1964: smc_table = xmalloc (struct smc_item, smc_size);
1965: if (!smc_table)
1966: return;
1967: for (i = 0; i < smc_size; i++) {
1968: smc_table[i].addr = 0xffffffff;
1969: smc_table[i].cnt = 0;
1970: }
1971: if (!memwatch_enabled)
1972: initialize_memwatch (0);
1973: if (v)
1974: smc_mode = 1;
1975: console_out_f (_T("SMCD enabled. Break=%d\n"), smc_mode);
1976: }
1977:
1978: #define SMC_MAXHITS 8
1979: static void smc_detector (uaecptr addr, int rwi, int size, uae_u32 *valp)
1980: {
1981: int i, hitcnt;
1982: uaecptr hitaddr, hitpc;
1983:
1984: if (!smc_table)
1985: return;
1986: if (addr >= smc_size)
1987: return;
1988: if (rwi == 2) {
1989: for (i = 0; i < size; i++) {
1990: if (smc_table[addr + i].cnt < SMC_MAXHITS) {
1991: smc_table[addr + i].addr = m68k_getpc ();
1992: }
1993: }
1994: return;
1995: }
1996: hitpc = smc_table[addr].addr;
1997: if (hitpc == 0xffffffff)
1998: return;
1999: hitaddr = addr;
2000: hitcnt = 0;
2001: while (addr < smc_size && smc_table[addr].addr != 0xffffffff) {
2002: smc_table[addr++].addr = 0xffffffff;
2003: hitcnt++;
2004: }
2005: if ((hitpc & 0xFFF80000) == 0xF80000)
2006: return;
2007: if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
2008: /* ignore single-word unconditional jump instructions
2009: * (instruction prefetch from PC+2 can cause false positives) */
2010: if (regs.irc == 0x4e75 || regs.irc == 4e74 || regs.irc == 0x4e72 || regs.irc == 0x4e77)
2011: return; /* RTS, RTD, RTE, RTR */
2012: if ((regs.irc & 0xff00) == 0x6000 && (regs.irc & 0x00ff) != 0 && (regs.irc & 0x00ff) != 0xff)
2013: return; /* BRA.B */
2014: }
2015: if (hitcnt < 100) {
2016: smc_table[hitaddr].cnt++;
2017: console_out_f (_T("SMC at %08X - %08X (%d) from %08X\n"),
2018: hitaddr, hitaddr + hitcnt, hitcnt, hitpc);
2019: if (smc_mode)
2020: activate_debugger ();
2021: if (smc_table[hitaddr].cnt >= SMC_MAXHITS)
2022: console_out_f (_T("* hit count >= %d, future hits ignored\n"), SMC_MAXHITS);
2023: }
2024: }
2025:
2026: uae_u8 *save_debug_memwatch (int *len, uae_u8 *dstptr)
2027: {
2028: uae_u8 *dstbak, *dst;
2029: int total;
2030:
2031: total = 0;
2032: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2033: if (mwnodes[i].size > 0)
2034: total++;
2035: }
2036: if (!total)
2037: return NULL;
2038:
2039: if (dstptr)
2040: dstbak = dst = dstptr;
2041: else
2042: dstbak = dst = xmalloc (uae_u8, 1000);
2043: save_u32 (1);
2044: save_u8 (total);
2045: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2046: struct memwatch_node *m = &mwnodes[i];
2047: if (m->size <= 0)
2048: continue;
2049: save_store_pos ();
2050: save_u8 (i);
2051: save_u8 (m->modval_written);
2052: save_u8 (m->mustchange);
2053: save_u8 (m->frozen);
2054: save_u8 (m->val_enabled);
2055: save_u8 (m->rwi);
2056: save_u32 (m->addr);
2057: save_u32 (m->size);
2058: save_u32 (m->modval);
2059: save_u32 (m->val_mask);
2060: save_u32 (m->val_size);
2061: save_u32 (m->val);
2062: save_u32 (m->pc);
2063: save_u32 (m->access_mask);
2064: save_u32 (m->reg);
2065: save_store_size ();
2066: }
2067: *len = dst - dstbak;
2068: return dstbak;
2069: }
2070:
2071: uae_u8 *restore_debug_memwatch (uae_u8 *src)
2072: {
2073: if (restore_u32 () != 1)
2074: return src;
2075: int total = restore_u8 ();
2076: for (int i = 0; i < total; i++) {
2077: restore_store_pos ();
2078: int idx = restore_u8 ();
2079: struct memwatch_node *m = &mwnodes[idx];
2080: m->modval_written = restore_u8 ();
2081: m->mustchange = restore_u8 ();
2082: m->frozen = restore_u8 ();
2083: m->val_enabled = restore_u8 ();
2084: m->rwi = restore_u8 ();
2085: m->addr = restore_u32 ();
2086: m->size = restore_u32 ();
2087: m->modval = restore_u32 ();
2088: m->val_mask = restore_u32 ();
2089: m->val_size = restore_u32 ();
2090: m->val = restore_u32 ();
2091: m->pc = restore_u32 ();
2092: m->access_mask = restore_u32();
2093: m->reg = restore_u32();
2094: restore_store_size ();
2095: }
2096: return src;
2097: }
2098:
2099: void restore_debug_memwatch_finish (void)
2100: {
2101: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2102: struct memwatch_node *m = &mwnodes[i];
2103: if (m->size) {
2104: if (!memwatch_enabled)
2105: initialize_memwatch (0);
2106: return;
2107: }
2108: }
2109: }
2110:
2111: static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u32 accessmask, uae_u32 reg)
2112: {
2113: int i, brk;
2114: uae_u32 val = *valp;
2115:
2116: if (illgdebug)
2117: illg_debug_do (addr, rwi, size, val);
2118:
2119: if (addressspaceheatmap)
2120: memwatch_heatmap (addr, rwi, size);
2121:
2122: addr = munge24 (addr);
2123: if (smc_table && (rwi >= 2))
2124: smc_detector (addr, rwi, size, valp);
2125: for (i = 0; i < MEMWATCH_TOTAL; i++) {
2126: struct memwatch_node *m = &mwnodes[i];
2127: uaecptr addr2 = m->addr;
2128: uaecptr addr3 = addr2 + m->size;
2129: int rwi2 = m->rwi;
2130: uae_u32 oldval = 0;
2131: int isoldval = 0;
2132:
2133: brk = 0;
2134: if (m->size == 0)
2135: continue;
2136: if (!(rwi & rwi2))
2137: continue;
2138: if (!(m->access_mask & accessmask))
2139: continue;
2140:
2141: if (addr >= addr2 && addr < addr3)
2142: brk = 1;
2143: if (!brk && size == 2 && (addr + 1 >= addr2 && addr + 1 < addr3))
2144: brk = 1;
2145: if (!brk && size == 4 && ((addr + 2 >= addr2 && addr + 2 < addr3) || (addr + 3 >= addr2 && addr + 3 < addr3)))
2146: brk = 1;
2147:
2148: if (!brk)
2149: continue;
2150: if (mem_banks[addr >> 16]->check (addr, size)) {
2151: uae_u8 *p = mem_banks[addr >> 16]->xlateaddr (addr);
2152: if (size == 1)
2153: oldval = p[0];
2154: else if (size == 2)
2155: oldval = (p[0] << 8) | p[1];
2156: else
2157: oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
2158: isoldval = 1;
2159: }
2160:
2161: if (!m->frozen && m->val_enabled) {
2162: int trigger = 0;
2163: uae_u32 mask = m->size == 4 ? 0xffffffff : (1 << (m->size * 8)) - 1;
2164: uae_u32 mval = m->val;
2165: int scnt = size;
2166: for (;;) {
2167: if (((mval & mask) & m->val_mask) == ((val & mask) & m->val_mask))
2168: trigger = 1;
2169: if (mask & 0x80000000)
2170: break;
2171: if (m->size == 1) {
2172: mask <<= 8;
2173: mval <<= 8;
2174: scnt--;
2175: } else if (m->size == 2) {
2176: mask <<= 16;
2177: scnt -= 2;
2178: mval <<= 16;
2179: } else {
2180: scnt -= 4;
2181: }
2182: if (scnt <= 0)
2183: break;
2184: }
2185: if (!trigger)
2186: continue;
2187: }
2188:
2189: if (m->mustchange && rwi == 2 && isoldval) {
2190: if (oldval == *valp)
2191: continue;
2192: }
2193:
2194: if (m->modval_written) {
2195: if (!rwi) {
2196: brk = 0;
2197: } else if (m->modval_written == 1) {
2198: m->modval_written = 2;
2199: m->modval = val;
2200: brk = 0;
2201: } else if (m->modval == val) {
2202: brk = 0;
2203: }
2204: }
2205: if (m->frozen) {
2206: if (m->val_enabled) {
2207: int shift = (addr + size - 1) - (m->addr + m->val_size - 1);
2208: uae_u32 sval;
2209: uae_u32 mask;
2210:
2211: if (m->val_size == 4)
2212: mask = 0xffffffff;
2213: else if (m->val_size == 2)
2214: mask = 0x0000ffff;
2215: else
2216: mask = 0x000000ff;
2217:
2218: sval = m->val;
2219: if (shift < 0) {
2220: shift = -8 * shift;
2221: sval >>= shift;
2222: mask >>= shift;
2223: } else {
2224: shift = 8 * shift;
2225: sval <<= shift;
2226: mask <<= shift;
2227: }
2228: *valp = (sval & mask) | ((*valp) & ~mask);
2229: write_log (_T("%p %p %08x %08x %d\n"), addr, m->addr, *valp, mask, shift);
2230: return 1;
2231: }
2232: return 0;
2233: }
2234: // if (!notinrom ())
2235: // return 1;
2236: mwhit.pc = M68K_GETPC;
2237: mwhit.addr = addr;
2238: mwhit.rwi = rwi;
2239: mwhit.size = size;
2240: mwhit.val = 0;
2241: mwhit.access_mask = accessmask;
2242: mwhit.reg = reg;
2243: if (mwhit.rwi & 2)
2244: mwhit.val = val;
2245: memwatch_triggered = i + 1;
2246: debugging = 1;
2247: set_special (SPCFLAG_BRK);
2248: return 1;
2249: }
2250: return 1;
2251: }
2252:
2253: #endif /* WINUAE_FOR_HATARI */
2254: #if 0
2255:
2256: static int mmu_hit (uaecptr addr, int size, int rwi, uae_u32 *v);
2257:
2258: static uae_u32 REGPARAM2 mmu_lget (uaecptr addr)
2259: {
2260: int off = debug_mem_off (&addr);
2261: uae_u32 v = 0;
2262: if (!mmu_hit (addr, 4, 0, &v))
2263: v = debug_mem_banks[off]->lget (addr);
2264: return v;
2265: }
2266: static uae_u32 REGPARAM2 mmu_wget (uaecptr addr)
2267: {
2268: int off = debug_mem_off (&addr);
2269: uae_u32 v = 0;
2270: if (!mmu_hit (addr, 2, 0, &v))
2271: v = debug_mem_banks[off]->wget (addr);
2272: return v;
2273: }
2274: static uae_u32 REGPARAM2 mmu_bget (uaecptr addr)
2275: {
2276: int off = debug_mem_off (&addr);
2277: uae_u32 v = 0;
2278: if (!mmu_hit(addr, 1, 0, &v))
2279: v = debug_mem_banks[off]->bget (addr);
2280: return v;
2281: }
2282: static void REGPARAM2 mmu_lput (uaecptr addr, uae_u32 v)
2283: {
2284: int off = debug_mem_off (&addr);
2285: if (!mmu_hit (addr, 4, 1, &v))
2286: debug_mem_banks[off]->lput (addr, v);
2287: }
2288: static void REGPARAM2 mmu_wput (uaecptr addr, uae_u32 v)
2289: {
2290: int off = debug_mem_off (&addr);
2291: if (!mmu_hit (addr, 2, 1, &v))
2292: debug_mem_banks[off]->wput (addr, v);
2293: }
2294: static void REGPARAM2 mmu_bput (uaecptr addr, uae_u32 v)
2295: {
2296: int off = debug_mem_off (&addr);
2297: if (!mmu_hit (addr, 1, 1, &v))
2298: debug_mem_banks[off]->bput (addr, v);
2299: }
2300:
2301: static uae_u32 REGPARAM2 debug_lget (uaecptr addr)
2302: {
2303: uae_u32 off = debug_mem_off (&addr);
2304: uae_u32 v;
2305: v = debug_mem_banks[off]->lget (addr);
2306: memwatch_func (addr, 1, 4, &v, MW_MASK_CPU, 0);
2307: return v;
2308: }
2309: static uae_u32 REGPARAM2 mmu_lgeti (uaecptr addr)
2310: {
2311: int off = debug_mem_off (&addr);
2312: uae_u32 v = 0;
2313: if (!mmu_hit (addr, 4, 4, &v))
2314: v = debug_mem_banks[off]->lgeti (addr);
2315: return v;
2316: }
2317: static uae_u32 REGPARAM2 mmu_wgeti (uaecptr addr)
2318: {
2319: int off = debug_mem_off (&addr);
2320: uae_u32 v = 0;
2321: if (!mmu_hit (addr, 2, 4, &v))
2322: v = debug_mem_banks[off]->wgeti (addr);
2323: return v;
2324: }
2325:
2326: static uae_u32 REGPARAM2 debug_wget (uaecptr addr)
2327: {
2328: int off = debug_mem_off (&addr);
2329: uae_u32 v;
2330: v = debug_mem_banks[off]->wget (addr);
2331: memwatch_func (addr, 1, 2, &v, MW_MASK_CPU, 0);
2332: return v;
2333: }
2334: static uae_u32 REGPARAM2 debug_bget (uaecptr addr)
2335: {
2336: int off = debug_mem_off (&addr);
2337: uae_u32 v;
2338: v = debug_mem_banks[off]->bget (addr);
2339: memwatch_func (addr, 1, 1, &v, MW_MASK_CPU, 0);
2340: return v;
2341: }
2342: static uae_u32 REGPARAM2 debug_lgeti (uaecptr addr)
2343: {
2344: int off = debug_mem_off (&addr);
2345: uae_u32 v;
2346: v = debug_mem_banks[off]->lgeti (addr);
2347: memwatch_func (addr, 4, 4, &v, MW_MASK_CPU, 0);
2348: return v;
2349: }
2350: static uae_u32 REGPARAM2 debug_wgeti (uaecptr addr)
2351: {
2352: int off = debug_mem_off (&addr);
2353: uae_u32 v;
2354: v = debug_mem_banks[off]->wgeti (addr);
2355: memwatch_func (addr, 4, 2, &v, MW_MASK_CPU, 0);
2356: return v;
2357: }
2358: static void REGPARAM2 debug_lput (uaecptr addr, uae_u32 v)
2359: {
2360: int off = debug_mem_off (&addr);
2361: if (memwatch_func (addr, 2, 4, &v, MW_MASK_CPU, 0))
2362: debug_mem_banks[off]->lput (addr, v);
2363: }
2364: static void REGPARAM2 debug_wput (uaecptr addr, uae_u32 v)
2365: {
2366: int off = debug_mem_off (&addr);
2367: if (memwatch_func (addr, 2, 2, &v, MW_MASK_CPU, 0))
2368: debug_mem_banks[off]->wput (addr, v);
2369: }
2370: static void REGPARAM2 debug_bput (uaecptr addr, uae_u32 v)
2371: {
2372: int off = debug_mem_off (&addr);
2373: if (memwatch_func (addr, 2, 1, &v, MW_MASK_CPU, 0))
2374: debug_mem_banks[off]->bput (addr, v);
2375: }
2376: static int REGPARAM2 debug_check (uaecptr addr, uae_u32 size)
2377: {
2378: return debug_mem_banks[munge24 (addr) >> 16]->check (addr, size);
2379: }
2380: static uae_u8 *REGPARAM2 debug_xlate (uaecptr addr)
2381: {
2382: return debug_mem_banks[munge24 (addr) >> 16]->xlateaddr (addr);
2383: }
2384:
2385: uae_u16 debug_wputpeekdma_chipset (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2386: {
2387: if (!memwatch_enabled)
2388: return v;
2389: addr &= 0x1fe;
2390: addr += 0xdff000;
2391: memwatch_func (addr, 2, 2, &v, mask, reg);
2392: return v;
2393: }
2394: uae_u16 debug_wputpeekdma_chipram (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2395: {
2396: if (!memwatch_enabled)
2397: return v;
2398: if (debug_mem_banks[addr >> 16] == NULL)
2399: return v;
2400: if (!currprefs.z3chipmem_size)
2401: addr &= chipmem_bank.mask;
2402: memwatch_func (addr & chipmem_bank.mask, 2, 2, &v, mask, reg);
2403: return v;
2404: }
2405: uae_u16 debug_wgetpeekdma_chipram (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2406: {
2407: uae_u32 vv = v;
2408: if (!memwatch_enabled)
2409: return v;
2410: if (debug_mem_banks[addr >> 16] == NULL)
2411: return v;
2412: if (!currprefs.z3chipmem_size)
2413: addr &= chipmem_bank.mask;
2414: memwatch_func (addr, 1, 2, &vv, mask, reg);
2415: return vv;
2416: }
2417:
2418: void debug_putlpeek (uaecptr addr, uae_u32 v)
2419: {
2420: if (!memwatch_enabled)
2421: return;
2422: memwatch_func (addr, 2, 4, &v, MW_MASK_CPU, 0);
2423: }
2424: void debug_wputpeek (uaecptr addr, uae_u32 v)
2425: {
2426: if (!memwatch_enabled)
2427: return;
2428: memwatch_func (addr, 2, 2, &v, MW_MASK_CPU, 0);
2429: }
2430: void debug_bputpeek (uaecptr addr, uae_u32 v)
2431: {
2432: if (!memwatch_enabled)
2433: return;
2434: memwatch_func (addr, 2, 1, &v, MW_MASK_CPU, 0);
2435: }
2436: void debug_bgetpeek (uaecptr addr, uae_u32 v)
2437: {
2438: uae_u32 vv = v;
2439: if (!memwatch_enabled)
2440: return;
2441: memwatch_func (addr, 1, 1, &vv, MW_MASK_CPU, 0);
2442: }
2443: void debug_wgetpeek (uaecptr addr, uae_u32 v)
2444: {
2445: uae_u32 vv = v;
2446: if (!memwatch_enabled)
2447: return;
2448: memwatch_func (addr, 1, 2, &vv, MW_MASK_CPU, 0);
2449: }
2450: void debug_lgetpeek (uaecptr addr, uae_u32 v)
2451: {
2452: uae_u32 vv = v;
2453: if (!memwatch_enabled)
2454: return;
2455: memwatch_func (addr, 1, 4, &vv, MW_MASK_CPU, 0);
2456: }
2457:
2458: #ifndef WINUAE_FOR_HATARI
2459:
2460: struct membank_store
2461: {
2462: addrbank *addr;
2463: addrbank newbank;
2464: int banknr;
2465: };
2466:
2467: static struct membank_store *membank_stores;
2468: static int membank_total;
2469: #define MEMWATCH_STORE_SLOTS 32
2470:
2471: static void memwatch_reset (void)
2472: {
2473: for (int i = 0; i < membank_total; i++) {
2474: addrbank *ab = debug_mem_banks[i];
2475: if (!ab)
2476: continue;
2477: map_banks_quick (ab, i, 1, 1);
2478: }
2479: for (int i = 0; membank_stores[i].addr; i++) {
2480: struct membank_store *ms = &membank_stores[i];
2481: xfree ((char*)ms->newbank.name);
2482: memset (ms, 0, sizeof (struct membank_store));
2483: ms->addr = NULL;
2484: }
2485: memset (debug_mem_banks, 0, membank_total * sizeof (addrbank*));
2486: }
2487:
2488: static void memwatch_remap (uaecptr addr)
2489: {
2490: int mode = 0;
2491: int i;
2492: int banknr;
2493: struct membank_store *ms;
2494: addrbank *bank;
2495: addrbank *newbank = NULL;
2496:
2497: addr &= ~65535;
2498: banknr = addr >> 16;
2499: if (debug_mem_banks[banknr])
2500: return;
2501: bank = mem_banks[banknr];
2502: for (i = 0 ; i < MEMWATCH_STORE_SLOTS; i++) {
2503: ms = &membank_stores[i];
2504: if (ms->addr == NULL)
2505: break;
2506: if (ms->addr == bank) {
2507: newbank = &ms->newbank;
2508: break;
2509: }
2510: }
2511: if (i >= MEMWATCH_STORE_SLOTS)
2512: return;
2513: if (!newbank) {
2514: TCHAR tmp[200];
2515: _stprintf (tmp, _T("%s [D]"), bank->name);
2516: ms->addr = bank;
2517: ms->banknr = banknr;
2518: newbank = &ms->newbank;
2519: memcpy (newbank, bank, sizeof addrbank);
2520: newbank->bget = mode ? mmu_bget : debug_bget;
2521: newbank->wget = mode ? mmu_wget : debug_wget;
2522: newbank->lget = mode ? mmu_lget : debug_lget;
2523: newbank->bput = mode ? mmu_bput : debug_bput;
2524: newbank->wput = mode ? mmu_wput : debug_wput;
2525: newbank->lput = mode ? mmu_lput : debug_lput;
2526: newbank->check = debug_check;
2527: newbank->xlateaddr = debug_xlate;
2528: newbank->wgeti = mode ? mmu_wgeti : debug_wgeti;
2529: newbank->lgeti = mode ? mmu_lgeti : debug_lgeti;
2530: newbank->name = my_strdup (tmp);
2531: if (!newbank->mask)
2532: newbank->mask = -1;
2533: }
2534: debug_mem_banks[banknr] = bank;
2535: map_banks_quick (newbank, banknr, 1, 1);
2536: // map aliases
2537: for (i = 0; i < membank_total; i++) {
2538: uaecptr addr2 = i << 16;
2539: addrbank *ab = &get_mem_bank(addr2);
2540: if (ab != ms->addr)
2541: continue;
2542: if ((addr2 & ab->mask) == (addr & bank->mask)) {
2543: debug_mem_banks[i] = ms->addr;
2544: map_banks_quick (newbank, i, 1, 1);
2545: }
2546: }
2547: }
2548:
2549: static void memwatch_setup (void)
2550: {
2551: memwatch_reset ();
2552: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2553: struct memwatch_node *m = &mwnodes[i];
2554: uae_u32 size = 0;
2555: if (!m->size)
2556: continue;
2557: while (size < m->size) {
2558: memwatch_remap (m->addr + size);
2559: size += 65536;
2560: }
2561: }
2562: }
2563:
2564: static int deinitialize_memwatch (void)
2565: {
2566: int oldmode;
2567:
2568: if (!memwatch_enabled && !mmu_enabled)
2569: return -1;
2570: memwatch_reset ();
2571: oldmode = mmu_enabled ? 1 : 0;
2572: xfree (debug_mem_banks);
2573: debug_mem_banks = NULL;
2574: xfree (debug_mem_area);
2575: debug_mem_area = NULL;
2576: xfree (membank_stores);
2577: membank_stores = NULL;
2578: memwatch_enabled = 0;
2579: mmu_enabled = 0;
2580: xfree (illgdebug);
2581: illgdebug = 0;
2582: return oldmode;
2583: }
2584:
2585: static void initialize_memwatch (int mode)
2586: {
2587: membank_total = currprefs.address_space_24 ? 256 : 65536;
2588: deinitialize_memwatch ();
2589: debug_mem_banks = xcalloc (addrbank*, membank_total);
2590: debug_mem_area = xcalloc (addrbank, membank_total);
2591: membank_stores = xcalloc (struct membank_store, MEMWATCH_STORE_SLOTS);
2592: #if 0
2593: int i, j, as;
2594: addrbank *a1, *a2, *oa;
2595: oa = NULL;
2596: for (i = 0; i < as; i++) {
2597: a1 = debug_mem_banks[i] = debug_mem_area + i;
2598: a2 = mem_banks[i];
2599: if (a2 != oa) {
2600: for (j = 0; membank_stores[j].addr; j++) {
2601: if (membank_stores[j].addr == a2)
2602: break;
2603: }
2604: if (membank_stores[j].addr == NULL) {
2605: membank_stores[j].addr = a2;
2606: memcpy (&membank_stores[j].store, a2, sizeof (addrbank));
2607: }
2608: }
2609: memcpy (a1, a2, sizeof (addrbank));
2610: }
2611: for (i = 0; i < as; i++) {
2612: a2 = mem_banks[i];
2613: a2->bget = mode ? mmu_bget : debug_bget;
2614: a2->wget = mode ? mmu_wget : debug_wget;
2615: a2->lget = mode ? mmu_lget : debug_lget;
2616: a2->bput = mode ? mmu_bput : debug_bput;
2617: a2->wput = mode ? mmu_wput : debug_wput;
2618: a2->lput = mode ? mmu_lput : debug_lput;
2619: a2->check = debug_check;
2620: a2->xlateaddr = debug_xlate;
2621: a2->wgeti = mode ? mmu_wgeti : debug_wgeti;
2622: a2->lgeti = mode ? mmu_lgeti : debug_lgeti;
2623: }
2624: #endif
2625: if (mode)
2626: mmu_enabled = 1;
2627: else
2628: memwatch_enabled = 1;
2629: }
2630:
2631: int debug_bankchange (int mode)
2632: {
2633: if (mode == -1) {
2634: int v = deinitialize_memwatch ();
2635: if (v < 0)
2636: return -2;
2637: return v;
2638: }
2639: if (mode >= 0) {
2640: initialize_memwatch (mode);
2641: memwatch_setup ();
2642: }
2643: return -1;
2644: }
2645:
2646: addrbank *get_mem_bank_real(uaecptr addr)
2647: {
2648: addrbank *ab = &get_mem_bank(addr);
2649: if (!memwatch_enabled)
2650: return ab;
2651: addrbank *ab2 = debug_mem_banks[addr >> 16];
2652: if (ab2)
2653: return ab2;
2654: return ab;
2655: }
2656:
2657: struct mw_acc
2658: {
2659: uae_u32 mask;
2660: const TCHAR *name;
2661: };
2662:
2663: static const struct mw_acc memwatch_access_masks[] =
2664: {
2665: { MW_MASK_ALL, _T("ALL") },
2666: { MW_MASK_ALL & ~MW_MASK_CPU, _T("DMA") },
2667: { MW_MASK_BLITTER_A | MW_MASK_BLITTER_B | MW_MASK_BLITTER_C | MW_MASK_BLITTER_D, _T("BLT") },
2668: { MW_MASK_AUDIO_0 | MW_MASK_AUDIO_1 | MW_MASK_AUDIO_2 | MW_MASK_AUDIO_3, _T("AUD") },
2669: { MW_MASK_BPL_0 | MW_MASK_BPL_1 | MW_MASK_BPL_2 | MW_MASK_BPL_3 |
2670: MW_MASK_BPL_4 | MW_MASK_BPL_5 | MW_MASK_BPL_6 | MW_MASK_BPL_7 , _T("BPL") },
2671: { MW_MASK_SPR_0 | MW_MASK_SPR_1 | MW_MASK_SPR_2 | MW_MASK_SPR_3 |
2672: MW_MASK_SPR_4 | MW_MASK_SPR_5 | MW_MASK_SPR_6 | MW_MASK_SPR_7, _T("SPR") },
2673:
2674: { MW_MASK_CPU, _T("CPU") },
2675: { MW_MASK_COPPER, _T("COP") },
2676: { MW_MASK_BLITTER_A, _T("BLTA") },
2677: { MW_MASK_BLITTER_B, _T("BLTB") },
2678: { MW_MASK_BLITTER_C, _T("BLTC") },
2679: { MW_MASK_BLITTER_D, _T("BLTD") },
2680: { MW_MASK_DISK, _T("DSK") },
2681: { MW_MASK_AUDIO_0, _T("AUD0") },
2682: { MW_MASK_AUDIO_1, _T("AUD1") },
2683: { MW_MASK_AUDIO_2, _T("AUD2") },
2684: { MW_MASK_AUDIO_3, _T("AUD3") },
2685: { MW_MASK_BPL_0, _T("BPL0") },
2686: { MW_MASK_BPL_1, _T("BPL1") },
2687: { MW_MASK_BPL_2, _T("BPL2") },
2688: { MW_MASK_BPL_3, _T("BPL3") },
2689: { MW_MASK_BPL_4, _T("BPL4") },
2690: { MW_MASK_BPL_5, _T("BPL5") },
2691: { MW_MASK_BPL_6, _T("BPL6") },
2692: { MW_MASK_BPL_7, _T("BPL7") },
2693: { MW_MASK_SPR_0, _T("SPR0") },
2694: { MW_MASK_SPR_1, _T("SPR1") },
2695: { MW_MASK_SPR_2, _T("SPR2") },
2696: { MW_MASK_SPR_3, _T("SPR3") },
2697: { MW_MASK_SPR_4, _T("SPR4") },
2698: { MW_MASK_SPR_5, _T("SPR5") },
2699: { MW_MASK_SPR_6, _T("SPR6") },
2700: { MW_MASK_SPR_7, _T("SPR7") },
2701: NULL
2702: };
2703:
2704: static TCHAR *getsizechar (int size)
2705: {
2706: if (size == 4)
2707: return _T(".l");
2708: if (size == 3)
2709: return _T(".3");
2710: if (size == 2)
2711: return _T(".w");
2712: if (size == 1)
2713: return _T(".b");
2714: return _T("");
2715: }
2716:
2717: void memwatch_dump2 (TCHAR *buf, int bufsize, int num)
2718: {
2719: int i;
2720: struct memwatch_node *mwn;
2721:
2722: if (buf)
2723: memset (buf, 0, bufsize * sizeof (TCHAR));
2724: for (i = 0; i < MEMWATCH_TOTAL; i++) {
2725: if ((num >= 0 && num == i) || (num < 0)) {
2726: uae_u32 usedmask = 0;
2727: mwn = &mwnodes[i];
2728: if (mwn->size == 0)
2729: continue;
2730: buf = buf_out (buf, &bufsize, _T("%2d: %08X - %08X (%d) %c%c%c"),
2731: i, mwn->addr, mwn->addr + (mwn->size - 1), mwn->size,
2732: (mwn->rwi & 1) ? 'R' : ' ', (mwn->rwi & 2) ? 'W' : ' ', (mwn->rwi & 4) ? 'I' : ' ');
2733: if (mwn->frozen)
2734: buf = buf_out (buf, &bufsize, _T(" F"));
2735: if (mwn->val_enabled)
2736: buf = buf_out (buf, &bufsize, _T(" =%X%s"), mwn->val, getsizechar (mwn->val_size));
2737: if (mwn->modval_written)
2738: buf = buf_out (buf, &bufsize, _T(" =M"));
2739: if (mwn->mustchange)
2740: buf = buf_out (buf, &bufsize, _T(" C"));
2741: for (int j = 0; memwatch_access_masks[j].mask; j++) {
2742: uae_u32 mask = memwatch_access_masks[j].mask;
2743: if ((mwn->access_mask & mask) == mask && (usedmask & mask) == 0) {
2744: buf = buf_out(buf, &bufsize, _T(" "));
2745: buf = buf_out(buf, &bufsize, memwatch_access_masks[j].name);
2746: usedmask |= mask;
2747: }
2748: }
2749: buf = buf_out (buf, &bufsize, _T("\n"));
2750: }
2751: }
2752: }
2753:
2754: static void memwatch_dump (int num)
2755: {
2756: TCHAR *buf;
2757: int multiplier = num < 0 ? MEMWATCH_TOTAL : 1;
2758:
2759: buf = xmalloc (TCHAR, 50 * multiplier);
2760: if (!buf)
2761: return;
2762: memwatch_dump2 (buf, 50 * multiplier, num);
2763: f_out (stdout, _T("%s"), buf);
2764: xfree (buf);
2765: }
2766:
2767: static void memwatch (TCHAR **c)
2768: {
2769: int num;
2770: struct memwatch_node *mwn;
2771: TCHAR nc, *cp;
2772:
2773: if (!memwatch_enabled) {
2774: initialize_memwatch (0);
2775: console_out (_T("Memwatch breakpoints enabled\n"));
2776: }
2777:
2778: cp = *c;
2779: ignore_ws (c);
2780: if (!more_params (c)) {
2781: memwatch_dump (-1);
2782: return;
2783: }
2784: nc = next_char (c);
2785: if (nc == '-') {
2786: deinitialize_memwatch ();
2787: console_out (_T("Memwatch breakpoints disabled\n"));
2788: return;
2789: }
2790: if (nc == 'd') {
2791: if (illgdebug) {
2792: ignore_ws (c);
2793: if (more_params (c)) {
2794: uae_u32 addr = readhex (c);
2795: uae_u32 len = 1;
2796: if (more_params (c))
2797: len = readhex (c);
2798: console_out_f (_T("Cleared logging addresses %08X - %08X\n"), addr, addr + len);
2799: while (len > 0) {
2800: addr &= 0xffffff;
2801: illgdebug[addr] = 7;
2802: addr++;
2803: len--;
2804: }
2805: } else {
2806: illg_free();
2807: console_out (_T("Illegal memory access logging disabled\n"));
2808: }
2809: } else {
2810: illg_init ();
2811: ignore_ws (c);
2812: illgdebug_break = 0;
2813: if (more_params (c))
2814: illgdebug_break = 1;
2815: console_out_f (_T("Illegal memory access logging enabled. Break=%d\n"), illgdebug_break);
2816: }
2817: return;
2818: }
2819: *c = cp;
2820: num = readint (c);
2821: if (num < 0 || num >= MEMWATCH_TOTAL)
2822: return;
2823: mwn = &mwnodes[num];
2824: mwn->size = 0;
2825: ignore_ws (c);
2826: if (!more_params (c)) {
2827: console_out_f (_T("Memwatch %d removed\n"), num);
2828: memwatch_setup ();
2829: return;
2830: }
2831: mwn->addr = readhex (c);
2832: mwn->size = 1;
2833: mwn->rwi = 7;
2834: mwn->val_enabled = 0;
2835: mwn->val_mask = 0xffffffff;
2836: mwn->val = 0;
2837: mwn->access_mask = 0;
2838: mwn->reg = 0xffffffff;
2839: mwn->frozen = 0;
2840: mwn->modval_written = 0;
2841: ignore_ws (c);
2842: if (more_params (c)) {
2843: mwn->size = readhex (c);
2844: ignore_ws (c);
2845: if (more_params (c)) {
2846: TCHAR *cs = *c;
2847: while (*cs) {
2848: for (int i = 0; memwatch_access_masks[i].mask; i++) {
2849: const TCHAR *n = memwatch_access_masks[i].name;
2850: int len = _tcslen(n);
2851: if (!_tcsnicmp(cs, n, len)) {
2852: if (cs[len] == 0 || cs[len] == 10 || cs[len] == 13) {
2853: mwn->access_mask |= memwatch_access_masks[i].mask;
2854: while (len > 0) {
2855: len--;
2856: cs[len] = ' ';
2857: }
2858: }
2859: }
2860: }
2861: cs++;
2862: }
2863: ignore_ws (c);
2864: if (more_params(c)) {
2865: for (;;) {
2866: TCHAR ncc = peek_next_char(c);
2867: TCHAR nc = _totupper (next_char (c));
2868: if (mwn->rwi == 7)
2869: mwn->rwi = 0;
2870: if (nc == 'F')
2871: mwn->frozen = 1;
2872: if (nc == 'W')
2873: mwn->rwi |= 2;
2874: if (nc == 'I')
2875: mwn->rwi |= 4;
2876: if (nc == 'R')
2877: mwn->rwi |= 1;
2878: if (ncc == ' ')
2879: break;
2880: if (!more_params(c))
2881: break;
2882: }
2883: ignore_ws (c);
2884: }
2885: if (more_params (c)) {
2886: if (_totupper (**c) == 'M') {
2887: mwn->modval_written = 1;
2888: } else if (_totupper (**c) == 'C') {
2889: mwn->mustchange = 1;
2890: } else {
2891: mwn->val = readhex (c, &mwn->val_size);
2892: mwn->val_enabled = 1;
2893: }
2894: }
2895: }
2896: }
2897: if (!mwn->access_mask)
2898: mwn->access_mask = MW_MASK_CPU;
2899: if (mwn->frozen && mwn->rwi == 0)
2900: mwn->rwi = 3;
2901: memwatch_setup ();
2902: memwatch_dump (num);
2903: }
2904:
2905: static void writeintomem (TCHAR **c)
2906: {
2907: uae_u32 addr = 0;
2908: uae_u32 val = 0;
2909: TCHAR cc;
2910: int len = 1;
2911:
2912: ignore_ws(c);
2913: addr = readhex (c);
2914:
2915: ignore_ws (c);
2916: if (!more_params (c))
2917: return;
2918: cc = peekchar (c);
2919: if (cc == '\'' || cc == '\"') {
2920: next_char (c);
2921: while (more_params (c)) {
2922: TCHAR str[2];
2923: char *astr;
2924: cc = next_char (c);
2925: if (cc == '\'' || cc == '\"')
2926: break;
2927: str[0] = cc;
2928: str[1] = 0;
2929: astr = ua (str);
2930: put_byte (addr, astr[0]);
2931: xfree (astr);
2932: addr++;
2933: }
2934: } else {
2935: for (;;) {
2936: ignore_ws (c);
2937: if (!more_params (c))
2938: break;
2939: val = readhex (c, &len);
2940:
2941: if (len == 4) {
2942: put_long (addr, val);
2943: cc = 'L';
2944: } else if (len == 2) {
2945: put_word (addr, val);
2946: cc = 'W';
2947: } else if (len == 1) {
2948: put_byte (addr, val);
2949: cc = 'B';
2950: } else {
2951: break;
2952: }
2953: console_out_f (_T("Wrote %X (%u) at %08X.%c\n"), val, val, addr, cc);
2954: addr += len;
2955: }
2956: }
2957: }
2958:
2959: static uae_u8 *dump_xlate (uae_u32 addr)
2960: {
2961: if (!mem_banks[addr >> 16]->check (addr, 1))
2962: return NULL;
2963: return mem_banks[addr >> 16]->xlateaddr (addr);
2964: }
2965:
2966: #if 0
2967: #define UAE_MEMORY_REGIONS_MAX 64
2968: #define UAE_MEMORY_REGION_NAME_LENGTH 64
2969:
2970: #define UAE_MEMORY_REGION_RAM (1 << 0)
2971: #define UAE_MEMORY_REGION_ALIAS (1 << 1)
2972: #define UAE_MEMORY_REGION_MIRROR (1 << 2)
2973:
2974: typedef struct UaeMemoryRegion {
2975: uaecptr start;
2976: int size;
2977: TCHAR name[UAE_MEMORY_REGION_NAME_LENGTH];
2978: TCHAR rom_name[UAE_MEMORY_REGION_NAME_LENGTH];
2979: uaecptr alias;
2980: int flags;
2981: } UaeMemoryRegion;
2982:
2983: typedef struct UaeMemoryMap {
2984: UaeMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
2985: int num_regions;
2986: } UaeMemoryMap;
2987: #endif
2988:
2989: static void memory_map_dump_3(UaeMemoryMap *map, int log)
2990: {
2991: bool imold;
2992: int i, j, max;
2993: addrbank *a1 = mem_banks[0];
2994: TCHAR txt[256];
2995:
2996: map->num_regions = 0;
2997: imold = currprefs.illegal_mem;
2998: currprefs.illegal_mem = false;
2999: max = currprefs.address_space_24 ? 256 : 65536;
3000: j = 0;
3001: for (i = 0; i < max + 1; i++) {
3002: addrbank *a2 = NULL;
3003: if (i < max)
3004: a2 = mem_banks[i];
3005: if (a1 != a2) {
3006: int k, mirrored, mirrored2, size, size_out;
3007: TCHAR size_ext;
3008: uae_u8 *caddr;
3009: TCHAR tmp[MAX_DPATH];
3010: const TCHAR *name = a1->name;
3011: struct addrbank_sub *sb = a1->sub_banks;
3012: int bankoffset = 0;
3013: int region_size;
3014:
3015: k = j;
3016: caddr = dump_xlate (k << 16);
3017: mirrored = caddr ? 1 : 0;
3018: k++;
3019: while (k < i && caddr) {
3020: if (dump_xlate (k << 16) == caddr)
3021: mirrored++;
3022: k++;
3023: }
3024: mirrored2 = mirrored;
3025: if (mirrored2 == 0)
3026: mirrored2 = 1;
3027:
3028: while (bankoffset < 65536) {
3029: int bankoffset2 = bankoffset;
3030: if (sb) {
3031: uaecptr daddr;
3032: if (!sb->bank)
3033: break;
3034: daddr = (j << 16) | bankoffset;
3035: a1 = get_sub_bank(&daddr);
3036: name = a1->name;
3037: for (;;) {
3038: bankoffset2 += MEMORY_MIN_SUBBANK;
3039: if (bankoffset2 >= 65536)
3040: break;
3041: daddr = (j << 16) | bankoffset2;
3042: addrbank *dab = get_sub_bank(&daddr);
3043: if (dab != a1)
3044: break;
3045: }
3046: sb++;
3047: size = (bankoffset2 - bankoffset) / 1024;
3048: region_size = size * 1024;
3049: } else {
3050: size = (i - j) << (16 - 10);
3051: region_size = ((i - j) << 16) / mirrored2;
3052: }
3053:
3054: if (name == NULL)
3055: name = _T("<none>");
3056:
3057: size_out = size;
3058: size_ext = 'K';
3059: if (j >= 256 && (size_out / mirrored2 >= 1024) && !((size_out / mirrored2) & 1023)) {
3060: size_out /= 1024;
3061: size_ext = 'M';
3062: }
3063: #if 1
3064: _stprintf (txt, _T("%08X %7d%c/%d = %7d%c %s"), (j << 16) | bankoffset, size_out, size_ext,
3065: mirrored, mirrored ? size_out / mirrored : size_out, size_ext, name);
3066: #endif
3067: tmp[0] = 0;
3068: if ((a1->flags & ABFLAG_ROM) && mirrored) {
3069: TCHAR *p = txt + _tcslen (txt);
3070: uae_u32 crc = 0xffffffff;
3071: if (a1->check(((j << 16) | bankoffset), (size * 1024) / mirrored))
3072: crc = get_crc32 (a1->xlateaddr((j << 16) | bankoffset), (size * 1024) / mirrored);
3073: struct romdata *rd = getromdatabycrc (crc);
3074: _stprintf (p, _T(" (%08X)"), crc);
3075: if (rd) {
3076: tmp[0] = '=';
3077: getromname (rd, tmp + 1);
3078: _tcscat (tmp, _T("\n"));
3079: }
3080: }
3081:
3082: if (a1 != &dummy_bank) {
3083: for (int m = 0; m < mirrored2; m++) {
3084: UaeMemoryRegion *r = &map->regions[map->num_regions];
3085: r->start = (j << 16) + bankoffset + region_size * m;
3086: r->size = region_size;
3087: r->flags = 0;
3088: r->memory = NULL;
3089: r->memory = dump_xlate((j << 16) | bankoffset);
3090: if (r->memory)
3091: r->flags |= UAE_MEMORY_REGION_RAM;
3092: /* just to make it easier to spot in debugger */
3093: r->alias = 0xffffffff;
3094: if (m >= 0) {
3095: r->alias = j << 16;
3096: r->flags |= UAE_MEMORY_REGION_ALIAS | UAE_MEMORY_REGION_MIRROR;
3097: }
3098: _stprintf(r->name, _T("%s"), name);
3099: _stprintf(r->rom_name, _T("%s"), tmp);
3100: map->num_regions += 1;
3101: }
3102: }
3103:
3104: #if 1
3105: _tcscat (txt, _T("\n"));
3106: if (log > 0)
3107: write_log (txt);
3108: else if (log == 0)
3109: console_out (txt);
3110: if (tmp[0]) {
3111: if (log > 0)
3112: write_log (tmp);
3113: else if (log == 0)
3114: console_out (tmp);
3115: }
3116: #endif
3117: if (!sb)
3118: break;
3119: bankoffset = bankoffset2;
3120: }
3121: j = i;
3122: a1 = a2;
3123: }
3124: }
3125: currprefs.illegal_mem = imold;
3126: }
3127:
3128: void uae_memory_map(UaeMemoryMap *map)
3129: {
3130: memory_map_dump_3(map, -1);
3131: }
3132:
3133: static void memory_map_dump_2 (int log)
3134: {
3135: UaeMemoryMap map;
3136: memory_map_dump_3(&map, log);
3137: #if 0
3138: for (int i = 0; i < map.num_regions; i++) {
3139: TCHAR txt[256];
3140: UaeMemoryRegion *r = &map.regions[i];
3141: int size = r->size / 1024;
3142: TCHAR size_ext = 'K';
3143: int mirrored = 1;
3144: int size_out = 0;
3145: _stprintf (txt, _T("%08X %7u%c/%d = %7u%c %s\n"), r->start, size, size_ext,
3146: r->flags & UAE_MEMORY_REGION_RAM, size, size_ext, r->name);
3147: if (log)
3148: write_log (_T("%s"), txt);
3149: else
3150: console_out (txt);
3151: if (r->rom_name[0]) {
3152: if (log)
3153: write_log (_T("%s"), r->rom_name);
3154: else
3155: console_out (r->rom_name);
3156: }
3157: }
3158: #endif
3159: }
3160:
3161: void memory_map_dump (void)
3162: {
3163: memory_map_dump_2 (1);
3164: }
3165:
3166: STATIC_INLINE uaecptr BPTR2APTR (uaecptr addr)
3167: {
3168: return addr << 2;
3169: }
3170: static TCHAR *BSTR2CSTR (uae_u8 *bstr)
3171: {
3172: TCHAR *s;
3173: char *cstr = xmalloc (char, bstr[0] + 1);
3174: if (cstr) {
3175: memcpy (cstr, bstr + 1, bstr[0]);
3176: cstr[bstr[0]] = 0;
3177: }
3178: s = au (cstr);
3179: xfree (cstr);
3180: return s;
3181: }
3182:
3183: static void print_task_info (uaecptr node, bool nonactive)
3184: {
3185: TCHAR *s;
3186: int process = get_byte_debug (node + 8) == 13 ? 1 : 0;
3187:
3188: console_out_f (_T("%08X: "), node);
3189: s = au ((char*)get_real_address (get_long_debug (node + 10)));
3190: console_out_f (process ? _T("PROCESS '%s'\n") : _T("TASK '%s'\n"), s);
3191: xfree (s);
3192: if (process) {
3193: uaecptr cli = BPTR2APTR (get_long_debug (node + 172));
3194: int tasknum = get_long_debug (node + 140);
3195: if (cli && tasknum) {
3196: uae_u8 *command_bstr = get_real_address (BPTR2APTR (get_long_debug (cli + 16)));
3197: TCHAR *command = BSTR2CSTR (command_bstr);
3198: console_out_f (_T(" [%d, '%s']\n"), tasknum, command);
3199: xfree (command);
3200: } else {
3201: console_out (_T("\n"));
3202: }
3203: }
3204: if (nonactive) {
3205: uae_u32 sigwait = get_long_debug(node + 22);
3206: if (sigwait)
3207: console_out_f(_T(" Waiting signals: %08x\n"), sigwait);
3208: uae_u32 sp = get_long_debug(node + 54) + 70;
3209: uae_u32 pc = get_long_debug(sp);
3210: console_out_f(_T(" SP: %08x PC: %08x\n"), sp, pc);
3211: }
3212: }
3213:
3214: static void show_exec_tasks (void)
3215: {
3216: uaecptr execbase = get_long_debug (4);
3217: uaecptr taskready = execbase + 406;
3218: uaecptr taskwait = execbase + 420;
3219: uaecptr node;
3220: console_out_f (_T("Execbase at 0x%08X\n"), execbase);
3221: console_out (_T("Current:\n"));
3222: node = get_long_debug (execbase + 276);
3223: print_task_info (node, false);
3224: console_out_f (_T("Ready:\n"));
3225: node = get_long_debug (taskready);
3226: while (node && get_long_debug(node)) {
3227: print_task_info (node, true);
3228: node = get_long_debug (node);
3229: }
3230: console_out (_T("Waiting:\n"));
3231: node = get_long_debug (taskwait);
3232: while (node && get_long_debug(node)) {
3233: print_task_info (node, true);
3234: node = get_long_debug (node);
3235: }
3236: }
3237:
3238: static uaecptr get_base (const uae_char *name, int offset)
3239: {
3240: uaecptr v = get_long_debug (4);
3241: addrbank *b = &get_mem_bank(v);
3242:
3243: if (!b || !b->check (v, 400) || !(b->flags & ABFLAG_RAM))
3244: return 0;
3245: v += offset;
3246: while (v = get_long_debug (v)) {
3247: uae_u32 v2;
3248: uae_u8 *p;
3249: b = &get_mem_bank (v);
3250: if (!b || !b->check (v, 32) || (!(b->flags & ABFLAG_RAM) && !(b->flags & ABFLAG_ROMIN)))
3251: goto fail;
3252: v2 = get_long_debug (v + 10); // name
3253: b = &get_mem_bank (v2);
3254: if (!b || !b->check (v2, 20))
3255: goto fail;
3256: if ((b->flags & ABFLAG_ROM) || (b->flags & ABFLAG_RAM) || (b->flags & ABFLAG_ROMIN)) {
3257: p = b->xlateaddr (v2);
3258: if (!memcmp (p, name, strlen (name) + 1))
3259: return v;
3260: }
3261: }
3262: return 0;
3263: fail:
3264: return 0xffffffff;
3265: }
3266:
3267: static TCHAR *getfrombstr(uaecptr pp)
3268: {
3269: uae_u8 *p = get_real_address ((uaecptr)(pp << 2));
3270: TCHAR *s = xmalloc (TCHAR, p[0] + 1);
3271: return au_copy (s, p[0] + 1, (char*)p + 1);
3272: }
3273:
3274: // read one byte from expansion autoconfig ROM
3275: static void copyromdata(uae_u8 bustype, uaecptr rom, int offset, uae_u8 *out, int size)
3276: {
3277: switch (bustype & 0xc0)
3278: {
3279: case 0x00: // nibble
3280: while (size-- > 0) {
3281: *out++ = (get_byte_debug(rom + offset * 4 + 0) & 0xf0) | ((get_byte_debug(rom + offset * 4 + 2) & 0xf0) >> 4);
3282: offset++;
3283: }
3284: break;
3285: case 0x40: // byte
3286: while (size-- > 0) {
3287: *out++ = get_byte_debug(rom + offset * 2);
3288: offset++;
3289: }
3290: break;
3291: case 0x80: // word
3292: default:
3293: while (size-- > 0) {
3294: *out++ = get_byte_debug(rom + offset);
3295: offset++;
3296: }
3297: break;
3298: }
3299: }
3300:
3301: static void show_exec_lists (TCHAR *t)
3302: {
3303: uaecptr execbase = get_long_debug (4);
3304: uaecptr list = 0, node;
3305: TCHAR c = t[0];
3306: TCHAR c2 = t[1];
3307:
3308: if (c == 'o' || c == 'O') { // doslist
3309: uaecptr dosbase = get_base ("dos.library", 378);
3310: if (dosbase) {
3311: uaecptr rootnode = get_long_debug (dosbase + 34);
3312: uaecptr dosinfo = get_long_debug (rootnode + 24) << 2;
3313: console_out_f (_T("ROOTNODE: %08x DOSINFO: %08x\n"), rootnode, dosinfo);
3314: uaecptr doslist = get_long_debug (dosinfo + 4) << 2;
3315: while (doslist) {
3316: int type = get_long_debug (doslist + 4);
3317: uaecptr msgport = get_long_debug (doslist + 8);
3318: TCHAR *name = getfrombstr (get_long_debug (doslist + 40));
3319: console_out_f (_T("%08x: %d %08x '%s'\n"), doslist, type, msgport, name);
3320: if (type == 0) {
3321: uaecptr fssm = get_long_debug(doslist + 28) << 2;
3322: console_out_f (_T(" - H=%08x Stack=%5d Pri=%2d Start=%08x Seg=%08x GV=%08x\n"),
3323: get_long_debug (doslist + 16) << 2, get_long_debug (doslist + 20),
3324: get_long_debug (doslist + 24), fssm,
3325: get_long_debug (doslist + 32) << 2, get_long_debug (doslist + 36));
3326: if (fssm >= 0x100 && (fssm & 3) == 0) {
3327: TCHAR *unitname = getfrombstr(get_long_debug(fssm + 4));
3328: console_out_f (_T(" %s:%d %08x\n"), unitname, get_long_debug(fssm), get_long_debug(fssm + 8));
3329: uaecptr de = get_long_debug(fssm + 8) << 2;
3330: if (de) {
3331: console_out_f (_T(" TableSize %u\n"), get_long_debug(de + 0));
3332: console_out_f (_T(" SizeBlock %u\n"), get_long_debug(de + 4));
3333: console_out_f (_T(" SecOrg %u\n"), get_long_debug(de + 8));
3334: console_out_f (_T(" Surfaces %u\n"), get_long_debug(de + 12));
3335: console_out_f (_T(" SectorPerBlock %u\n"), get_long_debug(de + 16));
3336: console_out_f (_T(" BlocksPerTrack %u\n"), get_long_debug(de + 20));
3337: console_out_f (_T(" Reserved %u\n"), get_long_debug(de + 24));
3338: console_out_f (_T(" PreAlloc %u\n"), get_long_debug(de + 28));
3339: console_out_f (_T(" Interleave %u\n"), get_long_debug(de + 32));
3340: console_out_f (_T(" LowCyl %u\n"), get_long_debug(de + 36));
3341: console_out_f (_T(" HighCyl %u (Total %u)\n"), get_long_debug(de + 40), get_long_debug(de + 40) - get_long_debug(de + 36) + 1);
3342: console_out_f (_T(" NumBuffers %u\n"), get_long_debug(de + 44));
3343: console_out_f (_T(" BufMemType 0x%08x\n"), get_long_debug(de + 48));
3344: console_out_f (_T(" MaxTransfer 0x%08x\n"), get_long_debug(de + 52));
3345: console_out_f (_T(" Mask 0x%08x\n"), get_long_debug(de + 56));
3346: console_out_f (_T(" BootPri %d\n"), get_long_debug(de + 60));
3347: console_out_f (_T(" DosType 0x%08x\n"), get_long_debug(de + 64));
3348: }
3349: xfree(unitname);
3350: }
3351: }
3352: xfree (name);
3353: doslist = get_long_debug (doslist) << 2;
3354: }
3355: } else {
3356: console_out_f (_T("can't find dos.library\n"));
3357: }
3358: return;
3359: } else if (c == 'i' || c == 'I') { // interrupts
3360: static const int it[] = { 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0 };
3361: static const int it2[] = { 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7 };
3362: list = execbase + 84;
3363: for (int i = 0; i < 16; i++) {
3364: console_out_f (_T("%2d %d: %08x\n"), i + 1, it2[i], list);
3365: if (it[i]) {
3366: console_out_f (_T(" [H] %08x\n"), get_long_debug (list));
3367: node = get_long_debug (list + 8);
3368: if (node) {
3369: uae_u8 *addr = get_real_address (get_long_debug (node + 10));
3370: TCHAR *name = addr ? au ((char*)addr) : au("<null>");
3371: console_out_f (_T(" %08x (C=%08X D=%08X) '%s'\n"), node, get_long_debug (list + 4), get_long_debug (list), name);
3372: xfree (name);
3373: }
3374: } else {
3375: int cnt = 0;
3376: node = get_long_debug (list);
3377: node = get_long_debug (node);
3378: while (get_long_debug (node)) {
3379: uae_u8 *addr = get_real_address (get_long_debug (node + 10));
3380: TCHAR *name = addr ? au ((char*)addr) : au("<null>");
3381: console_out_f (_T(" [S] %08x (C=%08x D=%08X) '%s'\n"), node, get_long_debug (node + 18), get_long_debug (node + 14), name);
3382: if (i == 4 - 1 || i == 14 - 1) {
3383: if (!_tcsicmp (name, _T("cia-a")) || !_tcsicmp (name, _T("cia-b"))) {
3384: static const TCHAR *ciai[] = { _T("A"), _T("B"), _T("ALRM"), _T("SP"), _T("FLG") };
3385: uaecptr cia = node + 22;
3386: for (int j = 0; j < 5; j++) {
3387: uaecptr ciap = get_long_debug (cia);
3388: console_out_f (_T(" %5s: %08x"), ciai[j], ciap);
3389: if (ciap) {
3390: uae_u8 *addr2 = get_real_address (get_long_debug (ciap + 10));
3391: TCHAR *name2 = addr ? au ((char*)addr2) : au("<null>");
3392: console_out_f (_T(" (C=%08x D=%08X) '%s'"), get_long_debug (ciap + 18), get_long_debug (ciap + 14), name2);
3393: xfree (name2);
3394: }
3395: console_out_f (_T("\n"));
3396: cia += 4;
3397: }
3398: }
3399: }
3400: xfree (name);
3401: node = get_long_debug (node);
3402: cnt++;
3403: }
3404: if (!cnt)
3405: console_out_f (_T(" [S] <none>\n"));
3406: }
3407: list += 12;
3408: }
3409: return;
3410: } else if (c == 'e') { // expansion
3411: uaecptr expbase = get_base("expansion.library", 378);
3412: if (expbase) {
3413: list = get_long_debug(expbase + 60);
3414: while (list && get_long_debug(list)) {
3415: uae_u32 addr = get_long_debug(list + 32);
3416: uae_u16 rom_vector = get_word_debug(list + 16 + 10);
3417: uae_u8 type = get_byte_debug(list + 16 + 0);
3418: console_out_f(_T("%02x %02x %08x %08x %04x %02x %08x %04x (%u/%u)\n"),
3419: type, get_byte_debug(list + 16 + 2),
3420: addr, get_long_debug(list + 36),
3421: get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1),
3422: get_long_debug(list + 16 + 6), rom_vector,
3423: get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1));
3424: if ((type & 0x10)) {
3425: uae_u8 diagarea[256];
3426: uae_u16 nameoffset;
3427: uaecptr rom = addr + rom_vector;
3428: uae_u8 config = get_byte_debug(rom);
3429: copyromdata(config, rom, 0, diagarea, 16);
3430: nameoffset = (diagarea[8] << 8) | diagarea[9];
3431: console_out_f(_T(" %02x %02x Size %04x Diag %04x Boot %04x Name %04x %04x %04x\n"),
3432: diagarea[0], diagarea[1],
3433: (diagarea[2] << 8) | diagarea[3],
3434: (diagarea[4] << 8) | diagarea[5],
3435: (diagarea[6] << 8) | diagarea[7],
3436: nameoffset,
3437: (diagarea[10] << 8) | diagarea[11],
3438: (diagarea[12] << 8) | diagarea[13]);
3439: if (nameoffset != 0 && nameoffset != 0xffff) {
3440: copyromdata(config, rom, nameoffset, diagarea, 256);
3441: diagarea[sizeof diagarea - 1] = 0;
3442: TCHAR *str = au((char*)diagarea);
3443: console_out_f(_T(" '%s'\n"), str);
3444: xfree(str);
3445: }
3446: }
3447: list = get_long_debug(list);
3448: }
3449: }
3450: } else if (c == 'R') { // residents
3451: list = get_long_debug(execbase + 300);
3452: while (list) {
3453: uaecptr resident = get_long_debug (list);
3454: if (!resident)
3455: break;
3456: if (resident & 0x80000000) {
3457: console_out_f (_T("-> %08X\n"), resident & 0x7fffffff);
3458: list = resident & 0x7fffffff;
3459: continue;
3460: }
3461: uae_u8 *addr;
3462: addr = get_real_address (get_long_debug (resident + 14));
3463: TCHAR *name1 = addr ? au ((char*)addr) : au("<null>");
3464: my_trim (name1);
3465: addr = get_real_address (get_long_debug (resident + 18));
3466: TCHAR *name2 = addr ? au ((char*)addr) : au("<null>");
3467: my_trim (name2);
3468: console_out_f (_T("%08X %08X: %02X %3d %02X %+3.3d '%s' ('%s')\n"),
3469: list, resident,
3470: get_byte_debug (resident + 10), get_byte_debug (resident + 11),
3471: get_byte_debug (resident + 12), (uae_s8)get_byte_debug (resident + 13),
3472: name1, name2);
3473: xfree (name2);
3474: xfree (name1);
3475: list += 4;
3476: }
3477: return;
3478: } else if (c == 'f' || c== 'F') { // filesystem.resource
3479: uaecptr fs = get_base ("FileSystem.resource", 336);
3480: if (fs) {
3481: static const TCHAR *fsnames[] = {
3482: _T("DosType"),
3483: _T("Version"),
3484: _T("PatchFlags"),
3485: _T("Type"),
3486: _T("Task"),
3487: _T("Lock"),
3488: _T("Handler"),
3489: _T("StackSize"),
3490: _T("Priority"),
3491: _T("Startup"),
3492: _T("SegList"),
3493: _T("GlobalVec"),
3494: NULL
3495: };
3496: uae_u8 *addr = get_real_address (get_long_debug (fs + 14));
3497: TCHAR *name = addr ? au ((char*)addr) : au ("<null>");
3498: my_trim (name);
3499: console_out_f (_T("%08x: '%s'\n"), fs, name);
3500: xfree (name);
3501: node = get_long_debug (fs + 18);
3502: while (get_long_debug (node)) {
3503: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
3504: my_trim (name);
3505: console_out_f (_T("%08x: '%s'\n"), node, name);
3506: xfree (name);
3507: for (int i = 0; fsnames[i]; i++) {
3508: uae_u32 v = get_long_debug (node + 14 + i * 4);
3509: console_out_f (_T("%16s = %08x %d\n"), fsnames[i], v, v);
3510: }
3511: console_out_f (_T("\n"));
3512: node = get_long_debug (node);
3513: }
3514:
3515: } else {
3516: console_out_f (_T("FileSystem.resource not found.\n"));
3517: }
3518: return;
3519: } else if (c == 'm' || c == 'M') { // memory
3520: list = execbase + 322;
3521: node = get_long_debug (list);
3522: while (get_long_debug (node)) {
3523: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
3524: uae_u16 v = get_word_debug (node + 8);
3525: console_out_f (_T("%08x %d %d %s\n"), node, (int)((v >> 8) & 0xff), (uae_s8)(v & 0xff), name);
3526: xfree (name);
3527: console_out_f (_T("Attributes %04x First %08x Lower %08x Upper %08x Free %d\n"),
3528: get_word_debug (node + 14), get_long_debug (node + 16), get_long_debug (node + 20),
3529: get_long_debug (node + 24), get_long_debug (node + 28));
3530: uaecptr mc = get_long_debug (node + 16);
3531: while (mc) {
3532: uae_u32 mc1 = get_long_debug (mc);
3533: uae_u32 mc2 = get_long_debug (mc + 4);
3534: console_out_f (_T(" %08x: %08x-%08x,%08x,%08x (%d)\n"), mc, mc, mc + mc2, mc1, mc2, mc2);
3535: mc = mc1;
3536: }
3537: console_out_f (_T("\n"));
3538: node = get_long_debug (node);
3539: }
3540: return;
3541: }
3542:
3543: bool full = false;
3544: switch (c)
3545: {
3546: case 'r': // resources
3547: list = execbase + 336;
3548: break;
3549: case 'd': // devices
3550: list = execbase + 350;
3551: full = true;
3552: break;
3553: case 'l': // libraries
3554: list = execbase + 378;
3555: full = true;
3556: break;
3557: case 'p': // ports
3558: list = execbase + 392;
3559: break;
3560: case 's': // semaphores
3561: list = execbase + 532;
3562: break;
3563: }
3564: if (list == 0)
3565: return;
3566: node = get_long_debug (list);
3567: while (get_long_debug (node)) {
3568: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
3569: uae_u16 v = get_word_debug (node + 8);
3570: console_out_f (_T("%08x %d %d"), node, (int)((v >> 8) & 0xff), (uae_s8)(v & 0xff));
3571: if (full) {
3572: uae_u16 ver = get_word_debug(node + 20);
3573: uae_u16 rev = get_word_debug(node + 22);
3574: uae_u32 op = get_word_debug(node + 32);
3575: console_out_f(_T(" %d.%d %d"), ver, rev, op);
3576: }
3577: console_out_f(_T(" %s"), name);
3578: xfree (name);
3579: if (full) {
3580: uaecptr idstring = get_long_debug(node + 24);
3581: if (idstring) {
3582: name = au((char*)get_real_address(idstring));
3583: console_out_f(_T(" (%s)"), name);
3584: xfree(name);
3585: }
3586: }
3587: console_out_f(_T("\n"));
3588: node = get_long_debug (node);
3589: }
3590: }
3591:
3592: static void breakfunc(uae_u32 v)
3593: {
3594: write_log(_T("Cycle breakpoint hit\n"));
3595: debugging = 1;
3596: set_special (SPCFLAG_BRK);
3597: }
3598:
3599: static int cycle_breakpoint(TCHAR **c)
3600: {
3601: TCHAR nc = (*c)[0];
3602: next_char(c);
3603: if (more_params(c)) {
3604: int count = readint(c);
3605: if (nc == 's') {
3606: if (more_params(c)) {
3607: int hp = readint(c);
3608: if (count >= vpos) {
3609: count = vpos - count;
3610: } else {
3611: count += maxvpos - vpos;
3612: }
3613: count *= maxhpos;
3614: if (hp >= current_hpos()) {
3615: count += hp - current_hpos();
3616: } else {
3617: count += maxhpos - current_hpos();
3618: }
3619: } else {
3620: count *= maxhpos;
3621: }
3622: }
3623: event2_newevent_x(-1, count, 0, breakfunc);
3624: return 1;
3625: }
3626: return 0;
3627: }
3628:
3629: #if 0
3630: static int trace_same_insn_count;
3631: static uae_u8 trace_insn_copy[10];
3632: static struct regstruct trace_prev_regs;
3633: #endif
3634: static uaecptr nextpc;
3635:
3636: int instruction_breakpoint (TCHAR **c)
3637: {
3638: struct breakpoint_node *bpn;
3639: int i;
3640:
3641: if (more_params (c)) {
3642: TCHAR nc = _totupper ((*c)[0]);
3643: if (nc == 'S') {
3644: next_char (c);
3645: sr_bpvalue = sr_bpmask = 0;
3646: if (more_params (c)) {
3647: sr_bpmask = 0xffff;
3648: sr_bpvalue = readhex (c);
3649: if (more_params (c))
3650: sr_bpmask = readhex (c);
3651: }
3652: console_out_f (_T("SR breakpoint, value=%04X, mask=%04X\n"), sr_bpvalue, sr_bpmask);
3653: return 0;
3654: } else if (nc == 'I') {
3655: next_char (c);
3656: if (more_params (c))
3657: skipins = readhex (c);
3658: else
3659: skipins = 0x10000;
3660: do_skip = 1;
3661: skipaddr_doskip = 1;
3662: return 1;
3663: } else if (nc == 'D' && (*c)[1] == 0) {
3664: for (i = 0; i < BREAKPOINT_TOTAL; i++)
3665: bpnodes[i].enabled = 0;
3666: console_out (_T("All breakpoints removed\n"));
3667: return 0;
3668: } else if (nc == 'L') {
3669: int got = 0;
3670: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
3671: bpn = &bpnodes[i];
3672: if (!bpn->enabled)
3673: continue;
3674: console_out_f (_T("%8X "), bpn->addr);
3675: got = 1;
3676: }
3677: if (!got)
3678: console_out (_T("No breakpoints\n"));
3679: else
3680: console_out (_T("\n"));
3681: return 0;
3682: }
3683: skipaddr_doskip = 1;
3684: skipaddr_start = readhex (c);
3685: if (more_params (c)) {
3686: skipaddr_end = readhex (c);
3687: } else {
3688: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
3689: bpn = &bpnodes[i];
3690: if (bpn->enabled && bpn->addr == skipaddr_start) {
3691: bpn->enabled = 0;
3692: console_out (_T("Breakpoint removed\n"));
3693: skipaddr_start = 0xffffffff;
3694: skipaddr_doskip = 0;
3695: return 0;
3696: }
3697: }
3698: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
3699: bpn = &bpnodes[i];
3700: if (bpn->enabled)
3701: continue;
3702: bpn->addr = skipaddr_start;
3703: bpn->enabled = 1;
3704: console_out (_T("Breakpoint added\n"));
3705: skipaddr_start = 0xffffffff;
3706: skipaddr_doskip = 0;
3707: break;
3708: }
3709: return 0;
3710: }
3711: }
3712: #if 0
3713: if (skipaddr_start == 0xC0DEDBAD) {
3714: trace_same_insn_count = 0;
3715: logfile = fopen ("uae.trace", "w");
3716: memcpy (trace_insn_copy, regs.pc_p, 10);
3717: memcpy (&trace_prev_regs, ®s, sizeof regs);
3718: }
3719: #endif
3720: do_skip = 1;
3721: skipaddr_doskip = -1;
3722: return 1;
3723: }
3724:
3725: static int process_breakpoint (TCHAR **c)
3726: {
3727: processptr = 0;
3728: xfree (processname);
3729: processname = NULL;
3730: if (!more_params (c))
3731: return 0;
3732: if (**c == '\"') {
3733: TCHAR pn[200];
3734: next_string (c, pn, 200, 0);
3735: processname = ua (pn);
3736: } else {
3737: processptr = readhex (c);
3738: }
3739: do_skip = 1;
3740: skipaddr_doskip = 1;
3741: skipaddr_start = 0;
3742: return 1;
3743: }
3744:
3745: static void savemem (TCHAR **cc)
3746: {
3747: uae_u8 b;
3748: uae_u32 src, src2, len, len2;
3749: TCHAR *name;
3750: FILE *fp;
3751:
3752: if (!more_params (cc))
3753: goto S_argh;
3754:
3755: name = *cc;
3756: while (**cc != '\0' && !isspace (**cc))
3757: (*cc)++;
3758: if (!isspace (**cc))
3759: goto S_argh;
3760:
3761: **cc = '\0';
3762: (*cc)++;
3763: if (!more_params (cc))
3764: goto S_argh;
3765: src2 = src = readhex (cc);
3766: if (!more_params (cc))
3767: goto S_argh;
3768: len2 = len = readhex (cc);
3769: fp = _tfopen (name, _T("wb"));
3770: if (fp == NULL) {
3771: console_out_f (_T("Couldn't open file '%s'\n"), name);
3772: return;
3773: }
3774: while (len > 0) {
3775: b = get_byte_debug (src);
3776: src++;
3777: len--;
3778: if (fwrite (&b, 1, 1, fp) != 1) {
3779: console_out (_T("Error writing file\n"));
3780: break;
3781: }
3782: }
3783: fclose (fp);
3784: if (len == 0)
3785: console_out_f (_T("Wrote %08X - %08X (%d bytes) to '%s'\n"),
3786: src2, src2 + len2, len2, name);
3787: return;
3788: S_argh:
3789: console_out (_T("S-command needs more arguments!\n"));
3790: }
3791:
3792: static void searchmem (TCHAR **cc)
3793: {
3794: int i, sslen, got, val, stringmode;
3795: uae_u8 ss[256];
3796: uae_u32 addr, endaddr;
3797: TCHAR nc;
3798:
3799: got = 0;
3800: sslen = 0;
3801: stringmode = 0;
3802: ignore_ws (cc);
3803: if (**cc == '"') {
3804: stringmode = 1;
3805: (*cc)++;
3806: while (**cc != '"' && **cc != 0) {
3807: ss[sslen++] = tolower (**cc);
3808: (*cc)++;
3809: }
3810: if (**cc != 0)
3811: (*cc)++;
3812: } else {
3813: for (;;) {
3814: if (**cc == 32 || **cc == 0)
3815: break;
3816: nc = _totupper (next_char (cc));
3817: if (isspace (nc))
3818: break;
3819: if (isdigit(nc))
3820: val = nc - '0';
3821: else
3822: val = nc - 'A' + 10;
3823: if (val < 0 || val > 15)
3824: return;
3825: val *= 16;
3826: if (**cc == 32 || **cc == 0)
3827: break;
3828: nc = _totupper (next_char (cc));
3829: if (isspace (nc))
3830: break;
3831: if (isdigit(nc))
3832: val += nc - '0';
3833: else
3834: val += nc - 'A' + 10;
3835: if (val < 0 || val > 255)
3836: return;
3837: ss[sslen++] = (uae_u8)val;
3838: }
3839: }
3840: if (sslen == 0)
3841: return;
3842: ignore_ws (cc);
3843: addr = 0;
3844: endaddr = lastaddr ();
3845: if (more_params (cc)) {
3846: addr = readhex (cc);
3847: if (more_params (cc))
3848: endaddr = readhex (cc);
3849: }
3850: console_out_f (_T("Searching from %08X to %08X..\n"), addr, endaddr);
3851: while ((addr = nextaddr (addr, endaddr, NULL)) != 0xffffffff) {
3852: if (addr == endaddr)
3853: break;
3854: for (i = 0; i < sslen; i++) {
3855: uae_u8 b = get_byte_debug (addr + i);
3856: if (stringmode) {
3857: if (tolower (b) != ss[i])
3858: break;
3859: } else {
3860: if (b != ss[i])
3861: break;
3862: }
3863: }
3864: if (i == sslen) {
3865: got++;
3866: console_out_f (_T(" %08X"), addr);
3867: if (got > 100) {
3868: console_out (_T("\nMore than 100 results, aborting.."));
3869: break;
3870: }
3871: }
3872: if (iscancel (65536)) {
3873: console_out_f (_T("Aborted at %08X\n"), addr);
3874: break;
3875: }
3876: }
3877: if (!got)
3878: console_out (_T("nothing found"));
3879: console_out (_T("\n"));
3880: }
3881:
3882: static int staterecorder (TCHAR **cc)
3883: {
3884: #if 0
3885: TCHAR nc;
3886:
3887: if (!more_params (cc)) {
3888: if (savestate_dorewind (1)) {
3889: debug_rewind = 1;
3890: return 1;
3891: }
3892: return 0;
3893: }
3894: nc = next_char (cc);
3895: if (nc == 'l') {
3896: savestate_listrewind ();
3897: return 0;
3898: }
3899: #endif
3900: return 0;
3901: }
3902:
3903: static int debugtest_modes[DEBUGTEST_MAX];
3904: static const TCHAR *debugtest_names[] = {
3905: _T("Blitter"), _T("Keyboard"), _T("Floppy")
3906: };
3907:
3908: void debugtest (enum debugtest_item di, const TCHAR *format, ...)
3909: {
3910: va_list parms;
3911: TCHAR buffer[1000];
3912:
3913: if (!debugtest_modes[di])
3914: return;
3915: va_start (parms, format);
3916: _vsntprintf (buffer, 1000 - 1, format, parms);
3917: va_end (parms);
3918: write_log (_T("%s PC=%08X: %s\n"), debugtest_names[di], M68K_GETPC, buffer);
3919: if (debugtest_modes[di] == 2)
3920: activate_debugger ();
3921: }
3922:
3923: static void debugtest_set (TCHAR **inptr)
3924: {
3925: int i, val, val2;
3926: ignore_ws (inptr);
3927:
3928: val2 = 1;
3929: if (!more_params (inptr)) {
3930: for (i = 0; i < DEBUGTEST_MAX; i++)
3931: debugtest_modes[i] = 0;
3932: console_out (_T("All debugtests disabled\n"));
3933: return;
3934: }
3935: val = readint (inptr);
3936: if (more_params (inptr)) {
3937: val2 = readint (inptr);
3938: if (val2 > 0)
3939: val2 = 2;
3940: }
3941: if (val < 0) {
3942: for (i = 0; i < DEBUGTEST_MAX; i++)
3943: debugtest_modes[i] = val2;
3944: console_out (_T("All debugtests enabled\n"));
3945: return;
3946: }
3947: if (val >= 0 && val < DEBUGTEST_MAX) {
3948: if (debugtest_modes[val])
3949: debugtest_modes[val] = 0;
3950: else
3951: debugtest_modes[val] = val2;
3952: console_out_f (_T("Debugtest '%s': %s. break = %s\n"),
3953: debugtest_names[val], debugtest_modes[val] ? _T("on") :_T("off"), val2 == 2 ? _T("on") : _T("off"));
3954: }
3955: }
3956:
3957: static void debug_sprite (TCHAR **inptr)
3958: {
3959: uaecptr saddr, addr, addr2;
3960: int xpos, xpos_ecs;
3961: int ypos, ypos_ecs;
3962: int ypose, ypose_ecs;
3963: int attach;
3964: uae_u64 w1, w2, ww1, ww2;
3965: int size = 1, width;
3966: int ecs, sh10;
3967: int y, i;
3968: TCHAR tmp[80];
3969: int max = 2;
3970:
3971: addr2 = 0;
3972: ignore_ws (inptr);
3973: addr = readhex (inptr);
3974: ignore_ws (inptr);
3975: if (more_params (inptr))
3976: size = readhex (inptr);
3977: if (size != 1 && size != 2 && size != 4) {
3978: addr2 = size;
3979: ignore_ws (inptr);
3980: if (more_params (inptr))
3981: size = readint (inptr);
3982: if (size != 1 && size != 2 && size != 4)
3983: size = 1;
3984: }
3985: for (;;) {
3986: ecs = 0;
3987: sh10 = 0;
3988: saddr = addr;
3989: width = size * 16;
3990: w1 = get_word_debug (addr);
3991: w2 = get_word_debug (addr + size * 2);
3992: console_out_f (_T(" %06X "), addr);
3993: for (i = 0; i < size * 2; i++)
3994: console_out_f (_T("%04X "), get_word_debug (addr + i * 2));
3995: console_out_f (_T("\n"));
3996:
3997: ypos = w1 >> 8;
3998: xpos = w1 & 255;
3999: ypose = w2 >> 8;
4000: attach = (w2 & 0x80) ? 1 : 0;
4001: if (w2 & 4)
4002: ypos |= 256;
4003: if (w2 & 2)
4004: ypose |= 256;
4005: ypos_ecs = ypos;
4006: ypose_ecs = ypose;
4007: if (w2 & 0x40)
4008: ypos_ecs |= 512;
4009: if (w2 & 0x20)
4010: ypose_ecs |= 512;
4011: xpos <<= 1;
4012: if (w2 & 0x01)
4013: xpos |= 1;
4014: xpos_ecs = xpos << 2;
4015: if (w2 & 0x10)
4016: xpos_ecs |= 2;
4017: if (w2 & 0x08)
4018: xpos_ecs |= 1;
4019: if (w2 & (0x40 | 0x20 | 0x10 | 0x08))
4020: ecs = 1;
4021: if (w1 & 0x80)
4022: sh10 = 1;
4023: if (ypose < ypos)
4024: ypose += 256;
4025:
4026: for (y = ypos; y < ypose; y++) {
4027: int x;
4028: addr += size * 4;
4029: if (addr2)
4030: addr2 += size * 4;
4031: if (size == 1) {
4032: w1 = get_word_debug (addr);
4033: w2 = get_word_debug (addr + 2);
4034: if (addr2) {
4035: ww1 = get_word_debug (addr2);
4036: ww2 = get_word_debug (addr2 + 2);
4037: }
4038: } else if (size == 2) {
4039: w1 = get_long_debug (addr);
4040: w2 = get_long_debug (addr + 4);
4041: if (addr2) {
4042: ww1 = get_long_debug (addr2);
4043: ww2 = get_long_debug (addr2 + 4);
4044: }
4045: } else if (size == 4) {
4046: w1 = get_long_debug (addr + 0);
4047: w2 = get_long_debug (addr + 8);
4048: w1 <<= 32;
4049: w2 <<= 32;
4050: w1 |= get_long_debug (addr + 4);
4051: w2 |= get_long_debug (addr + 12);
4052: if (addr2) {
4053: ww1 = get_long_debug (addr2 + 0);
4054: ww2 = get_long_debug (addr2 + 8);
4055: ww1 <<= 32;
4056: ww2 <<= 32;
4057: ww1 |= get_long_debug (addr2 + 4);
4058: ww2 |= get_long_debug (addr2 + 12);
4059: }
4060: }
4061: width = size * 16;
4062: for (x = 0; x < width; x++) {
4063: int v1 = w1 & 1;
4064: int v2 = w2 & 1;
4065: int v = v1 * 2 + v2;
4066: w1 >>= 1;
4067: w2 >>= 1;
4068: if (addr2) {
4069: int vv1 = ww1 & 1;
4070: int vv2 = ww2 & 1;
4071: int vv = vv1 * 2 + vv2;
4072: vv1 >>= 1;
4073: vv2 >>= 1;
4074: v *= 4;
4075: v += vv;
4076: tmp[width - (x + 1)] = v >= 10 ? 'A' + v - 10 : v + '0';
4077: } else {
4078: tmp[width - (x + 1)] = v + '0';
4079: }
4080: }
4081: tmp[width] = 0;
4082: console_out_f (_T("%3d %06X %s\n"), y, addr, tmp);
4083: }
4084:
4085: console_out_f (_T("Sprite address %08X, width = %d\n"), saddr, size * 16);
4086: console_out_f (_T("OCS: StartX=%d StartY=%d EndY=%d\n"), xpos, ypos, ypose);
4087: console_out_f (_T("ECS: StartX=%d (%d.%d) StartY=%d EndY=%d%s\n"), xpos_ecs, xpos_ecs / 4, xpos_ecs & 3, ypos_ecs, ypose_ecs, ecs ? _T(" (*)") : _T(""));
4088: console_out_f (_T("Attach: %d. AGA SSCAN/SH10 bit: %d\n"), attach, sh10);
4089:
4090: addr += size * 4;
4091: if (get_word_debug (addr) == 0 && get_word_debug (addr + size * 4) == 0)
4092: break;
4093: max--;
4094: if (max <= 0)
4095: break;
4096: }
4097:
4098: }
4099:
4100: int debug_write_memory_16 (uaecptr addr, uae_u16 v)
4101: {
4102: addrbank *ad;
4103:
4104: ad = &get_mem_bank (addr);
4105: if (ad) {
4106: ad->wput (addr, v);
4107: return 1;
4108: }
4109: return -1;
4110: }
4111: int debug_write_memory_8 (uaecptr addr, uae_u8 v)
4112: {
4113: addrbank *ad;
4114:
4115: ad = &get_mem_bank (addr);
4116: if (ad) {
4117: ad->bput (addr, v);
4118: return 1;
4119: }
4120: return -1;
4121: }
4122: int debug_peek_memory_16 (uaecptr addr)
4123: {
4124: addrbank *ad;
4125:
4126: ad = &get_mem_bank (addr);
4127: if (ad->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
4128: return ad->wget (addr);
4129: if (ad == &custom_bank) {
4130: addr &= 0x1fe;
4131: return (ar_custom[addr + 0] << 8) | ar_custom[addr + 1];
4132: }
4133: return -1;
4134: }
4135: int debug_read_memory_16 (uaecptr addr)
4136: {
4137: addrbank *ad;
4138:
4139: ad = &get_mem_bank (addr);
4140: if (ad)
4141: return ad->wget (addr);
4142: return -1;
4143: }
4144: int debug_read_memory_8 (uaecptr addr)
4145: {
4146: addrbank *ad;
4147:
4148: ad = &get_mem_bank (addr);
4149: if (ad)
4150: return ad->bget (addr);
4151: return -1;
4152: }
4153:
4154: static void disk_debug (TCHAR **inptr)
4155: {
4156: TCHAR parm[10];
4157: int i;
4158:
4159: if (**inptr == 'd') {
4160: (*inptr)++;
4161: ignore_ws (inptr);
4162: disk_debug_logging = readint (inptr);
4163: console_out_f (_T("Disk logging level %d\n"), disk_debug_logging);
4164: return;
4165: }
4166: disk_debug_mode = 0;
4167: disk_debug_track = -1;
4168: ignore_ws (inptr);
4169: if (!next_string (inptr, parm, sizeof (parm) / sizeof (TCHAR), 1))
4170: goto end;
4171: for (i = 0; i < _tcslen(parm); i++) {
4172: if (parm[i] == 'R')
4173: disk_debug_mode |= DISK_DEBUG_DMA_READ;
4174: if (parm[i] == 'W')
4175: disk_debug_mode |= DISK_DEBUG_DMA_WRITE;
4176: if (parm[i] == 'P')
4177: disk_debug_mode |= DISK_DEBUG_PIO;
4178: }
4179: if (more_params(inptr))
4180: disk_debug_track = readint (inptr);
4181: if (disk_debug_track < 0 || disk_debug_track > 2 * 83)
4182: disk_debug_track = -1;
4183: if (disk_debug_logging == 0)
4184: disk_debug_logging = 1;
4185: end:
4186: console_out_f (_T("Disk breakpoint mode %c%c%c track %d\n"),
4187: disk_debug_mode & DISK_DEBUG_DMA_READ ? 'R' : '-',
4188: disk_debug_mode & DISK_DEBUG_DMA_WRITE ? 'W' : '-',
4189: disk_debug_mode & DISK_DEBUG_PIO ? 'P' : '-',
4190: disk_debug_track);
4191: }
4192:
4193: static void find_ea (TCHAR **inptr)
4194: {
4195: uae_u32 ea, sea, dea;
4196: uaecptr addr, end;
4197: int hits = 0;
4198:
4199: addr = 0;
4200: end = lastaddr ();
4201: ea = readhex (inptr);
4202: if (more_params(inptr)) {
4203: addr = readhex (inptr);
4204: if (more_params(inptr))
4205: end = readhex (inptr);
4206: }
4207: console_out_f (_T("Searching from %08X to %08X\n"), addr, end);
4208: while((addr = nextaddr (addr, end, &end)) != 0xffffffff) {
4209: if ((addr & 1) == 0 && addr + 6 <= end) {
4210: sea = 0xffffffff;
4211: dea = 0xffffffff;
4212: m68k_disasm_ea (addr, NULL, 1, &sea, &dea);
4213: if (ea == sea || ea == dea) {
4214: m68k_disasm (addr, NULL, 1);
4215: hits++;
4216: if (hits > 100) {
4217: console_out_f (_T("Too many hits. End addr = %08X\n"), addr);
4218: break;
4219: }
4220: }
4221: if (iscancel (65536)) {
4222: console_out_f (_T("Aborted at %08X\n"), addr);
4223: break;
4224: }
4225: }
4226: }
4227: }
4228:
4229: static void m68k_modify (TCHAR **inptr)
4230: {
4231: uae_u32 v;
4232: TCHAR parm[10];
4233: TCHAR c1, c2;
4234: int i;
4235:
4236: if (!next_string (inptr, parm, sizeof (parm) / sizeof (TCHAR), 1))
4237: return;
4238: c1 = _totupper (parm[0]);
4239: c2 = 99;
4240: if (c1 == 'A' || c1 == 'D' || c1 == 'P') {
4241: c2 = _totupper (parm[1]);
4242: if (isdigit (c2))
4243: c2 -= '0';
4244: else
4245: c2 = 99;
4246: }
4247: v = readhex (inptr);
4248: if (c1 == 'A' && c2 < 8)
4249: regs.regs[8 + c2] = v;
4250: else if (c1 == 'D' && c2 < 8)
4251: regs.regs[c2] = v;
4252: else if (c1 == 'P' && c2 == 0)
4253: regs.irc = v;
4254: else if (c1 == 'P' && c2 == 1)
4255: regs.ir = v;
4256: else if (!_tcscmp (parm, _T("SR"))) {
4257: regs.sr = v;
4258: MakeFromSR ();
4259: } else if (!_tcscmp (parm, _T("CCR"))) {
4260: regs.sr = (regs.sr & ~31) | (v & 31);
4261: MakeFromSR ();
4262: } else if (!_tcscmp (parm, _T("USP"))) {
4263: regs.usp = v;
4264: } else if (!_tcscmp (parm, _T("ISP"))) {
4265: regs.isp = v;
4266: } else if (!_tcscmp (parm, _T("PC"))) {
4267: m68k_setpc (v);
4268: fill_prefetch ();
4269: } else {
4270: for (i = 0; m2cregs[i].regname; i++) {
4271: if (!_tcscmp (parm, m2cregs[i].regname))
4272: val_move2c2 (m2cregs[i].regno, v);
4273: }
4274: }
4275: }
4276:
4277: static void ppc_disasm(uaecptr addr, uaecptr *nextpc, int cnt)
4278: {
4279: PPCD_CB disa;
4280:
4281: while(cnt-- > 0) {
4282: uae_u32 instr = get_long_debug(addr);
4283: disa.pc = addr;
4284: disa.instr = instr;
4285: PPCDisasm(&disa);
4286: TCHAR *mnemo = au(disa.mnemonic);
4287: TCHAR *ops = au(disa.operands);
4288: console_out_f(_T("%08X %08X %-12s%-30s\n"), addr, instr, mnemo, ops);
4289: xfree(ops);
4290: xfree(mnemo);
4291: addr += 4;
4292: }
4293: if (nextpc)
4294: *nextpc = addr;
4295: }
4296:
4297: static uaecptr nxdis, nxmem;
4298: static bool ppcmode;
4299:
4300: static BOOL debug_line (TCHAR *input)
4301: {
4302: TCHAR cmd, *inptr;
4303: uaecptr addr;
4304:
4305: inptr = input;
4306: cmd = next_char (&inptr);
4307:
4308: switch (cmd)
4309: {
4310: case 'c': dumpcia (); dumpdisk (); dumpcustom (); break;
4311: case 'i':
4312: {
4313: if (*inptr == 'l') {
4314: next_char (&inptr);
4315: if (more_params (&inptr)) {
4316: debug_illegal_mask = readhex (&inptr);
4317: } else {
4318: debug_illegal_mask = debug_illegal ? 0 : -1;
4319: debug_illegal_mask &= ~((uae_u64)255 << 24); // mask interrupts
4320: }
4321: console_out_f (_T("Exception breakpoint mask: %0I64X\n"), debug_illegal_mask);
4322: debug_illegal = debug_illegal_mask ? 1 : 0;
4323: } else {
4324: addr = 0xffffffff;
4325: if (more_params (&inptr))
4326: addr = readhex (&inptr);
4327: dump_vectors (addr);
4328: }
4329: break;
4330: }
4331: case 'e': dump_custom_regs (tolower(*inptr) == 'a'); break;
4332: case 'r':
4333: {
4334: if (*inptr == 'c')
4335: m68k_dumpcache ();
4336: else if (more_params(&inptr))
4337: m68k_modify (&inptr);
4338: else
4339: m68k_dumpstate (&nextpc);
4340: }
4341: break;
4342: case 'D': deepcheatsearch (&inptr); break;
4343: case 'C': cheatsearch (&inptr); break;
4344: case 'W': writeintomem (&inptr); break;
4345: case 'w': memwatch (&inptr); break;
4346: case 'S': savemem (&inptr); break;
4347: case 's':
4348: if (*inptr == 'c') {
4349: screenshot (1, 1);
4350: } else if (*inptr == 'p') {
4351: inptr++;
4352: debug_sprite (&inptr);
4353: } else if (*inptr == 'm') {
4354: if (*(inptr + 1) == 'c') {
4355: next_char (&inptr);
4356: next_char (&inptr);
4357: if (!smc_table)
4358: smc_detect_init (&inptr);
4359: else
4360: smc_free ();
4361: }
4362: } else {
4363: searchmem (&inptr);
4364: }
4365: break;
4366: case 'd':
4367: {
4368: if (*inptr == 'i') {
4369: next_char (&inptr);
4370: disk_debug (&inptr);
4371: } else if (*inptr == 'j') {
4372: inptr++;
4373: inputdevice_logging = 1 | 2;
4374: if (more_params (&inptr))
4375: inputdevice_logging = readint (&inptr);
4376: console_out_f (_T("Input logging level %d\n"), inputdevice_logging);
4377: } else if (*inptr == 'm') {
4378: memory_map_dump_2 (0);
4379: } else if (*inptr == 't') {
4380: next_char (&inptr);
4381: debugtest_set (&inptr);
4382: #ifdef _WIN32
4383: } else if (*inptr == 'g') {
4384: extern void update_disassembly (uae_u32);
4385: next_char (&inptr);
4386: if (more_params (&inptr))
4387: update_disassembly (readhex (&inptr));
4388: #endif
4389: } else {
4390: uae_u32 daddr;
4391: int count;
4392: if (*inptr == 'p') {
4393: ppcmode = true;
4394: next_char(&inptr);
4395: } else if(*inptr == 'o') {
4396: ppcmode = false;
4397: next_char(&inptr);
4398: }
4399: if (more_params (&inptr))
4400: daddr = readhex (&inptr);
4401: else
4402: daddr = nxdis;
4403: if (more_params (&inptr))
4404: count = readhex (&inptr);
4405: else
4406: count = 10;
4407: if (ppcmode) {
4408: ppc_disasm(daddr, &nxdis, count);
4409: } else {
4410: m68k_disasm (daddr, &nxdis, count);
4411: }
4412: }
4413: }
4414: break;
4415: case 'T':
4416: if (inptr[0] == 't' || inptr[0] == 0)
4417: show_exec_tasks ();
4418: else
4419: show_exec_lists (&inptr[0]);
4420: break;
4421: case 't':
4422: no_trace_exceptions = 0;
4423: if (*inptr != 't') {
4424: if (more_params (&inptr))
4425: skipaddr_doskip = readint (&inptr);
4426: if (skipaddr_doskip <= 0 || skipaddr_doskip > 10000)
4427: skipaddr_doskip = 1;
4428: } else {
4429: no_trace_exceptions = 1;
4430: }
4431: set_special (SPCFLAG_BRK);
4432: exception_debugging = 1;
4433: return true;
4434: case 'z':
4435: skipaddr_start = nextpc;
4436: skipaddr_doskip = 1;
4437: do_skip = 1;
4438: exception_debugging = 1;
4439: return true;
4440:
4441: case 'f':
4442: if (inptr[0] == 'a') {
4443: next_char (&inptr);
4444: find_ea (&inptr);
4445: } else if (inptr[0] == 'p') {
4446: inptr++;
4447: if (process_breakpoint (&inptr))
4448: return true;
4449: } else if (inptr[0] == 'c' || inptr[0] == 's') {
4450: if (cycle_breakpoint(&inptr))
4451: return true;
4452: } else if (inptr[0] == 'e' && inptr[1] == 'n') {
4453: break_if_enforcer = break_if_enforcer ? false : true;
4454: console_out_f(_T("Break when enforcer hit: %s\n"), break_if_enforcer ? _T("enabled") : _T("disabled"));
4455: } else {
4456: if (instruction_breakpoint (&inptr))
4457: return true;
4458: }
4459: break;
4460:
4461: case 'q':
4462: uae_quit();
4463: deactivate_debugger();
4464: return true;
4465:
4466: case 'g':
4467: if (more_params (&inptr)) {
4468: m68k_setpc (readhex (&inptr));
4469: fill_prefetch ();
4470: }
4471: deactivate_debugger();
4472: return true;
4473:
4474: case 'x':
4475: if (_totupper(inptr[0]) == 'X') {
4476: debugger_change(-1);
4477: } else {
4478: deactivate_debugger();
4479: close_console();
4480: return true;
4481: }
4482: break;
4483:
4484: case 'H':
4485: {
4486: int count, temp, badly, skip;
4487: uae_u32 addr = 0;
4488: uae_u32 oldpc = m68k_getpc ();
4489: struct regstruct save_regs = regs;
4490:
4491: badly = 0;
4492: if (inptr[0] == 'H') {
4493: badly = 1;
4494: inptr++;
4495: }
4496:
4497: if (more_params(&inptr))
4498: count = readint (&inptr);
4499: else
4500: count = 10;
4501: if (count > 1000) {
4502: addr = count;
4503: count = MAX_HIST;
4504: }
4505: if (count < 0)
4506: break;
4507: skip = count;
4508: if (more_params (&inptr))
4509: skip = count - readint (&inptr);
4510:
4511: temp = lasthist;
4512: while (count-- > 0 && temp != firsthist) {
4513: if (temp == 0)
4514: temp = MAX_HIST - 1;
4515: else
4516: temp--;
4517: }
4518: while (temp != lasthist) {
4519: regs = history[temp];
4520: if (history[temp].pc == addr || addr == 0) {
4521: m68k_setpc (history[temp].pc);
4522: if (badly) {
4523: m68k_dumpstate (NULL);
4524: } else {
4525: console_out_f(_T("%2d "), history[temp].intmask ? history[temp].intmask : (history[temp].s ? -1 : 0));
4526: m68k_disasm (history[temp].pc, NULL, 1);
4527: }
4528: if (addr && history[temp].pc == addr)
4529: break;
4530: }
4531: if (skip-- < 0)
4532: break;
4533: if (++temp == MAX_HIST)
4534: temp = 0;
4535: }
4536: regs = save_regs;
4537: m68k_setpc (oldpc);
4538: }
4539: break;
4540: case 'M':
4541: if (more_params (&inptr)) {
4542: switch (next_char (&inptr))
4543: {
4544: case 'a':
4545: if (more_params (&inptr))
4546: audio_channel_mask = readhex (&inptr);
4547: console_out_f (_T("Audio mask = %02X\n"), audio_channel_mask);
4548: break;
4549: case 's':
4550: if (more_params (&inptr))
4551: debug_sprite_mask = readhex (&inptr);
4552: console_out_f (_T("Sprite mask: %02X\n"), debug_sprite_mask);
4553: break;
4554: case 'b':
4555: if (more_params (&inptr)) {
4556: debug_bpl_mask = readhex (&inptr) & 0xff;
4557: if (more_params (&inptr))
4558: debug_bpl_mask_one = readhex (&inptr) & 0xff;
4559: notice_screen_contents_lost ();
4560: }
4561: console_out_f (_T("Bitplane mask: %02X (%02X)\n"), debug_bpl_mask, debug_bpl_mask_one);
4562: break;
4563: }
4564: }
4565: break;
4566: case 'm':
4567: {
4568: uae_u32 maddr;
4569: int lines;
4570: #ifdef _WIN32
4571: if (*inptr == 'g') {
4572: extern void update_memdump (uae_u32);
4573: next_char (&inptr);
4574: if (more_params (&inptr))
4575: update_memdump (readhex (&inptr));
4576: break;
4577: }
4578: #endif
4579: if (*inptr == 'm' && inptr[1] == 'u') {
4580: if (currprefs.mmu_model) {
4581: inptr += 2;
4582: if (more_params (&inptr))
4583: debug_mmu_mode = readint (&inptr);
4584: else
4585: debug_mmu_mode = 0;
4586: console_out_f (_T("MMU translation function code = %d\n"), debug_mmu_mode);
4587: }
4588: break;
4589: }
4590: if (more_params (&inptr)) {
4591: maddr = readhex (&inptr);
4592: } else {
4593: maddr = nxmem;
4594: }
4595: if (more_params (&inptr))
4596: lines = readhex (&inptr);
4597: else
4598: lines = 20;
4599: dumpmem (maddr, &nxmem, lines);
4600: }
4601: break;
4602: case 'v':
4603: case 'V':
4604: {
4605: int v1 = vpos, v2 = 0;
4606: if (more_params (&inptr))
4607: v1 = readint (&inptr);
4608: if (more_params (&inptr))
4609: v2 = readint (&inptr);
4610: if (debug_dma) {
4611: decode_dma_record (v2, v1, cmd == 'v', false);
4612: } else {
4613: debug_dma = v1 < 0 ? -v1 : 1;
4614: console_out_f (_T("DMA debugger enabled, mode=%d.\n"), debug_dma);
4615: }
4616: }
4617: break;
4618: case 'o':
4619: {
4620: if (copper_debugger (&inptr)) {
4621: debugger_active = 0;
4622: debugging = 0;
4623: return true;
4624: }
4625: break;
4626: }
4627: case 'O':
4628: break;
4629: case 'b':
4630: if (staterecorder (&inptr))
4631: return true;
4632: break;
4633: case 'U':
4634: if (currprefs.mmu_model && more_params (&inptr)) {
4635: int i;
4636: uaecptr addrl = readhex (&inptr);
4637: uaecptr addrp;
4638: console_out_f (_T("%08X translates to:\n"), addrl);
4639: for (i = 0; i < 4; i++) {
4640: bool super = (i & 2) != 0;
4641: bool data = (i & 1) != 0;
4642: console_out_f (_T("S%dD%d="), super, data);
4643: TRY(prb) {
4644: if (currprefs.mmu_model >= 68040)
4645: addrp = mmu_translate (addrl, super, data, false);
4646: else
4647: addrp = mmu030_translate (addrl, super, data, false);
4648: console_out_f (_T("%08X"), addrp);
4649: TRY(prb2) {
4650: if (currprefs.mmu_model >= 68040)
4651: addrp = mmu_translate (addrl, super, data, true);
4652: else
4653: addrp = mmu030_translate (addrl, super, data, true);
4654: console_out_f (_T(" RW"));
4655: } CATCH(prb2) {
4656: console_out_f (_T(" RO"));
4657: } ENDTRY
4658: } CATCH(prb) {
4659: console_out_f (_T("***********"));
4660: } ENDTRY
4661: console_out_f (_T(" "));
4662: }
4663: console_out_f (_T("\n"));
4664: }
4665: break;
4666: case 'h':
4667: case '?':
4668: if (more_params (&inptr))
4669: converter (&inptr);
4670: else
4671: debug_help ();
4672: break;
4673: }
4674: return false;
4675: }
4676:
4677: static void debug_1 (void)
4678: {
4679: TCHAR input[MAX_LINEWIDTH];
4680:
4681: m68k_dumpstate (&nextpc);
4682: nxdis = nextpc; nxmem = 0;
4683: debugger_active = 1;
4684:
4685: for (;;) {
4686: int v;
4687:
4688: if (!debugger_active)
4689: return;
4690: update_debug_info ();
4691: console_out (_T(">"));
4692: console_flush ();
4693: debug_linecounter = 0;
4694: v = console_get (input, MAX_LINEWIDTH);
4695: if (v < 0)
4696: return;
4697: if (v == 0)
4698: continue;
4699: if (debug_line (input))
4700: return;
4701: }
4702: }
4703:
4704: static void addhistory (void)
4705: {
4706: uae_u32 pc = m68k_getpc ();
4707: // if (!notinrom())
4708: // return;
4709: history[lasthist] = regs;
4710: history[lasthist].pc = m68k_getpc ();
4711: if (++lasthist == MAX_HIST)
4712: lasthist = 0;
4713: if (lasthist == firsthist) {
4714: if (++firsthist == MAX_HIST) firsthist = 0;
4715: }
4716: }
4717:
4718: static void debug_continue(void)
4719: {
4720: set_special (SPCFLAG_BRK);
4721: }
4722:
4723:
4724: void debug (void)
4725: {
4726: int i;
4727: int wasactive;
4728:
4729: if (savestate_state)
4730: return;
4731:
4732: bogusframe = 1;
4733: addhistory ();
4734:
4735: #if 0
4736: if (do_skip && skipaddr_start == 0xC0DEDBAD) {
4737: if (trace_same_insn_count > 0) {
4738: if (memcmp (trace_insn_copy, regs.pc_p, 10) == 0
4739: && memcmp (trace_prev_regs.regs, regs.regs, sizeof regs.regs) == 0)
4740: {
4741: trace_same_insn_count++;
4742: return;
4743: }
4744: }
4745: if (trace_same_insn_count > 1)
4746: fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
4747: m68k_dumpstate (logfile, &nextpc);
4748: trace_same_insn_count = 1;
4749: memcpy (trace_insn_copy, regs.pc_p, 10);
4750: memcpy (&trace_prev_regs, ®s, sizeof regs);
4751: }
4752: #endif
4753:
4754: if (!memwatch_triggered) {
4755: if (do_skip) {
4756: uae_u32 pc;
4757: uae_u16 opcode;
4758: int bp = 0;
4759:
4760: pc = munge24 (m68k_getpc ());
4761: opcode = currprefs.cpu_model < 68020 && (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) ? regs.ir : get_word_debug (pc);
4762:
4763: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
4764: if (!bpnodes[i].enabled)
4765: continue;
4766: if (bpnodes[i].addr == pc) {
4767: bp = 1;
4768: console_out_f (_T("Breakpoint at %08X\n"), pc);
4769: break;
4770: }
4771: }
4772:
4773: if (skipaddr_doskip) {
4774: if (skipaddr_start == pc)
4775: bp = 1;
4776: if ((processptr || processname) && notinrom()) {
4777: uaecptr execbase = get_long_debug (4);
4778: uaecptr activetask = get_long_debug (execbase + 276);
4779: int process = get_byte_debug (activetask + 8) == 13 ? 1 : 0;
4780: char *name = (char*)get_real_address (get_long_debug (activetask + 10));
4781: if (process) {
4782: uaecptr cli = BPTR2APTR(get_long_debug (activetask + 172));
4783: uaecptr seglist = 0;
4784:
4785: uae_char *command = NULL;
4786: if (cli) {
4787: if (processname)
4788: command = (char*)get_real_address (BPTR2APTR(get_long_debug (cli + 16)));
4789: seglist = BPTR2APTR(get_long_debug (cli + 60));
4790: } else {
4791: seglist = BPTR2APTR(get_long_debug (activetask + 128));
4792: seglist = BPTR2APTR(get_long_debug (seglist + 12));
4793: }
4794: if (activetask == processptr || (processname && (!stricmp (name, processname) || (command && command[0] && !strnicmp (command + 1, processname, command[0]) && processname[command[0]] == 0)))) {
4795: while (seglist) {
4796: uae_u32 size = get_long_debug (seglist - 4) - 4;
4797: if (pc >= (seglist + 4) && pc < (seglist + size)) {
4798: bp = 1;
4799: break;
4800: }
4801: seglist = BPTR2APTR(get_long_debug (seglist));
4802: }
4803: }
4804: }
4805: } else if (skipins != 0xffffffff) {
4806: if (skipins == 0x10000) {
4807: if (opcode == 0x4e75 || opcode == 0x4e73 || opcode == 0x4e77)
4808: bp = 1;
4809: } else if (opcode == skipins)
4810: bp = 1;
4811: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip < 0) {
4812: if ((pc < 0xe00000 || pc >= 0x1000000) && opcode != 0x4ef9)
4813: bp = 1;
4814: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip > 0) {
4815: bp = 1;
4816: } else if (skipaddr_end != 0xffffffff) {
4817: if (pc >= skipaddr_start && pc < skipaddr_end)
4818: bp = 1;
4819: }
4820: }
4821: if (sr_bpmask || sr_bpvalue) {
4822: MakeSR ();
4823: if ((regs.sr & sr_bpmask) == sr_bpvalue) {
4824: console_out (_T("SR breakpoint\n"));
4825: bp = 1;
4826: }
4827: }
4828: if (!bp) {
4829: debug_continue();
4830: return;
4831: }
4832: }
4833: } else {
4834: console_out_f (_T("Memwatch %d: break at %08X.%c %c%c%c %08X PC=%08X "), memwatch_triggered - 1, mwhit.addr,
4835: mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'),
4836: (mwhit.rwi & 1) ? 'R' : ' ', (mwhit.rwi & 2) ? 'W' : ' ', (mwhit.rwi & 4) ? 'I' : ' ',
4837: mwhit.val, mwhit.pc);
4838: for (i = 0; memwatch_access_masks[i].mask; i++) {
4839: if (mwhit.access_mask == memwatch_access_masks[i].mask)
4840: console_out_f (_T("%s (%03x)\n"), memwatch_access_masks[i].name, mwhit.reg);
4841: }
4842: memwatch_triggered = 0;
4843: }
4844: if (skipaddr_doskip > 0) {
4845: skipaddr_doskip--;
4846: if (skipaddr_doskip > 0) {
4847: debug_continue();
4848: return;
4849: }
4850: }
4851:
4852: wasactive = ismouseactive ();
4853: #ifdef WITH_PPC
4854: uae_ppc_pause(1);
4855: #endif
4856: inputdevice_unacquire ();
4857: pause_sound ();
4858: setmouseactive (0);
4859: activate_console ();
4860: do_skip = 0;
4861: skipaddr_start = 0xffffffff;
4862: skipaddr_end = 0xffffffff;
4863: skipins = 0xffffffff;
4864: skipaddr_doskip = 0;
4865: exception_debugging = 0;
4866: debug_rewind = 0;
4867: processptr = 0;
4868: #if 0
4869: if (!currprefs.statecapture) {
4870: changed_prefs.statecapture = currprefs.statecapture = 1;
4871: savestate_init ();
4872: }
4873: #endif
4874: debug_1 ();
4875: if (!debug_rewind && !currprefs.cachesize
4876: #ifdef FILESYS
4877: && nr_units () == 0
4878: #endif
4879: ) {
4880: savestate_capture (1);
4881: }
4882: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
4883: if (bpnodes[i].enabled)
4884: do_skip = 1;
4885: }
4886: if (sr_bpmask || sr_bpvalue)
4887: do_skip = 1;
4888: if (do_skip) {
4889: set_special (SPCFLAG_BRK);
4890: debugging = -1;
4891: }
4892: resume_sound ();
4893: inputdevice_acquire (TRUE);
4894: #ifdef WITH_PPC
4895: uae_ppc_pause(0);
4896: #endif
4897: setmouseactive (wasactive ? 2 : 0);
4898: }
4899:
4900: const TCHAR *debuginfo (int mode)
4901: {
4902: static TCHAR txt[100];
4903: uae_u32 pc = M68K_GETPC;
4904: _stprintf (txt, _T("PC=%08X INS=%04X %04X %04X"),
4905: pc, get_word_debug (pc), get_word_debug (pc + 2), get_word_debug (pc + 4));
4906: return txt;
4907: }
4908:
4909: #endif /* WINUAE_FOR_HATARI */
4910:
4911: void mmu_disasm (uaecptr pc, int lines)
4912: {
4913: debug_mmu_mode = regs.s ? 6 : 2;
4914: m68k_dumpstate (0xffffffff, NULL);
4915: m68k_disasm (pc, NULL, lines);
4916: }
4917:
4918: static int mmu_logging;
4919:
4920: #define MMU_PAGE_SHIFT 16
4921:
4922: struct mmudata {
4923: uae_u32 flags;
4924: uae_u32 addr;
4925: uae_u32 len;
4926: uae_u32 remap;
4927: uae_u32 p_addr;
4928: };
4929:
4930: static struct mmudata *mmubanks;
4931: static uae_u32 mmu_struct, mmu_callback, mmu_regs;
4932: static uae_u32 mmu_fault_bank_addr, mmu_fault_addr;
4933: static int mmu_fault_size, mmu_fault_rw;
4934: static int mmu_slots;
4935: static struct regstruct mmur;
4936:
4937: struct mmunode {
4938: struct mmudata *mmubank;
4939: struct mmunode *next;
4940: };
4941: static struct mmunode **mmunl;
4942: extern regstruct mmu_backup_regs;
4943:
4944: #define MMU_READ_U (1 << 0)
4945: #define MMU_WRITE_U (1 << 1)
4946: #define MMU_READ_S (1 << 2)
4947: #define MMU_WRITE_S (1 << 3)
4948: #define MMU_READI_U (1 << 4)
4949: #define MMU_READI_S (1 << 5)
4950:
4951: #define MMU_MAP_READ_U (1 << 8)
4952: #define MMU_MAP_WRITE_U (1 << 9)
4953: #define MMU_MAP_READ_S (1 << 10)
4954: #define MMU_MAP_WRITE_S (1 << 11)
4955: #define MMU_MAP_READI_U (1 << 12)
4956: #define MMU_MAP_READI_S (1 << 13)
4957:
4958: void mmu_do_hit (void)
4959: {
4960: int i;
4961: uaecptr p;
4962: uae_u32 pc;
4963:
4964: mmu_triggered = 0;
4965: pc = m68k_getpc ();
4966: p = mmu_regs + 18 * 4;
4967: put_long (p, pc);
4968: regs = mmu_backup_regs;
4969: regs.intmask = 7;
4970: regs.t0 = regs.t1 = 0;
4971: if (!regs.s) {
4972: regs.usp = m68k_areg (regs, 7);
4973: if (currprefs.cpu_model >= 68020)
4974: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
4975: else
4976: m68k_areg (regs, 7) = regs.isp;
4977: regs.s = 1;
4978: }
4979: MakeSR ();
4980: m68k_setpc (mmu_callback);
4981: fill_prefetch ();
4982:
4983: if (currprefs.cpu_model > 68000) {
4984: for (i = 0 ; i < 9; i++) {
4985: m68k_areg (regs, 7) -= 4;
4986: put_long (m68k_areg (regs, 7), 0);
4987: }
4988: m68k_areg (regs, 7) -= 4;
4989: put_long (m68k_areg (regs, 7), mmu_fault_addr);
4990: m68k_areg (regs, 7) -= 2;
4991: put_word (m68k_areg (regs, 7), 0); /* WB1S */
4992: m68k_areg (regs, 7) -= 2;
4993: put_word (m68k_areg (regs, 7), 0); /* WB2S */
4994: m68k_areg (regs, 7) -= 2;
4995: put_word (m68k_areg (regs, 7), 0); /* WB3S */
4996: m68k_areg (regs, 7) -= 2;
4997: put_word (m68k_areg (regs, 7),
4998: (mmu_fault_rw ? 0 : 0x100) | (mmu_fault_size << 5)); /* SSW */
4999: m68k_areg (regs, 7) -= 4;
5000: put_long (m68k_areg (regs, 7), mmu_fault_bank_addr);
5001: m68k_areg (regs, 7) -= 2;
5002: put_word (m68k_areg (regs, 7), 0x7002);
5003: }
5004: m68k_areg (regs, 7) -= 4;
5005: put_long (m68k_areg (regs, 7), get_long_debug (p - 4));
5006: m68k_areg (regs, 7) -= 2;
5007: put_word (m68k_areg (regs, 7), mmur.sr);
5008: #ifdef JIT
5009: set_special(SPCFLAG_END_COMPILE);
5010: #endif
5011: }
5012:
5013: static void mmu_do_hit_pre (struct mmudata *md, uaecptr addr, int size, int rwi, uae_u32 v)
5014: {
5015: uae_u32 p, pc;
5016: int i;
5017:
5018: mmur = regs;
5019: pc = m68k_getpc ();
5020: if (mmu_logging)
5021: console_out_f (_T("MMU: hit %08X SZ=%d RW=%d V=%08X PC=%08X\n"), addr, size, rwi, v, pc);
5022:
5023: p = mmu_regs;
5024: put_long (p, 0); p += 4;
5025: for (i = 0; i < 16; i++) {
5026: put_long (p, regs.regs[i]);
5027: p += 4;
5028: }
5029: put_long (p, pc); p += 4;
5030: put_long (p, 0); p += 4;
5031: put_long (p, regs.usp); p += 4;
5032: put_long (p, regs.isp); p += 4;
5033: put_long (p, regs.msp); p += 4;
5034: put_word (p, regs.sr); p += 2;
5035: put_word (p, (size << 1) | ((rwi & 2) ? 1 : 0)); /* size and rw */ p += 2;
5036: put_long (p, addr); /* fault address */ p += 4;
5037: put_long (p, md->p_addr); /* bank address */ p += 4;
5038: put_long (p, v); p += 4;
5039: mmu_fault_addr = addr;
5040: mmu_fault_bank_addr = md->p_addr;
5041: mmu_fault_size = size;
5042: mmu_fault_rw = rwi;
5043: mmu_triggered = 1;
5044: }
5045:
5046: static int mmu_hit (uaecptr addr, int size, int rwi, uae_u32 *v)
5047: {
5048: int s, trig;
5049: uae_u32 flags;
5050: struct mmudata *md;
5051: struct mmunode *mn;
5052:
5053: if (mmu_triggered)
5054: return 1;
5055:
5056: mn = mmunl[addr >> MMU_PAGE_SHIFT];
5057: if (mn == NULL)
5058: return 0;
5059:
5060: s = regs.s;
5061: while (mn) {
5062: md = mn->mmubank;
5063: if (addr >= md->addr && addr < md->addr + md->len) {
5064: flags = md->flags;
5065: if (flags & (MMU_MAP_READ_U | MMU_MAP_WRITE_U | MMU_MAP_READ_S | MMU_MAP_WRITE_S | MMU_MAP_READI_U | MMU_MAP_READI_S)) {
5066: trig = 0;
5067: if (!s && (flags & MMU_MAP_READ_U) && (rwi & 1))
5068: trig = 1;
5069: if (!s && (flags & MMU_MAP_WRITE_U) && (rwi & 2))
5070: trig = 1;
5071: if (s && (flags & MMU_MAP_READ_S) && (rwi & 1))
5072: trig = 1;
5073: if (s && (flags & MMU_MAP_WRITE_S) && (rwi & 2))
5074: trig = 1;
5075: if (!s && (flags & MMU_MAP_READI_U) && (rwi & 4))
5076: trig = 1;
5077: if (s && (flags & MMU_MAP_READI_S) && (rwi & 4))
5078: trig = 1;
5079: if (trig) {
5080: uaecptr maddr = md->remap + (addr - md->addr);
5081: if (maddr == addr) /* infinite mmu hit loop? no thanks.. */
5082: return 1;
5083: if (mmu_logging)
5084: console_out_f (_T("MMU: remap %08X -> %08X SZ=%d RW=%d\n"), addr, maddr, size, rwi);
5085: if ((rwi & 2)) {
5086: switch (size)
5087: {
5088: case 4:
5089: put_long (maddr, *v);
5090: break;
5091: case 2:
5092: put_word (maddr, *v);
5093: break;
5094: case 1:
5095: put_byte (maddr, *v);
5096: break;
5097: }
5098: } else {
5099: switch (size)
5100: {
5101: case 4:
5102: *v = get_long_debug (maddr);
5103: break;
5104: case 2:
5105: *v = get_word_debug (maddr);
5106: break;
5107: case 1:
5108: *v = get_byte_debug (maddr);
5109: break;
5110: }
5111: }
5112: return 1;
5113: }
5114: }
5115: if (flags & (MMU_READ_U | MMU_WRITE_U | MMU_READ_S | MMU_WRITE_S | MMU_READI_U | MMU_READI_S)) {
5116: trig = 0;
5117: if (!s && (flags & MMU_READ_U) && (rwi & 1))
5118: trig = 1;
5119: if (!s && (flags & MMU_WRITE_U) && (rwi & 2))
5120: trig = 1;
5121: if (s && (flags & MMU_READ_S) && (rwi & 1))
5122: trig = 1;
5123: if (s && (flags & MMU_WRITE_S) && (rwi & 2))
5124: trig = 1;
5125: if (!s && (flags & MMU_READI_U) && (rwi & 4))
5126: trig = 1;
5127: if (s && (flags & MMU_READI_S) && (rwi & 4))
5128: trig = 1;
5129: if (trig) {
5130: mmu_do_hit_pre (md, addr, size, rwi, *v);
5131: return 1;
5132: }
5133: }
5134: }
5135: mn = mn->next;
5136: }
5137: return 0;
5138: }
5139:
5140: static void mmu_free_node(struct mmunode *mn)
5141: {
5142: if (!mn)
5143: return;
5144: mmu_free_node (mn->next);
5145: xfree (mn);
5146: }
5147:
5148: static void mmu_free(void)
5149: {
5150: struct mmunode *mn;
5151: int i;
5152:
5153: for (i = 0; i < mmu_slots; i++) {
5154: mn = mmunl[i];
5155: mmu_free_node (mn);
5156: }
5157: xfree (mmunl);
5158: mmunl = NULL;
5159: xfree (mmubanks);
5160: mmubanks = NULL;
5161: }
5162:
5163: static int getmmubank(struct mmudata *snptr, uaecptr p)
5164: {
5165: snptr->flags = get_long_debug (p);
5166: if (snptr->flags == 0xffffffff)
5167: return 1;
5168: snptr->addr = get_long_debug (p + 4);
5169: snptr->len = get_long_debug (p + 8);
5170: snptr->remap = get_long_debug (p + 12);
5171: snptr->p_addr = p;
5172: return 0;
5173: }
5174:
5175: int mmu_init(int mode, uaecptr parm, uaecptr parm2)
5176: {
5177: uaecptr p, p2, banks;
5178: int size;
5179: struct mmudata *snptr;
5180: struct mmunode *mn;
5181: static int wasjit;
5182: #ifdef JIT
5183: if (currprefs.cachesize) {
5184: wasjit = currprefs.cachesize;
5185: changed_prefs.cachesize = 0;
5186: console_out (_T("MMU: JIT disabled\n"));
5187: check_prefs_changed_comp ();
5188: }
5189: if (mode == 0) {
5190: if (mmu_enabled) {
5191: mmu_free ();
5192: deinitialize_memwatch ();
5193: console_out (_T("MMU: disabled\n"));
5194: changed_prefs.cachesize = wasjit;
5195: }
5196: mmu_logging = 0;
5197: return 1;
5198: }
5199: #endif
5200:
5201: if (mode == 1) {
5202: if (!mmu_enabled)
5203: return 0xffffffff;
5204: return mmu_struct;
5205: }
5206:
5207: p = parm;
5208: mmu_struct = p;
5209: if (get_long_debug (p) != 1) {
5210: console_out_f (_T("MMU: version mismatch %d <> %d\n"), get_long_debug (p), 1);
5211: return 0;
5212: }
5213: p += 4;
5214: mmu_logging = get_long_debug (p) & 1;
5215: p += 4;
5216: mmu_callback = get_long_debug (p);
5217: p += 4;
5218: mmu_regs = get_long_debug (p);
5219: p += 4;
5220:
5221: if (mode == 3) {
5222: int off;
5223: uaecptr addr = get_long_debug (parm2 + 4);
5224: if (!mmu_enabled)
5225: return 0;
5226: off = addr >> MMU_PAGE_SHIFT;
5227: mn = mmunl[off];
5228: while (mn) {
5229: if (mn->mmubank->p_addr == parm2) {
5230: getmmubank(mn->mmubank, parm2);
5231: if (mmu_logging)
5232: console_out_f (_T("MMU: bank update %08X: %08X - %08X %08X\n"),
5233: mn->mmubank->flags, mn->mmubank->addr, mn->mmubank->len + mn->mmubank->addr,
5234: mn->mmubank->remap);
5235: }
5236: mn = mn->next;
5237: }
5238: return 1;
5239: }
5240:
5241: mmu_slots = 1 << ((currprefs.address_space_24 ? 24 : 32) - MMU_PAGE_SHIFT);
5242: mmunl = xcalloc (struct mmunode*, mmu_slots);
5243: size = 1;
5244: p2 = get_long_debug (p);
5245: while (get_long_debug (p2) != 0xffffffff) {
5246: p2 += 16;
5247: size++;
5248: }
5249: p = banks = get_long_debug (p);
5250: snptr = mmubanks = xmalloc (struct mmudata, size);
5251: for (;;) {
5252: int off;
5253: if (getmmubank(snptr, p))
5254: break;
5255: p += 16;
5256: off = snptr->addr >> MMU_PAGE_SHIFT;
5257: if (mmunl[off] == NULL) {
5258: mn = mmunl[off] = xcalloc (struct mmunode, 1);
5259: } else {
5260: mn = mmunl[off];
5261: while (mn->next)
5262: mn = mn->next;
5263: mn = mn->next = xcalloc (struct mmunode, 1);
5264: }
5265: mn->mmubank = snptr;
5266: snptr++;
5267: }
5268:
5269: initialize_memwatch (1);
5270: console_out_f (_T("MMU: enabled, %d banks, CB=%08X S=%08X BNK=%08X SF=%08X, %d*%d\n"),
5271: size - 1, mmu_callback, parm, banks, mmu_regs, mmu_slots, 1 << MMU_PAGE_SHIFT);
5272: set_special (SPCFLAG_BRK);
5273: return 1;
5274: }
5275:
5276: void debug_parser (const TCHAR *cmd, TCHAR *out, uae_u32 outsize)
5277: {
5278: TCHAR empty[2] = { 0 };
5279: TCHAR *input = my_strdup (cmd);
5280: if (out == NULL && outsize == 0) {
5281: setconsolemode (empty, 1);
5282: } else if (out != NULL && outsize > 0) {
5283: out[0] = 0;
5284: setconsolemode (out, outsize);
5285: }
5286: debug_line (input);
5287: setconsolemode (NULL, 0);
5288: xfree (input);
5289: }
5290:
5291: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.