|
|
1.1 root 1: /*
2: Hatari - debuginfo.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: debuginfo.c - functions needed to show info about the atari HW & OS
8: components and "lock" that info to be shown on entering the debugger.
9: */
10: const char DebugInfo_fileid[] = "Hatari debuginfo.c : " __DATE__ " " __TIME__;
11:
12: #include <stdio.h>
13: #include <assert.h>
14: #include "main.h"
15: #include "configuration.h"
16: #include "debugInfo.h"
17: #include "debugcpu.h"
18: #include "debugdsp.h"
19: #include "debugui.h"
20: #include "dsp.h"
21: #include "evaluate.h"
1.1.1.2 ! root 22: #include "file.h"
! 23: #include "gemdos.h"
1.1 root 24: #include "ioMem.h"
25: #include "m68000.h"
26: #include "stMemory.h"
27: #include "tos.h"
1.1.1.2 ! root 28: #include "screen.h"
! 29: #include "vdi.h"
1.1 root 30: #include "video.h"
31:
32:
33: /* ------------------------------------------------------------------
34: * TOS information
35: */
36: #define OS_SYSBASE 0x4F2
37: #define OS_HEADER_SIZE 0x30
38:
39: #define COOKIE_JAR 0x5A0
40:
41: #define BASEPAGE_SIZE 0x100
42:
43: #define GEM_MAGIC 0x87654321
44: #define GEM_MUPB_SIZE 0xC
45:
46: #define RESET_MAGIC 0x31415926
47: #define RESET_VALID 0x426
48: #define RESET_VECTOR 0x42A
49:
50: #define COUNTRY_SPAIN 4
51:
1.1.1.2 ! root 52:
1.1 root 53: /**
54: * DebugInfo_GetSysbase: set osversion to given argument.
55: * return sysbase address on success and zero on failure.
56: */
57: static Uint32 DebugInfo_GetSysbase(Uint16 *osversion)
58: {
59: Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE);
60:
61: if (!STMemory_ValidArea(sysbase, OS_HEADER_SIZE)) {
62: fprintf(stderr, "Invalid TOS base address!\n");
63: return 0;
64: }
65: if (sysbase != TosAddress || sysbase != STMemory_ReadLong(sysbase+0x08)) {
66: fprintf(stderr, "Sysbase and os_beg address in OS header mismatch!\n");
67: return 0;
68: }
69: *osversion = STMemory_ReadWord(sysbase+0x02);
70: return sysbase;
71: }
72:
73: /**
74: * DebugInfo_CurrentBasepage: get currently running TOS program basepage
75: */
76: static Uint32 DebugInfo_CurrentBasepage(void)
77: {
78: Uint32 basepage, sysbase;
79: Uint16 osversion, osconf;
80:
81: sysbase = DebugInfo_GetSysbase(&osversion);
82: if (!sysbase) {
83: return 0;
84: }
85: if (osversion >= 0x0102) {
86: basepage = STMemory_ReadLong(sysbase+0x28);
87: } else {
88: osconf = STMemory_ReadWord(sysbase+0x1C);
89: if((osconf>>1) == COUNTRY_SPAIN) {
90: basepage = 0x873C;
91: } else {
92: basepage = 0x602C;
93: }
94: }
95: if (STMemory_ValidArea(basepage, 4)) {
96: return STMemory_ReadLong(basepage);
97: }
98: fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage);
99: return 0;
100: }
101:
1.1.1.2 ! root 102:
! 103: /**
! 104: * GetSegmentAddress: return segment address at given offset in
! 105: * TOS process basepage or zero if that is missing/invalid.
! 106: */
! 107: static Uint32 GetSegmentAddress(unsigned offset)
! 108: {
! 109: Uint32 basepage = DebugInfo_CurrentBasepage();
! 110: if (!basepage) {
! 111: return 0;
! 112: }
! 113: if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) ||
! 114: STMemory_ReadLong(basepage) != basepage) {
! 115: fprintf(stderr, "Basepage address 0x%06x is invalid!\n", basepage);
! 116: return 0;
! 117: }
! 118: return STMemory_ReadLong(basepage+offset);
! 119: }
! 120:
! 121: /**
! 122: * DebugInfo_GetTEXT: return current program TEXT segment address
! 123: * or zero if basepage missing/invalid. For virtual debugger variable.
! 124: */
! 125: Uint32 DebugInfo_GetTEXT(void)
! 126: {
! 127: return GetSegmentAddress(0x08);
! 128: }
! 129: /**
! 130: * DebugInfo_GetDATA: return current program DATA segment address
! 131: * or zero if basepage missing/invalid. For virtual debugger variable.
! 132: */
! 133: Uint32 DebugInfo_GetDATA(void)
! 134: {
! 135: return GetSegmentAddress(0x010);
! 136: }
! 137: /**
! 138: * DebugInfo_GetBSS: return current program BSS segment address
! 139: * or zero if basepage missing/invalid. For virtual debugger variable.
! 140: */
! 141: Uint32 DebugInfo_GetBSS(void)
! 142: {
! 143: return GetSegmentAddress(0x18);
! 144: }
! 145:
! 146:
1.1 root 147: /**
148: * DebugInfo_Basepage: show TOS process basepage information
149: * at given address.
150: */
151: static void DebugInfo_Basepage(Uint32 basepage)
152: {
153: Uint8 cmdlen;
154: Uint32 env;
155:
156: if (!basepage) {
157: /* default to current process basepage */
158: basepage = DebugInfo_CurrentBasepage();
159: if (!basepage) {
160: return;
161: }
162: }
163: fprintf(stderr, "Process basepage information:\n");
164: if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) ||
165: STMemory_ReadLong(basepage) != basepage) {
166: fprintf(stderr, "- address 0x%06x is invalid!\n", basepage);
167: return;
168: }
169: fprintf(stderr, "- TPA start : 0x%06x\n", STMemory_ReadLong(basepage));
170: fprintf(stderr, "- TPA end +1 : 0x%06x\n", STMemory_ReadLong(basepage+0x04));
171: fprintf(stderr, "- Text segment : 0x%06x\n", STMemory_ReadLong(basepage+0x08));
172: fprintf(stderr, "- Text size : 0x%x\n", STMemory_ReadLong(basepage+0x0C));
173: fprintf(stderr, "- Data segment : 0x%06x\n", STMemory_ReadLong(basepage+0x10));
174: fprintf(stderr, "- Data size : 0x%x\n", STMemory_ReadLong(basepage+0x14));
175: fprintf(stderr, "- BSS segment : 0x%06x\n", STMemory_ReadLong(basepage+0x18));
176: fprintf(stderr, "- BSS size : 0x%x\n", STMemory_ReadLong(basepage+0x1C));
177: fprintf(stderr, "- Process DTA : 0x%06x\n", STMemory_ReadLong(basepage+0x20));
178: fprintf(stderr, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24));
179:
180: env = STMemory_ReadLong(basepage+0x2C);
181: fprintf(stderr, "- Environment : 0x%06x\n", env);
182: if (STMemory_ValidArea(env, 4096)) {
183: Uint32 end = env + 4096;
184: while (env < end && *(STRam+env)) {
185: fprintf(stderr, "'%s'\n", STRam+env);
186: env += strlen((const char *)(STRam+env)) + 1;
187: }
188: }
189: cmdlen = STMemory_ReadByte(basepage+0x80);
190: fprintf(stderr, "- Command argslen: %d\n", cmdlen);
191: if (cmdlen) {
192: int offset = 0;
193: while (offset < cmdlen) {
194: fprintf(stderr, " '%s'", STRam+basepage+0x81+offset);
195: offset += strlen((const char *)(STRam+basepage+0x81+offset)) + 1;
196: }
197: fprintf(stderr, "\n");
198: }
199: }
200:
201: /**
202: * DebugInfo_OSHeader: display TOS OS Header
203: */
204: static void DebugInfo_OSHeader(Uint32 dummy)
205: {
206: Uint32 sysbase, gemblock, basepage;
1.1.1.2 ! root 207: Uint16 osversion, osconf, langbits;
! 208: const char *lang;
! 209: static const char langs[][3] = {
! 210: "us", "de", "fr", "uk", "es", "it", "se", "ch" /* fr */, "ch" /* de */,
! 211: "tr", "fi", "no", "dk", "sa", "nl", "cs", "hu"
! 212: };
1.1 root 213:
214: sysbase = DebugInfo_GetSysbase(&osversion);
215: if (!sysbase) {
216: return;
217: }
1.1.1.2 ! root 218: fprintf(stderr, "TOS OS header information:\n");
1.1 root 219: fprintf(stderr, "OS base addr : 0x%06x\n", sysbase);
220: fprintf(stderr, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C));
221: fprintf(stderr, "TOS version : 0x%x\n", osversion);
222:
223: fprintf(stderr, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04));
224: fprintf(stderr, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR));
225: fprintf(stderr, "Reset valid : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC);
226:
227: gemblock = STMemory_ReadLong(sysbase+0x14);
228: fprintf(stderr, "GEM Memory Usage Parameter Block:\n");
229: if (STMemory_ValidArea(gemblock, GEM_MUPB_SIZE)) {
230: fprintf(stderr, "- Block addr : 0x%06x\n", gemblock);
231: fprintf(stderr, "- GEM magic : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC);
232: fprintf(stderr, "- GEM entry : 0x%06x\n", STMemory_ReadLong(gemblock+4));
233: fprintf(stderr, "- GEM end : 0x%06x\n", STMemory_ReadLong(gemblock+8));
234: } else {
235: fprintf(stderr, "- is at INVALID 0x%06x address.\n", gemblock);
236: }
237:
238: fprintf(stderr, "OS date : 0x%x\n", STMemory_ReadLong(sysbase+0x14));
239: fprintf(stderr, "OS DOS date : 0x%x\n", STMemory_ReadLong(sysbase+0x1E));
240:
241: osconf = STMemory_ReadWord(sysbase+0x1C);
1.1.1.2 ! root 242: langbits = osconf >> 1;
! 243: if (langbits == 127) {
! 244: lang = "all";
! 245: } else if (langbits < ARRAYSIZE(langs)) {
! 246: lang = langs[langbits];
! 247: } else {
! 248: lang = "unknown";
! 249: }
! 250: fprintf(stderr, "OS Conf bits : 0x%04x (%s, %s)\n", osconf, lang, osconf&1 ? "PAL":"NTSC");
1.1 root 251:
252: if (osversion >= 0x0102) {
1.1.1.2 ! root 253: /* last 3 OS header fields are only available as of TOS 1.02 */
1.1 root 254: fprintf(stderr, "Memory pool : 0x%06x\n", STMemory_ReadLong(sysbase+0x20));
255: fprintf(stderr, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24));
256: } else {
1.1.1.2 ! root 257: /* TOS 1.0 */
! 258: fprintf(stderr, "Memory pool : 0x0056FA\n");
1.1 root 259: fprintf(stderr, "Kbshift addr : 0x000E1B\n");
260: }
261: basepage = DebugInfo_CurrentBasepage();
262: if (basepage) {
263: fprintf(stderr, "Basepage : 0x%06x\n", basepage);
264: }
265: }
266:
267:
1.1.1.2 ! root 268: /**
! 269: * DebugInfo_Cookiejar: display TOS Cookiejar content
! 270: */
! 271: static void DebugInfo_Cookiejar(Uint32 dummy)
! 272: {
! 273: int items;
! 274:
! 275: Uint32 jar = STMemory_ReadLong(COOKIE_JAR);
! 276: if (!jar) {
! 277: fprintf(stderr, "Cookiejar is empty.\n");
! 278: return;
! 279: }
! 280:
! 281: fprintf(stderr, "Cookiejar contents:\n");
! 282: items = 0;
! 283: while (STMemory_ValidArea(jar, 8) && STMemory_ReadLong(jar)) {
! 284: fprintf(stderr, "%c%c%c%c = 0x%08x\n",
! 285: STRam[jar], STRam[jar+1], STRam[jar+2], STRam[jar+3],
! 286: STMemory_ReadLong(jar+4));
! 287: jar += 8;
! 288: items++;
! 289: }
! 290: fprintf(stderr, "%d items at 0x%06x.\n", items, STMemory_ReadLong(COOKIE_JAR));
! 291: }
! 292:
! 293:
! 294: /**
! 295: * DebugInfo_Video: display video related information
! 296: */
! 297: static void DebugInfo_Video(Uint32 dummy)
! 298: {
! 299: const char *mode;
! 300: switch (OverscanMode) {
! 301: case OVERSCANMODE_NONE:
! 302: mode = "none";
! 303: break;
! 304: case OVERSCANMODE_TOP:
! 305: mode = "top";
! 306: break;
! 307: case OVERSCANMODE_BOTTOM:
! 308: mode = "bottom";
! 309: break;
! 310: case OVERSCANMODE_TOP|OVERSCANMODE_BOTTOM:
! 311: mode = "top+bottom";
! 312: break;
! 313: default:
! 314: mode = "unknown";
! 315: }
! 316: fprintf(stderr, "Video base : 0x%x\n", VideoBase);
! 317: fprintf(stderr, "VBL counter : %d\n", nVBLs);
! 318: fprintf(stderr, "HBL line : %d\n", nHBL);
! 319: fprintf(stderr, "V-overscan : %s\n", mode);
! 320: fprintf(stderr, "Refresh rate : %d Hz\n", nScreenRefreshRate);
! 321: fprintf(stderr, "Frame skips : %d\n", nFrameSkips);
! 322: }
! 323:
1.1 root 324: /* ------------------------------------------------------------------
325: * Falcon HW information
326: */
327:
328: /**
329: * DebugInfo_Videl : display the Videl registers values.
330: */
331: static void DebugInfo_Videl(Uint32 dummy)
332: {
333: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
334: fprintf(stderr, "Not Falcon - no Videl!\n");
335: return;
336: }
337:
1.1.1.2 ! root 338: fprintf(stderr, "$FF8006.b : monitor type : %02x\n", IoMem_ReadByte(0xff8006));
! 339: fprintf(stderr, "$FF8201.b : Video Base Hi : %02x\n", IoMem_ReadByte(0xff8201));
! 340: fprintf(stderr, "$FF8203.b : Video Base Mi : %02x\n", IoMem_ReadByte(0xff8203));
! 341: fprintf(stderr, "$FF8205.b : Video Count Hi : %02x\n", IoMem_ReadByte(0xff8205));
! 342: fprintf(stderr, "$FF8207.b : Video Count Mi : %02x\n", IoMem_ReadByte(0xff8207));
! 343: fprintf(stderr, "$FF8209.b : Video Count Lo : %02x\n", IoMem_ReadByte(0xff8209));
! 344: fprintf(stderr, "$FF820A.b : Sync mode : %02x\n", IoMem_ReadByte(0xff820a));
! 345: fprintf(stderr, "$FF820D.b : Video Base Lo : %02x\n", IoMem_ReadByte(0xff820d));
! 346: fprintf(stderr, "$FF820E.w : offset to next line : %04x\n", IoMem_ReadWord(0xff820e));
! 347: fprintf(stderr, "$FF8210.w : VWRAP - line width : %04x\n", IoMem_ReadWord(0xff8210));
! 348: fprintf(stderr, "$FF8260.b : ST shift mode : %02x\n", IoMem_ReadByte(0xff8260));
! 349: fprintf(stderr, "$FF8264.w : Horizontal scroll register : %04x\n", IoMem_ReadWord(0xff8264));
! 350: fprintf(stderr, "$FF8266.w : Falcon shift mode : %04x\n", IoMem_ReadWord(0xff8266));
1.1 root 351: fprintf(stderr, "\n");
1.1.1.2 ! root 352: fprintf(stderr, "$FF8280.w : HHC - Horizontal Hold Counter : %04x\n", IoMem_ReadWord(0xff8280));
! 353: fprintf(stderr, "$FF8282.w : HHT - Horizontal Hold Timer : %04x\n", IoMem_ReadWord(0xff8282));
! 354: fprintf(stderr, "$FF8284.w : HBB - Horizontal Border Begin : %04x\n", IoMem_ReadWord(0xff8284));
! 355: fprintf(stderr, "$FF8286.w : HBE - Horizontal Border End : %04x\n", IoMem_ReadWord(0xff8286));
! 356: fprintf(stderr, "$FF8288.w : HDB - Horizontal Display Begin : %04x\n", IoMem_ReadWord(0xff8288));
! 357: fprintf(stderr, "$FF828A.w : HDE - Horizontal Display End : %04x\n", IoMem_ReadWord(0xff828a));
! 358: fprintf(stderr, "$FF828C.w : HSS - Horizontal SS : %04x\n", IoMem_ReadWord(0xff828c));
! 359: fprintf(stderr, "$FF828E.w : HFS - Horizontal FS : %04x\n", IoMem_ReadWord(0xff828e));
! 360: fprintf(stderr, "$FF8290.w : HEE - Horizontal EE : %04x\n", IoMem_ReadWord(0xff8290));
1.1 root 361: fprintf(stderr, "\n");
1.1.1.2 ! root 362: fprintf(stderr, "$FF82A0.w : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0));
! 363: fprintf(stderr, "$FF82A2.w : VFT - Vertical Frequency Timer : %04x\n", IoMem_ReadWord(0xff82a2));
! 364: fprintf(stderr, "$FF82A4.w : VBB - Vertical Border Begin : %04x\n", IoMem_ReadWord(0xff82a4));
! 365: fprintf(stderr, "$FF82A6.w : VBE - Vertical Border End : %04x\n", IoMem_ReadWord(0xff82a6));
! 366: fprintf(stderr, "$FF82A8.w : VDB - Vertical Display Begin : %04x\n", IoMem_ReadWord(0xff82a8));
! 367: fprintf(stderr, "$FF82AA.w : VDE - Vertical Display End : %04x\n", IoMem_ReadWord(0xff82aa));
! 368: fprintf(stderr, "$FF82AC.w : VSS - Vertical SS : %04x\n", IoMem_ReadWord(0xff82ac));
1.1 root 369: fprintf(stderr, "\n");
1.1.1.2 ! root 370: fprintf(stderr, "$FF82C0.w : VCO - Video control : %04x\n", IoMem_ReadWord(0xff82c0));
! 371: fprintf(stderr, "$FF82C2.w : VMD - Video mode : %04x\n", IoMem_ReadWord(0xff82c2));
! 372: fprintf(stderr, "\n-------------------------\n");
! 373:
! 374: fprintf(stderr, "Video base : %08x\n", (IoMem_ReadByte(0xff8201)<<16) +
! 375: (IoMem_ReadByte(0xff8203)<<8) +
! 376: IoMem_ReadByte(0xff820d));
! 377: fprintf(stderr, "Video count : %08x\n", (IoMem_ReadByte(0xff8205)<<16) +
! 378: (IoMem_ReadByte(0xff8207)<<8) +
! 379: IoMem_ReadByte(0xff8209));
1.1 root 380: }
381:
382: /**
383: * DebugInfo_Crossbar : display the Crossbar registers values.
384: */
385: static void DebugInfo_Crossbar(Uint32 dummy)
386: {
387: char matrixDMA[5], matrixDAC[5], matrixDSP[5], matrixEXT[5];
388: char frqDMA[11], frqDAC[11], frqDSP[11], frqEXT[11];
1.1.1.2 ! root 389: char frqSTE[30], frq25Mhz[30], frq32Mhz[30];
1.1 root 390: char dataSize[15];
391:
1.1.1.2 ! root 392: static const Uint32 Ste_SampleRates[4] = {
! 393: 6258, 12517, 25033, 50066
! 394: };
! 395:
! 396: static const Uint32 Falcon_SampleRates_25Mhz[15] = {
! 397: 49170, 32780, 24585, 19668, 16390, 14049, 12292, 10927, 9834, 8940, 8195, 7565, 7024, 6556, 6146
! 398: };
! 399:
! 400: static const Uint32 Falcon_SampleRates_32Mhz[15] = {
! 401: 62500, 41666, 31250, 25000, 20833, 17857, 15624, 13889, 12500, 11363, 10416, 9615, 8928, 8333, 7812
! 402: };
! 403:
1.1 root 404: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
405: fprintf(stderr, "Not Falcon - no Crossbar!\n");
406: return;
407: }
408:
1.1.1.2 ! root 409: fprintf(stderr, "$FF8900.b : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8900));
! 410: fprintf(stderr, "$FF8901.b : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8901));
! 411: fprintf(stderr, "$FF8903.b : Frame Start High : %02x\n", IoMem_ReadByte(0xff8903));
! 412: fprintf(stderr, "$FF8905.b : Frame Start middle : %02x\n", IoMem_ReadByte(0xff8905));
! 413: fprintf(stderr, "$FF8907.b : Frame Start low : %02x\n", IoMem_ReadByte(0xff8907));
! 414: fprintf(stderr, "$FF8909.b : Frame Count High : %02x\n", IoMem_ReadByte(0xff8909));
! 415: fprintf(stderr, "$FF890B.b : Frame Count middle : %02x\n", IoMem_ReadByte(0xff890b));
! 416: fprintf(stderr, "$FF890D.b : Frame Count low : %02x\n", IoMem_ReadByte(0xff890d));
! 417: fprintf(stderr, "$FF890F.b : Frame End High : %02x\n", IoMem_ReadByte(0xff890f));
! 418: fprintf(stderr, "$FF8911.b : Frame End middle : %02x\n", IoMem_ReadByte(0xff8911));
! 419: fprintf(stderr, "$FF8913.b : Frame End low : %02x\n", IoMem_ReadByte(0xff8913));
1.1 root 420: fprintf(stderr, "\n");
1.1.1.2 ! root 421: fprintf(stderr, "$FF8920.b : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8920));
! 422: fprintf(stderr, "$FF8921.b : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8921));
! 423: fprintf(stderr, "$FF8930.w : DMA Crossbar Input Select Controller : %04x\n", IoMem_ReadWord(0xff8930));
! 424: fprintf(stderr, "$FF8932.w : DMA Crossbar Output Select Controller : %04x\n", IoMem_ReadWord(0xff8932));
1.1 root 425: fprintf(stderr, "\n");
1.1.1.2 ! root 426: fprintf(stderr, "$FF8934.b : External Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8934));
! 427: fprintf(stderr, "$FF8935.b : Internal Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8935));
! 428: fprintf(stderr, "$FF8936.b : Record Track select : %02x\n", IoMem_ReadByte(0xff8936));
! 429: fprintf(stderr, "$FF8937.b : Codec Input Source : %02x\n", IoMem_ReadByte(0xff8937));
! 430: fprintf(stderr, "$FF8938.b : Codec ADC Input : %02x\n", IoMem_ReadByte(0xff8938));
! 431: fprintf(stderr, "$FF8939.b : Gain Settings Per Channel : %02x\n", IoMem_ReadByte(0xff8939));
! 432: fprintf(stderr, "$FF893A.b : Attenuation Settings Per Channel : %02x\n", IoMem_ReadByte(0xff893a));
! 433: fprintf(stderr, "$FF893C.w : Codec Status : %04x\n", IoMem_ReadWord(0xff893c));
! 434: fprintf(stderr, "$FF8940.w : GPIO Data Direction : %04x\n", IoMem_ReadWord(0xff8940));
! 435: fprintf(stderr, "$FF8942.w : GPIO Data : %04x\n", IoMem_ReadWord(0xff8942));
1.1 root 436: fprintf(stderr, "\n");
437:
438: /* DAC connexion */
1.1.1.2 ! root 439: switch ((IoMem_ReadWord(0xff8932) >> 13) & 0x3) {
! 440: case 0 :
! 441: /* DAC connexion with DMA Playback */
! 442: if ((IoMem_ReadWord(0xff8930) & 0x1) == 1)
! 443: strcpy(matrixDAC, "OOXO");
! 444: else
! 445: strcpy(matrixDAC, "OOHO");
! 446: break;
! 447: case 1 :
! 448: /* DAC connexion with DSP Transmit */
! 449: if ((IoMem_ReadWord(0xff8930) & 0x10) == 0x10)
! 450: strcpy(matrixDAC, "OXOO");
! 451: else
! 452: strcpy(matrixDAC, "OHOO");
! 453: break;
! 454: case 2 :
! 455: /* DAC connexion with External Input */
! 456: if ((IoMem_ReadWord(0xff8930) & 0x100) == 0x100)
! 457: strcpy(matrixDAC, "XOOO");
! 458: else
! 459: strcpy(matrixDAC, "HOOO");
! 460: break;
! 461: case 3 :
! 462: /* DAC connexion with ADC */
! 463: strcpy(matrixDAC, "OOOX");
! 464: break;
1.1 root 465: }
1.1.1.2 ! root 466:
1.1 root 467: /* DMA connexion */
1.1.1.2 ! root 468: switch (IoMem_ReadWord(0xff8932) & 0x7) {
! 469: case 0 : strcpy(matrixDMA, "OOHO"); break;
! 470: case 1 : strcpy(matrixDMA, "OOXO"); break;
! 471: case 2 : strcpy(matrixDMA, "OHOO"); break;
! 472: case 3 : strcpy(matrixDMA, "OXOO"); break;
! 473: case 4 : strcpy(matrixDMA, "HOOO"); break;
! 474: case 5 : strcpy(matrixDMA, "XOOO"); break;
! 475: case 6 : strcpy(matrixDMA, "OOOH"); break;
! 476: case 7 : strcpy(matrixDMA, "OOOX"); break;
1.1 root 477: }
478:
479: /* DSP connexion */
1.1.1.2 ! root 480: switch ((IoMem_ReadWord(0xff8932) >> 4) & 0x7) {
! 481: case 0 : strcpy(matrixDSP, "OOHO"); break;
! 482: case 1 : strcpy(matrixDSP, "OOXO"); break;
! 483: case 2 : strcpy(matrixDSP, "OHOO"); break;
! 484: case 3 : strcpy(matrixDSP, "OXOO"); break;
! 485: case 4 : strcpy(matrixDSP, "HOOO"); break;
! 486: case 5 : strcpy(matrixDSP, "XOOO"); break;
! 487: case 6 : strcpy(matrixDSP, "OOOH"); break;
! 488: case 7 : strcpy(matrixDSP, "OOOX"); break;
1.1 root 489: }
490:
491: /* External input connexion */
1.1.1.2 ! root 492: switch ((IoMem_ReadWord(0xff8932) >> 8) & 0x7) {
! 493: case 0 : strcpy(matrixEXT, "OOHO"); break;
! 494: case 1 : strcpy(matrixEXT, "OOXO"); break;
! 495: case 2 : strcpy(matrixEXT, "OHOO"); break;
! 496: case 3 : strcpy(matrixEXT, "OXOO"); break;
! 497: case 4 : strcpy(matrixEXT, "HOOO"); break;
! 498: case 5 : strcpy(matrixEXT, "XOOO"); break;
! 499: case 6 : strcpy(matrixEXT, "OOOH"); break;
! 500: case 7 : strcpy(matrixEXT, "OOOX"); break;
1.1 root 501: }
502:
503: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
504: strcpy(frqDSP, "(STe Freq)");
1.1.1.2 ! root 505: strcpy(frqDMA, "(STe Freq)");
! 506: strcpy(frqEXT, "(STe Freq)");
! 507: strcpy(frqDAC, "(STe Freq)");
! 508: }
! 509: else {
! 510: /* DSP Clock */
1.1 root 511: switch ((IoMem_ReadWord(0xff8930) >> 5) & 0x3) {
512: case 0: strcpy(frqDSP, " (25 Mhz) "); break;
513: case 1: strcpy(frqDSP, "(External)"); break;
514: case 2: strcpy(frqDSP, " (32 Mhz) "); break;
1.1.1.2 ! root 515: default: strcpy(frqDSP, "undefined "); break;
1.1 root 516: }
517:
1.1.1.2 ! root 518: /* DMA Clock */
1.1 root 519: switch ((IoMem_ReadWord(0xff8930) >> 1) & 0x3) {
520: case 0: strcpy(frqDMA, " (25 Mhz) "); break;
521: case 1: strcpy(frqDMA, "(External)"); break;
522: case 2: strcpy(frqDMA, " (32 Mhz) "); break;
1.1.1.2 ! root 523: default: strcpy(frqDMA, "undefined "); break;
1.1 root 524: }
525:
1.1.1.2 ! root 526: /* External Clock */
1.1 root 527: switch ((IoMem_ReadWord(0xff8930) >> 9) & 0x3) {
528: case 0: strcpy(frqEXT, " (25 Mhz) "); break;
529: case 1: strcpy(frqEXT, "(External)"); break;
530: case 2: strcpy(frqEXT, " (32 Mhz) "); break;
1.1.1.2 ! root 531: default: strcpy(frqEXT, "undefined "); break;
1.1 root 532: }
533:
1.1.1.2 ! root 534: /* DAC Clock */
1.1 root 535: strcpy(frqDAC, " (25 Mhz) ");
536: }
537:
538: /* data size */
539: switch ((IoMem_ReadByte(0xff8921) >> 6) & 0x3) {
540: case 0: strcpy (dataSize, "8 bits stereo"); break;
541: case 1: strcpy (dataSize, "16 bits stereo"); break;
542: case 2: strcpy (dataSize, "8 bits mono"); break;
543: default: strcpy (dataSize, "undefined"); break;
544: }
545:
1.1.1.2 ! root 546: /* STE, 25Mhz and 32 Mhz sound frequencies */
! 547: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
! 548: sprintf(frqSTE, "Ste Freq : %d Khz", Ste_SampleRates[IoMem_ReadByte(0xff8921) & 0x3]);
! 549: strcpy (frq25Mhz, "25 Mhz Freq : - Khz");
! 550: strcpy (frq32Mhz, "32 Mzh Freq : - Khz");
! 551: }
! 552: else {
! 553: strcpy (frqSTE, "Ste Freq : - Khz");
! 554: sprintf(frq25Mhz, "25 Mhz Freq : %d Khz", Falcon_SampleRates_25Mhz[(IoMem_ReadByte(0xff8935) & 0xf) - 1]);
! 555: sprintf(frq32Mhz, "32 Mzh Freq : %d Khz", Falcon_SampleRates_32Mhz[(IoMem_ReadByte(0xff8935) & 0xf) - 1]);
! 556: }
! 557:
1.1 root 558: /* Display the crossbar Matrix */
559: fprintf(stderr, " INPUT\n");
560: fprintf(stderr, "External Imp ---%c------%c------%c------%c\n", matrixDAC[0], matrixDMA[0], matrixDSP[0], matrixEXT[0]);
561: fprintf(stderr, "%s | | | | O = no connexion\n", frqEXT);
562: fprintf(stderr, " | | | | X = connexion\n");
563: fprintf(stderr, "Dsp Transmit ---%c------%c------%c------%c H = Handshake connexion\n", matrixDAC[1], matrixDMA[1], matrixDSP[1], matrixEXT[1]);
564: fprintf(stderr, "%s | | | |\n", frqDSP);
565: fprintf(stderr, " | | | | %s\n", dataSize);
566: fprintf(stderr, "DMA PlayBack ---%c------%c------%c------%c\n", matrixDAC[2], matrixDMA[2], matrixDSP[2], matrixEXT[2]);
1.1.1.2 ! root 567: fprintf(stderr, "%s | | | | Sound Freq :\n", frqDMA);
! 568: fprintf(stderr, " | | | | %s\n", frqSTE);
! 569: fprintf(stderr, "ADC ---%c------%c------%c------%c %s\n", matrixDAC[3], matrixDMA[3], matrixDSP[3], matrixEXT[3], frq25Mhz);
! 570: fprintf(stderr, "%s | | | | %s\n", frqDAC, frq32Mhz);
1.1 root 571: fprintf(stderr, " | | | |\n");
572: fprintf(stderr, " DAC DMA DSP External OUTPUT\n");
573: fprintf(stderr, " Record Record Out\n");
574: fprintf(stderr, "\n");
575: }
576:
577:
578: /* ------------------------------------------------------------------
579: * CPU and DSP information wrappers
580: */
581:
582: /**
583: * Helper to call debugcpu.c and debugdsp.c debugger commands
584: */
585: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg)
586: {
587: char cmdbuffer[16], argbuffer[12];
588: char *argv[] = { cmdbuffer, NULL };
589: int argc = 1;
590:
591: assert(strlen(command) < sizeof(cmdbuffer));
592: strcpy(cmdbuffer, command);
593: if (arg) {
594: sprintf(argbuffer, "$%x", arg);
595: argv[argc++] = argbuffer;
596: }
597: func(argc, argv);
598: }
599:
600: static void DebugInfo_CpuRegister(Uint32 arg)
601: {
602: DebugInfo_CallCommand(DebugCpu_Register, "register", arg);
603: }
604: static void DebugInfo_CpuDisAsm(Uint32 arg)
605: {
606: DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg);
607: }
608: static void DebugInfo_CpuMemDump(Uint32 arg)
609: {
610: DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg);
611: }
612:
613: #if ENABLE_DSP_EMU
614:
615: static void DebugInfo_DspRegister(Uint32 arg)
616: {
617: DebugInfo_CallCommand(DebugDsp_Register, "dspreg", arg);
618: }
619: static void DebugInfo_DspDisAsm(Uint32 arg)
620: {
621: DebugInfo_CallCommand(DebugDsp_DisAsm, "dspdisasm", arg);
622: }
623:
624: static void DebugInfo_DspMemDump(Uint32 arg)
625: {
626: char cmdbuf[] = "dspmemdump";
627: char addrbuf[6], spacebuf[2] = "X";
628: char *argv[] = { cmdbuf, spacebuf, addrbuf };
629: spacebuf[0] = (arg>>16)&0xff;
630: sprintf(addrbuf, "$%x", (Uint16)(arg&0xffff));
631: DebugDsp_MemDump(3, argv);
632: }
633:
634: /**
635: * Convert arguments to Uint32 arg suitable for DSP memdump callback
636: */
637: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[])
638: {
639: Uint32 value;
640: char space;
641: if (argc != 2) {
642: return 0;
643: }
644: space = toupper(argv[0][0]);
645: if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) {
646: fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]);
647: return 0;
648: }
649: if (!Eval_Number(argv[1], &value) || value > 0xffff) {
650: fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]);
651: return 0;
652: }
653: return ((Uint32)space<<16) | value;
654: }
655:
656: #endif /* ENABLE_DSP_EMU */
657:
658:
659: static void DebugInfo_RegAddr(Uint32 arg)
660: {
661: bool forDsp;
662: char regname[3];
663: Uint32 *regvalue, mask;
664: char cmdbuf[12], addrbuf[6];
665: char *argv[] = { cmdbuf, addrbuf };
666:
667: regname[0] = (arg>>24)&0xff;
668: regname[1] = (arg>>16)&0xff;
669: regname[2] = '\0';
670:
671: if (DebugCpu_GetRegisterAddress(regname, ®value)) {
672: mask = 0xffffffff;
673: forDsp = false;
674: } else {
675: if (!DSP_GetRegisterAddress(regname, ®value, &mask)) {
676: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", regname);
677: return;
678: }
679: forDsp = true;
680: }
681: sprintf(addrbuf, "$%x", *regvalue & mask);
682:
683: if ((arg & 0xff) == 'D') {
684: strcpy(cmdbuf, "disasm");
685: if (forDsp) {
686: #if ENABLE_DSP_EMU
687: DebugDsp_DisAsm(2, argv);
688: #endif
689: } else {
690: DebugCpu_DisAsm(2, argv);
691: }
692: } else {
693: strcpy(cmdbuf, "memdump");
694: if (forDsp) {
695: #if ENABLE_DSP_EMU
696: DebugDsp_MemDump(2, argv);
697: #endif
698: } else {
699: DebugCpu_MemDump(2, argv);
700: }
701: }
702: }
703:
704: /**
705: * Convert arguments to Uint32 arg suitable for RegAddr callback
706: */
707: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[])
708: {
709: Uint32 value, *regaddr;
710: if (argc != 2) {
711: return 0;
712: }
713:
714: if (strcmp(argv[0], "disasm") == 0) {
715: value = 'D';
716: } else if (strcmp(argv[0], "memdump") == 0) {
717: value = 'M';
718: } else {
719: fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]);
720: return 0;
721: }
722:
723: if (strlen(argv[1]) != 2 ||
724: (!DebugCpu_GetRegisterAddress(argv[1], ®addr) &&
725: (toupper(argv[1][0]) != 'R' || !isdigit(argv[1][1]) || argv[1][2]))) {
726: /* not CPU register or Rx DSP register */
727: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]);
728: return 0;
729: }
730:
731: value |= argv[1][0] << 24;
732: value |= argv[1][1] << 16;
733: value &= 0xffff00ff;
734: return value;
735: }
736:
737:
738: /* ------------------------------------------------------------------
1.1.1.2 ! root 739: * wrappers for command to parse debugger input file
! 740: */
! 741:
! 742: /* file name to be given before calling the Parse function,
! 743: * needs to be set separately as it's a host pointer which
! 744: * can be 64-bit i.e. may not fit into Uint32.
! 745: */
! 746: static char *parse_filename;
! 747:
! 748: /**
! 749: * Parse and exec commands in the previously given debugger input file
! 750: */
! 751: static void DebugInfo_FileParse(Uint32 dummy)
! 752: {
! 753: if (parse_filename) {
! 754: DebugUI_ParseFile(parse_filename);
! 755: } else {
! 756: fputs("ERROR: debugger input file name to parse isn't set!\n", stderr);
! 757: }
! 758: }
! 759:
! 760: /**
! 761: * Set which input file to parse.
! 762: * Return true if file exists, false on error
! 763: */
! 764: static Uint32 DebugInfo_FileArgs(int argc, char *argv[])
! 765: {
! 766: if (argc != 1) {
! 767: return false;
! 768: }
! 769: if (!File_Exists(argv[0])) {
! 770: fprintf(stderr, "ERROR: given file '%s' doesn't exist!\n", argv[0]);
! 771: return false;
! 772: }
! 773: if (parse_filename) {
! 774: free(parse_filename);
! 775: }
! 776: parse_filename = strdup(argv[0]);
! 777: return true;
! 778: }
! 779:
! 780:
! 781: /* ------------------------------------------------------------------
1.1 root 782: * Debugger & readline TAB completion integration
783: */
784:
785: /**
786: * Default information on entering the debugger
787: */
788: static void DebugInfo_Default(Uint32 dummy)
789: {
790: int hbl, fcycles, lcycles;
791: Video_GetPosition(&fcycles, &hbl, &lcycles);
792: fprintf(stderr, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=",
793: M68000_GetPC(), nVBLs, fcycles, hbl, lcycles);
794: if (bDspEnabled)
795: fprintf(stderr, "$%x\n", DSP_GetPC());
796: else
797: fprintf(stderr, "N/A\n");
798: }
799:
800: static const struct {
1.1.1.2 ! root 801: /* if overlaps with other functionality, list only for lock command */
1.1 root 802: bool lock;
803: const char *name;
804: void (*func)(Uint32 arg);
805: /* convert args in argv into single Uint32 for func */
806: Uint32 (*args)(int argc, char *argv[]);
807: const char *info;
808: } infotable[] = {
1.1.1.2 ! root 809: { false,"aes", AES_Info, NULL, "Show AES vector contents (with <value>, show opcodes)" },
1.1 root 810: { false,"basepage", DebugInfo_Basepage, NULL, "Show program basepage info at given <address>" },
1.1.1.2 ! root 811: { false,"cookiejar", DebugInfo_Cookiejar, NULL, "Show TOS Cookiejar contents" },
1.1 root 812: { false,"crossbar", DebugInfo_Crossbar, NULL, "Show Falcon crossbar HW register values" },
813: { true, "default", DebugInfo_Default, NULL, "Show default debugger entry information" },
814: { true, "disasm", DebugInfo_CpuDisAsm, NULL, "Disasm CPU from PC or given <address>" },
815: #if ENABLE_DSP_EMU
816: { true, "dspdisasm", DebugInfo_DspDisAsm, NULL, "Disasm DSP from given <address>" },
817: { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" },
1.1.1.2 ! root 818: { true, "dspregs", DebugInfo_DspRegister,NULL, "Show DSP registers values" },
1.1 root 819: #endif
1.1.1.2 ! root 820: { true, "file", DebugInfo_FileParse, DebugInfo_FileArgs, "Parse commands from given debugger input <file>" },
! 821: { false,"gemdos", GemDOS_Info, NULL, "Show GEMDOS HDD emu info (with <value>, show opcodes)" },
1.1 root 822: { true, "memdump", DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" },
823: { false,"osheader", DebugInfo_OSHeader, NULL, "Show TOS OS header information" },
824: { true, "regaddr", DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" },
1.1.1.2 ! root 825: { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU registers values" },
! 826: { false,"vdi", VDI_Info, NULL, "Show VDI vector contents (with <value>, show opcodes)" },
! 827: { false,"videl", DebugInfo_Videl, NULL, "Show Falcon Videl HW registers values" },
! 828: { false,"video", DebugInfo_Video, NULL, "Show Video related values" }
1.1 root 829: };
830:
1.1.1.2 ! root 831: static int LockedFunction = 4; /* index for the "default" function */
1.1 root 832: static Uint32 LockedArgument;
833:
834: /**
835: * Show selected debugger session information
836: * (when debugger is (again) entered)
837: */
838: void DebugInfo_ShowSessionInfo(void)
839: {
840: infotable[LockedFunction].func(LockedArgument);
841: }
842:
843:
844: /**
845: * Readline match callback for info subcommand name completion.
846: * STATE = 0 -> different text from previous one.
847: * Return next match or NULL if no matches.
848: */
849: static char *DebugInfo_Match(const char *text, int state, bool lock)
850: {
851: static int i, len;
852: const char *name;
853:
854: if (!state) {
855: /* first match */
856: len = strlen(text);
857: i = 0;
858: }
859: /* next match */
860: while (i++ < ARRAYSIZE(infotable)) {
861: if (!lock && infotable[i-1].lock) {
862: continue;
863: }
864: name = infotable[i-1].name;
865: if (strncmp(name, text, len) == 0)
866: return (strdup(name));
867: }
868: return NULL;
869: }
870: char *DebugInfo_MatchLock(const char *text, int state)
871: {
872: return DebugInfo_Match(text, state, true);
873: }
874: char *DebugInfo_MatchInfo(const char *text, int state)
875: {
876: return DebugInfo_Match(text, state, false);
877: }
878:
879:
880: /**
881: * Show requested command information.
882: */
883: int DebugInfo_Command(int nArgc, char *psArgs[])
884: {
885: Uint32 value;
886: const char *cmd;
887: bool ok, lock;
888: int i, sub;
889:
890: sub = -1;
891: if (nArgc > 1) {
892: cmd = psArgs[1];
893: /* which subcommand? */
894: for (i = 0; i < ARRAYSIZE(infotable); i++) {
895: if (strcmp(cmd, infotable[i].name) == 0) {
896: sub = i;
897: break;
898: }
899: }
900: }
901:
902: if (infotable[sub].args) {
903: /* value needs callback specific conversion */
904: value = infotable[sub].args(nArgc-2, psArgs+2);
905: ok = !!value;
906: } else {
907: if (nArgc > 2) {
908: /* value is normal number */
909: ok = Eval_Number(psArgs[2], &value);
910: } else {
911: value = 0;
912: ok = true;
913: }
914: }
915:
916: lock = (strcmp(psArgs[0], "lock") == 0);
917:
918: if (sub < 0 || !ok) {
919: /* no subcommand or something wrong with value, show info */
920: fprintf(stderr, "%s subcommands are:\n", psArgs[0]);
921: for (i = 0; i < ARRAYSIZE(infotable); i++) {
922: if (!lock && infotable[i].lock) {
923: continue;
924: }
925: fprintf(stderr, "- %s: %s\n",
926: infotable[i].name, infotable[i].info);
927: }
928: return DEBUGGER_CMDDONE;
929: }
930:
931: if (lock) {
932: /* lock given subcommand and value */
933: LockedFunction = sub;
934: LockedArgument = value;
935: fprintf(stderr, "Locked %s output.\n", psArgs[1]);
936: } else {
937: /* do actual work */
938: infotable[sub].func(value);
939: }
940: return DEBUGGER_CMDDONE;
941: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.