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