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