PageRenderTime 71ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 1ms

/debug.cpp

https://github.com/tonioni/WinUAE
C++ | 7823 lines | 7210 code | 509 blank | 104 comment | 2449 complexity | cf330f5eec37f77f7e4a85245c01a51d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  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. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12. #include <ctype.h>
  13. #include <signal.h>
  14. #include "options.h"
  15. #include "uae.h"
  16. #include "memory.h"
  17. #include "custom.h"
  18. #include "newcpu.h"
  19. #include "cpu_prefetch.h"
  20. #include "debug.h"
  21. #include "disasm.h"
  22. #include "debugmem.h"
  23. #include "cia.h"
  24. #include "xwin.h"
  25. #include "identify.h"
  26. #include "audio.h"
  27. #include "sounddep/sound.h"
  28. #include "disk.h"
  29. #include "savestate.h"
  30. #include "autoconf.h"
  31. #include "akiko.h"
  32. #include "inputdevice.h"
  33. #include "crc32.h"
  34. #include "cpummu.h"
  35. #include "rommgr.h"
  36. #include "inputrecord.h"
  37. #include "calc.h"
  38. #include "cpummu.h"
  39. #include "cpummu030.h"
  40. #include "ar.h"
  41. #include "pci.h"
  42. #include "ppc/ppcd.h"
  43. #include "uae/io.h"
  44. #include "uae/ppc.h"
  45. #include "drawing.h"
  46. #include "devices.h"
  47. #include "blitter.h"
  48. #include "ini.h"
  49. #include "readcpu.h"
  50. #include "cputbl.h"
  51. #include "keybuf.h"
  52. static int trace_mode;
  53. static uae_u32 trace_param[3];
  54. int debugger_active;
  55. static int debug_rewind;
  56. static int memwatch_triggered;
  57. static int inside_debugger;
  58. int debugger_used;
  59. int memwatch_access_validator;
  60. int memwatch_enabled;
  61. int debugging;
  62. int exception_debugging;
  63. int no_trace_exceptions;
  64. int debug_copper = 0;
  65. int debug_dma = 0, debug_heatmap = 0;
  66. int debug_sprite_mask = 0xff;
  67. int debug_illegal = 0;
  68. uae_u64 debug_illegal_mask;
  69. static int debug_mmu_mode;
  70. static bool break_if_enforcer;
  71. static uaecptr debug_pc;
  72. static int trace_cycles;
  73. static int last_hpos1, last_hpos2;
  74. static int last_vpos1, last_vpos2;
  75. static int last_frame = -1;
  76. static uae_u32 last_cycles1, last_cycles2;
  77. static uaecptr processptr;
  78. static uae_char *processname;
  79. static uaecptr debug_copper_pc;
  80. extern int audio_channel_mask;
  81. extern int inputdevice_logging;
  82. static void debug_cycles(void)
  83. {
  84. trace_cycles = 1;
  85. last_cycles2 = get_cycles();
  86. last_vpos2 = vpos;
  87. last_hpos2 = current_hpos();
  88. }
  89. void deactivate_debugger (void)
  90. {
  91. inside_debugger = 0;
  92. debugger_active = 0;
  93. debugging = 0;
  94. exception_debugging = 0;
  95. processptr = 0;
  96. xfree (processname);
  97. processname = NULL;
  98. debugmem_enable();
  99. debug_pc = 0xffffffff;
  100. keybuf_ignore_next_release();
  101. }
  102. void activate_debugger (void)
  103. {
  104. disasm_init();
  105. if (isfullscreen() > 0)
  106. return;
  107. debugger_load_libraries();
  108. debugger_used = 1;
  109. inside_debugger = 1;
  110. debug_pc = 0xffffffff;
  111. trace_mode = 0;
  112. if (debugger_active) {
  113. // already in debugger but some break point triggered
  114. // during disassembly etc..
  115. return;
  116. }
  117. debug_cycles();
  118. debugger_active = 1;
  119. set_special (SPCFLAG_BRK);
  120. debugging = 1;
  121. mmu_triggered = 0;
  122. debugmem_disable();
  123. }
  124. void activate_debugger_new(void)
  125. {
  126. activate_debugger();
  127. debug_pc = M68K_GETPC;
  128. }
  129. void activate_debugger_new_pc(uaecptr pc, int len)
  130. {
  131. activate_debugger();
  132. trace_mode = TRACE_RANGE_PC;
  133. trace_param[0] = pc;
  134. trace_param[1] = pc + len;
  135. }
  136. bool debug_enforcer(void)
  137. {
  138. if (!break_if_enforcer)
  139. return false;
  140. activate_debugger();
  141. return true;
  142. }
  143. int firsthist = 0;
  144. int lasthist = 0;
  145. struct cpuhistory {
  146. struct regstruct regs;
  147. int fp, vpos, hpos;
  148. };
  149. static struct cpuhistory history[MAX_HIST];
  150. static const TCHAR help[] = {
  151. _T(" HELP for UAE Debugger\n")
  152. _T(" -----------------------\n\n")
  153. _T(" g [<address>] Start execution at the current address or <address>.\n")
  154. _T(" c Dump state of the CIA, disk drives and custom registers.\n")
  155. _T(" r Dump state of the CPU.\n")
  156. _T(" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n")
  157. _T(" rc[d] Show CPU instruction or data cache contents.\n")
  158. _T(" m <address> [<lines>] Memory dump starting at <address>.\n")
  159. _T(" a <address> Assembler.\n")
  160. _T(" d <address> [<lines>] Disassembly starting at <address>.\n")
  161. _T(" t [instructions] Step one or more instructions.\n")
  162. _T(" z Step through one instruction - useful for JSR, DBRA etc.\n")
  163. _T(" f Step forward until PC in RAM (\"boot block finder\").\n")
  164. _T(" f <address> Add/remove breakpoint.\n")
  165. _T(" fa <address> [<start>] [<end>]\n")
  166. _T(" Find effective address <address>.\n")
  167. _T(" fi Step forward until PC points to RTS, RTD or RTE.\n")
  168. _T(" fi <opcode> [<w2>] [<w3>] Step forward until PC points to <opcode>.\n")
  169. _T(" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active.\n")
  170. _T(" fl List breakpoints.\n")
  171. _T(" fd Remove all breakpoints.\n")
  172. _T(" fs <lines to wait> | <vpos> <hpos> Wait n scanlines/position.\n")
  173. _T(" fc <CCKs to wait> Wait n color clocks.\n")
  174. _T(" fo <num> <reg> <oper> <val> [<mask> <val2>] Conditional register breakpoint.\n")
  175. _T(" reg=Dx,Ax,PC,USP,ISP,VBR,SR. oper:!=,==,<,>,>=,<=,-,!- (-=val to val2 range).\n")
  176. _T(" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>.\n")
  177. _T(" e[x] Dump contents of all custom registers, ea = AGA colors.\n")
  178. _T(" i [<addr>] Dump contents of interrupt and trap vectors.\n")
  179. _T(" il [<mask>] Exception breakpoint.\n")
  180. _T(" o <0-2|addr> [<lines>]View memory as Copper instructions.\n")
  181. _T(" od Enable/disable Copper vpos/hpos tracing.\n")
  182. _T(" ot Copper single step trace.\n")
  183. _T(" ob <addr> Copper breakpoint.\n")
  184. _T(" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions.\n")
  185. _T(" C <value> Search for values like energy or lifes in games.\n")
  186. _T(" Cl List currently found trainer addresses.\n")
  187. _T(" D[idxzs <[max diff]>] Deep trainer. i=new value must be larger, d=smaller,\n")
  188. _T(" x = must be same, z = must be different, s = restart.\n")
  189. _T(" W <addr> <values[.x] separated by space> Write into Amiga memory.\n")
  190. _T(" W <addr> 'string' Write into Amiga memory.\n")
  191. _T(" Wf <addr> <endaddr> <bytes or string like above>, fill memory.\n")
  192. _T(" Wc <addr> <endaddr> <destaddr>, copy memory.\n")
  193. _T(" w <num> <address> <length> <R/W/I> <F/C/L/N> [<value>[.x]] (read/write/opcode) (freeze/mustchange/logonly/nobreak).\n")
  194. _T(" Add/remove memory watchpoints.\n")
  195. _T(" wd [<0-1>] Enable illegal access logger. 1 = enable break.\n")
  196. _T(" L <file> <addr> [<n>] Load a block of Amiga memory.\n")
  197. _T(" S <file> <addr> <n> Save a block of Amiga memory.\n")
  198. _T(" s \"<string>\"/<values> [<addr>] [<length>]\n")
  199. _T(" Search for string/bytes.\n")
  200. _T(" T or Tt Show exec tasks and their PCs.\n")
  201. _T(" Td,Tl,Tr,Tp,Ts,TS,Ti,TO,TM,Tf Show devs, libs, resources, ports, semaphores,\n")
  202. _T(" residents, interrupts, doslist, memorylist, fsres.\n")
  203. _T(" b Step to previous state capture position.\n")
  204. _T(" M<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites.\n")
  205. _T(" sp <addr> [<addr2][<size>] Dump sprite information.\n")
  206. _T(" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n")
  207. _T(" Also enables level 1 disk logging.\n")
  208. _T(" did <log level> Enable disk logging.\n")
  209. _T(" dj [<level bitmask>] Enable joystick/mouse input debugging.\n")
  210. _T(" smc [<0-1>] Enable self-modifying code detector. 1 = enable break.\n")
  211. _T(" dm Dump current address space map.\n")
  212. _T(" v <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode).\n")
  213. _T(" v [-1 to -4] = enable visual DMA debugger.\n")
  214. _T(" vh [<ratio> <lines>] \"Heat map\"\n")
  215. _T(" I <custom event> Send custom event string\n")
  216. _T(" ?<value> Hex ($ and 0x)/Bin (%)/Dec (!) converter and calculator.\n")
  217. #ifdef _WIN32
  218. _T(" x Close debugger.\n")
  219. _T(" xx Switch between console and GUI debugger.\n")
  220. _T(" mg <address> Memory dump starting at <address> in GUI.\n")
  221. _T(" dg <address> Disassembly starting at <address> in GUI.\n")
  222. #endif
  223. _T(" q Quit the emulator. You don't want to use this command.\n\n")
  224. };
  225. void debug_help (void)
  226. {
  227. console_out (help);
  228. }
  229. struct mw_acc {
  230. uae_u32 mask;
  231. const TCHAR *name;
  232. };
  233. static const struct mw_acc memwatch_access_masks[] =
  234. {
  235. { MW_MASK_ALL, _T("ALL") },
  236. { MW_MASK_NONE, _T("NONE") },
  237. { MW_MASK_ALL & ~(MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W), _T("DMA") },
  238. { MW_MASK_BLITTER_A | MW_MASK_BLITTER_B | MW_MASK_BLITTER_C | MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F, _T("BLT") },
  239. { MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F, _T("BLTD") },
  240. { MW_MASK_AUDIO_0 | MW_MASK_AUDIO_1 | MW_MASK_AUDIO_2 | MW_MASK_AUDIO_3, _T("AUD") },
  241. { MW_MASK_BPL_0 | MW_MASK_BPL_1 | MW_MASK_BPL_2 | MW_MASK_BPL_3 |
  242. MW_MASK_BPL_4 | MW_MASK_BPL_5 | MW_MASK_BPL_6 | MW_MASK_BPL_7, _T("BPL") },
  243. { MW_MASK_SPR_0 | MW_MASK_SPR_1 | MW_MASK_SPR_2 | MW_MASK_SPR_3 |
  244. MW_MASK_SPR_4 | MW_MASK_SPR_5 | MW_MASK_SPR_6 | MW_MASK_SPR_7, _T("SPR") },
  245. { MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPU") },
  246. { MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPUD") },
  247. { MW_MASK_CPU_I, _T("CPUI") },
  248. { MW_MASK_CPU_D_R, _T("CPUDR") },
  249. { MW_MASK_CPU_D_W, _T("CPUDW") },
  250. { MW_MASK_COPPER, _T("COP") },
  251. { MW_MASK_BLITTER_A, _T("BLTA") },
  252. { MW_MASK_BLITTER_B, _T("BLTB") },
  253. { MW_MASK_BLITTER_C, _T("BLTC") },
  254. { MW_MASK_BLITTER_D_N, _T("BLTDN") },
  255. { MW_MASK_BLITTER_D_L, _T("BLTDL") },
  256. { MW_MASK_BLITTER_D_F, _T("BLTDF") },
  257. { MW_MASK_DISK, _T("DSK") },
  258. { MW_MASK_AUDIO_0, _T("AUD0") },
  259. { MW_MASK_AUDIO_1, _T("AUD1") },
  260. { MW_MASK_AUDIO_2, _T("AUD2") },
  261. { MW_MASK_AUDIO_3, _T("AUD3") },
  262. { MW_MASK_BPL_0, _T("BPL0") },
  263. { MW_MASK_BPL_1, _T("BPL1") },
  264. { MW_MASK_BPL_2, _T("BPL2") },
  265. { MW_MASK_BPL_3, _T("BPL3") },
  266. { MW_MASK_BPL_4, _T("BPL4") },
  267. { MW_MASK_BPL_5, _T("BPL5") },
  268. { MW_MASK_BPL_6, _T("BPL6") },
  269. { MW_MASK_BPL_7, _T("BPL7") },
  270. { MW_MASK_SPR_0, _T("SPR0") },
  271. { MW_MASK_SPR_1, _T("SPR1") },
  272. { MW_MASK_SPR_2, _T("SPR2") },
  273. { MW_MASK_SPR_3, _T("SPR3") },
  274. { MW_MASK_SPR_4, _T("SPR4") },
  275. { MW_MASK_SPR_5, _T("SPR5") },
  276. { MW_MASK_SPR_6, _T("SPR6") },
  277. { MW_MASK_SPR_7, _T("SPR7") },
  278. { 0, NULL },
  279. };
  280. static void mw_help(void)
  281. {
  282. for (int i = 0; memwatch_access_masks[i].mask; i++) {
  283. console_out_f(_T("%s "), memwatch_access_masks[i].name);
  284. }
  285. console_out_f(_T("\n"));
  286. }
  287. static int debug_linecounter;
  288. #define MAX_LINECOUNTER 1000
  289. static int debug_out (const TCHAR *format, ...)
  290. {
  291. va_list parms;
  292. TCHAR buffer[4000];
  293. va_start (parms, format);
  294. _vsntprintf (buffer, 4000 - 1, format, parms);
  295. va_end (parms);
  296. console_out (buffer);
  297. if (debug_linecounter < MAX_LINECOUNTER)
  298. debug_linecounter++;
  299. if (debug_linecounter >= MAX_LINECOUNTER)
  300. return 0;
  301. return 1;
  302. }
  303. uae_u32 get_byte_debug (uaecptr addr)
  304. {
  305. uae_u32 v = 0xff;
  306. if (debug_mmu_mode) {
  307. flagtype olds = regs.s;
  308. regs.s = (debug_mmu_mode & 4) != 0;
  309. TRY(p) {
  310. if (currprefs.mmu_model == 68030) {
  311. v = mmu030_get_generic (addr, debug_mmu_mode, sz_byte, MMU030_SSW_SIZE_B);
  312. } else {
  313. if (debug_mmu_mode & 1) {
  314. bool odd = (addr & 1) != 0;
  315. addr &= ~1;
  316. v = mmu_get_iword(addr, sz_byte);
  317. if (!odd)
  318. v >>= 8;
  319. } else {
  320. v = mmu_get_user_byte (addr, regs.s != 0, false, sz_byte, false);
  321. }
  322. }
  323. } CATCH(p) {
  324. } ENDTRY
  325. regs.s = olds;
  326. } else {
  327. v = get_byte (addr);
  328. }
  329. return v;
  330. }
  331. uae_u32 get_word_debug (uaecptr addr)
  332. {
  333. uae_u32 v = 0xffff;
  334. if (debug_mmu_mode) {
  335. flagtype olds = regs.s;
  336. regs.s = (debug_mmu_mode & 4) != 0;
  337. TRY(p) {
  338. if (currprefs.mmu_model == 68030) {
  339. v = mmu030_get_generic (addr, debug_mmu_mode, sz_word, MMU030_SSW_SIZE_W);
  340. } else {
  341. if (debug_mmu_mode & 1) {
  342. v = mmu_get_iword(addr, sz_word);
  343. } else {
  344. v = mmu_get_user_word (addr, regs.s != 0, false, sz_word, false);
  345. }
  346. }
  347. } CATCH(p) {
  348. } ENDTRY
  349. regs.s = olds;
  350. } else {
  351. v = get_word (addr);
  352. }
  353. return v;
  354. }
  355. uae_u32 get_long_debug (uaecptr addr)
  356. {
  357. uae_u32 v = 0xffffffff;
  358. if (debug_mmu_mode) {
  359. flagtype olds = regs.s;
  360. regs.s = (debug_mmu_mode & 4) != 0;
  361. TRY(p) {
  362. if (currprefs.mmu_model == 68030) {
  363. v = mmu030_get_generic (addr, debug_mmu_mode, sz_long, MMU030_SSW_SIZE_L);
  364. } else {
  365. if (debug_mmu_mode & 1) {
  366. v = mmu_get_ilong(addr, sz_long);
  367. } else {
  368. v = mmu_get_user_long (addr, regs.s != 0, false, sz_long, false);
  369. }
  370. }
  371. } CATCH(p) {
  372. } ENDTRY
  373. regs.s = olds;
  374. } else {
  375. v = get_long (addr);
  376. }
  377. return v;
  378. }
  379. uae_u32 get_iword_debug (uaecptr addr)
  380. {
  381. if (debug_mmu_mode) {
  382. return get_word_debug (addr);
  383. } else {
  384. if (valid_address (addr, 2))
  385. return get_word (addr);
  386. return 0xffff;
  387. }
  388. }
  389. uae_u32 get_ilong_debug (uaecptr addr)
  390. {
  391. if (debug_mmu_mode) {
  392. return get_long_debug (addr);
  393. } else {
  394. if (valid_address (addr, 4))
  395. return get_long (addr);
  396. return 0xffffffff;
  397. }
  398. }
  399. uae_u8 *get_real_address_debug(uaecptr addr)
  400. {
  401. if (debug_mmu_mode) {
  402. flagtype olds = regs.s;
  403. TRY(p) {
  404. if (currprefs.mmu_model >= 68040)
  405. addr = mmu_translate(addr, 0, regs.s != 0, (debug_mmu_mode & 1), false, 0);
  406. else
  407. addr = mmu030_translate(addr, regs.s != 0, (debug_mmu_mode & 1), false);
  408. } CATCH(p) {
  409. } ENDTRY
  410. }
  411. return get_real_address(addr);
  412. }
  413. int debug_safe_addr (uaecptr addr, int size)
  414. {
  415. if (debug_mmu_mode) {
  416. flagtype olds = regs.s;
  417. regs.s = (debug_mmu_mode & 4) != 0;
  418. TRY(p) {
  419. if (currprefs.mmu_model >= 68040)
  420. addr = mmu_translate (addr, 0, regs.s != 0, (debug_mmu_mode & 1), false, size);
  421. else
  422. addr = mmu030_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
  423. } CATCH(p) {
  424. STOPTRY;
  425. return 0;
  426. } ENDTRY
  427. regs.s = olds;
  428. }
  429. addrbank *ab = &get_mem_bank (addr);
  430. if (!ab)
  431. return 0;
  432. if (ab->flags & ABFLAG_SAFE)
  433. return 1;
  434. if (!ab->check (addr, size))
  435. return 0;
  436. if (ab->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
  437. return 1;
  438. return 0;
  439. }
  440. static bool iscancel (int counter)
  441. {
  442. static int cnt;
  443. cnt++;
  444. if (cnt < counter)
  445. return false;
  446. cnt = 0;
  447. if (!console_isch ())
  448. return false;
  449. console_getch ();
  450. return true;
  451. }
  452. static bool isoperator(TCHAR **cp)
  453. {
  454. TCHAR c = **cp;
  455. return c == '+' || c == '-' || c == '/' || c == '*' || c == '(' || c == ')';
  456. }
  457. static void ignore_ws (TCHAR **c)
  458. {
  459. while (**c && _istspace(**c))
  460. (*c)++;
  461. }
  462. static TCHAR peekchar (TCHAR **c)
  463. {
  464. return **c;
  465. }
  466. static TCHAR readchar (TCHAR **c)
  467. {
  468. TCHAR cc = **c;
  469. (*c)++;
  470. return cc;
  471. }
  472. static TCHAR next_char(TCHAR **c)
  473. {
  474. ignore_ws (c);
  475. return *(*c)++;
  476. }
  477. static TCHAR next_char2(TCHAR **c)
  478. {
  479. return *(*c)++;
  480. }
  481. static TCHAR peek_next_char (TCHAR **c)
  482. {
  483. TCHAR *pc = *c;
  484. return pc[1];
  485. }
  486. static int more_params(TCHAR **c)
  487. {
  488. ignore_ws(c);
  489. return (**c) != 0;
  490. }
  491. static int more_params2(TCHAR **c)
  492. {
  493. return (**c) != 0;
  494. }
  495. static uae_u32 readint (TCHAR **c);
  496. static uae_u32 readbin (TCHAR **c);
  497. static uae_u32 readhex (TCHAR **c);
  498. static const TCHAR *debugoper[] = {
  499. _T("=="),
  500. _T("!="),
  501. _T("<="),
  502. _T(">="),
  503. _T("<"),
  504. _T(">"),
  505. _T("-"),
  506. _T("!-"),
  507. NULL
  508. };
  509. static int getoperidx(TCHAR **c)
  510. {
  511. int i;
  512. TCHAR *p = *c;
  513. TCHAR tmp[10];
  514. int extra = 0;
  515. i = 0;
  516. while (p[i]) {
  517. tmp[i] = _totupper(p[i]);
  518. if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
  519. break;
  520. i++;
  521. }
  522. tmp[i] = 0;
  523. if (!_tcsncmp(tmp, _T("!="), 2)) {
  524. (*c) += 2;
  525. return BREAKPOINT_CMP_NEQUAL;
  526. } else if (!_tcsncmp(tmp, _T("=="), 2)) {
  527. (*c) += 2;
  528. return BREAKPOINT_CMP_EQUAL;
  529. } else if (!_tcsncmp(tmp, _T(">="), 2)) {
  530. (*c) += 2;
  531. return BREAKPOINT_CMP_LARGER_EQUAL;
  532. } else if (!_tcsncmp(tmp, _T("<="), 2)) {
  533. (*c) += 2;
  534. return BREAKPOINT_CMP_SMALLER_EQUAL;
  535. } else if (!_tcsncmp(tmp, _T(">"), 1)) {
  536. (*c) += 1;
  537. return BREAKPOINT_CMP_LARGER;
  538. } else if (!_tcsncmp(tmp, _T("<"), 1)) {
  539. (*c) += 1;
  540. return BREAKPOINT_CMP_SMALLER;
  541. } else if (!_tcsncmp(tmp, _T("-"), 1)) {
  542. (*c) += 1;
  543. return BREAKPOINT_CMP_RANGE;
  544. } else if (!_tcsncmp(tmp, _T("!-"), 2)) {
  545. (*c) += 2;
  546. return BREAKPOINT_CMP_NRANGE;
  547. }
  548. return -1;
  549. }
  550. static const TCHAR *debugregs[] = {
  551. _T("D0"),
  552. _T("D1"),
  553. _T("D2"),
  554. _T("D3"),
  555. _T("D4"),
  556. _T("D5"),
  557. _T("D6"),
  558. _T("D7"),
  559. _T("A0"),
  560. _T("A1"),
  561. _T("A2"),
  562. _T("A3"),
  563. _T("A4"),
  564. _T("A5"),
  565. _T("A6"),
  566. _T("A7"),
  567. _T("PC"),
  568. _T("USP"),
  569. _T("MSP"),
  570. _T("ISP"),
  571. _T("VBR"),
  572. _T("SR"),
  573. _T("CCR"),
  574. _T("CACR"),
  575. _T("CAAR"),
  576. _T("SFC"),
  577. _T("DFC"),
  578. _T("TC"),
  579. _T("ITT0"),
  580. _T("ITT1"),
  581. _T("DTT0"),
  582. _T("DTT1"),
  583. _T("BUSC"),
  584. _T("PCR"),
  585. NULL
  586. };
  587. static int getregidx(TCHAR **c)
  588. {
  589. int i;
  590. TCHAR *p = *c;
  591. TCHAR tmp[10];
  592. int extra = 0;
  593. i = 0;
  594. while (p[i]) {
  595. tmp[i] = _totupper(p[i]);
  596. if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
  597. break;
  598. i++;
  599. }
  600. tmp[i] = 0;
  601. for (int i = 0; debugregs[i]; i++) {
  602. if (!_tcsncmp(tmp, debugregs[i], _tcslen(debugregs[i]))) {
  603. (*c) += _tcslen(debugregs[i]);
  604. return i;
  605. }
  606. }
  607. return -1;
  608. }
  609. static uae_u32 returnregx(int regid)
  610. {
  611. if (regid < BREAKPOINT_REG_PC)
  612. return regs.regs[regid];
  613. switch(regid)
  614. {
  615. case BREAKPOINT_REG_PC:
  616. return M68K_GETPC;
  617. case BREAKPOINT_REG_USP:
  618. return regs.usp;
  619. case BREAKPOINT_REG_MSP:
  620. return regs.msp;
  621. case BREAKPOINT_REG_ISP:
  622. return regs.isp;
  623. case BREAKPOINT_REG_VBR:
  624. return regs.vbr;
  625. case BREAKPOINT_REG_SR:
  626. MakeSR();
  627. return regs.sr;
  628. case BREAKPOINT_REG_CCR:
  629. MakeSR();
  630. return regs.sr & 31;
  631. case BREAKPOINT_REG_CACR:
  632. return regs.cacr;
  633. case BREAKPOINT_REG_CAAR:
  634. return regs.caar;
  635. case BREAKPOINT_REG_SFC:
  636. return regs.sfc;
  637. case BREAKPOINT_REG_DFC:
  638. return regs.dfc;
  639. case BREAKPOINT_REG_TC:
  640. if (currprefs.cpu_model == 68030)
  641. return tc_030;
  642. return regs.tcr;
  643. case BREAKPOINT_REG_ITT0:
  644. if (currprefs.cpu_model == 68030)
  645. return tt0_030;
  646. return regs.itt0;
  647. case BREAKPOINT_REG_ITT1:
  648. if (currprefs.cpu_model == 68030)
  649. return tt1_030;
  650. return regs.itt1;
  651. case BREAKPOINT_REG_DTT0:
  652. return regs.dtt0;
  653. case BREAKPOINT_REG_DTT1:
  654. return regs.dtt1;
  655. case BREAKPOINT_REG_BUSC:
  656. return regs.buscr;
  657. case BREAKPOINT_REG_PCR:
  658. return regs.fpcr;
  659. }
  660. return 0;
  661. }
  662. static int readregx (TCHAR **c, uae_u32 *valp)
  663. {
  664. int i;
  665. uae_u32 addr;
  666. TCHAR *p = *c;
  667. TCHAR tmp[10], *tp;
  668. int extra = 0;
  669. addr = 0;
  670. i = 0;
  671. while (p[i]) {
  672. tmp[i] = _totupper (p[i]);
  673. if (i >= sizeof (tmp) / sizeof (TCHAR) - 1)
  674. break;
  675. i++;
  676. }
  677. tmp[i] = 0;
  678. tp = tmp;
  679. if (_totupper (tmp[0]) == 'R') {
  680. tp = tmp + 1;
  681. extra = 1;
  682. }
  683. if (!_tcsncmp (tp, _T("USP"), 3)) {
  684. addr = regs.usp;
  685. (*c) += 3;
  686. } else if (!_tcsncmp (tp, _T("VBR"), 3)) {
  687. addr = regs.vbr;
  688. (*c) += 3;
  689. } else if (!_tcsncmp (tp, _T("MSP"), 3)) {
  690. addr = regs.msp;
  691. (*c) += 3;
  692. } else if (!_tcsncmp (tp, _T("ISP"), 3)) {
  693. addr = regs.isp;
  694. (*c) += 3;
  695. } else if (!_tcsncmp (tp, _T("PC"), 2)) {
  696. addr = regs.pc;
  697. (*c) += 2;
  698. } else if (tp[0] == 'A' || tp[0] == 'D') {
  699. int reg = 0;
  700. if (tp[0] == 'A')
  701. reg += 8;
  702. reg += tp[1] - '0';
  703. if (reg < 0 || reg > 15)
  704. return 0;
  705. addr = regs.regs[reg];
  706. (*c) += 2;
  707. } else {
  708. return 0;
  709. }
  710. *valp = addr;
  711. (*c) += extra;
  712. return 1;
  713. }
  714. static bool readbinx (TCHAR **c, uae_u32 *valp)
  715. {
  716. uae_u32 val = 0;
  717. bool first = true;
  718. ignore_ws (c);
  719. for (;;) {
  720. TCHAR nc = **c;
  721. if (nc != '1' && nc != '0') {
  722. if (first)
  723. return false;
  724. break;
  725. }
  726. first = false;
  727. (*c)++;
  728. val <<= 1;
  729. if (nc == '1')
  730. val |= 1;
  731. }
  732. *valp = val;
  733. return true;
  734. }
  735. static bool readhexx (TCHAR **c, uae_u32 *valp)
  736. {
  737. uae_u32 val = 0;
  738. TCHAR nc;
  739. ignore_ws (c);
  740. if (!isxdigit (peekchar (c)))
  741. return false;
  742. while (isxdigit (nc = **c)) {
  743. (*c)++;
  744. val *= 16;
  745. nc = _totupper (nc);
  746. if (isdigit (nc)) {
  747. val += nc - '0';
  748. } else {
  749. val += nc - 'A' + 10;
  750. }
  751. }
  752. *valp = val;
  753. return true;
  754. }
  755. static bool readintx (TCHAR **c, uae_u32 *valp)
  756. {
  757. uae_u32 val = 0;
  758. TCHAR nc;
  759. int negative = 0;
  760. ignore_ws (c);
  761. if (**c == '-')
  762. negative = 1, (*c)++;
  763. if (!isdigit (peekchar (c)))
  764. return false;
  765. while (isdigit (nc = **c)) {
  766. (*c)++;
  767. val *= 10;
  768. val += nc - '0';
  769. }
  770. *valp = val * (negative ? -1 : 1);
  771. return true;
  772. }
  773. static int checkvaltype2 (TCHAR **c, uae_u32 *val, TCHAR def)
  774. {
  775. TCHAR nc;
  776. ignore_ws (c);
  777. nc = _totupper (**c);
  778. if (nc == '!') {
  779. (*c)++;
  780. return readintx (c, val) ? 1 : 0;
  781. }
  782. if (nc == '$') {
  783. (*c)++;
  784. return readhexx (c, val) ? 1 : 0;
  785. }
  786. if (nc == '0' && _totupper ((*c)[1]) == 'X') {
  787. (*c)+= 2;
  788. return readhexx (c, val) ? 1 : 0;
  789. }
  790. if (nc == '%') {
  791. (*c)++;
  792. return readbinx (c, val) ? 1: 0;
  793. }
  794. if (nc >= 'A' && nc <= 'Z' && nc != 'A' && nc != 'D') {
  795. if (readregx (c, val))
  796. return 1;
  797. }
  798. TCHAR name[256];
  799. name[0] = 0;
  800. for (int i = 0; i < sizeof name / sizeof(TCHAR) - 1; i++) {
  801. nc = (*c)[i];
  802. if (nc == 0 || nc == ' ')
  803. break;
  804. name[i] = nc;
  805. name[i + 1] = 0;
  806. }
  807. if (name[0]) {
  808. TCHAR *np = name;
  809. if (*np == '#')
  810. np++;
  811. if (debugmem_get_symbol_value(np, val)) {
  812. (*c) += _tcslen(name);
  813. return 1;
  814. }
  815. }
  816. if (def == '!') {
  817. return readintx (c, val) ? -1 : 0;
  818. } else if (def == '$') {
  819. return readhexx (c, val) ? -1 : 0;
  820. } else if (def == '%') {
  821. return readbinx (c, val) ? -1 : 0;
  822. }
  823. return 0;
  824. }
  825. static int readsize (int val, TCHAR **c)
  826. {
  827. TCHAR cc = _totupper (readchar(c));
  828. if (cc == 'B')
  829. return 1;
  830. if (cc == 'W')
  831. return 2;
  832. if (cc == '3')
  833. return 3;
  834. if (cc == 'L')
  835. return 4;
  836. return 0;
  837. }
  838. static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
  839. {
  840. TCHAR form[256], *p;
  841. bool gotop = false;
  842. double out;
  843. form[0] = 0;
  844. if (size)
  845. *size = 0;
  846. p = form;
  847. for (;;) {
  848. uae_u32 v;
  849. if (!checkvaltype2 (cp, &v, def))
  850. return 0;
  851. *val = v;
  852. // stupid but works!
  853. _stprintf(p, _T("%u"), v);
  854. p += _tcslen (p);
  855. if (peekchar (cp) == '.') {
  856. readchar (cp);
  857. if (size)
  858. *size = readsize (v, cp);
  859. }
  860. if (!isoperator (cp))
  861. break;
  862. gotop = true;
  863. *p++= readchar (cp);
  864. *p = 0;
  865. }
  866. if (!gotop) {
  867. if (size && *size == 0) {
  868. uae_s32 v = (uae_s32)(*val);
  869. if (v > 65535 || v < -32767) {
  870. *size = 4;
  871. } else if (v > 255 || v < -127) {
  872. *size = 2;
  873. } else {
  874. *size = 1;
  875. }
  876. }
  877. return 1;
  878. }
  879. if (calc (form, &out)) {
  880. *val = (uae_u32)out;
  881. if (size && *size == 0) {
  882. uae_s32 v = (uae_s32)(*val);
  883. if (v > 255 || v < -127) {
  884. *size = 2;
  885. } else if (v > 65535 || v < -32767) {
  886. *size = 4;
  887. } else {
  888. *size = 1;
  889. }
  890. }
  891. return 1;
  892. }
  893. return 0;
  894. }
  895. static uae_u32 readnum (TCHAR **c, int *size, TCHAR def)
  896. {
  897. uae_u32 val;
  898. if (checkvaltype (c, &val, size, def))
  899. return val;
  900. return 0;
  901. }
  902. static uae_u32 readint (TCHAR **c)
  903. {
  904. int size;
  905. return readnum (c, &size, '!');
  906. }
  907. static uae_u32 readhex (TCHAR **c)
  908. {
  909. int size;
  910. return readnum (c, &size, '$');
  911. }
  912. static uae_u32 readbin (TCHAR **c)
  913. {
  914. int size;
  915. return readnum (c, &size, '%');
  916. }
  917. static uae_u32 readint (TCHAR **c, int *size)
  918. {
  919. return readnum (c, size, '!');
  920. }
  921. static uae_u32 readhex (TCHAR **c, int *size)
  922. {
  923. return readnum (c, size, '$');
  924. }
  925. static int next_string (TCHAR **c, TCHAR *out, int max, int forceupper)
  926. {
  927. TCHAR *p = out;
  928. int startmarker = 0;
  929. if (**c == '\"') {
  930. startmarker = 1;
  931. (*c)++;
  932. }
  933. *p = 0;
  934. while (**c != 0) {
  935. if (**c == '\"' && startmarker)
  936. break;
  937. if (**c == 32 && !startmarker) {
  938. ignore_ws (c);
  939. break;
  940. }
  941. *p = next_char (c);
  942. if (forceupper)
  943. *p = _totupper(*p);
  944. *++p = 0;
  945. max--;
  946. if (max <= 1)
  947. break;
  948. }
  949. return _tcslen (out);
  950. }
  951. static void converter (TCHAR **c)
  952. {
  953. uae_u32 v = readint (c);
  954. TCHAR s[100];
  955. int i;
  956. for (i = 0; i < 32; i++)
  957. s[i] = (v & (1 << (31 - i))) ? '1' : '0';
  958. s[i] = 0;
  959. console_out_f (_T("0x%08X = %%%s = %u = %d\n"), v, s, v, (uae_s32)v);
  960. }
  961. int notinrom (void)
  962. {
  963. uaecptr pc = munge24 (m68k_getpc ());
  964. if (pc < 0x00e00000 || pc > 0x00ffffff)
  965. return 1;
  966. return 0;
  967. }
  968. static uae_u32 lastaddr (void)
  969. {
  970. int lastbank = currprefs.address_space_24 ? 255 : 65535;
  971. for (int i = lastbank; i >= 0; i--) {
  972. addrbank *ab = get_mem_bank_real(i << 16);
  973. if (ab->baseaddr && (ab->flags & ABFLAG_RAM)) {
  974. return (i + 1) << 16;
  975. }
  976. }
  977. return 0;
  978. }
  979. static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *endp, bool verbose)
  980. {
  981. addrbank *ab;
  982. int lastbank = currprefs.address_space_24 ? 255 : 65535;
  983. if (addr != 0xffffffff) {
  984. addrbank *ab2 = get_mem_bank_real(addr);
  985. addr++;
  986. ab = get_mem_bank_real(addr);
  987. if (ab->baseaddr && (ab->flags & ABFLAG_RAM) && ab == ab2)
  988. return addr;
  989. } else {
  990. addr = 0;
  991. }
  992. while (addr < (lastbank << 16)) {
  993. ab = get_mem_bank_real(addr);
  994. if (ab->baseaddr && (ab->flags & ABFLAG_RAM))
  995. break;
  996. addr += 65536;
  997. }
  998. if (addr >= (lastbank << 16)) {
  999. if (endp)
  1000. *endp = 0xffffffff;
  1001. return 0xffffffff;
  1002. }
  1003. uaecptr start = addr;
  1004. while (addr <= (lastbank << 16)) {
  1005. addrbank *ab2 = get_mem_bank_real(addr);
  1006. if ((last && last != 0xffffffff && addr >= last) || !ab2->baseaddr || !(ab2->flags & ABFLAG_RAM) || ab != ab2) {
  1007. if (endp)
  1008. *endp = addr;
  1009. break;
  1010. }
  1011. addr += 65536;
  1012. }
  1013. if (verbose) {
  1014. console_out_f(_T("Scanning.. %08x - %08x (%s)\n"), start, addr, get_mem_bank(start).name);
  1015. }
  1016. return start;
  1017. }
  1018. uaecptr dumpmem2 (uaecptr addr, TCHAR *out, int osize)
  1019. {
  1020. int i, cols = 8;
  1021. int nonsafe = 0;
  1022. if (osize <= (9 + cols * 5 + 1 + 2 * cols))
  1023. return addr;
  1024. _stprintf (out, _T("%08X "), addr);
  1025. for (i = 0; i < cols; i++) {
  1026. uae_u8 b1, b2;
  1027. b1 = b2 = 0;
  1028. if (debug_safe_addr (addr, 1)) {
  1029. b1 = get_byte_debug (addr + 0);
  1030. b2 = get_byte_debug (addr + 1);
  1031. _stprintf (out + 9 + i * 5, _T("%02X%02X "), b1, b2);
  1032. out[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
  1033. out[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
  1034. } else {
  1035. nonsafe++;
  1036. _tcscpy (out + 9 + i * 5, _T("**** "));
  1037. out[9 + cols * 5 + 1 + i * 2 + 0] = '*';
  1038. out[9 + cols * 5 + 1 + i * 2 + 1] = '*';
  1039. }
  1040. addr += 2;
  1041. }
  1042. out[9 + cols * 5] = ' ';
  1043. out[9 + cols * 5 + 1 + 2 * cols] = 0;
  1044. if (nonsafe == cols) {
  1045. addrbank *ab = &get_mem_bank (addr);
  1046. if (ab->name)
  1047. memcpy (out + (9 + 4 + 1) * sizeof (TCHAR), ab->name, _tcslen (ab->name) * sizeof (TCHAR));
  1048. }
  1049. return addr;
  1050. }
  1051. static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
  1052. {
  1053. TCHAR line[MAX_LINEWIDTH + 1];
  1054. for (;lines--;) {
  1055. addr = dumpmem2 (addr, line, sizeof(line));
  1056. debug_out (_T("%s"), line);
  1057. if (!debug_out (_T("\n")))
  1058. break;
  1059. }
  1060. *nxmem = addr;
  1061. }
  1062. static void dump_custom_regs(bool aga, bool ext)
  1063. {
  1064. int len;
  1065. uae_u8 *p1, *p2, *p3, *p4;
  1066. TCHAR extra1[256], extra2[256];
  1067. extra1[0] = 0;
  1068. extra2[0] = 0;
  1069. if (aga) {
  1070. dump_aga_custom();
  1071. return;
  1072. }
  1073. p1 = p2 = save_custom (&len, 0, 1);
  1074. p1 += 4; // skip chipset type
  1075. for (int i = 0; i < 4; i++) {
  1076. p4 = p1 + 0xa0 + i * 16;
  1077. p3 = save_audio (i, &len, 0);
  1078. p4[0] = p3[12];
  1079. p4[1] = p3[13];
  1080. p4[2] = p3[14];
  1081. p4[3] = p3[15];
  1082. p4[4] = p3[4];
  1083. p4[5] = p3[5];
  1084. p4[6] = p3[8];
  1085. p4[7] = p3[9];
  1086. p4[8] = 0;
  1087. p4[9] = p3[1];
  1088. p4[10] = p3[10];
  1089. p4[11] = p3[11];
  1090. free (p3);
  1091. }
  1092. int total = 0;
  1093. int i = 0;
  1094. while (custd[i].name) {
  1095. if (!(custd[i].special & CD_NONE))
  1096. total++;
  1097. i++;
  1098. }
  1099. int cnt1 = 0;
  1100. int cnt2 = 0;
  1101. i = 0;
  1102. while (i < total / 2 + 1) {
  1103. for (;;) {
  1104. cnt2++;
  1105. if (!(custd[cnt2].special & CD_NONE))
  1106. break;
  1107. }
  1108. i++;
  1109. }
  1110. for (int i = 0; i < total / 2 + 1; i++) {
  1111. uae_u16 v1, v2;
  1112. int addr1, addr2;
  1113. addr1 = custd[cnt1].adr & 0x1ff;
  1114. addr2 = custd[cnt2].adr & 0x1ff;
  1115. v1 = (p1[addr1 + 0] << 8) | p1[addr1 + 1];
  1116. v2 = (p1[addr2 + 0] << 8) | p1[addr2 + 1];
  1117. if (ext) {
  1118. struct custom_store *cs;
  1119. cs = &custom_storage[addr1 >> 1];
  1120. _stprintf(extra1, _T("\t%04X %08X %s"), cs->value, cs->pc & ~1, (cs->pc & 1) ? _T("COP") : _T("CPU"));
  1121. cs = &custom_storage[addr2 >> 1];
  1122. _stprintf(extra2, _T("\t%04X %08X %s"), cs->value, cs->pc & ~1, (cs->pc & 1) ? _T("COP") : _T("CPU"));
  1123. }
  1124. console_out_f (_T("%03X %s\t%04X%s\t%03X %s\t%04X%s\n"),
  1125. addr1, custd[cnt1].name, v1, extra1,
  1126. addr2, custd[cnt2].name, v2, extra2);
  1127. for (;;) {
  1128. cnt1++;
  1129. if (!(custd[cnt1].special & CD_NONE))
  1130. break;
  1131. }
  1132. for (;;) {
  1133. cnt2++;
  1134. if (!(custd[cnt2].special & CD_NONE))
  1135. break;
  1136. }
  1137. }
  1138. xfree(p2);
  1139. }
  1140. static void dump_vectors (uaecptr addr)
  1141. {
  1142. int i = 0, j = 0;
  1143. if (addr == 0xffffffff)
  1144. addr = regs.vbr;
  1145. while (int_labels[i].name || trap_labels[j].name) {
  1146. if (int_labels[i].name) {
  1147. console_out_f (_T("$%08X %02d: %12s $%08X "), int_labels[i].adr + addr, int_labels[i].adr / 4,
  1148. int_labels[i].name, get_long_debug (int_labels[i].adr + addr));
  1149. i++;
  1150. }
  1151. if (trap_labels[j].name) {
  1152. console_out_f (_T("$%08X %02d: %12s $%08X"), trap_labels[j].adr + addr, trap_labels[j].adr / 4,
  1153. trap_labels[j].name, get_long_debug (trap_labels[j].adr + addr));
  1154. j++;
  1155. }
  1156. console_out (_T("\n"));
  1157. }
  1158. }
  1159. static void disassemble_wait (FILE *file, unsigned long insn)
  1160. {
  1161. int vp, hp, ve, he, bfd, v_mask, h_mask;
  1162. int doout = 0;
  1163. vp = (insn & 0xff000000) >> 24;
  1164. hp = (insn & 0x00fe0000) >> 16;
  1165. ve = (insn & 0x00007f00) >> 8;
  1166. he = (insn & 0x000000fe);
  1167. bfd = (insn & 0x00008000) >> 15;
  1168. /* bit15 can never be masked out*/
  1169. v_mask = vp & (ve | 0x80);
  1170. h_mask = hp & he;
  1171. if (v_mask > 0) {
  1172. doout = 1;
  1173. console_out (_T("vpos "));
  1174. if (ve != 0x7f) {
  1175. console_out_f (_T("& 0x%02x "), ve);
  1176. }
  1177. console_out_f (_T(">= 0x%02x"), v_mask);
  1178. }
  1179. if (he > 0) {
  1180. if (v_mask > 0) {
  1181. console_out (_T(" and"));
  1182. }
  1183. console_out (_T(" hpos "));
  1184. if (he != 0xfe) {
  1185. console_out_f (_T("& 0x%02x "), he);
  1186. }
  1187. console_out_f (_T(">= 0x%02x"), h_mask);
  1188. } else {
  1189. if (doout)
  1190. console_out (_T(", "));
  1191. console_out (_T(", ignore horizontal"));
  1192. }
  1193. console_out_f (_T("\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n"),
  1194. vp, ve, hp, he, bfd);
  1195. }
  1196. #define NR_COPPER_RECORDS 100000
  1197. /* Record copper activity for the debugger. */
  1198. struct cop_rec
  1199. {
  1200. uae_u16 w1, w2;
  1201. int hpos, vpos;
  1202. int bhpos, bvpos;
  1203. uaecptr addr, nextaddr;
  1204. };
  1205. static struct cop_rec *cop_record[2];
  1206. static int nr_cop_records[2], curr_cop_set, selected_cop_set;
  1207. #define NR_DMA_REC_HPOS 256
  1208. #define NR_DMA_REC_VPOS 1000
  1209. static struct dma_rec *dma_record[2];
  1210. static int dma_record_toggle, dma_record_frame[2];
  1211. void record_dma_reset (void)
  1212. {
  1213. int v, h;
  1214. struct dma_rec *dr, *dr2;
  1215. if (!dma_record[0])
  1216. return;
  1217. dma_record_toggle ^= 1;
  1218. dr = dma_record[dma_record_toggle];
  1219. for (v = 0; v < NR_DMA_REC_VPOS; v++) {
  1220. for (h = 0; h < NR_DMA_REC_HPOS; h++) {
  1221. dr2 = &dr[v * NR_DMA_REC_HPOS + h];
  1222. memset (dr2, 0, sizeof (struct dma_rec));
  1223. dr2->reg = 0xffff;
  1224. dr2->cf_reg = 0xffff;
  1225. dr2->addr = 0xffffffff;
  1226. }
  1227. }
  1228. }
  1229. void record_copper_reset (void)
  1230. {
  1231. /* Start a new set of copper records. */
  1232. curr_cop_set ^= 1;
  1233. nr_cop_records[curr_cop_set] = 0;
  1234. }
  1235. STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a)
  1236. {
  1237. uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff];
  1238. if (a)
  1239. v |= a[255 - ((c >> 24) & 0xff)];
  1240. return v;
  1241. }
  1242. STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8)
  1243. {
  1244. if (x <= 0)
  1245. return;
  1246. switch (bpp) {
  1247. case 1:
  1248. buf[x] = (uae_u8)c8;
  1249. break;
  1250. case 2:
  1251. {
  1252. uae_u16 *p = (uae_u16*)buf + x;
  1253. *p = (uae_u16)c8;
  1254. break;
  1255. }
  1256. case 3:
  1257. /* no 24 bit yet */
  1258. break;
  1259. case 4:
  1260. {
  1261. uae_u32 *p = (uae_u32*)buf + x;
  1262. *p = c8;
  1263. break;
  1264. }
  1265. }
  1266. }
  1267. #define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL)
  1268. #define DMARECORD_SUBITEMS 8
  1269. struct dmadebug
  1270. {
  1271. uae_u32 l[DMARECORD_SUBITEMS];
  1272. uae_u8 r, g, b;
  1273. bool enabled;
  1274. int max;
  1275. const TCHAR *name;
  1276. };
  1277. static uae_u32 intlevc[] = { 0x000000, 0x444444, 0x008800, 0xffff00, 0x000088, 0x880000, 0xff0000, 0xffffff };
  1278. static struct dmadebug debug_colors[DMARECORD_MAX];
  1279. static bool debug_colors_set;
  1280. static void set_dbg_color(int index, int extra, uae_u8 r, uae_u8 g, uae_u8 b, int max, const TCHAR *name)
  1281. {
  1282. if (extra == 0) {
  1283. debug_colors[index].r = r;
  1284. debug_colors[index].g = g;
  1285. debug_colors[index].b = b;
  1286. debug_colors[index].enabled = true;
  1287. }
  1288. if (name != NULL)
  1289. debug_colors[index].name = name;
  1290. if (max > 0)
  1291. debug_colors[index].max = max;
  1292. debug_colors[index].l[extra] = lc((r << 16) | (g << 8) | (b << 0));
  1293. }
  1294. static void set_debug_colors(void)
  1295. {
  1296. if (debug_colors_set)
  1297. return;
  1298. debug_colors_set = true;
  1299. set_dbg_color(0, 0, 0x22, 0x22, 0x22, 1, _T("-"));
  1300. set_dbg_color(DMARECORD_REFRESH, 0, 0x44, 0x44, 0x44, 4, _T("Refresh"));
  1301. set_dbg_color(DMARECORD_CPU, 0, 0xa2, 0x53, 0x42, 2, _T("CPU")); // code
  1302. set_dbg_color(DMARECORD_COPPER, 0, 0xee, 0xee, 0x00, 3, _T("Copper"));
  1303. set_dbg_color(DMARECORD_AUDIO, 0, 0xff, 0x00, 0x00, 4, _T("Audio"));
  1304. set_dbg_color(DMARECORD_BLITTER, 0, 0x00, 0x88, 0x88, 2, _T("Blitter"));
  1305. set_dbg_color(DMARECORD_BITPLANE, 0, 0x00, 0x00, 0xff, 8, _T("Bitplane"));
  1306. set_dbg_color(DMARECORD_SPRITE, 0, 0xff, 0x00, 0xff, 8, _T("Sprite"));
  1307. set_dbg_color(DMARECORD_DISK, 0, 0xff, 0xff, 0xff, 3, _T("Disk"));
  1308. for (int i = 0; i < DMARECORD_MAX; i++) {
  1309. for (int j = 1; j < DMARECORD_SUBITEMS; j++) {
  1310. debug_colors[i].l[j] = debug_colors[i].l[0];
  1311. }
  1312. }
  1313. set_dbg_color(DMARECORD_CPU, 1, 0xad, 0x98, 0xd6, 0, NULL); // data
  1314. set_dbg_color(DMARECORD_COPPER, 1, 0xaa, 0xaa, 0x22, 0, NULL); // wait
  1315. set_dbg_color(DMARECORD_COPPER, 2, 0x66, 0x66, 0x44, 0, NULL); // special
  1316. set_dbg_color(DMARECORD_BLITTER, 1, 0x00, 0x88, 0xff, 0, NULL); // fill
  1317. set_dbg_color(DMARECORD_BLITTER, 2, 0x00, 0xff, 0x00, 0, NULL); // line
  1318. }
  1319. static void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
  1320. {
  1321. int y, x, xx, dx, xplus, yplus;
  1322. struct dma_rec *dr;
  1323. int t;
  1324. if (debug_dma >= 4)
  1325. yplus = 2;
  1326. else
  1327. yplus = 1;
  1328. if (debug_dma >= 5)
  1329. xplus = 3;
  1330. else if (debug_dma >= 3)
  1331. xplus = 2;
  1332. else
  1333. xplus = 1;
  1334. t = dma_record_toggle ^ 1;
  1335. y = line / yplus;
  1336. if (yplus < 2)
  1337. y -= 8;
  1338. if (y < 0)
  1339. return;
  1340. if (y > maxvpos)
  1341. return;
  1342. if (y >= height)
  1343. return;
  1344. dx = width - xplus * ((maxhpos + 1) & ~1) - 16;
  1345. uae_s8 intlev = 0;
  1346. for (x = 0; x < maxhpos; x++) {
  1347. uae_u32 c = debug_colors[0].l[0];
  1348. xx = x * xplus + dx;
  1349. dr = &dma_record[t][y * NR_DMA_REC_HPOS + x];
  1350. if (dr->reg != 0xffff && debug_colors[dr->type].enabled) {
  1351. c = debug_colors[dr->type].l[dr->extra];
  1352. }
  1353. if (dr->intlev > intlev)
  1354. intlev = dr->intlev;
  1355. putpixel (buf, bpp, xx + 4, c);
  1356. if (xplus)
  1357. putpixel (buf, bpp, xx + 4 + 1, c);
  1358. if (debug_dma >= 6)
  1359. putpixel (buf, bpp, xx + 4 + 2, c);
  1360. }
  1361. putpixel (buf, bpp, dx + 0, 0);
  1362. putpixel (buf, bpp, dx + 1, lc(intlevc[intlev]));
  1363. putpixel (buf, bpp, dx + 2, lc(intlevc[intlev]));
  1364. putpixel (buf, bpp, dx + 3, 0);
  1365. }
  1366. #define HEATMAP_WIDTH 256
  1367. #define HEATMAP_HEIGHT 256
  1368. #define HEATMAP_COUNT 32
  1369. #define HEATMAP_DIV 8
  1370. static const int max_heatmap = 16 * 1048576; // 16M
  1371. static uae_u32 *heatmap_debug_colors;
  1372. static struct memory_heatmap *heatmap;
  1373. struct memory_heatmap
  1374. {
  1375. uae_u32 mask;
  1376. uae_u32 cpucnt;
  1377. uae_u16 cnt;
  1378. uae_u16 type, extra;
  1379. };
  1380. static void debug_draw_heatmap(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
  1381. {
  1382. struct memory_heatmap *mht = heatmap;
  1383. int dx = 16;
  1384. int y = line;
  1385. if (y < 0 || y >= HEATMAP_HEIGHT)
  1386. return;
  1387. mht += y * HEATMAP_WIDTH;
  1388. for (int x = 0; x < HEATMAP_WIDTH; x++) {
  1389. uae_u32 c = heatmap_debug_colors[mht->cnt * DMARECORD_MAX + mht->type];
  1390. //c = heatmap_debug_colors[(HEATMAP_COUNT - 1) * DMARECORD_MAX + DMARECORD_CPU_I];
  1391. int xx = x + dx;
  1392. putpixel(buf, bpp, xx, c);
  1393. if (mht->cnt > 0)
  1394. mht->cnt--;
  1395. mht++;
  1396. }
  1397. }
  1398. void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
  1399. {
  1400. if (!heatmap_debug_colors) {
  1401. heatmap_debug_colors = xcalloc(uae_u32, DMARECORD_MAX * HEATMAP_COUNT);
  1402. set_debug_colors();
  1403. for (int i = 0; i < HEATMAP_COUNT; i++) {
  1404. uae_u32 *cp = heatmap_debug_colors + i * DMARECORD_MAX;
  1405. for (int j = 0; j < DMARECORD_MAX; j++) {
  1406. uae_u8 r = debug_colors[j].r;
  1407. uae_u8 g = debug_colors[j].g;
  1408. uae_u8 b = debug_colors[j].b;
  1409. r = r * i / HEATMAP_COUNT;
  1410. g = g * i / HEATMAP_COUNT;
  1411. b = b * i / HEATMAP_COUNT;
  1412. cp[j] = lc((r << 16) | (g << 8) | (b << 0));
  1413. }
  1414. }
  1415. }
  1416. if (heatmap) {
  1417. debug_draw_heatmap(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
  1418. } else if (dma_record[0]) {
  1419. debug_draw_cycles(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
  1420. }
  1421. }
  1422. struct heatmapstore
  1423. {
  1424. TCHAR *s;
  1425. double v;
  1426. };
  1427. static void heatmap_stats(TCHAR **c)
  1428. {
  1429. int range = 95;
  1430. int maxlines = 30;
  1431. double max;
  1432. int maxcnt;
  1433. uae_u32 mask = MW_MASK_CPU_I;
  1434. const TCHAR *maskname = NULL;
  1435. if (more_params(c)) {
  1436. if (**c == 'c' && peek_next_char(c) == 0) {
  1437. for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
  1438. struct memory_heatmap *hm = &heatmap[i];
  1439. memset(hm, 0, sizeof(struct memory_heatmap));
  1440. }
  1441. console_out(_T("heatmap data cleared\n"));
  1442. return;
  1443. }
  1444. if (!isdigit(peek_next_char(c))) {
  1445. TCHAR str[100];
  1446. if (next_string(c, str, sizeof str / sizeof (TCHAR), true)) {
  1447. for (int j = 0; memwatch_access_masks[j].mask; j++) {
  1448. if (!_tcsicmp(str, memwatch_access_masks[j].name)) {
  1449. mask = memwatch_access_masks[j].mask;
  1450. maskname = memwatch_access_masks[j].name;
  1451. console_out_f(_T("Mask %08x Name %s\n"), mask, maskname);
  1452. break;
  1453. }
  1454. }
  1455. }
  1456. if (more_params(c)) {
  1457. maxlines = readint(c);
  1458. }
  1459. } else {
  1460. range = readint(c);
  1461. if (more_params(c)) {
  1462. maxlines = readint(c);
  1463. }
  1464. }
  1465. }
  1466. if (maxlines <= 0)
  1467. maxlines = 10000;
  1468. if (mask != MW_MASK_CPU_I) {
  1469. int found = -1;
  1470. int firstaddress = 0;
  1471. for (int lines = 0; lines < maxlines; lines++) {
  1472. for (; firstaddress < max_heatmap / HEATMAP_DIV; firstaddress++) {
  1473. struct memory_heatmap *hm = &heatmap[firstaddress];
  1474. if (hm->mask & mask)
  1475. break;
  1476. }
  1477. if (firstaddress == max_heatmap / HEATMAP_DIV)
  1478. return;
  1479. int lastaddress;
  1480. for (lastaddress = firstaddress; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
  1481. struct memory_heatmap *hm = &heatmap[lastaddress];
  1482. if (!(hm->mask & mask))
  1483. break;
  1484. }
  1485. lastaddress--;
  1486. console_out_f(_T("%03d: %08x - %08x %08x (%d) %s\n"),
  1487. lines,
  1488. firstaddress * HEATMAP_DIV, lastaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
  1489. lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
  1490. lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
  1491. maskname);
  1492. firstaddress = lastaddress + 1;
  1493. }
  1494. } else {
  1495. #define MAX_HEATMAP_LINES 1000
  1496. struct heatmapstore linestore[MAX_HEATMAP_LINES] = { 0 };
  1497. int storecnt = 0;
  1498. uae_u32 maxlimit = 0xffffffff;
  1499. max = 0;
  1500. maxcnt = 0;
  1501. for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
  1502. struct memory_heatmap *hm = &heatmap[i];
  1503. if (hm->cpucnt > 0) {
  1504. max += hm->cpucnt;
  1505. maxcnt++;
  1506. }
  1507. }
  1508. if (!maxcnt) {
  1509. console_out(_T("No CPU accesses found\n"));
  1510. return;
  1511. }
  1512. for (int lines = 0; lines < maxlines; lines++) {
  1513. int found = -1;
  1514. int foundcnt = 0;
  1515. for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
  1516. struct memory_heatmap *hm = &heatmap[i];
  1517. if (hm->cpucnt > 0 && hm->cpucnt > foundcnt && hm->cpucnt < maxlimit) {
  1518. foundcnt = hm->cpucnt;
  1519. found = i;
  1520. }
  1521. }
  1522. if (found < 0)
  1523. break;
  1524. int totalcnt = 0;
  1525. int cntrange = foundcnt * range / 100;
  1526. if (cntrange <= 0)
  1527. cntrange = 1;
  1528. int lastaddress;
  1529. for (lastaddress = found; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
  1530. struct memory_heatmap *hm = &heatmap[lastaddress];
  1531. if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
  1532. break;
  1533. totalcnt += hm->cpucnt;
  1534. }
  1535. lastaddress--;
  1536. int firstaddress;
  1537. for (firstaddress = found - 1; firstaddress >= 0; firstaddress--) {
  1538. struct memory_heatmap *hm = &heatmap[firstaddress];
  1539. if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
  1540. break;
  1541. totalcnt += hm->cpucnt;
  1542. }
  1543. firstaddress--;
  1544. firstaddress *= HEATMAP_DIV;
  1545. lastaddress *= HEATMAP_DIV;
  1546. TCHAR tmp[100];
  1547. double pct = totalcnt / max * 100.0;
  1548. _stprintf(tmp, _T("%03d: %08x - %08x %08x (%d) %.5f%%\n"), lines + 1,
  1549. firstaddress, lastaddress + HEATMAP_DIV - 1,
  1550. lastaddress - firstaddress + HEATMAP_DIV - 1,
  1551. lastaddress - firstaddress + HEATMAP_DIV - 1,
  1552. pct);
  1553. linestore[storecnt].s = my_strdup(tmp);
  1554. linestore[storecnt].v = pct;
  1555. storecnt++;
  1556. if (storecnt >= MAX_HEATMAP_LINES)
  1557. break;
  1558. maxlimit = foundcnt;
  1559. }
  1560. for (int lines1 = 0; lines1 < storecnt; lines1++) {
  1561. for (int lines2 = lines1 + 1; lines2 < storecnt; lines2++) {
  1562. if (linestore[lines1].v < linestore[lines2].v) {
  1563. struct heatmapstore hms;
  1564. memcpy(&hms, &linestore[lines1], sizeof(struct heatmapstore));
  1565. memcpy(&linestore[lines1], &linestore[lines2], sizeof(struct heatmapstore));
  1566. memcpy(&linestore[lines2], &hms, sizeof(struct heatmapstore));
  1567. }
  1568. }
  1569. }
  1570. for (int lines1 = 0; lines1 < storecnt; lines1++) {
  1571. console_out(linestore[lines1].s);
  1572. xfree(linestore[lines1].s);
  1573. }
  1574. }
  1575. }
  1576. static void free_heatmap(void)
  1577. {
  1578. xfree(heatmap);
  1579. heatmap = NULL;
  1580. debug_heatmap = 0;
  1581. }
  1582. static void init_heatmap(void)
  1583. {
  1584. if (!heatmap)
  1585. heatmap = xcalloc(struct memory_heatmap, max_heatmap / HEATMAP_DIV);
  1586. }
  1587. static void memwatch_heatmap (uaecptr addr, int rwi, int size, uae_u32 accessmask)
  1588. {
  1589. if (addr >= max_heatmap || !heatmap)
  1590. return;
  1591. struct memory_heatmap *hm = &heatmap[addr / HEATMAP_DIV];
  1592. if (accessmask & MW_MASK_CPU_I) {
  1593. hm->cpucnt++;
  1594. }
  1595. hm->cnt = HEATMAP_COUNT - 1;
  1596. int type = 0;
  1597. int extra = 0;
  1598. for (int i = 0; i < 32; i++) {
  1599. if (accessmask & (1 << i)) {
  1600. switch (1 << i)
  1601. {
  1602. case MW_MASK_BPL_0:
  1603. case MW_MASK_BPL_1:
  1604. case MW_MASK_BPL_2:
  1605. case MW_MASK_BPL_3:
  1606. case MW_MASK_BPL_4:
  1607. case MW_MASK_BPL_5:
  1608. case MW_MASK_BPL_6:
  1609. case MW_MASK_BPL_7:
  1610. type = DMARECORD_BITPLANE;
  1611. break;
  1612. case MW_MASK_AUDIO_0:
  1613. case MW_MASK_AUDIO_1:
  1614. case MW_MASK_AUDIO_2:
  1615. case MW_MASK_AUDIO_3:
  1616. type = DMARECORD_AUDIO;
  1617. break;
  1618. case MW_MASK_BLITTER_A:
  1619. case MW_MASK_BLITTER_B:
  1620. case MW_MASK_BLITTER_C:
  1621. case MW_MASK_BLITTER_D_N:
  1622. case MW_MASK_BLITTER_D_F:
  1623. case MW_MASK_BLITTER_D_L:
  1624. type = DMARECORD_BLITTER;
  1625. break;
  1626. case MW_MASK_COPPER:
  1627. type = DMARECORD_COPPER;
  1628. break;
  1629. case MW_MASK_DISK:
  1630. type = DMARECORD_DISK;
  1631. break;
  1632. case MW_MASK_CPU_I:
  1633. type = DMARECORD_CPU;
  1634. break;
  1635. case MW_MASK_CPU_D_R:
  1636. case MW_MASK_CPU_D_W:
  1637. type = DMARECORD_CPU;
  1638. extra = 1;
  1639. break;
  1640. }
  1641. }
  1642. }
  1643. hm->type = type;
  1644. hm->extra = extra;
  1645. hm->mask |= accessmask;
  1646. }
  1647. void record_dma_event (uae_u32 evt, int hpos, int vpos)
  1648. {
  1649. struct dma_rec *dr;
  1650. if (!dma_record[0])
  1651. return;
  1652. if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
  1653. return;
  1654. dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
  1655. dr->evt |= evt;
  1656. }
  1657. void record_dma_replace(int hpos, int vpos, int type, int extra)
  1658. {
  1659. struct dma_rec *dr;
  1660. if (!dma_record[0])
  1661. return;
  1662. if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
  1663. return;
  1664. dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
  1665. if (dr->reg == 0xffff) {
  1666. write_log(_T("DMA record replace without old data!\n"));
  1667. return;
  1668. }
  1669. if (dr->type != type) {
  1670. write_log(_T("DMA record replace type change %d -> %d!\n"), dr->type, type);
  1671. return;
  1672. }
  1673. dr->extra = extra;
  1674. }
  1675. static void dma_conflict(int vpos, int hpos, struct dma_rec *dr, int reg, bool write)
  1676. {
  1677. write_log(_T("DMA conflict %c: v=%d h=%d OREG=%04X NREG=%04X\n"), write ? 'W' : 'R', vpos, hpos, dr->reg, reg);
  1678. }
  1679. void record_dma_write(uae_u16 reg, uae_u32 dat, uae_u32 addr, int hpos, int vpos, int type, int extra)
  1680. {
  1681. struct dma_rec *dr;
  1682. if (!dma_record[0]) {
  1683. dma_record[0] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
  1684. dma_record[1] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
  1685. dma_record_toggle = 0;
  1686. record_dma_reset();
  1687. dma_record_frame[0] = -1;
  1688. dma_record_frame[1] = -1;
  1689. }
  1690. if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
  1691. return;
  1692. dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
  1693. dma_record_frame[dma_record_toggle] = timeframes;
  1694. if (dr->reg != 0xffff) {
  1695. dr->cf_reg = reg;
  1696. dr->cf_dat = dat;
  1697. dr->cf_addr = addr;
  1698. dma_conflict(vpos, hpos, dr, reg, false);
  1699. return;
  1700. }
  1701. dr->reg = reg;
  1702. dr->dat = dat;
  1703. dr->addr = addr;
  1704. dr->type = type;
  1705. dr->extra = extra;
  1706. dr->intlev = regs.intmask;
  1707. dr->size = 2;
  1708. last_dma_rec = dr;
  1709. }
  1710. struct dma_rec *last_dma_rec;
  1711. void record_dma_read_value(uae_u32 v)
  1712. {
  1713. if (last_dma_rec) {
  1714. if (last_dma_rec->cf_reg != 0xffff) {
  1715. last_dma_rec->cf_dat = v;
  1716. } else {
  1717. last_dma_rec->dat = v;
  1718. }
  1719. last_dma_rec->size = 2;
  1720. }
  1721. }
  1722. void record_dma_read_value_wide(uae_u64 v, bool quad)
  1723. {
  1724. if (last_dma_rec) {
  1725. if (last_dma_rec->cf_reg != 0xffff) {
  1726. last_dma_rec->cf_dat = v;
  1727. } else {
  1728. last_dma_rec->dat = v;
  1729. }
  1730. last_dma_rec->size = quad ? 8 : 4;
  1731. }
  1732. }
  1733. void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra)
  1734. {
  1735. struct dma_rec *dr;
  1736. if (!dma_record[0]) {
  1737. dma_record[0] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
  1738. dma_record[1] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
  1739. dma_record_toggle = 0;
  1740. record_dma_reset ();
  1741. dma_record_frame[0] = -1;
  1742. dma_record_frame[1] = -1;
  1743. }
  1744. if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
  1745. return;
  1746. dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
  1747. dma_record_frame[dma_record_toggle] = timeframes;
  1748. if (dr->reg != 0xffff) {
  1749. if (dr->reg != reg) {
  1750. dma_conflict(vpos, hpos, dr, reg, false);
  1751. dr->cf_reg = reg;
  1752. dr->cf_addr = addr;
  1753. }
  1754. return;
  1755. }
  1756. dr->reg = reg;
  1757. dr->dat = 0;
  1758. dr->addr = addr;
  1759. dr->type = type;
  1760. dr->extra = extra;
  1761. dr->intlev = regs.intmask;
  1762. last_dma_rec = dr;
  1763. }
  1764. static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 cycles, TCHAR *l1, TCHAR *l2, TCHAR *l3, TCHAR *l4, TCHAR *l5)
  1765. {
  1766. int longsize = dr->size;
  1767. bool got = false;
  1768. int r = dr->reg;
  1769. int regsize = 3;
  1770. const TCHAR *sr;
  1771. int br = dr->extra & 7;
  1772. int chcnt = -1;
  1773. TCHAR srtext[10];
  1774. bool extra64 = false;
  1775. uae_u32 extraval;
  1776. bool noval = false;
  1777. if (l1)
  1778. l1[0] = 0;
  1779. if (l2)
  1780. l2[0] = 0;
  1781. if (l3)
  1782. l3[0] = 0;
  1783. if (l4)
  1784. l4[0] = 0;
  1785. if (l5)
  1786. l5[0] = 0;
  1787. if (dr->type != 0 || dr->reg != 0xffff || dr->evt)
  1788. got = true;
  1789. sr = _T(" ");
  1790. if (dr->type == DMARECORD_COPPER) {
  1791. if (dr->extra == 3)
  1792. sr = _T("COPW");
  1793. else
  1794. sr = _T("COP ");
  1795. } else if (dr->type == DMARECORD_BLITTER) {
  1796. if (dr->extra & 0x20) {
  1797. if (br == 0)
  1798. sr = _T("BLL-A");
  1799. if (br == 1)
  1800. sr = _T("BLL-B");
  1801. if (br == 2)
  1802. sr = _T("BLL-C");
  1803. if (br == 3)
  1804. sr = _T("BLL-D");
  1805. } else if (dr->extra & 0x10) {
  1806. if (br == 0)
  1807. sr = _T("BLF-A");
  1808. if (br == 1)
  1809. sr = _T("BLF-B");
  1810. if (br == 2)
  1811. sr = _T("BLF-C");
  1812. if (br == 3)
  1813. sr = _T("BLF-D");
  1814. } else {
  1815. if (br == 0)
  1816. sr = _T("BLT-A");
  1817. if (br == 1)
  1818. sr = _T("BLT-B");
  1819. if (br == 2)
  1820. sr = _T("BLT-C");
  1821. if (br == 3)
  1822. sr = _T("BLT-D");
  1823. }
  1824. regsize = 2;
  1825. } else if (dr->type == DMARECORD_REFRESH) {
  1826. sr = _T("RFS");
  1827. chcnt = br;
  1828. noval = true;
  1829. } else if (dr->type == DMARECORD_AUDIO) {
  1830. sr = _T("AUD");
  1831. chcnt = br;
  1832. } else if (dr->type == DMARECORD_DISK) {
  1833. sr = _T("DSK");
  1834. chcnt = br;
  1835. } else if (dr->type == DMARECORD_SPRITE) {
  1836. sr = _T("SPR");
  1837. chcnt = br;
  1838. } else if (dr->type == DMARECORD_BITPLANE) {
  1839. sr = _T("BPL");
  1840. chcnt = br + 1;
  1841. }
  1842. if (dr->cf_reg != 0xffff) {
  1843. _stprintf(srtext, _T("!%03x "), dr->cf_reg);
  1844. chcnt = -1;
  1845. } else {
  1846. _tcscpy(srtext, sr);
  1847. }
  1848. _stprintf (l1, _T("[%02X %3d]"), hpos, hpos);
  1849. if (l4) {
  1850. _tcscpy (l4, _T(" "));
  1851. }
  1852. if (r != 0xffff) {
  1853. if (r & 0x1000) {
  1854. if ((r & 0x0100) == 0x0000)
  1855. _tcscpy (l2, _T("CPU-R "));
  1856. else if ((r & 0x0100) == 0x0100)
  1857. _tcscpy (l2, _T("CPU-W "));
  1858. if ((r & 0xff) == 4) {
  1859. l2[5] = 'L';
  1860. longsize = 4;
  1861. }
  1862. if ((r & 0xff) == 2)
  1863. l2[5] = 'W';
  1864. if ((r & 0xff) == 1)
  1865. l2[5] = 'B';
  1866. } else {
  1867. if (chcnt >= 0) {
  1868. if (regsize == 3)
  1869. _stprintf(l2, _T("%3s%d %03X"), srtext, chcnt, r);
  1870. else
  1871. _stprintf(l2, _T("%4s%d %02X"), srtext, chcnt, r);
  1872. } else {
  1873. if (regsize == 3)
  1874. _stprintf(l2, _T("%4s %03X"), srtext, r);
  1875. else
  1876. _stprintf(l2, _T("%5s %02X"), srtext, r);
  1877. }
  1878. }
  1879. if (l3 && !noval) {
  1880. uae_u64 v = dr->dat;
  1881. if (longsize == 4) {
  1882. _stprintf(l3, _T("%08X"), (uae_u32)v);
  1883. } else if (longsize == 8) {
  1884. _stprintf(l3, _T("%08X"), (uae_u32)(v >> 32));
  1885. extra64 = true;
  1886. extraval = (uae_u32)v;
  1887. } else {
  1888. _stprintf(l3, _T(" %04X"), (uae_u32)(v & 0xffff));
  1889. }
  1890. }
  1891. if (l4 && dr->addr != 0xffffffff)
  1892. _stprintf (l4, _T("%08X"), dr->addr & 0x00ffffff);
  1893. } else {
  1894. _tcscpy (l2, _T(" "));
  1895. if (l3) {
  1896. _tcscpy (l3, _T(" "));
  1897. }
  1898. }
  1899. if (l3) {
  1900. int cl2 = 0;
  1901. if (dr->evt & DMA_EVENT_BLITFINALD)
  1902. l3[cl2++] = 'D';
  1903. if (dr->evt & DMA_EVENT_BLITSTARTFINISH)
  1904. l3[cl2++] = 'B';
  1905. if (dr->evt & DMA_EVENT_CPUBLITTERSTEAL)
  1906. l3[cl2++] = 's';
  1907. if (dr->evt & DMA_EVENT_CPUBLITTERSTOLEN)
  1908. l3[cl2++] = 'S';
  1909. if (dr->evt & DMA_EVENT_BLITIRQ)
  1910. l3[cl2++] = 'b';
  1911. if (dr->evt & DMA_EVENT_BPLFETCHUPDATE)
  1912. l3[cl2++] = 'p';
  1913. if (dr->evt & (DMA_EVENT_COPPERWAKE | DMA_EVENT_COPPERSKIP))
  1914. l3[cl2++] = 'W';
  1915. if (dr->evt & DMA_EVENT_NOONEGETS) {
  1916. l3[cl2++] = '#';
  1917. } else if (dr->evt & DMA_EVENT_COPPERWANTED) {
  1918. l3[cl2++] = 'c';
  1919. }
  1920. if (dr->evt & DMA_EVENT_CPUIRQ)
  1921. l3[cl2++] = 'I';
  1922. if (dr->evt & DMA_EVENT_INTREQ)
  1923. l3[cl2++] = 'i';
  1924. if (dr->evt & DMA_EVENT_SPECIAL)
  1925. l3[cl2++] = 'X';
  1926. if (dr->evt & DMA_EVENT_DDFSTRT)
  1927. l3[cl2++] = '0';
  1928. if (dr->evt & DMA_EVENT_DDFSTOP)
  1929. l3[cl2++] = '1';
  1930. if (dr->evt & DMA_EVENT_DDFSTOP2)
  1931. l3[cl2++] = '2';
  1932. if (dr->evt & DMA_EVENT_HDIWS) {
  1933. l3[cl2++] = '(';
  1934. }
  1935. if (dr->evt & DMA_EVENT_HDIWE) {
  1936. l3[cl2++] = ')';
  1937. }
  1938. if (dr->evt & DMA_EVENT_HBS) {
  1939. l3[cl2++] = '[';
  1940. }
  1941. if (dr->evt & DMA_EVENT_HBE) {
  1942. l3[cl2++] = ']';
  1943. }
  1944. if (dr->evt & DMA_EVENT_HSS) {
  1945. l3[cl2++] = '{';
  1946. }
  1947. if (dr->evt & DM

Large files files are truncated, but you can click here to view the full file