/*****************************************************************************/
/*									     */
/*									     */
/*	CP/M emulator version 0.1					     */
/*									     */
/*	written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)		     */
/*	June-1994							     */
/*									     */
/*	This file is distributed under the GNU COPYRIGHT		     */
/*	see COPYRIGHT.GNU for Copyright details				     */
/*									     */
/*									     */
/*****************************************************************************/
/* this module is inoperable */

#include "cpmemu.h"

static int numbytes;

static void byte(char *s, unsigned o) {
    static char hextab[] = "0123456789abcdef";
    s[0] = hextab[o >> 4];
    s[1] = hextab[o & 15];
}

#define NBIOSCALLS	17

static int dis_sub(unsigned pc, char *s) {

    if (pc >= BIOS) {
	static const char *biosfunc[] = {
	    "COLDBOOT", "WARMBOOT", "Console Status", "Console Input",
	    "Console Output", "List Output", "Punch Output", "Reader Input",
	    "Home", "Select Disk", "Set Track", "Set Sector", "Set DMA",
	    "Read", "Write", "List Status", "Sector Translate" };
#if 0	/* here are jumps which may lead elsewhere */
	if (pc < BIOS + 3 * NBIOSCALLS && !((pc-BIOS) % 3)) {
	    sprintf(s, "BIOS %s\n", biosfunc[(pc-BIOS)/3]);
	    return 3;
	}
#endif
	if (pc >= 0xff6cU && pc < 0xff6cU+NBIOSCALLS) {
	    sprintf(s, "BIOS %s", biosfunc[pc-0xff6cU]);
	    return 1;
	}
	if (pc < BIOS + 3 * NBIOSCALLS && !((pc-BIOS) % 3))
	    ;
	else {
	    sprintf(s, "BIOS (illegal place)");
	    return 1;
	}
    }

    if ((pc == BDOS || pc == 5) && z80regs.pc == pc) {
	static const char *bdosfunc[] = {
    /* 00 */ "System Reset", "Console Input", "Console Output",
    /* 03 */ "Aux. Input", "Aux. Output", "List Output",
    /* 06 */ "Direct I/O", "Aux. Input Status", "Aux. Output Status",
    /* 09 */ "Print String", "Read Console Buffer", "Get Console Status",
    /* 12 */ "Return Version Number", "Reset Disk System",
    /* 14 */ "Select Disk", "Open File", "Close File",
    /* 17 */ "Search for First", "Search for Next", "Delete File",
    /* 20 */ "Read Sequential", "Write Sequential", "Make File",
    /* 23 */ "Rename File",    "Return Login Vector", "Return Current Disk",
    /* 26 */ "Set DMA Address", "Get Addr(Alloc)", "Write Protect Disk",
    /* 29 */ "Get R/O-Vector", "Set File Attributes", "Get Addr. of DPB",
    /* 32 */ "Set/Get User Code", "Read Random", "Write Random",
    /* 35 */ "Compute File Size", "Set Random Record", "Reset Drive",
    /* 38 */ "Access Drive", "Free Drive", "Write Random with Zero Fill",
    /* 41 */ "Change directory (extension)" };

	if ((z80regs.bc & 0xff) < sizeof(bdosfunc) / sizeof(bdosfunc[0]))
            sprintf(s, "BDOS %s, arg %04x", bdosfunc[z80regs.bc & 0xff],
		    z80regs.de);
        else
            sprintf(s, "BDOS (0x%02x), arg %04x", z80regs.bc & 0xff,
		    z80regs.de);
        return 3;
    }
    {   unsigned const char *PC;
	PC = disz80(z80mem+pc, s, pc);
	if (!(PC - z80mem - pc)) {
	    sprintf(s, "unknown");
	    return 1;
	}
	return PC - z80mem - pc;
    }
}

static char *disassemble(unsigned pc) {
    static char s[60];
    int i;
    numbytes = dis_sub(pc, s+12);
    memset(s, ' ', 12);
    for (i = 0; i < numbytes; ++i)
	byte(s+3*i, z80mem[pc+i]);
    return s;
}

void disassem(unsigned *loc, int num) {
    while (num--) {
	printf("%04x %s\n", *loc, disassemble(*loc));
	*loc = (*loc + numbytes) & 0xffff;
    }
}

static char *flags(unsigned f) {
    static char s[10];
    const char *fl = "SZ0H0VNC";
    int i;
    strcpy(s, "        ");
    for (i = 0; i < 8; ++i) {
        if (f & 0x80)
            s[i] = fl[i];
        f <<= 1;
    }
    return s;
}

void dispregs(unsigned pc) {
    printf("%s A=%02x BC=%04x DE=%04x HL=%04x SP=%04x PC=%04x  %s\n",
	   flags(z80regs.af >> 8), z80regs.af & 0xff,
	   z80regs.bc, z80regs.de, z80regs.hl, z80regs.sp,
	   pc, disassemble(pc));
    fflush(stdout);
}

void dispregs2(void) {
    printf("%s a=%02x bc=%04x de=%04x hl=%04x IX=%04x IY=%04x  I=%02x R=%02x\n",
	   flags(z80regs.af2 >> 8), z80regs.af2 & 0xff,
	   z80regs.bc2, z80regs.de2, z80regs.hl2, z80regs.ix, z80regs.iy, z80regs.ir >> 8, z80regs.ir & 0xff);
    fflush(stdout);
}

void memdump(unsigned addr, int lines) {
    int i, j;
    for (i = 0; i < lines; ++i) {
	printf("%04x ", addr);
	for (j = 0; j < 16; ++j) {
	    if (j == 8)
		printf(" -");
	    printf(" %02x", z80mem[addr+j]);
	}
	printf("  ");
	for (j = 0; j < 16; ++j) {
	    if (j == 8)
		printf(" ");
	    printf("%c", z80mem[addr+j] < ' ' ? '.' : z80mem[addr+j]);
	}
	printf("\n");
	addr += 16;
    }
}
