Annotation of hatari/src/debug/debugInfo.c, revision 1.1.1.6

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>
1.1.1.6 ! root       14: #include <ctype.h>
        !            15: 
1.1       root       16: #include "main.h"
1.1.1.4   root       17: #include "bios.h"
1.1.1.5   root       18: #include "blitter.h"
1.1       root       19: #include "configuration.h"
1.1.1.6 ! root       20: #include "crossbar.h"
1.1       root       21: #include "debugInfo.h"
                     22: #include "debugcpu.h"
                     23: #include "debugdsp.h"
                     24: #include "debugui.h"
1.1.1.5   root       25: #include "debug_priv.h"
1.1       root       26: #include "dsp.h"
                     27: #include "evaluate.h"
1.1.1.2   root       28: #include "file.h"
                     29: #include "gemdos.h"
1.1.1.3   root       30: #include "history.h"
1.1       root       31: #include "ioMem.h"
                     32: #include "m68000.h"
1.1.1.6 ! root       33: #include "psg.h"
1.1       root       34: #include "stMemory.h"
                     35: #include "tos.h"
1.1.1.2   root       36: #include "screen.h"
                     37: #include "vdi.h"
1.1       root       38: #include "video.h"
1.1.1.6 ! root       39: #include "videl.h"
1.1.1.4   root       40: #include "xbios.h"
1.1.1.6 ! root       41: #include "newcpu.h"
        !            42: #include "68kDisass.h"
1.1       root       43: 
                     44: 
                     45: /* ------------------------------------------------------------------
                     46:  * TOS information
                     47:  */
                     48: #define OS_SYSBASE 0x4F2
                     49: #define OS_HEADER_SIZE 0x30
                     50: 
                     51: #define COOKIE_JAR 0x5A0
                     52: 
                     53: #define BASEPAGE_SIZE 0x100
                     54: 
                     55: #define GEM_MAGIC 0x87654321
                     56: #define GEM_MUPB_SIZE 0xC
                     57: 
                     58: #define RESET_MAGIC 0x31415926
                     59: #define RESET_VALID 0x426
                     60: #define RESET_VECTOR 0x42A
                     61: 
                     62: #define COUNTRY_SPAIN 4
                     63: 
1.1.1.2   root       64: 
1.1       root       65: /**
1.1.1.5   root       66:  * DebugInfo_GetSysbase: get and validate system base
                     67:  * return on success sysbase address (+ set rombase), on failure return zero
1.1       root       68:  */
1.1.1.5   root       69: static Uint32 DebugInfo_GetSysbase(Uint32 *rombase)
1.1       root       70: {
                     71:        Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE);
                     72: 
                     73:        if (!STMemory_ValidArea(sysbase, OS_HEADER_SIZE)) {
1.1.1.5   root       74:                fprintf(stderr, "Invalid TOS sysbase RAM address (0x%x)!\n", sysbase);
1.1       root       75:                return 0;
                     76:        }
1.1.1.5   root       77:        /* under TOS, sysbase = os_beg = TosAddress, but not under MiNT -> use os_beg */
                     78:        *rombase = STMemory_ReadLong(sysbase+0x08);
                     79:        if (!STMemory_ValidArea(*rombase, OS_HEADER_SIZE)) {
                     80:                fprintf(stderr, "Invalid TOS sysbase ROM address (0x%x)!\n", *rombase);
                     81:                return 0;
                     82:        }
                     83:        if (*rombase != TosAddress) {
                     84:                fprintf(stderr, "os_beg (0x%x) != TOS address (0x%x), header in RAM not set up yet?\n",
                     85:                        *rombase, TosAddress);
1.1       root       86:                return 0;
                     87:        }
                     88:        return sysbase;
                     89: }
                     90: 
                     91: /**
1.1.1.5   root       92:  * DebugInfo_CurrentBasepage: get and validate currently running program basepage.
                     93:  * if given sysbase is zero, use system sysbase.
1.1       root       94:  */
1.1.1.5   root       95: static Uint32 DebugInfo_CurrentBasepage(Uint32 sysbase)
1.1       root       96: {
1.1.1.5   root       97:        Uint32 basepage;
1.1       root       98:        Uint16 osversion, osconf;
                     99: 
                    100:        if (!sysbase) {
1.1.1.5   root      101:                Uint32 rombase;
                    102:                sysbase = DebugInfo_GetSysbase(&rombase);
                    103:                if (!sysbase) {
                    104:                        return 0;
                    105:                }
1.1       root      106:        }
1.1.1.5   root      107:        osversion = STMemory_ReadWord(sysbase+0x02);
1.1       root      108:        if (osversion >= 0x0102) {
                    109:                basepage = STMemory_ReadLong(sysbase+0x28);
                    110:        } else {
                    111:                osconf = STMemory_ReadWord(sysbase+0x1C);
                    112:                if((osconf>>1) == COUNTRY_SPAIN) {
                    113:                        basepage = 0x873C;
                    114:                } else {
                    115:                        basepage = 0x602C;
                    116:                }
                    117:        }
                    118:        if (STMemory_ValidArea(basepage, 4)) {
                    119:                return STMemory_ReadLong(basepage);
                    120:        }
                    121:        fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage);
                    122:        return 0;
                    123: }
                    124: 
1.1.1.2   root      125: 
                    126: /**
1.1.1.5   root      127:  * GetBasepageValue: return basepage value at given offset in
1.1.1.2   root      128:  * TOS process basepage or zero if that is missing/invalid.
                    129:  */
1.1.1.5   root      130: static Uint32 GetBasepageValue(unsigned offset)
1.1.1.2   root      131: {
1.1.1.5   root      132:        Uint32 basepage = DebugInfo_CurrentBasepage(0);
1.1.1.2   root      133:        if (!basepage) {
                    134:                return 0;
                    135:        }
                    136:        if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) ||
                    137:            STMemory_ReadLong(basepage) != basepage) {
                    138:                fprintf(stderr, "Basepage address 0x%06x is invalid!\n", basepage);
                    139:                return 0;
                    140:        }
                    141:        return STMemory_ReadLong(basepage+offset);
                    142: }
                    143: 
                    144: /**
                    145:  * DebugInfo_GetTEXT: return current program TEXT segment address
                    146:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    147:  */
                    148: Uint32 DebugInfo_GetTEXT(void)
                    149: {
1.1.1.5   root      150:        return GetBasepageValue(0x08);
                    151: }
                    152: /**
                    153:  * DebugInfo_GetTEXTEnd: return current program TEXT segment end address
                    154:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    155:  */
                    156: Uint32 DebugInfo_GetTEXTEnd(void)
                    157: {
                    158:        Uint32 addr = GetBasepageValue(0x08);
                    159:        if (addr) {
                    160:                return addr + GetBasepageValue(0x0C) - 1;
                    161:        }
                    162:        return 0;
1.1.1.2   root      163: }
                    164: /**
                    165:  * DebugInfo_GetDATA: return current program DATA segment address
                    166:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    167:  */
                    168: Uint32 DebugInfo_GetDATA(void)
                    169: {
1.1.1.5   root      170:        return GetBasepageValue(0x010);
1.1.1.2   root      171: }
                    172: /**
                    173:  * DebugInfo_GetBSS: return current program BSS segment address
                    174:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    175:  */
                    176: Uint32 DebugInfo_GetBSS(void)
                    177: {
1.1.1.5   root      178:        return GetBasepageValue(0x18);
1.1.1.2   root      179: }
                    180: 
                    181: 
1.1       root      182: /**
                    183:  * DebugInfo_Basepage: show TOS process basepage information
                    184:  * at given address.
                    185:  */
                    186: static void DebugInfo_Basepage(Uint32 basepage)
                    187: {
                    188:        Uint8 cmdlen;
                    189:        Uint32 env;
                    190: 
                    191:        if (!basepage) {
                    192:                /* default to current process basepage */
1.1.1.5   root      193:                basepage = DebugInfo_CurrentBasepage(0);
1.1       root      194:                if (!basepage) {
                    195:                        return;
                    196:                }
                    197:        }
                    198:        fprintf(stderr, "Process basepage information:\n");
                    199:        if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) ||
                    200:            STMemory_ReadLong(basepage) != basepage) {
                    201:                fprintf(stderr, "- address 0x%06x is invalid!\n", basepage);
                    202:                return;
                    203:        }
                    204:        fprintf(stderr, "- TPA start      : 0x%06x\n", STMemory_ReadLong(basepage));
                    205:        fprintf(stderr, "- TPA end +1     : 0x%06x\n", STMemory_ReadLong(basepage+0x04));
                    206:        fprintf(stderr, "- Text segment   : 0x%06x\n", STMemory_ReadLong(basepage+0x08));
                    207:        fprintf(stderr, "- Text size      : 0x%x\n",   STMemory_ReadLong(basepage+0x0C));
                    208:        fprintf(stderr, "- Data segment   : 0x%06x\n", STMemory_ReadLong(basepage+0x10));
                    209:        fprintf(stderr, "- Data size      : 0x%x\n",   STMemory_ReadLong(basepage+0x14));
                    210:        fprintf(stderr, "- BSS segment    : 0x%06x\n", STMemory_ReadLong(basepage+0x18));
                    211:        fprintf(stderr, "- BSS size       : 0x%x\n",   STMemory_ReadLong(basepage+0x1C));
                    212:        fprintf(stderr, "- Process DTA    : 0x%06x\n", STMemory_ReadLong(basepage+0x20));
                    213:        fprintf(stderr, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24));
                    214: 
                    215:        env = STMemory_ReadLong(basepage+0x2C);
                    216:        fprintf(stderr, "- Environment    : 0x%06x\n", env);
                    217:        if (STMemory_ValidArea(env, 4096)) {
                    218:                Uint32 end = env + 4096;
                    219:                while (env < end && *(STRam+env)) {
                    220:                        fprintf(stderr, "'%s'\n", STRam+env);
                    221:                        env += strlen((const char *)(STRam+env)) + 1;
                    222:                }
                    223:        }
                    224:        cmdlen = STMemory_ReadByte(basepage+0x80);
                    225:        fprintf(stderr, "- Command argslen: %d\n", cmdlen);
                    226:        if (cmdlen) {
                    227:                int offset = 0;
                    228:                while (offset < cmdlen) {
                    229:                        fprintf(stderr, " '%s'", STRam+basepage+0x81+offset);
                    230:                        offset += strlen((const char *)(STRam+basepage+0x81+offset)) + 1;
                    231:                }
                    232:                fprintf(stderr, "\n");
                    233:        }
                    234: }
                    235: 
                    236: /**
1.1.1.5   root      237:  * DebugInfo_PrintOSHeader: output OS Header information
1.1       root      238:  */
1.1.1.5   root      239: static void DebugInfo_PrintOSHeader(Uint32 sysbase)
1.1       root      240: {
1.1.1.5   root      241:        Uint32 gemblock, basepage;
1.1.1.2   root      242:        Uint16 osversion, osconf, langbits;
                    243:        const char *lang;
                    244:        static const char langs[][3] = {
                    245:                "us", "de", "fr", "uk", "es", "it", "se", "ch" /* fr */, "ch" /* de */,
                    246:                "tr", "fi", "no", "dk", "sa", "nl", "cs", "hu"
                    247:        };
1.1       root      248: 
1.1.1.5   root      249:        osversion = STMemory_ReadWord(sysbase+0x02);
1.1       root      250:        fprintf(stderr, "OS base addr : 0x%06x\n", sysbase);
                    251:        fprintf(stderr, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C));
                    252:        fprintf(stderr, "TOS version  : 0x%x\n", osversion);
                    253: 
                    254:        fprintf(stderr, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04));
                    255:        fprintf(stderr, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR));
                    256:        fprintf(stderr, "Reset valid  : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC);
                    257: 
                    258:        gemblock = STMemory_ReadLong(sysbase+0x14);
                    259:        fprintf(stderr, "GEM Memory Usage Parameter Block:\n");
                    260:        if (STMemory_ValidArea(gemblock, GEM_MUPB_SIZE)) {
                    261:                fprintf(stderr, "- Block addr : 0x%06x\n", gemblock);
                    262:                fprintf(stderr, "- GEM magic  : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC);
                    263:                fprintf(stderr, "- GEM entry  : 0x%06x\n", STMemory_ReadLong(gemblock+4));
                    264:                fprintf(stderr, "- GEM end    : 0x%06x\n", STMemory_ReadLong(gemblock+8));
                    265:        } else {
                    266:                fprintf(stderr, "- is at INVALID 0x%06x address.\n", gemblock);
                    267:        }
                    268: 
                    269:        fprintf(stderr, "OS date      : 0x%x\n", STMemory_ReadLong(sysbase+0x14));
                    270:        fprintf(stderr, "OS DOS date  : 0x%x\n", STMemory_ReadLong(sysbase+0x1E));
                    271: 
                    272:        osconf = STMemory_ReadWord(sysbase+0x1C);
1.1.1.2   root      273:        langbits = osconf >> 1;
                    274:        if (langbits == 127) {
                    275:                lang = "all";
                    276:        } else if (langbits < ARRAYSIZE(langs)) {
                    277:                lang = langs[langbits];
                    278:        } else {
                    279:                lang = "unknown";
                    280:        }
                    281:        fprintf(stderr, "OS Conf bits : 0x%04x (%s, %s)\n", osconf, lang, osconf&1 ? "PAL":"NTSC");
1.1       root      282: 
                    283:        if (osversion >= 0x0102) {
1.1.1.2   root      284:                /* last 3 OS header fields are only available as of TOS 1.02 */
1.1       root      285:                fprintf(stderr, "Memory pool  : 0x%06x\n", STMemory_ReadLong(sysbase+0x20));
                    286:                fprintf(stderr, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24));
                    287:        } else {
1.1.1.2   root      288:                /* TOS 1.0 */
                    289:                fprintf(stderr, "Memory pool  : 0x0056FA\n");
1.1       root      290:                fprintf(stderr, "Kbshift addr : 0x000E1B\n");
                    291:        }
1.1.1.5   root      292:        basepage = DebugInfo_CurrentBasepage(sysbase);
1.1       root      293:        if (basepage) {
                    294:                fprintf(stderr, "Basepage     : 0x%06x\n", basepage);
                    295:        }
                    296: }
                    297: 
1.1.1.5   root      298: /**
                    299:  * DebugInfo_OSHeader: display TOS OS Header and RAM one
                    300:  * if their addresses differ
                    301:  */
                    302: static void DebugInfo_OSHeader(Uint32 dummy)
                    303: {
                    304:        Uint32 sysbase, rombase;
                    305: 
                    306:        sysbase = DebugInfo_GetSysbase(&rombase);
                    307:        if (!sysbase) {
                    308:                return;
                    309:        }
                    310:        fprintf(stderr, "OS header information:\n");
                    311:        DebugInfo_PrintOSHeader(sysbase);
                    312:        if (sysbase != rombase) {
                    313:                fprintf(stderr, "\nROM TOS OS header information:\n");
                    314:                DebugInfo_PrintOSHeader(rombase);
                    315:                return;
                    316:        }
                    317: }
1.1       root      318: 
1.1.1.2   root      319: /**
                    320:  * DebugInfo_Cookiejar: display TOS Cookiejar content
                    321:  */
                    322: static void DebugInfo_Cookiejar(Uint32 dummy)
                    323: {
                    324:        int items;
                    325: 
                    326:        Uint32 jar = STMemory_ReadLong(COOKIE_JAR);
                    327:        if (!jar) {
                    328:                fprintf(stderr, "Cookiejar is empty.\n");
                    329:                return;
                    330:        }
                    331: 
                    332:        fprintf(stderr, "Cookiejar contents:\n");
                    333:        items = 0;
                    334:        while (STMemory_ValidArea(jar, 8) && STMemory_ReadLong(jar)) {
                    335:                fprintf(stderr, "%c%c%c%c = 0x%08x\n",
                    336:                        STRam[jar], STRam[jar+1], STRam[jar+2], STRam[jar+3],
                    337:                        STMemory_ReadLong(jar+4));
                    338:                jar += 8;
                    339:                items++;
                    340:        }
                    341:        fprintf(stderr, "%d items at 0x%06x.\n", items, STMemory_ReadLong(COOKIE_JAR));
                    342: }
                    343: 
                    344: 
1.1       root      345: /* ------------------------------------------------------------------
                    346:  * CPU and DSP information wrappers
                    347:  */
                    348: 
                    349: /**
                    350:  * Helper to call debugcpu.c and debugdsp.c debugger commands
                    351:  */
                    352: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg)
                    353: {
                    354:        char cmdbuffer[16], argbuffer[12];
                    355:        char *argv[] = { cmdbuffer, NULL };
                    356:        int argc = 1;
                    357: 
                    358:        assert(strlen(command) < sizeof(cmdbuffer));
                    359:        strcpy(cmdbuffer, command);
                    360:        if (arg) {
                    361:                sprintf(argbuffer, "$%x", arg);
                    362:                argv[argc++] = argbuffer;
                    363:        }
                    364:        func(argc, argv);
                    365: }
                    366: 
                    367: static void DebugInfo_CpuRegister(Uint32 arg)
                    368: {
                    369:        DebugInfo_CallCommand(DebugCpu_Register, "register", arg);
                    370: }
                    371: static void DebugInfo_CpuDisAsm(Uint32 arg)
                    372: {
                    373:        DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg);
                    374: }
                    375: static void DebugInfo_CpuMemDump(Uint32 arg)
                    376: {
                    377:        DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg);
                    378: }
                    379: 
                    380: #if ENABLE_DSP_EMU
                    381: 
                    382: static void DebugInfo_DspRegister(Uint32 arg)
                    383: {
                    384:        DebugInfo_CallCommand(DebugDsp_Register, "dspreg", arg);
                    385: }
                    386: static void DebugInfo_DspDisAsm(Uint32 arg)
                    387: {
                    388:        DebugInfo_CallCommand(DebugDsp_DisAsm, "dspdisasm", arg);
                    389: }
                    390: 
                    391: static void DebugInfo_DspMemDump(Uint32 arg)
                    392: {
                    393:        char cmdbuf[] = "dspmemdump";
                    394:        char addrbuf[6], spacebuf[2] = "X";
                    395:        char *argv[] = { cmdbuf, spacebuf, addrbuf };
                    396:        spacebuf[0] = (arg>>16)&0xff;
                    397:        sprintf(addrbuf, "$%x", (Uint16)(arg&0xffff));
                    398:        DebugDsp_MemDump(3, argv);
                    399: }
                    400: 
                    401: /**
                    402:  * Convert arguments to Uint32 arg suitable for DSP memdump callback
                    403:  */
                    404: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[])
                    405: {
                    406:        Uint32 value;
                    407:        char space;
                    408:        if (argc != 2) {
                    409:                return 0;
                    410:        }
1.1.1.6 ! root      411:        space = toupper((unsigned char)argv[0][0]);
1.1       root      412:        if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) {
                    413:                fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]);
                    414:                return 0;
                    415:        }
                    416:        if (!Eval_Number(argv[1], &value) || value > 0xffff) {
                    417:                fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]);
                    418:                return 0;
                    419:        }
                    420:        return ((Uint32)space<<16) | value;
                    421: }
                    422: 
                    423: #endif  /* ENABLE_DSP_EMU */
                    424: 
                    425: 
                    426: static void DebugInfo_RegAddr(Uint32 arg)
                    427: {
                    428:        bool forDsp;
                    429:        char regname[3];
1.1.1.5   root      430:        Uint32 *reg32, regvalue, mask;
1.1       root      431:        char cmdbuf[12], addrbuf[6];
                    432:        char *argv[] = { cmdbuf, addrbuf };
                    433:        
                    434:        regname[0] = (arg>>24)&0xff;
                    435:        regname[1] = (arg>>16)&0xff;
                    436:        regname[2] = '\0';
                    437: 
1.1.1.5   root      438:        if (DebugCpu_GetRegisterAddress(regname, &reg32)) {
                    439:                regvalue = *reg32;
1.1       root      440:                mask = 0xffffffff;
                    441:                forDsp = false;
                    442:        } else {
1.1.1.5   root      443:                int regsize = DSP_GetRegisterAddress(regname, &reg32, &mask);
                    444:                switch (regsize) {
                    445:                        /* currently regaddr supports only 32-bit Rx regs, but maybe later... */
                    446:                case 16:
                    447:                        regvalue = *((Uint16*)reg32);
                    448:                        break;
                    449:                case 32:
                    450:                        regvalue = *reg32;
                    451:                        break;
                    452:                default:
1.1       root      453:                        fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", regname);
                    454:                        return;
                    455:                }
                    456:                forDsp = true;
                    457:        }
1.1.1.5   root      458:                sprintf(addrbuf, "$%x", regvalue & mask);
1.1       root      459: 
                    460:        if ((arg & 0xff) == 'D') {
                    461:                if (forDsp) {
                    462: #if ENABLE_DSP_EMU
1.1.1.5   root      463:                        strcpy(cmdbuf, "dd");
1.1       root      464:                        DebugDsp_DisAsm(2, argv);
                    465: #endif
                    466:                } else {
1.1.1.5   root      467:                        strcpy(cmdbuf, "d");
1.1       root      468:                        DebugCpu_DisAsm(2, argv);
                    469:                }
                    470:        } else {
                    471:                if (forDsp) {
                    472: #if ENABLE_DSP_EMU
1.1.1.5   root      473:                        /* use "Y" address space */
                    474:                        char cmd[] = "dm"; char space[] = "y";
                    475:                        char *dargv[] = { cmd, space, addrbuf };
                    476:                        DebugDsp_MemDump(3, dargv);
1.1       root      477: #endif
                    478:                } else {
1.1.1.5   root      479:                        strcpy(cmdbuf, "m");
1.1       root      480:                        DebugCpu_MemDump(2, argv);
                    481:                }
                    482:        }
                    483: }
                    484: 
                    485: /**
                    486:  * Convert arguments to Uint32 arg suitable for RegAddr callback
                    487:  */
                    488: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[])
                    489: {
                    490:        Uint32 value, *regaddr;
                    491:        if (argc != 2) {
                    492:                return 0;
                    493:        }
                    494: 
                    495:        if (strcmp(argv[0], "disasm") == 0) {
                    496:                value = 'D';
                    497:        } else if (strcmp(argv[0], "memdump") == 0) {
                    498:                value = 'M';
                    499:        } else {
                    500:                fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]);
                    501:                return 0;
                    502:        }
                    503: 
                    504:        if (strlen(argv[1]) != 2 ||
                    505:            (!DebugCpu_GetRegisterAddress(argv[1], &regaddr) &&
1.1.1.6 ! root      506:             (toupper((unsigned char)argv[1][0]) != 'R'
        !           507:              || !isdigit((unsigned char)argv[1][1]) || argv[1][2]))) {
1.1       root      508:                /* not CPU register or Rx DSP register */
                    509:                fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]);
                    510:                return 0;
                    511:        }
                    512:        
                    513:        value |= argv[1][0] << 24;
                    514:        value |= argv[1][1] << 16;
                    515:        value &= 0xffff00ff;
                    516:        return value;
                    517: }
                    518: 
                    519: 
                    520: /* ------------------------------------------------------------------
1.1.1.2   root      521:  * wrappers for command to parse debugger input file
                    522:  */
                    523: 
                    524: /* file name to be given before calling the Parse function,
                    525:  * needs to be set separately as it's a host pointer which
                    526:  * can be 64-bit i.e. may not fit into Uint32.
                    527:  */
                    528: static char *parse_filename;
                    529: 
                    530: /**
                    531:  * Parse and exec commands in the previously given debugger input file
                    532:  */
                    533: static void DebugInfo_FileParse(Uint32 dummy)
                    534: {
                    535:        if (parse_filename) {
1.1.1.5   root      536:                DebugUI_ParseFile(parse_filename, true);
1.1.1.2   root      537:        } else {
                    538:                fputs("ERROR: debugger input file name to parse isn't set!\n", stderr);
                    539:        }
                    540: }
                    541: 
                    542: /**
                    543:  * Set which input file to parse.
                    544:  * Return true if file exists, false on error
                    545:  */
                    546: static Uint32 DebugInfo_FileArgs(int argc, char *argv[])
                    547: {
                    548:        if (argc != 1) {
                    549:                return false;
                    550:        }
                    551:        if (!File_Exists(argv[0])) {
                    552:                fprintf(stderr, "ERROR: given file '%s' doesn't exist!\n", argv[0]);
                    553:                return false;
                    554:        }
                    555:        if (parse_filename) {
                    556:                free(parse_filename);
                    557:        }
                    558:        parse_filename = strdup(argv[0]);
                    559:        return true;
                    560: }
                    561: 
                    562: 
                    563: /* ------------------------------------------------------------------
1.1       root      564:  * Debugger & readline TAB completion integration
                    565:  */
                    566: 
                    567: /**
                    568:  * Default information on entering the debugger
                    569:  */
                    570: static void DebugInfo_Default(Uint32 dummy)
                    571: {
                    572:        int hbl, fcycles, lcycles;
1.1.1.6 ! root      573:         uaecptr nextpc, pc = M68000_GetPC();
1.1       root      574:        Video_GetPosition(&fcycles, &hbl, &lcycles);
1.1.1.6 ! root      575: 
1.1       root      576:        fprintf(stderr, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=",
1.1.1.6 ! root      577:                pc, nVBLs, fcycles, hbl, lcycles);
1.1       root      578:        if (bDspEnabled)
                    579:                fprintf(stderr, "$%x\n", DSP_GetPC());
                    580:        else
                    581:                fprintf(stderr, "N/A\n");
1.1.1.6 ! root      582: 
        !           583:        Disasm(stderr, pc, &nextpc, 1);
1.1       root      584: }
                    585: 
                    586: static const struct {
1.1.1.2   root      587:        /* if overlaps with other functionality, list only for lock command */
1.1       root      588:        bool lock;
                    589:        const char *name;
                    590:        void (*func)(Uint32 arg);
                    591:        /* convert args in argv into single Uint32 for func */
                    592:        Uint32 (*args)(int argc, char *argv[]);
                    593:        const char *info;
                    594: } infotable[] = {
1.1.1.2   root      595:        { false,"aes",       AES_Info,             NULL, "Show AES vector contents (with <value>, show opcodes)" },
1.1.1.6 ! root      596:        { false,"basepage",  DebugInfo_Basepage,   NULL, "Show program basepage contents at given <address>" },
1.1.1.4   root      597:        { false,"bios",      Bios_Info,            NULL, "Show BIOS opcodes" },
1.1.1.6 ! root      598:        { false,"blitter",   Blitter_Info,         NULL, "Show Blitter register contents" },
1.1.1.2   root      599:        { false,"cookiejar", DebugInfo_Cookiejar,  NULL, "Show TOS Cookiejar contents" },
1.1.1.6 ! root      600:        { false,"crossbar",  Crossbar_Info,        NULL, "Show Falcon Crossbar register contents" },
1.1       root      601:        { true, "default",   DebugInfo_Default,    NULL, "Show default debugger entry information" },
                    602:        { true, "disasm",    DebugInfo_CpuDisAsm,  NULL, "Disasm CPU from PC or given <address>" },
                    603: #if ENABLE_DSP_EMU
1.1.1.5   root      604:        { false, "dsp",      DSP_Info,             NULL, "Show misc. DSP core info (stack etc)" },
1.1       root      605:        { true, "dspdisasm", DebugInfo_DspDisAsm,  NULL, "Disasm DSP from given <address>" },
                    606:        { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" },
1.1.1.6 ! root      607:        { true, "dspregs",   DebugInfo_DspRegister,NULL, "Show DSP register contents" },
1.1       root      608: #endif
1.1.1.2   root      609:        { true, "file",      DebugInfo_FileParse, DebugInfo_FileArgs, "Parse commands from given debugger input <file>" },
1.1.1.6 ! root      610:        { false,"gemdos",    GemDOS_Info,          NULL, "Show GEMDOS HDD emu information (with <value>, show opcodes)" },
1.1.1.3   root      611:        { true, "history",   History_Show,         NULL, "Show history of last <count> instructions" },
1.1       root      612:        { true, "memdump",   DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" },
1.1.1.6 ! root      613:        { false,"osheader",  DebugInfo_OSHeader,   NULL, "Show TOS OS header contents" },
1.1       root      614:        { true, "regaddr",   DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" },
1.1.1.6 ! root      615:        { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register contents" },
1.1.1.2   root      616:        { false,"vdi",       VDI_Info,             NULL, "Show VDI vector contents (with <value>, show opcodes)" },
1.1.1.6 ! root      617:        { false,"videl",     Videl_Info,           NULL, "Show Falcon Videl register contents" },
        !           618:        { false,"video",     Video_Info,           NULL, "Show Video information" },
        !           619:        { false,"xbios",     XBios_Info,           NULL, "Show XBIOS opcodes" },
        !           620:        { false,"ym",        PSG_Info,             NULL, "Show YM-2149 register contents" },
1.1       root      621: };
                    622: 
1.1.1.5   root      623: static int LockedFunction = 6; /* index for the "default" function */
1.1       root      624: static Uint32 LockedArgument;
                    625: 
                    626: /**
                    627:  * Show selected debugger session information
                    628:  * (when debugger is (again) entered)
                    629:  */
                    630: void DebugInfo_ShowSessionInfo(void)
                    631: {
                    632:        infotable[LockedFunction].func(LockedArgument);
                    633: }
                    634: 
                    635: 
                    636: /**
                    637:  * Readline match callback for info subcommand name completion.
                    638:  * STATE = 0 -> different text from previous one.
                    639:  * Return next match or NULL if no matches.
                    640:  */
                    641: static char *DebugInfo_Match(const char *text, int state, bool lock)
                    642: {
                    643:        static int i, len;
                    644:        const char *name;
                    645:        
                    646:        if (!state) {
                    647:                /* first match */
                    648:                len = strlen(text);
                    649:                i = 0;
                    650:        }
                    651:        /* next match */
                    652:        while (i++ < ARRAYSIZE(infotable)) {
                    653:                if (!lock && infotable[i-1].lock) {
                    654:                        continue;
                    655:                }
                    656:                name = infotable[i-1].name;
                    657:                if (strncmp(name, text, len) == 0)
                    658:                        return (strdup(name));
                    659:        }
                    660:        return NULL;
                    661: }
                    662: char *DebugInfo_MatchLock(const char *text, int state)
                    663: {
                    664:        return DebugInfo_Match(text, state, true);
                    665: }
                    666: char *DebugInfo_MatchInfo(const char *text, int state)
                    667: {
                    668:        return DebugInfo_Match(text, state, false);
                    669: }
                    670: 
                    671: 
                    672: /**
                    673:  * Show requested command information.
                    674:  */
                    675: int DebugInfo_Command(int nArgc, char *psArgs[])
                    676: {
                    677:        Uint32 value;
                    678:        const char *cmd;
                    679:        bool ok, lock;
                    680:        int i, sub;
                    681: 
                    682:        sub = -1;
                    683:        if (nArgc > 1) {
                    684:                cmd = psArgs[1];                
                    685:                /* which subcommand? */
                    686:                for (i = 0; i < ARRAYSIZE(infotable); i++) {
                    687:                        if (strcmp(cmd, infotable[i].name) == 0) {
                    688:                                sub = i;
                    689:                                break;
                    690:                        }
                    691:                }
                    692:        }
                    693: 
1.1.1.5   root      694:        if (sub >= 0 && infotable[sub].args) {
1.1       root      695:                /* value needs callback specific conversion */
                    696:                value = infotable[sub].args(nArgc-2, psArgs+2);
                    697:                ok = !!value;
                    698:        } else {
                    699:                if (nArgc > 2) {
                    700:                        /* value is normal number */
                    701:                        ok = Eval_Number(psArgs[2], &value);
                    702:                } else {
                    703:                        value = 0;
                    704:                        ok = true;
                    705:                }
                    706:        }
                    707: 
                    708:        lock = (strcmp(psArgs[0], "lock") == 0);
                    709:        
                    710:        if (sub < 0 || !ok) {
                    711:                /* no subcommand or something wrong with value, show info */
                    712:                fprintf(stderr, "%s subcommands are:\n", psArgs[0]);
                    713:                for (i = 0; i < ARRAYSIZE(infotable); i++) {
                    714:                        if (!lock && infotable[i].lock) {
                    715:                                continue;
                    716:                        }
                    717:                        fprintf(stderr, "- %s: %s\n",
                    718:                                infotable[i].name, infotable[i].info);
                    719:                }
                    720:                return DEBUGGER_CMDDONE;
                    721:        }
                    722: 
                    723:        if (lock) {
                    724:                /* lock given subcommand and value */
                    725:                LockedFunction = sub;
                    726:                LockedArgument = value;
                    727:                fprintf(stderr, "Locked %s output.\n", psArgs[1]);
                    728:        } else {
                    729:                /* do actual work */
                    730:                infotable[sub].func(value);
                    731:        }
                    732:        return DEBUGGER_CMDDONE;
                    733: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.