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