--- hatari/src/debug/debugInfo.c 2019/04/09 08:48:37 1.1 +++ hatari/src/debug/debugInfo.c 2019/04/09 08:59:18 1.1.1.10 @@ -1,8 +1,8 @@ /* Hatari - debuginfo.c - This file is distributed under the GNU Public License, version 2 or at - your option any later version. Read the file gpl.txt for details. + This file is distributed under the GNU General Public License, version 2 + or at your option any later version. Read the file gpl.txt for details. debuginfo.c - functions needed to show info about the atari HW & OS components and "lock" that info to be shown on entering the debugger. @@ -11,20 +11,35 @@ const char DebugInfo_fileid[] = "Hatari #include #include +#include + #include "main.h" +#include "bios.h" +#include "blitter.h" #include "configuration.h" +#include "crossbar.h" #include "debugInfo.h" #include "debugcpu.h" #include "debugdsp.h" #include "debugui.h" +#include "debug_priv.h" #include "dsp.h" #include "evaluate.h" +#include "file.h" +#include "gemdos.h" +#include "history.h" #include "ioMem.h" #include "m68000.h" +#include "psg.h" #include "stMemory.h" #include "tos.h" +#include "screen.h" +#include "vdi.h" #include "video.h" - +#include "videl.h" +#include "xbios.h" +#include "newcpu.h" +#include "68kDisass.h" /* ------------------------------------------------------------------ * TOS information @@ -32,6 +47,7 @@ const char DebugInfo_fileid[] = "Hatari #define OS_SYSBASE 0x4F2 #define OS_HEADER_SIZE 0x30 +#define OS_PHYSTOP 0x42E #define COOKIE_JAR 0x5A0 #define BASEPAGE_SIZE 0x100 @@ -45,38 +61,58 @@ const char DebugInfo_fileid[] = "Hatari #define COUNTRY_SPAIN 4 + /** - * DebugInfo_GetSysbase: set osversion to given argument. - * return sysbase address on success and zero on failure. + * DebugInfo_GetSysbase: get and validate system base + * If warnings is set, output warnings if no valid system base + * return on success sysbase address (+ set rombase), on failure return zero */ -static Uint32 DebugInfo_GetSysbase(Uint16 *osversion) +static Uint32 DebugInfo_GetSysbase(Uint32 *rombase, bool warnings) { Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE); - if (!STMemory_ValidArea(sysbase, OS_HEADER_SIZE)) { - fprintf(stderr, "Invalid TOS base address!\n"); + if ( !STMemory_CheckAreaType (sysbase, OS_HEADER_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) { + if (warnings) { + fprintf(stderr, "Invalid TOS sysbase RAM address (0x%x)!\n", sysbase); + } return 0; } - if (sysbase != TosAddress || sysbase != STMemory_ReadLong(sysbase+0x08)) { - fprintf(stderr, "Sysbase and os_beg address in OS header mismatch!\n"); - return 0; + /* under TOS, sysbase = os_beg = TosAddress, but not under MiNT -> use os_beg */ + *rombase = STMemory_ReadLong(sysbase+0x08); + if ( !STMemory_CheckAreaType (*rombase, OS_HEADER_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) { + if (warnings) { + fprintf(stderr, "Invalid TOS sysbase ROM address (0x%x)!\n", *rombase); + } + *rombase = 0; + } + if (*rombase != TosAddress) { + if (warnings) { + fprintf(stderr, "os_beg (0x%x) != TOS address (0x%x), header in RAM not set up yet?\n", + *rombase, TosAddress); + } } - *osversion = STMemory_ReadWord(sysbase+0x02); return sysbase; } /** - * DebugInfo_CurrentBasepage: get currently running TOS program basepage + * DebugInfo_CurrentBasepage: get and validate currently running program basepage. + * if given sysbase is zero, use system sysbase. + * If warnings is set, output warnings if no valid basepage + * return on success basepage address, on failure return zero */ -static Uint32 DebugInfo_CurrentBasepage(void) +static Uint32 DebugInfo_CurrentBasepage(Uint32 sysbase, bool warnings) { - Uint32 basepage, sysbase; + Uint32 basepage; Uint16 osversion, osconf; - sysbase = DebugInfo_GetSysbase(&osversion); if (!sysbase) { - return 0; + Uint32 rombase; + sysbase = DebugInfo_GetSysbase(&rombase, warnings); + if (!sysbase) { + return 0; + } } + osversion = STMemory_ReadWord(sysbase+0x02); if (osversion >= 0x0102) { basepage = STMemory_ReadLong(sysbase+0x28); } else { @@ -87,316 +123,283 @@ static Uint32 DebugInfo_CurrentBasepage( basepage = 0x602C; } } - if (STMemory_ValidArea(basepage, 4)) { + if ( STMemory_CheckAreaType ( basepage, 4, ABFLAG_RAM ) ) { return STMemory_ReadLong(basepage); } - fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage); + if (warnings) { + fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage); + } + return 0; +} + + +/** + * GetBasepageValue: return basepage value at given offset in + * TOS process basepage or zero if that is missing/invalid. + */ +static Uint32 GetBasepageValue(unsigned offset) +{ + Uint32 basepage = DebugInfo_CurrentBasepage(0, false); + if (!basepage) { + return 0; + } + if ( !STMemory_CheckAreaType ( basepage, BASEPAGE_SIZE, ABFLAG_RAM ) || + STMemory_ReadLong(basepage) != basepage) { + return 0; + } + return STMemory_ReadLong(basepage+offset); +} + +/** + * DebugInfo_DTA: if no DTA address given, get one from current + * basepage and ask GEMDOS to show its info. + */ +static void DebugInfo_DTA(FILE *fp, Uint32 dta_addr) +{ + if (!dta_addr) { + dta_addr = GetBasepageValue(0x20); + if (!dta_addr) { + fprintf(fp, "ERROR: no valid basepage!\n"); + return; + } + } + GemDOS_InfoDTA(fp, dta_addr); +} + +/** + * DebugInfo_GetTEXT: return current program TEXT segment address + * or zero if basepage missing/invalid. For virtual debugger variable. + */ +Uint32 DebugInfo_GetTEXT(void) +{ + return GetBasepageValue(0x08); +} +/** + * DebugInfo_GetTEXTEnd: return address following current program TEXT segment + * or zero if basepage missing/invalid. For virtual debugger variable. + */ +Uint32 DebugInfo_GetTEXTEnd(void) +{ + Uint32 addr = GetBasepageValue(0x08); + if (addr) { + return addr + GetBasepageValue(0x0C); + } return 0; } +/** + * DebugInfo_GetDATA: return current program DATA segment address + * or zero if basepage missing/invalid. For virtual debugger variable. + */ +Uint32 DebugInfo_GetDATA(void) +{ + return GetBasepageValue(0x010); +} +/** + * DebugInfo_GetBSS: return current program BSS segment address + * or zero if basepage missing/invalid. For virtual debugger variable. + */ +Uint32 DebugInfo_GetBSS(void) +{ + return GetBasepageValue(0x18); +} +/** + * DebugInfo_GetBASEPAGE: return current basepage address. + */ +Uint32 DebugInfo_GetBASEPAGE(void) +{ + return DebugInfo_CurrentBasepage(0, false); +} + + +/** + * output nil-terminated string from any Atari memory type + */ +static Uint32 print_mem_str(Uint32 addr, Uint32 end) +{ + Uint8 chr; + while (addr < end && (chr = STMemory_ReadByte(addr++))) { + fputc(chr, stderr); + } + return addr; +} /** * DebugInfo_Basepage: show TOS process basepage information * at given address. */ -static void DebugInfo_Basepage(Uint32 basepage) +static void DebugInfo_Basepage(FILE *fp, Uint32 basepage) { Uint8 cmdlen; - Uint32 env; + Uint32 addr; if (!basepage) { /* default to current process basepage */ - basepage = DebugInfo_CurrentBasepage(); + basepage = DebugInfo_CurrentBasepage(0, true); if (!basepage) { return; } } - fprintf(stderr, "Process basepage information:\n"); - if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) || + fprintf(fp, "Process basepage (0x%x) information:\n", basepage); + if ( !STMemory_CheckAreaType ( basepage, BASEPAGE_SIZE, ABFLAG_RAM ) || STMemory_ReadLong(basepage) != basepage) { - fprintf(stderr, "- address 0x%06x is invalid!\n", basepage); + fprintf(fp, "- address 0x%06x is invalid!\n", basepage); return; } - fprintf(stderr, "- TPA start : 0x%06x\n", STMemory_ReadLong(basepage)); - fprintf(stderr, "- TPA end +1 : 0x%06x\n", STMemory_ReadLong(basepage+0x04)); - fprintf(stderr, "- Text segment : 0x%06x\n", STMemory_ReadLong(basepage+0x08)); - fprintf(stderr, "- Text size : 0x%x\n", STMemory_ReadLong(basepage+0x0C)); - fprintf(stderr, "- Data segment : 0x%06x\n", STMemory_ReadLong(basepage+0x10)); - fprintf(stderr, "- Data size : 0x%x\n", STMemory_ReadLong(basepage+0x14)); - fprintf(stderr, "- BSS segment : 0x%06x\n", STMemory_ReadLong(basepage+0x18)); - fprintf(stderr, "- BSS size : 0x%x\n", STMemory_ReadLong(basepage+0x1C)); - fprintf(stderr, "- Process DTA : 0x%06x\n", STMemory_ReadLong(basepage+0x20)); - fprintf(stderr, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24)); - - env = STMemory_ReadLong(basepage+0x2C); - fprintf(stderr, "- Environment : 0x%06x\n", env); - if (STMemory_ValidArea(env, 4096)) { - Uint32 end = env + 4096; - while (env < end && *(STRam+env)) { - fprintf(stderr, "'%s'\n", STRam+env); - env += strlen((const char *)(STRam+env)) + 1; - } - } - cmdlen = STMemory_ReadByte(basepage+0x80); - fprintf(stderr, "- Command argslen: %d\n", cmdlen); + fprintf(fp, "- TPA start : 0x%06x\n", STMemory_ReadLong(basepage)); + fprintf(fp, "- TPA end +1 : 0x%06x\n", STMemory_ReadLong(basepage+0x04)); + fprintf(fp, "- Text segment : 0x%06x\n", STMemory_ReadLong(basepage+0x08)); + fprintf(fp, "- Text size : 0x%x\n", STMemory_ReadLong(basepage+0x0C)); + fprintf(fp, "- Data segment : 0x%06x\n", STMemory_ReadLong(basepage+0x10)); + fprintf(fp, "- Data size : 0x%x\n", STMemory_ReadLong(basepage+0x14)); + fprintf(fp, "- BSS segment : 0x%06x\n", STMemory_ReadLong(basepage+0x18)); + fprintf(fp, "- BSS size : 0x%x\n", STMemory_ReadLong(basepage+0x1C)); + fprintf(fp, "- Process DTA : 0x%06x\n", STMemory_ReadLong(basepage+0x20)); + fprintf(fp, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24)); + + addr = STMemory_ReadLong(basepage+0x2C); + fprintf(fp, "- Environment : 0x%06x\n", addr); + if ( STMemory_CheckAreaType ( addr, 4096, ABFLAG_RAM ) ) { + Uint32 end = addr + 4096; + while (addr < end && STMemory_ReadByte(addr)) { + fprintf(fp, " '"); + addr = print_mem_str(addr, end); + addr = print_mem_str(addr, end); + fprintf(fp, "'\n"); + } + } + addr = basepage+0x80; + cmdlen = STMemory_ReadByte(addr++); + fprintf(fp, "- Command argslen: %d (at 0x%06x)\n", cmdlen, addr); if (cmdlen) { - int offset = 0; - while (offset < cmdlen) { - fprintf(stderr, " '%s'", STRam+basepage+0x81+offset); - offset += strlen((const char *)(STRam+basepage+0x81+offset)) + 1; + Uint32 end = addr + cmdlen; + fprintf(fp, " '"); + for (;;) { + addr = print_mem_str(addr, end); + if (addr >= end) { + break; + } + fputc(' ', fp); } - fprintf(stderr, "\n"); + fprintf(fp, "'\n"); } } + /** - * DebugInfo_OSHeader: display TOS OS Header + * DebugInfo_PrintOSHeader: output OS Header information */ -static void DebugInfo_OSHeader(Uint32 dummy) +static void DebugInfo_PrintOSHeader(FILE *fp, Uint32 sysbase) { - Uint32 sysbase, gemblock, basepage; - Uint16 osversion, osconf; + Uint32 gemblock, basepage; + Uint16 osversion, datespec, osconf, langbits; + const char *lang; + static const char langs[][3] = { + "us", "de", "fr", "uk", "es", "it", "se", "ch" /* fr */, "ch" /* de */, + "tr", "fi", "no", "dk", "sa", "nl", "cs", "hu" + }; - sysbase = DebugInfo_GetSysbase(&osversion); - if (!sysbase) { - return; - } - fprintf(stderr, "OS base addr : 0x%06x\n", sysbase); - fprintf(stderr, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C)); - fprintf(stderr, "TOS version : 0x%x\n", osversion); - - fprintf(stderr, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04)); - fprintf(stderr, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR)); - fprintf(stderr, "Reset valid : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC); + /* first more technical info */ + + osversion = STMemory_ReadWord(sysbase+0x02); + fprintf(fp, "OS base addr : 0x%06x\n", sysbase); + fprintf(fp, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C)); + + fprintf(fp, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04)); + fprintf(fp, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR)); + fprintf(fp, "Reset valid : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC); gemblock = STMemory_ReadLong(sysbase+0x14); - fprintf(stderr, "GEM Memory Usage Parameter Block:\n"); - if (STMemory_ValidArea(gemblock, GEM_MUPB_SIZE)) { - fprintf(stderr, "- Block addr : 0x%06x\n", gemblock); - fprintf(stderr, "- GEM magic : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC); - fprintf(stderr, "- GEM entry : 0x%06x\n", STMemory_ReadLong(gemblock+4)); - fprintf(stderr, "- GEM end : 0x%06x\n", STMemory_ReadLong(gemblock+8)); + fprintf(fp, "GEM Memory Usage Parameter Block:\n"); + if ( STMemory_CheckAreaType ( gemblock, GEM_MUPB_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) { + fprintf(fp, "- Block addr : 0x%06x\n", gemblock); + fprintf(fp, "- GEM magic : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC); + fprintf(fp, "- GEM entry : 0x%06x\n", STMemory_ReadLong(gemblock+4)); + fprintf(fp, "- GEM end : 0x%06x\n", STMemory_ReadLong(gemblock+8)); } else { - fprintf(stderr, "- is at INVALID 0x%06x address.\n", gemblock); + fprintf(fp, "- is at INVALID 0x%06x address.\n", gemblock); } - fprintf(stderr, "OS date : 0x%x\n", STMemory_ReadLong(sysbase+0x14)); - fprintf(stderr, "OS DOS date : 0x%x\n", STMemory_ReadLong(sysbase+0x1E)); - - osconf = STMemory_ReadWord(sysbase+0x1C); - fprintf(stderr, "OS Conf bits : lang=%d, %s\n", osconf>>1, osconf&1 ? "PAL":"NTSC"); - fprintf(stderr, "Cookie Jar : 0x%06x\n", STMemory_ReadLong(COOKIE_JAR)); - - /* last 3 OS header fields are only available as of TOS 1.02 */ if (osversion >= 0x0102) { - fprintf(stderr, "Memory pool : 0x%06x\n", STMemory_ReadLong(sysbase+0x20)); - fprintf(stderr, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24)); + /* last 3 OS header fields are only available as of TOS 1.02 */ + fprintf(fp, "Memory pool : 0x%06x\n", STMemory_ReadLong(sysbase+0x20)); + fprintf(fp, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24)); } else { - /* TODO: GEMDOS memory pool address for TOS 1.0? */ - fprintf(stderr, "Kbshift addr : 0x000E1B\n"); + /* TOS 1.0 */ + fprintf(fp, "Memory pool : 0x0056FA\n"); + fprintf(fp, "Kbshift addr : 0x000E1B\n"); } - basepage = DebugInfo_CurrentBasepage(); + basepage = DebugInfo_CurrentBasepage(sysbase, true); if (basepage) { - fprintf(stderr, "Basepage : 0x%06x\n", basepage); + fprintf(fp, "Basepage : 0x%06x\n", basepage); } -} + /* and then basic TOS information */ -/* ------------------------------------------------------------------ - * Falcon HW information - */ + fputs("\n", fp); + fprintf(fp, "TOS version : 0x%x%s\n", osversion, bIsEmuTOS ? " (EmuTOS)" : ""); + /* Bits: 0-4 = day (1-31), 5-8 = month (1-12), 9-15 = years (since 1980) */ + datespec = STMemory_ReadWord(sysbase+0x1E); + fprintf(fp, "Build date : %04d-%02d-%02d\n", (datespec >> 9) + 1980, + (datespec & 0x1E0) >> 5, datespec & 0x1f); + + osconf = STMemory_ReadWord(sysbase+0x1C); + langbits = osconf >> 1; + if (langbits == 127) { + lang = "all"; + } else if (langbits < ARRAY_SIZE(langs)) { + lang = langs[langbits]; + } else { + lang = "unknown"; + } + fprintf(fp, "OS config : %s, %s (0x%x)\n", lang, osconf&1 ? "PAL":"NTSC", osconf); + fprintf(fp, "Phystop : %d KB\n", (STMemory_ReadLong(OS_PHYSTOP) + 511) / 1024); +} /** - * DebugInfo_Videl : display the Videl registers values. + * DebugInfo_OSHeader: display TOS OS Header and RAM one + * if their addresses differ */ -static void DebugInfo_Videl(Uint32 dummy) +static void DebugInfo_OSHeader(FILE *fp, Uint32 dummy) { - if (ConfigureParams.System.nMachineType != MACHINE_FALCON) { - fprintf(stderr, "Not Falcon - no Videl!\n"); + Uint32 sysbase, rombase; + + sysbase = DebugInfo_GetSysbase(&rombase, true); + if (!sysbase) { + return; + } + fprintf(fp, "OS header information:\n"); + DebugInfo_PrintOSHeader(fp, sysbase); + if (sysbase != rombase && rombase) { + fprintf(fp, "\nROM TOS OS header information:\n"); + DebugInfo_PrintOSHeader(fp, rombase); return; } - - fprintf(stderr, "$FF8006 : monitor type : %02x\n", IoMem_ReadByte(0xff8006)); - fprintf(stderr, "$FF820E : offset to next line : %04x\n", IoMem_ReadWord(0xff820e)); - fprintf(stderr, "$FF8210 : VWRAP - line width : %04x\n", IoMem_ReadWord(0xff8210)); - fprintf(stderr, "$FF8260 : ST shift mode : %02x\n", IoMem_ReadByte(0xff8260)); - fprintf(stderr, "$FF8265 : Horizontal scroll register : %02x\n", IoMem_ReadByte(0xff8265)); - fprintf(stderr, "$FF8266 : Falcon shift mode : %04x\n", IoMem_ReadWord(0xff8266)); - fprintf(stderr, "\n"); - fprintf(stderr, "$FF8280 : HHC - Horizontal Hold Counter : %04x\n", IoMem_ReadWord(0xff8280)); - fprintf(stderr, "$FF8282 : HHT - Horizontal Hold Timer : %04x\n", IoMem_ReadWord(0xff8282)); - fprintf(stderr, "$FF8284 : HBB - Horizontal Border Begin : %04x\n", IoMem_ReadWord(0xff8284)); - fprintf(stderr, "$FF8286 : HBE - Horizontal Border End : %04x\n", IoMem_ReadWord(0xff8286)); - fprintf(stderr, "$FF8288 : HDB - Horizontal Display Begin : %04x\n", IoMem_ReadWord(0xff8288)); - fprintf(stderr, "$FF828A : HDE - Horizontal Display End : %04x\n", IoMem_ReadWord(0xff828a)); - fprintf(stderr, "$FF828C : HSS - Horizontal SS : %04x\n", IoMem_ReadWord(0xff828c)); - fprintf(stderr, "$FF828E : HFS - Horizontal FS : %04x\n", IoMem_ReadWord(0xff828e)); - fprintf(stderr, "$FF8290 : HEE - Horizontal EE : %04x\n", IoMem_ReadWord(0xff8290)); - fprintf(stderr, "\n"); - fprintf(stderr, "$FF82A0 : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0)); - fprintf(stderr, "$FF82A2 : VFT - Vertical Frequency Timer : %04x\n", IoMem_ReadWord(0xff82a2)); - fprintf(stderr, "$FF82A4 : VBB - Vertical Border Begin : %04x\n", IoMem_ReadWord(0xff82a4)); - fprintf(stderr, "$FF82A6 : VBE - Vertical Border End : %04x\n", IoMem_ReadWord(0xff82a6)); - fprintf(stderr, "$FF82A8 : VDB - Vertical Display Begin : %04x\n", IoMem_ReadWord(0xff82a8)); - fprintf(stderr, "$FF82AA : VDE - Vertical Display End : %04x\n", IoMem_ReadWord(0xff82aa)); - fprintf(stderr, "$FF82AC : VSS - Vertical SS : %04x\n", IoMem_ReadWord(0xff82ac)); - fprintf(stderr, "\n"); - fprintf(stderr, "$FF82C0 : VCO - Video control : %04x\n", IoMem_ReadWord(0xff82c0)); - fprintf(stderr, "$FF82C2 : VMD - Video mode : %04x\n", IoMem_ReadWord(0xff82c2)); - fprintf(stderr, "\n"); } /** - * DebugInfo_Crossbar : display the Crossbar registers values. - */ -static void DebugInfo_Crossbar(Uint32 dummy) -{ - char matrixDMA[5], matrixDAC[5], matrixDSP[5], matrixEXT[5]; - char frqDMA[11], frqDAC[11], frqDSP[11], frqEXT[11]; - char dataSize[15]; - - if (ConfigureParams.System.nMachineType != MACHINE_FALCON) { - fprintf(stderr, "Not Falcon - no Crossbar!\n"); + * DebugInfo_Cookiejar: display TOS Cookiejar content + */ +static void DebugInfo_Cookiejar(FILE *fp, Uint32 dummy) +{ + int items; + + Uint32 jar = STMemory_ReadLong(COOKIE_JAR); + if (!jar) { + fprintf(fp, "Cookiejar is empty.\n"); return; } - fprintf(stderr, "$FF8900 : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8900)); - fprintf(stderr, "$FF8901 : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8901)); - fprintf(stderr, "$FF8903 : Frame Start High : %02x\n", IoMem_ReadByte(0xff8903)); - fprintf(stderr, "$FF8905 : Frame Start middle : %02x\n", IoMem_ReadByte(0xff8905)); - fprintf(stderr, "$FF8907 : Frame Start low : %02x\n", IoMem_ReadByte(0xff8907)); - fprintf(stderr, "$FF8909 : Frame Count High : %02x\n", IoMem_ReadByte(0xff8909)); - fprintf(stderr, "$FF890B : Frame Count middle : %02x\n", IoMem_ReadByte(0xff890b)); - fprintf(stderr, "$FF890D : Frame Count low : %02x\n", IoMem_ReadByte(0xff890d)); - fprintf(stderr, "$FF890f : Frame End High : %02x\n", IoMem_ReadByte(0xff890f)); - fprintf(stderr, "$FF8911 : Frame End middle : %02x\n", IoMem_ReadByte(0xff8911)); - fprintf(stderr, "$FF8913 : Frame End low : %02x\n", IoMem_ReadByte(0xff8913)); - fprintf(stderr, "\n"); - fprintf(stderr, "$FF8920 : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8920)); - fprintf(stderr, "$FF8921 : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8921)); - fprintf(stderr, "$FF8930 : DMA Crossbar Input Select Controller : %04x\n", IoMem_ReadWord(0xff8930)); - fprintf(stderr, "$FF8932 : DMA Crossbar Output Select Controller : %04x\n", IoMem_ReadWord(0xff8932)); - fprintf(stderr, "\n"); - fprintf(stderr, "$FF8934 : External Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8934)); - fprintf(stderr, "$FF8935 : Internal Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8935)); - fprintf(stderr, "$FF8936 : Record Track select : %02x\n", IoMem_ReadByte(0xff8936)); - fprintf(stderr, "$FF8937 : Codec Input Source : %02x\n", IoMem_ReadByte(0xff8937)); - fprintf(stderr, "$FF8938 : Codec ADC Input : %02x\n", IoMem_ReadByte(0xff8938)); - fprintf(stderr, "$FF8939 : Gain Settings Per Channel : %02x\n", IoMem_ReadByte(0xff8939)); - fprintf(stderr, "$FF893A : Attenuation Settings Per Channel : %02x\n", IoMem_ReadByte(0xff893a)); - fprintf(stderr, "$FF893C : Codec Status : %04x\n", IoMem_ReadWord(0xff893c)); - fprintf(stderr, "$FF8940 : GPIO Data Direction : %04x\n", IoMem_ReadWord(0xff8940)); - fprintf(stderr, "$FF8942 : GPIO Data : %04x\n", IoMem_ReadWord(0xff8942)); - fprintf(stderr, "\n"); - - /* DAC connexion */ - switch ((IoMem_ReadWord(0xff8932) >> 13) & 3) { - case 0 : strcpy(matrixDAC, "OOXO"); break; - case 1 : strcpy(matrixDAC, "OXOO"); break; - case 2 : strcpy(matrixDAC, "XOOO"); break; - case 3 : strcpy(matrixDAC, "OOOX"); break; - } - - /* DMA connexion */ - switch ((IoMem_ReadWord(0xff8932) >> 1) & 3) { - case 0 : strcpy(matrixDMA, "OOXO"); break; - case 1 : strcpy(matrixDMA, "OXOO"); break; - case 2 : strcpy(matrixDMA, "XOOO"); break; - case 3 : strcpy(matrixDMA, "OOOX"); break; - } - - /* DSP connexion */ - switch ((IoMem_ReadWord(0xff8932) >> 5) & 3) { - case 0 : strcpy(matrixDSP, "OOXO"); break; - case 1 : strcpy(matrixDSP, "OXOO"); break; - case 2 : strcpy(matrixDSP, "XOOO"); break; - case 3 : strcpy(matrixDSP, "OOOX"); break; - } - - /* External input connexion */ - switch ((IoMem_ReadWord(0xff8932) >> 9) & 3) { - case 0 : strcpy(matrixEXT, "OOXO"); break; - case 1 : strcpy(matrixEXT, "OXOO"); break; - case 2 : strcpy(matrixEXT, "XOOO"); break; - case 3 : strcpy(matrixEXT, "OOOX"); break; - } - - /* HandShake mode test */ - if ((IoMem_ReadWord(0xff8932) & 7) == 2) { - matrixDMA[1] = 'H'; - } - - /* HandShake mode test */ - if ((IoMem_ReadWord(0xff8932) & 0xf) == 2) { - matrixDSP[2] = 'H'; - } - - /* DSP Frequency */ - if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) { - strcpy(frqDSP, "(STe Freq)"); - }else { - switch ((IoMem_ReadWord(0xff8930) >> 5) & 0x3) { - case 0: strcpy(frqDSP, " (25 Mhz) "); break; - case 1: strcpy(frqDSP, "(External)"); break; - case 2: strcpy(frqDSP, " (32 Mhz) "); break; - default: strcpy(frqDSP, "undefined "); break;break; - } - } - - /* DMA Frequency */ - if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) { - strcpy(frqDMA, "(STe Freq)"); - }else { - switch ((IoMem_ReadWord(0xff8930) >> 1) & 0x3) { - case 0: strcpy(frqDMA, " (25 Mhz) "); break; - case 1: strcpy(frqDMA, "(External)"); break; - case 2: strcpy(frqDMA, " (32 Mhz) "); break; - default: strcpy(frqDMA, "undefined "); break;break; - } - } - - /* External Frequency */ - if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) { - strcpy(frqEXT, "(STe Freq)"); - }else { - switch ((IoMem_ReadWord(0xff8930) >> 9) & 0x3) { - case 0: strcpy(frqEXT, " (25 Mhz) "); break; - case 1: strcpy(frqEXT, "(External)"); break; - case 2: strcpy(frqEXT, " (32 Mhz) "); break; - default: strcpy(frqEXT, "undefined "); break;break; - } - } - - /* DAC Frequency */ - if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) { - strcpy(frqDAC, "(STe Freq)"); - }else { - strcpy(frqDAC, " (25 Mhz) "); - } - - /* data size */ - switch ((IoMem_ReadByte(0xff8921) >> 6) & 0x3) { - case 0: strcpy (dataSize, "8 bits stereo"); break; - case 1: strcpy (dataSize, "16 bits stereo"); break; - case 2: strcpy (dataSize, "8 bits mono"); break; - default: strcpy (dataSize, "undefined"); break; - } - - /* Display the crossbar Matrix */ - fprintf(stderr, " INPUT\n"); - fprintf(stderr, "External Imp ---%c------%c------%c------%c\n", matrixDAC[0], matrixDMA[0], matrixDSP[0], matrixEXT[0]); - fprintf(stderr, "%s | | | | O = no connexion\n", frqEXT); - fprintf(stderr, " | | | | X = connexion\n"); - fprintf(stderr, "Dsp Transmit ---%c------%c------%c------%c H = Handshake connexion\n", matrixDAC[1], matrixDMA[1], matrixDSP[1], matrixEXT[1]); - fprintf(stderr, "%s | | | |\n", frqDSP); - fprintf(stderr, " | | | | %s\n", dataSize); - fprintf(stderr, "DMA PlayBack ---%c------%c------%c------%c\n", matrixDAC[2], matrixDMA[2], matrixDSP[2], matrixEXT[2]); - fprintf(stderr, "%s | | | |\n", frqDMA); - fprintf(stderr, " | | | |\n"); - fprintf(stderr, "ADC ---%c------%c------%c------%c\n", matrixDAC[3], matrixDMA[3], matrixDSP[3], matrixEXT[3]); - fprintf(stderr, "%s | | | |\n", frqDAC); - fprintf(stderr, " DAC DMA DSP External OUTPUT\n"); - fprintf(stderr, " Record Record Out\n"); - fprintf(stderr, "\n"); + fprintf(fp, "Cookiejar contents:\n"); + items = 0; + while ( STMemory_CheckAreaType (jar, 8, ABFLAG_RAM ) && STMemory_ReadLong(jar)) { + fprintf(fp, "%c%c%c%c = 0x%08x\n", + STMemory_ReadByte(jar+0), STMemory_ReadByte(jar+1), + STMemory_ReadByte(jar+2), STMemory_ReadByte(jar+3), + STMemory_ReadLong(jar+4)); + jar += 8; + items++; + } + fprintf(fp, "%d items at 0x%06x.\n", items, STMemory_ReadLong(COOKIE_JAR)); } @@ -422,31 +425,31 @@ static void DebugInfo_CallCommand(int (* func(argc, argv); } -static void DebugInfo_CpuRegister(Uint32 arg) +static void DebugInfo_CpuRegister(FILE *fp, Uint32 arg) { DebugInfo_CallCommand(DebugCpu_Register, "register", arg); } -static void DebugInfo_CpuDisAsm(Uint32 arg) +static void DebugInfo_CpuDisAsm(FILE *fp, Uint32 arg) { DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg); } -static void DebugInfo_CpuMemDump(Uint32 arg) +static void DebugInfo_CpuMemDump(FILE *fp, Uint32 arg) { DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg); } #if ENABLE_DSP_EMU -static void DebugInfo_DspRegister(Uint32 arg) +static void DebugInfo_DspRegister(FILE *fp, Uint32 arg) { DebugInfo_CallCommand(DebugDsp_Register, "dspreg", arg); } -static void DebugInfo_DspDisAsm(Uint32 arg) +static void DebugInfo_DspDisAsm(FILE *fp, Uint32 arg) { DebugInfo_CallCommand(DebugDsp_DisAsm, "dspdisasm", arg); } -static void DebugInfo_DspMemDump(Uint32 arg) +static void DebugInfo_DspMemDump(FILE *fp, Uint32 arg) { char cmdbuf[] = "dspmemdump"; char addrbuf[6], spacebuf[2] = "X"; @@ -466,7 +469,7 @@ static Uint32 DebugInfo_DspMemArgs(int a if (argc != 2) { return 0; } - space = toupper(argv[0][0]); + space = toupper((unsigned char)argv[0][0]); if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) { fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]); return 0; @@ -481,11 +484,11 @@ static Uint32 DebugInfo_DspMemArgs(int a #endif /* ENABLE_DSP_EMU */ -static void DebugInfo_RegAddr(Uint32 arg) +static void DebugInfo_RegAddr(FILE *fp, Uint32 arg) { bool forDsp; char regname[3]; - Uint32 *regvalue, mask; + Uint32 *reg32, regvalue, mask; char cmdbuf[12], addrbuf[6]; char *argv[] = { cmdbuf, addrbuf }; @@ -493,34 +496,48 @@ static void DebugInfo_RegAddr(Uint32 arg regname[1] = (arg>>16)&0xff; regname[2] = '\0'; - if (DebugCpu_GetRegisterAddress(regname, ®value)) { + if (DebugCpu_GetRegisterAddress(regname, ®32)) { + regvalue = *reg32; mask = 0xffffffff; forDsp = false; } else { - if (!DSP_GetRegisterAddress(regname, ®value, &mask)) { + int regsize = DSP_GetRegisterAddress(regname, ®32, &mask); + switch (regsize) { + /* currently regaddr supports only 32-bit Rx regs, but maybe later... */ + case 16: + regvalue = *((Uint16*)reg32); + break; + case 32: + regvalue = *reg32; + break; + default: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", regname); return; } forDsp = true; } - sprintf(addrbuf, "$%x", *regvalue & mask); + sprintf(addrbuf, "$%x", regvalue & mask); if ((arg & 0xff) == 'D') { - strcpy(cmdbuf, "disasm"); if (forDsp) { #if ENABLE_DSP_EMU + strcpy(cmdbuf, "dd"); DebugDsp_DisAsm(2, argv); #endif } else { + strcpy(cmdbuf, "d"); DebugCpu_DisAsm(2, argv); } } else { - strcpy(cmdbuf, "memdump"); if (forDsp) { #if ENABLE_DSP_EMU - DebugDsp_MemDump(2, argv); + /* use "Y" address space */ + char cmd[] = "dm"; char space[] = "y"; + char *dargv[] = { cmd, space, addrbuf }; + DebugDsp_MemDump(3, dargv); #endif } else { + strcpy(cmdbuf, "m"); DebugCpu_MemDump(2, argv); } } @@ -547,7 +564,8 @@ static Uint32 DebugInfo_RegAddrArgs(int if (strlen(argv[1]) != 2 || (!DebugCpu_GetRegisterAddress(argv[1], ®addr) && - (toupper(argv[1][0]) != 'R' || !isdigit(argv[1][1]) || argv[1][2]))) { + (toupper((unsigned char)argv[1][0]) != 'R' + || !isdigit((unsigned char)argv[1][1]) || argv[1][2]))) { /* not CPU register or Rx DSP register */ fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]); return 0; @@ -561,50 +579,110 @@ static Uint32 DebugInfo_RegAddrArgs(int /* ------------------------------------------------------------------ + * wrappers for command to parse debugger input file + */ + +/* file name to be given before calling the Parse function, + * needs to be set separately as it's a host pointer which + * can be 64-bit i.e. may not fit into Uint32. + */ +static char *parse_filename; + +/** + * Parse and exec commands in the previously given debugger input file + */ +static void DebugInfo_FileParse(FILE *fp, Uint32 dummy) +{ + if (parse_filename) { + DebugUI_ParseFile(parse_filename, true); + } else { + fputs("ERROR: debugger input file name to parse isn't set!\n", stderr); + } +} + +/** + * Set which input file to parse. + * Return true if file exists, false on error + */ +static Uint32 DebugInfo_FileArgs(int argc, char *argv[]) +{ + if (argc != 1) { + return false; + } + if (!File_Exists(argv[0])) { + fprintf(stderr, "ERROR: given file '%s' doesn't exist!\n", argv[0]); + return false; + } + if (parse_filename) { + free(parse_filename); + } + parse_filename = strdup(argv[0]); + return true; +} + + +/* ------------------------------------------------------------------ * Debugger & readline TAB completion integration */ /** * Default information on entering the debugger */ -static void DebugInfo_Default(Uint32 dummy) +static void DebugInfo_Default(FILE *fp, Uint32 dummy) { int hbl, fcycles, lcycles; + uaecptr nextpc, pc = M68000_GetPC(); Video_GetPosition(&fcycles, &hbl, &lcycles); - fprintf(stderr, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=", - M68000_GetPC(), nVBLs, fcycles, hbl, lcycles); + + fprintf(fp, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=", + pc, nVBLs, fcycles, hbl, lcycles); if (bDspEnabled) - fprintf(stderr, "$%x\n", DSP_GetPC()); + fprintf(fp, "$%x\n", DSP_GetPC()); else - fprintf(stderr, "N/A\n"); + fprintf(fp, "N/A\n"); + + Disasm(fp, pc, &nextpc, 1); } static const struct { - /* whether callback is used only for locking */ + /* if overlaps with other functionality, list only for lock command */ bool lock; const char *name; - void (*func)(Uint32 arg); + void (*func)(FILE *fp, Uint32 arg); /* convert args in argv into single Uint32 for func */ Uint32 (*args)(int argc, char *argv[]); const char *info; } infotable[] = { - { false,"basepage", DebugInfo_Basepage, NULL, "Show program basepage info at given
" }, - { false,"crossbar", DebugInfo_Crossbar, NULL, "Show Falcon crossbar HW register values" }, + { false,"aes", AES_Info, NULL, "Show AES vector contents (with , show opcodes)" }, + { false,"basepage", DebugInfo_Basepage, NULL, "Show program basepage contents at given
" }, + { false,"bios", Bios_Info, NULL, "Show BIOS opcodes" }, + { false,"blitter", Blitter_Info, NULL, "Show Blitter register contents" }, + { false,"cookiejar", DebugInfo_Cookiejar, NULL, "Show TOS Cookiejar contents" }, + { false,"crossbar", Crossbar_Info, NULL, "Show Falcon Crossbar register contents" }, { true, "default", DebugInfo_Default, NULL, "Show default debugger entry information" }, { true, "disasm", DebugInfo_CpuDisAsm, NULL, "Disasm CPU from PC or given
" }, #if ENABLE_DSP_EMU + { false, "dsp", DSP_Info, NULL, "Show misc. DSP core info (stack etc)" }, { true, "dspdisasm", DebugInfo_DspDisAsm, NULL, "Disasm DSP from given
" }, { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given
" }, - { true, "dspregs", DebugInfo_DspRegister,NULL, "Show DSP register values" }, + { true, "dspregs", DebugInfo_DspRegister,NULL, "Show DSP register contents" }, #endif + { false, "dta", DebugInfo_DTA, NULL, "Show current [or given] DTA information" }, + { true, "file", DebugInfo_FileParse, DebugInfo_FileArgs, "Parse commands from given debugger input " }, + { false,"gemdos", GemDOS_Info, NULL, "Show GEMDOS HDD emu information (with , show opcodes)" }, + { true, "history", History_Show, NULL, "Show history of last instructions" }, { true, "memdump", DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given
" }, - { false,"osheader", DebugInfo_OSHeader, NULL, "Show TOS OS header information" }, + { false,"osheader", DebugInfo_OSHeader, NULL, "Show TOS OS header contents" }, { true, "regaddr", DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show from CPU/DSP address pointed by " }, - { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register values" }, - { false,"videl", DebugInfo_Videl, NULL, "Show Falcon Videl HW register values" } + { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register contents" }, + { false,"vdi", VDI_Info, NULL, "Show VDI vector contents (with , show opcodes)" }, + { false,"videl", Videl_Info, NULL, "Show Falcon Videl register contents" }, + { false,"video", Video_Info, NULL, "Show Video information" }, + { false,"xbios", XBios_Info, NULL, "Show XBIOS opcodes" }, + { false,"ym", PSG_Info, NULL, "Show YM-2149 register contents" }, }; -static int LockedFunction = 2; /* index for the "default" function */ +static int LockedFunction = 6; /* index for the "default" function */ static Uint32 LockedArgument; /** @@ -613,7 +691,7 @@ static Uint32 LockedArgument; */ void DebugInfo_ShowSessionInfo(void) { - infotable[LockedFunction].func(LockedArgument); + infotable[LockedFunction].func(stderr, LockedArgument); } @@ -633,7 +711,7 @@ static char *DebugInfo_Match(const char i = 0; } /* next match */ - while (i++ < ARRAYSIZE(infotable)) { + while (i++ < ARRAY_SIZE(infotable)) { if (!lock && infotable[i-1].lock) { continue; } @@ -667,7 +745,7 @@ int DebugInfo_Command(int nArgc, char *p if (nArgc > 1) { cmd = psArgs[1]; /* which subcommand? */ - for (i = 0; i < ARRAYSIZE(infotable); i++) { + for (i = 0; i < ARRAY_SIZE(infotable); i++) { if (strcmp(cmd, infotable[i].name) == 0) { sub = i; break; @@ -675,7 +753,7 @@ int DebugInfo_Command(int nArgc, char *p } } - if (infotable[sub].args) { + if (sub >= 0 && infotable[sub].args) { /* value needs callback specific conversion */ value = infotable[sub].args(nArgc-2, psArgs+2); ok = !!value; @@ -694,7 +772,7 @@ int DebugInfo_Command(int nArgc, char *p if (sub < 0 || !ok) { /* no subcommand or something wrong with value, show info */ fprintf(stderr, "%s subcommands are:\n", psArgs[0]); - for (i = 0; i < ARRAYSIZE(infotable); i++) { + for (i = 0; i < ARRAY_SIZE(infotable); i++) { if (!lock && infotable[i].lock) { continue; } @@ -711,7 +789,7 @@ int DebugInfo_Command(int nArgc, char *p fprintf(stderr, "Locked %s output.\n", psArgs[1]); } else { /* do actual work */ - infotable[sub].func(value); + infotable[sub].func(stderr, value); } return DEBUGGER_CMDDONE; }