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