CP/M emulator for Unix - Part 02/03
D'Arcy J.M. Cain
darcy at druid.uucp
Thu Jan 17 09:40:30 AEST 1991
Here is my CP/M emulator part 2 as mentioned in comp.os.cpm
#!/bin/sh
# this is cpm.02 (part 2 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file cpm.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> 'cpm.c' &&
X }
X
X def_drive = *entry;
X strcpy(cpm_drive[0],cpm_drive[def_drive]);
X entry[0] = entry[1] = ' ';
X tail = chop_cmd(entry);
X }
X
X if (*entry == 0)
X return(0);
X
X debug(entry);
X
X if (strcmp(entry, "DIR") == 0)
X fsystem("ls -C %s", tail);
X else if (strcmp(entry, "DUMP") == 0)
X fsystem("hd %s", tail);
X else if (strcmp(entry, "ED") == 0)
X fsystem("$EDITOR %s", tail);
X else if (strcmp(entry, "ERA") == 0)
X fsystem("rm %s", tail);
#ifdef CPM_DEBUG
X else if (strcmp(entry, "DASM") == 0)
X {
X if(++dasm_flag > 2)
X dasm_flag = 0;
X
X fprintf(stderr, "DASM is %d\r\n", dasm_flag);
X }
#endif
X else if (strcmp(entry, "SAVE") == 0)
X {
X char *fname = chop_cmd(tail);
X int p = atoi(tail);
X
X if ((p == 0) || (*fname == 0))
X fprintf(stderr, "Usage: SAVE #pages filename\r\n");
X else
X {
X if ((fp = fopen(real_name(fname), "wb")) == NULL)
X perror("\aCan't open save file");
X else
X {
X if (fwrite(ram + 256, 256, p, fp) != p)
X perror("\aCan't write to file");
X
X fclose(fp);
X }
X }
X }
X else if (strcmp(entry, "TYPE") == 0)
X {
X char *ptr;
X
X while (*tail)
X {
X ptr = tail;
X tail = chop_cmd(ptr);
X fsystem("cat %s", ptr);
X }
X }
X else if (strcmp(entry, "EXIT") == 0)
X cleanup(0);
X else
#ifdef CPM_DEBUG
X {
X time_t start = time(NULL);
X int r = run(real_name(entry));
X
X fprintf(stderr, "Run took %ld seconds\n\r", time(NULL) - start);
X return(r);
X }
#else
X return(run(real_name(entry)));
#endif
X
X return(0);
}
#endif
X
void main(int argc, char **argv)
{
#ifdef COMPILE_TEST
X /* test code useful for testing different architectures */
X int test;
X
X test = (int)(&acc);
X printf("Position of A = %d\n", (int)(&A) - test);
X printf("Position of FLAGS = %d\n", (int)(&FLAGS) - test);
X
X test = (int)(&gr);
X printf("Position of B = %d\n", (int)(&B) - test);
X printf("Position of C = %d\n", (int)(&C) - test);
X printf("Position of BC = %d\n", (int)(&BC) - test);
X printf("Position of D = %d\n", (int)(&D) - test);
X printf("Position of E = %d\n", (int)(&E) - test);
X printf("Position of DE = %d\n", (int)(&DE) - test);
X printf("Position of H = %d\n", (int)(&H) - test);
X printf("Position of L = %d\n", (int)(&L) - test);
X printf("Position of HL = %d\n", (int)(&HL) - test);
X
X AF = 0x1234;
X printf("AF = %04.4x, A = %02.2x, FLAGS = %02.2x\n", AF, A, FLAGS);
X printf("Flags: S=%d Z=%d H=%d P=%d N=%d C=%d\n",
X SIGN, ZERO, HALF_CARRY, PARITY, BCD, CARRY);
X acc_bank = 1;
X AF = 0x4321;
X printf("AF = %04.4x, A = %02.2x, FLAGS = %02.2x\n", AF, A, FLAGS);
X printf("Flags: S=%d Z=%d H=%d P=%d N=%d C=%d\n",
X SIGN, ZERO, HALF_CARRY, PARITY, BCD, CARRY);
X
X BC = 0x2345;
X printf("BC = %04.4x, B = %02.2x, C = %02.2x\n", BC, B, C);
X gr_bank = 1;
X BC = 0x5432;
X printf("BC = %04.4x, B = %02.2x, C = %02.2x\n", BC, B, C);
X gr_bank = 0;
X
X DE = 0x3456;
X printf("DE = %04.4x, D = %02.2x, E = %02.2x\n", DE, D, E);
X gr_bank = 1;
X DE = 0x6543;
X printf("DE = %04.4x, D = %02.2x, E = %02.2x\n", DE, D, E);
X gr_bank = 0;
X
X HL = 0x4567;
X printf("HL = %04.4x, H = %02.2x, L = %02.2x\n", HL, H, L);
X gr_bank = 1;
X HL = 0x7654;
X printf("HL = %04.4x, H = %02.2x, L = %02.2x\n", HL, H, L);
X gr_bank = 0;
X
X A = BC = DE = HL = SP = PC = 0;
X
X while (PC < TEST_SIZE)
X {
X dump_registers(stdout);
X
X if (decode())
X {
X printf("* * * Processor error * * *\n");
X exit(1);
X }
X }
X
X dump_registers(stdout);
X
X for (test = 0; test < 0x10; test++)
X printf("%02.2x ", ram[test]);
X
X printf("\n");
X for (test = 0xfff0; test < 0x10000; test++)
X printf("%02.2x ", ram[test]);
X
X printf("\nTest code ended normally\n");
X exit(0);
#else
X
X char entry[256];
X int c;
X
X getcwd(cpm_drive[1], 127);
X entry[0] = 0;
X debug("");
X
X while ((c = getopt(argc, argv, "d:c:r:p:h")) != -1)
X {
X char *ptr;
X int k;
X
X switch (c)
X {
X case 'd':
X ptr = optarg + 2;
X
X if (optarg[1] == ':')
X k = toupper(*optarg) - '@';
X else
X {
X k = 1;
X ptr = optarg;
X
X while ((k < 17) && (*cpm_drive[k]))
X k++;
X }
X
X if ((k < 1) || (k > 16))
X {
X fprintf(stderr, "Can't set up %s\n", optarg);
X exit(1);
X }
X
X strcpy(cpm_drive[k], ptr);
X break;
X
X case 'c':
X strcpy(entry, optarg);
X break;
X
X case 'r':
X reader = open_device(optarg, "r");
X break;
X
X case 'p':
X punch = open_device(optarg, "w");
X break;
X
X case 'l':
X list = open_device(optarg, "w");
X break;
X
X default:
X fprintf(stderr,
"Usage:\n");
X fprintf(stderr,
"cpm [options]\n");
X fprintf(stderr,
" Options:\n");
X fprintf(stderr,
" -d [d:]directory map CP/M drive to Unix directory. If the\n");
X fprintf(stderr,
" second character is not a colon then the next\n");
X fprintf(stderr,
" available drive letter is used otherwise the\n");
X fprintf(stderr,
" letter preceding the colon is used.\n");
X fprintf(stderr,
" -c command runs the command file then exits. builtins\n");
X fprintf(stderr,
" not supported. COM file must exist\n");
X fprintf(stderr,
" -[r|p|l] dev This allows the I/O to be routed through the\n");
X fprintf(stderr,
" Unix file system. The devices mapped are as\n");
X fprintf(stderr,
" follows: r = RDR input, p = PUN output and l for\n");
X fprintf(stderr,
" LST output. The dev argument is opened as a Unix\n");
X fprintf(stderr,
" file and I/O for specified device is done through\n");
X fprintf(stderr,
" it. If the first character is '!' then the rest\n");
X fprintf(stderr,
" of the line is taken as a command and popen() is\n");
X fprintf(stderr,
" called to handle the I/O.\n");
X fprintf(stderr,
" -h Show this help screen\n");
X
X exit(1);
X }
X }
X
X strcpy(cpm_drive[0], cpm_drive[1]);
X def_drive = 1;
X
X if ((console = open("/dev/tty", O_RDWR)) == -1)
X {
X perror("Can't open terminal");
X exit(1);
X }
X
X if (ioctl(console, TCGETA, &old_term) == -1)
X {
X perror("Can't get terminal parameters");
X exit(-1);
X }
X
X termp = old_term;
X termp.c_oflag = 0;
X termp.c_lflag = ISIG;
X termp.c_cc[VEOF] = 1;
X termp.c_cc[VSWTCH] = 0xff;
X
X if (ioctl(console, TCSETA, &termp) == -1)
X {
X perror("Can't set terminal parameters");
X exit(1);
X }
X
X signal(SIGHUP, cleanup);
X signal(SIGINT, cleanup);
X signal(SIGQUIT, cleanup);
X signal(SIGTERM, cleanup);
X debug("Signals captured");
X
X setbuf(stdout, NULL);
X
X fprintf(stderr, "\nCP/U - Control Program for Unix\r\n");
X fprintf(stderr, "CP/M emulator Version 0.900\r\n");
X fprintf(stderr, "Written by D'Arcy J.M. Cain\r\n");
X fprintf(stderr, "darcy at druid.UUCP\r\n");
X
X if (*entry)
X {
X do_command(entry);
X ioctl(console, TCSETA, &old_term);
X exit(0);
X }
X
X debug("Start main loop");
X
X for (;;)
X {
X fprintf(stderr, "%c> ", def_drive + '@');
X entry[get_str(entry, 128)] = 0;
X
X if (*entry)
X {
X if (do_command(entry) == -1)
X {
X debug("chop_cmd(entry)");
X chop_cmd(entry);
X debug("strtoup(entry)");
X strtoup(entry);
X debug("fprintf(stderr, \"%s?\r\n\", entry)");
X fprintf(stderr, "%s?\r\n", entry);
X }
X }
X }
#endif
}
SHAR_EOF
chmod 0640 cpm.c ||
echo 'restore of cpm.c failed'
Wc_c="`wc -c < 'cpm.c'`"
test 26734 -eq "$Wc_c" ||
echo 'cpm.c: original size 26734, current size' "$Wc_c"
# ============= dasm.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'dasm.c' &&
/*
dasm
X
CP/M emulator - instruction disassembler
Written by D'Arcy J.M. Cain
darcy at druid
X
*/
X
#include <stdio.h>
#include <string.h>
#include "cpm.h"
X
#define get_prog_word(buf) (buf[1] + (buf[2] << 8))
#define get_prog_byte(buf) (*buf)
X
static char *get_b_reg(int reg)
{
X switch(reg & 0x07)
X {
X case 7: return("A");
X case 6: return("(HL)");
X case 0: return("B");
X case 1: return("C");
X case 2: return("D");
X case 3: return("E");
X case 4: return("H");
X case 5: return("L");
X }
X
X return(NULL);
}
X
static char *get_w_reg(int reg)
{
X switch (reg & 0x03)
X {
X case 2: return("HL");
X case 1: return("DE");
X case 0: return("BC");
X case 3: return("SP");
X }
X
X return(NULL);
}
X
static char *get_s_reg(int reg)
{
X switch (reg & 0x03)
X {
X case 2: return("HL");
X case 1: return("DE");
X case 0: return("BC");
X case 3: return("AF");
X }
X
X return(NULL);
}
X
static int relative(int r)
{
X if (r & 0x80)
X r |= -256;
X
X return(PC + r + 2);
}
X
static char *condition(int word)
{
X switch (word & 0x07)
X {
X case 0: return("NZ");
X case 1: return("Z");
X case 2: return("NC");
X case 3: return("C");
X case 4: return("PO");
X case 5: return("PE");
X case 6: return("P");
X case 7: return("M");
X }
X
X return("\a* * * Internal error (condition()) * * *");
}
X
const char *dasm(const byte *buf)
{
X static char str[32];
X char s[32];
X
X switch (*buf & 0xc0) /* get class of opcode */
X {
X case 0x40: /* data transfer */
X if (*buf == 0x76) /* HALT - special case */
X return("HALT");
X
X sprintf(str, "LD\t%s, %s", get_b_reg(*buf >> 3), get_b_reg(*buf));
X return(str);
X
X case 0x80: /* 8 bit math & logic */
X strcpy(s, get_b_reg(*buf));
X strcpy(str, "* * * Internal error * * *");
X
math_immediate: /* comes from misc instructions */
X switch ((*buf >> 3) & 7) /* logic op */
X {
X case 1: /* ADC */
X sprintf(str, "ADC\tA, %s", s);
X break;
X
X case 0: /* ADD */
X sprintf(str, "ADD\tA, %s", s);
X break;
X
X case 3: /* SBC */
X sprintf(str, "SBC\tA, %s", s);
X break;
X
X case 2: /* SUB */
X sprintf(str, "SUB\tA, %s", s);
X break;
X
X case 4: /* AND */
X sprintf(str, "AND\tA, %s", s);
X break;
X
X case 5: /* XOR */
X sprintf(str, "XOR\tA, %s", s);
X break;
X
X case 6: /* OR */
X sprintf(str, "OR\tA, %s", s);
X break;
X
X case 7: /* CP */
X sprintf(str, "CP\tA, %s", s);
X break;
X } /* end - logic op */
X
X return(str);
X
X case 0xc0: /* Misc */
X if ((*buf & 0x07) == 0x06)
X {
X sprintf(s, "0%02.2xH", buf[1]);
X goto math_immediate; /* sometimes they're necessary */
X }
X
X if ((*buf & 0x0f) == 1) /* POP */
X {
X sprintf(str, "POP\t%s", get_s_reg(*buf >> 4));
X return(str);
X }
X
X if ((*buf & 0x0f) == 5) /* PUSH */
X {
X sprintf(str, "PUSH\t%s", get_s_reg(*buf >> 4));
X return(str);
X }
X
X
X switch (*buf & 0x07) /* BRANCH */
X {
X case 0: /* RET cc */
X sprintf(str, "RET\t%s", condition(*buf >> 3));
X return(str);
X
X case 2: /* JP cc */
X sprintf(str, "JP\t%s, 0%02.2x%02.2xH",
X condition(*buf >> 3), buf[2], buf[1]);
X return(str);
X
X case 4: /* CALL cc */
X sprintf(str, "CALL\t%s, 0%02.2x%02.2xH",
X condition(*buf >> 3), buf[2], buf[1]);
X return(str);
X
X case 7: /* RST n */
X sprintf(str, "RST\t%d", (*buf >> 3) & 0x07);
X return(str);
X } /* end - BRANCH */
X
X switch (*buf) /* misc */
X {
X case 0xcd: /* CALL */
X sprintf(str, "CALL\t0%02.2x%02.2xH", buf[2], buf[1]);
X return(str);
X
X case 0xc3: /* JP */
X sprintf(str, "JP\t0%02.2x%02.2xH", buf[2], buf[1]);
X return(str);
X
X case 0xc9: /* RET */
X sprintf(str, "RET");
X return(str);
X
X case 0xeb: /* EX DE, HL */
X return("EX\tDE, HL");
X
X case 0xe9: /* JP (HL) */
X return("JP\t(HL)");
X
X case 0xe3: /* EX (SP), HL */
X return("EX\t(SP), HL");
X
X case 0xf9: /* LD SP, HL */
X return("LD\tSP, HL");
X
X case 0xf3: /* DI */
X return("DI");
X
X case 0xfb: /* EI */
X return("EI");
X } /* misc */
X
X sprintf(str, "Unrecognized command (0x%02.2x)", *buf);
X return(str);
X
X case 0:
X switch (*buf & 0x07) /* misc data (3) */
X {
X case 4: /* INC byte */
X sprintf(str, "INC\t%s", get_b_reg(*buf >> 3));
X return(str);
X
X case 5: /* DEC byte */
X sprintf(str, "DEC\t%s", get_b_reg(*buf >> 3));
X return(str);
X
X case 6: /* LD byte immediate */
X sprintf(str, "LD\t%s, 0%02.2xH",
X get_b_reg(*buf >> 3), buf[1]);
X return(str);
X } /* end - misc data (3) */
X
X switch (*buf & 0x0f) /* misc data (4) */
X {
X case 1: /* LD word immediate */
X sprintf(str, "LD\t%s, 0%02.2x%02.2xH",
X get_w_reg(*buf >> 4), buf[2], buf[1]);
X return(str);
X
X case 0x03: /* INC word */
X sprintf(str, "INC\t%s", get_w_reg(*buf >> 4));
X return(str);
X
X case 0x0b: /* DEC word */
X sprintf(str, "DEC\t%s", get_w_reg(*buf >> 4));
X return(str);
X
X case 0x09: /* ADD HL, ss */
X sprintf(str, "ADD\tHL, %s", get_w_reg(*buf >> 4));
X return(str);
X } /* end - misc date (4) */
X
X switch (*buf) /* misc data */
X {
X case 0: /* NOP */
X return("NOP");
X
X case 0x02: /* LD (BC), A */
X return("LD\t(BC), A");
X
X case 0x10:
X sprintf(str, "DJNZ\t0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x20:
X sprintf(str, "JR\tNZ, 0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x30:
X sprintf(str, "JR\tNC, 0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x18:
X sprintf(str, "JR\t, 0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x28:
X sprintf(str, "JR\tZ, 0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x38:
X sprintf(str, "JR\tC, 0%04.4xH", relative(buf[1]));
X return(str);
X
X case 0x12: /* LD (DE), A */
X return("LD\t(DE), A");
X
X case 0x22: /* LD (nn), HL */
X sprintf(str, "LD\t(0%02.2x%02.2xH), HL", buf[2], buf[1]);
X return(str);
X
X case 0x32: /* LD (nn), A */
X sprintf(str, "LD\t(0%02.2x%02.2xH), A", buf[2], buf[1]);
X return(str);
X
X case 0x0a: /* LD A, (BC) */
X return("LD\tA, (BC)");
X
X case 0x1a: /* LD A, (DE) */
X return("LD\tA, (DE)");
X
X case 0x2a: /* LD HL, (nn) */
X sprintf(str, "LD\tHL, (0%02.2x%02.2xH)", buf[2], buf[1]);
X return(str);
X
X case 0x3a: /* LD A, (nn) */
X sprintf(str, "LD\tA, (0%02.2x%02.2xH)", buf[2], buf[1]);
X return(str);
X
X case 7: /* RLCA */
X return("RLCA");
X
X case 0x0f: /* RRCA */
X return("RRCA");
X
X case 0x17: /* RLA */
X return("RLA");
X
X case 0x1f: /* RRA */
X return("RRA");
X
X case 0x27: /* DAA */
X return("DAA");
X
X case 0x2f: /* CPL */
X return("CPL");
X
X case 0x37: /* SCF */
X return("SCF");
X
X case 0x3f: /* CCF */
X return("CCF");
X } /* end - misc date */
X
X return("* * * Internal error * * *");
X } /* end class */
X
X return("* * * Internal error * * *");
}
SHAR_EOF
chmod 0640 dasm.c ||
echo 'restore of dasm.c failed'
Wc_c="`wc -c < 'dasm.c'`"
test 7099 -eq "$Wc_c" ||
echo 'dasm.c: original size 7099, current size' "$Wc_c"
# ============= decode.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'decode.c' &&
/*
X * execute()
X *
X * There are 256 possible opcodes. The switch statement selects one.
X * $Header: /g/zmob/zrun/RCS/execute.c,v 1.1.1.5 84/04/19 17:51:14 bennet Exp $
X */
X
#include "cpm.h"
X
static byte partab[256]= /* Parity table, 1=even */
{
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,
X 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,
};
X
static byte setmask[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
static byte resmask[] = { ~1, ~2, ~4, ~8, ~16, ~32, ~64, ~128 };
X
int pop(void)
{
X long r = ram[SP++];
X return(r + (ram[SP++] << 8));
}
X
void push(int v)
{
X ram[--SP] = v >> 8;
X ram[--SP] = v & 0xff;
}
X
int decode(void)
{
X byte *ptr;
X long a, s, s1;
X byte opcode = ram[PC++];
X
X if (PC >= BDOS)
X {
X PC = pop();
X return(0);
X }
X
X switch(opcode)
X {
X case 0: /* 00 NOP */
X when 1: /* 01 LD BC,nn */
X C = ram[PC++];
X B = ram[PC++];
X when 2: /* 02 LD (BC),A */
X ram[BC] = A;
X when 3: /* 03 INC BC */
X ++BC;
X when 4: /* 04 INC B */
X HALF_CARRY = (lonyb(B) == 0xf);
X ++B;
X SIGN = B >> 7;
X ZERO = B == 0;
X PARITY = B == 0x80;
X BCD = 0;
X when 5: /* 05 DEC B */
X HALF_CARRY = lonyb(B) != 0;
X --B;
X SIGN = B >> 7;
X ZERO = B == 0;
X PARITY = B == 0x7f;
X BCD = 1;
X when 6: /* 06 LD B,n */
X B = ram[PC++];
X when 7: /* 07 RLCA */
X HALF_CARRY = BCD = 0;
X CARRY = A >> 7;
X A = (A << 1);
X if (CARRY) ++A;
X when 8: /* 08 EX AF,AF' */
X acc_bank = acc_bank ? 0 : 1;
X when 9: /* 09 ADD HL,BC */
X s = BC;
X a = (HL & 0xfff) + (s & 0xfff);
X s += HL;
X HL = s;
X BCD = 0;
X CARRY = s >> 16;
X HALF_CARRY = a >> 12;
X when 10: /* 0a LD A,(BC) */
X A = ram[BC];
X when 11: /* 0b DEC BC */
X --BC;
X when 12: /* 0c INC C */
X HALF_CARRY = lonyb(C) == 0xf;
X ++C;
X SIGN = C >> 7;
X ZERO = C == 0;
X PARITY = C == 0x80;
X BCD = 0;
X when 13: /* 0d DEC C */
X HALF_CARRY = lonyb(C) != 0;
X --C;
X SIGN = C >> 7;
X ZERO = C == 0;
X PARITY = C == 0x7f;
X BCD = 1;
X when 14: /* 0e LD C,n */
X C = ram[PC++];
X when 15: /* 0f RRCA */
X BCD = HALF_CARRY = 0;
X CARRY = A;
X A = (A >> 1) | (CARRY ? 128 : 0);
X when 16: /* 10 DJNZ e */
X s = (int)(ram[PC++]);
X if (--B) PC += s;
X when 17: /* 11 LD DE,nn */
X E = ram[PC++];
X D = ram[PC++];
X when 18: /* 12 LD (DE),A */
X ram[DE] = A;
X when 19: /* 13 INC DE */
X ++DE;
X when 20: /* 14 INC D */
X HALF_CARRY = lonyb(D) == 0xf;
X ++D;
X SIGN = D >> 7;
X ZERO = D == 0;
X PARITY = D == 0x80;
X BCD = 0;
X when 21: /* 15 DEC D */
X HALF_CARRY = lonyb(D) != 0;
X --D;
X SIGN = D >> 7;
X ZERO = D == 0;
X PARITY = D == 0x7f;
X BCD = 1;
X when 22: /* 16 LD D,n */
X D = ram[PC++];
X when 23: /* 17 RLA */
X s = A << 1;
X A = s | CARRY;
X CARRY = s >> 8;
X BCD = HALF_CARRY = 0;
X when 24: /* 18 JR e */
X PC += (int)(ram[PC]);
X when 25: /* 19 ADD HL,DE */
X s = DE;
X a = (HL & 0xfff) + (s & 0xfff);
X s += HL;
X HL = s;
X BCD = 0;
X CARRY = s >> 16;
X HALF_CARRY = a >> 12;
X when 26: /* 1a LD A,(DE) */
X A = ram[DE];
X when 27: /* 1b DEC DE */
X --DE;
X when 28: /* 1c INC E */
X HALF_CARRY = lonyb(E) == 0xf;
X ++E;
X SIGN = E >> 7;
X ZERO = E == 0;
X PARITY = E == 0x80;
X BCD = 0;
X when 29: /* 1d DEC E */
X HALF_CARRY = lonyb(E) != 0;
X --E;
X SIGN = E >> 7;
X ZERO = E == 0;
X PARITY = E == 0x7f;
X BCD = 1;
X when 30: /* 1e LD E,n */
X E = ram[PC++];
X when 31: /* 1f RRA */
X CARRY = (s = A | (CARRY << 8));
X A = s >> 1;
X BCD = HALF_CARRY = 0;
X when 32: /* 20 JR NZ,e */
X if (ZERO) ++PC;
X else PC += (int)(ram[PC]);
X when 33: /* 21 LD HL,nn */
X L = ram[PC++];
X H = ram[PC++];
X when 34: /* 22 LD (nn),HL */
X TEMPL = ram[PC++];
X TEMPH = ram[PC++];
X ram[TEMP] = L;
X ram[TEMP + 1] = H;
X when 35: /* 23 INC HL */
X ++HL;
X when 36: /* 24 INC H */
X HALF_CARRY = lonyb(H) == 0xf;
X ++H;
X SIGN = H >> 7;
X ZERO = H == 0;
X PARITY = H == 0x80;
X BCD = 0;
X when 37: /* 25 DEC H */
X HALF_CARRY = lonyb(H) != 0;
X --H;
X SIGN = H >> 7;
X ZERO = H == 0;
X PARITY = H == 0x7f;
X BCD = 1;
X when 38: /* 26 LD H,n */
X H = ram[PC++];
X when 39: /* 27 DAA */
X s = A & 0x0f;
X a = (A >> 4) & 0x0f;
X s1 = 0;
X
X if (BCD)
X {
X if (CARRY)
X {
X if (HALF_CARRY)
X s1 = ((a > 5) && (s > 5)) ? 0x9a : 0;
X else
X s1 = ((a > 6) && (s < 10)) ? 0xa0 : 0;
X }
X else
X if(HALF_CARRY)
X s1 = ((a < 9) && (s > 5)) ? 0xfa : 0;
X }
X else
X {
X if (CARRY)
X {
X if(HALF_CARRY)
X s1 = ((a < 4) && (s < 4)) ? 0x66 : 0;
X else if (a < 3)
X s1 = (s < 10) ? 0x60 : 0x66;
X }
X else
X {
X if(HALF_CARRY)
X {
X if (s < 4)
X if (a > 9)
X {
X s1 = 0x66;
X CARRY = 1;
X }
X else s1 = 0x06;
X }
X else
X {
X if ((a > 8) && (s > 9))
X {
X s1 = 0x66;
X CARRY = 1;
X }
X else if ((a > 9) && (s < 10))
X {
X s1 = 0x60;
X CARRY = 1;
X }
X else if ((a < 10) && (s < 10))
X ;
X else if ((a < 9) && (s > 9))
X s1 = 6;
X }
X }
X }
X
X HALF_CARRY = ((int)(A) + (int)(s1)) > 0xf;
X A += s1;
X SIGN = A >> 7;
X ZERO = (A == 0);
X PARITY = partab[A];
X when 40: /* 28 JR Z,e */
X if (ZERO) PC += (int)(ram[PC]);
X else ++PC;
X when 41: /* 29 ADD HL,HL */
X s = HL;
X a = (HL & 0xfff) + (s & 0xfff);
X s += HL;
X HL = s;
X BCD = 0;
X CARRY = s >> 16;
X HALF_CARRY = a >> 12;
X when 42: /* 2a LD HL,(nn) */
X TEMPL = ram[PC++];
X TEMPH = ram[PC++];
X L = ram[TEMP];
X H = ram[TEMP + 1];
X when 43: /* 2b DEC HL */
X --HL;
X when 44: /* 2c INC L */
X HALF_CARRY = lonyb(L) == 0xf;
X ++L;
X SIGN = L >> 7;
X ZERO = L == 0;
X PARITY = L == 0x80;
X BCD = 0;
X when 45: /* 2d DEC L */
X HALF_CARRY = lonyb(L) != 0;
X --L;
X SIGN = L >> 7;
X ZERO = L == 0;
X PARITY = L == 0x7f;
X BCD = 1;
X when 46: /* 2e LD L,n */
X L = ram[PC++];
X when 47: /* 2f CPL */
X A = ~A;
X HALF_CARRY = BCD = 1;
X when 48: /* 30 JR NC,e */
X if(CARRY) ++PC;
X else PC += (int)(ram[PC]);
X when 49: /* 31 LD SP,nn */
X SPL = ram[PC++];
X SPH = ram[PC++];
X when 50: /* 32 LD (nn),A */
X TEMPL = ram[PC++];
X TEMPH = ram[PC++];
X ram[TEMP] = A;
X when 51: /* 33 INC SP */
X ++SP;
X when 52: /* 34 INC (HL) */
X HALF_CARRY = lonyb(ram[HL]) == 0xf;
X ++ram[HL];
X SIGN = ram[HL] >> 7;
X ZERO = ram[HL] == 0;
X PARITY = ram[HL] == 0x80;
X BCD = 0;
X when 53: /* 35 DEC (HL) */
X HALF_CARRY = lonyb(ram[HL]) != 0;
X --ram[HL];
X SIGN = ram[HL] >> 7;
X ZERO = ram[HL] == 0;
X PARITY = ram[HL] == 0x7f;
X BCD = 1;
X when 54: /* 36 LD (HL),n */
X ram[HL] = ram[PC++];
X when 55: /* 37 SCF */
X HALF_CARRY = BCD = 0;
X CARRY = 1;
X when 56: /* 38 JR C,e */
X if (CARRY) PC += (int)(ram[PC]);
X else ++PC;
X when 57: /* 39 ADD HL,SP */
X s = SP;
X a = (HL & 0xfff) + (s & 0xfff);
X s += HL;
X HL = s;
X BCD = 0;
X CARRY = s >> 16;
X HALF_CARRY = a >> 12;
X when 58: /* 3a LD A,(nn) */
X TEMPL = ram[PC++];
X TEMPH = ram[PC++];
X A = ram[TEMP];
X when 59: /* 3b DEC SP */
X --SP;
X when 60: /* 3c INC A */
X HALF_CARRY = lonyb(A) == 0xf;
X ++A;
X SIGN = A >> 7;
X ZERO = A == 0;
X PARITY = A == 0x80;
X BCD = 0;
X when 61: /* 3d DEC A */
X HALF_CARRY = lonyb(A) != 0;
X --A;
X SIGN = A >> 7;
X ZERO = A == 0;
X PARITY = A == 0x7f;
X BCD = 1;
X when 62: /* 3e LD A,n */
X A = ram[PC++];
X when 63: /* 3f CCF */
X HALF_CARRY = CARRY;
X CARRY = ~CARRY;
X BCD = 0;
X when 64: /* 40 LD B,B */
X when 65: /* 41 LD B,C */
X B = C;
X when 66: /* 42 LD B,D */
X B = D;
X when 67: /* 43 LD B,E */
X B = E;
X when 68: /* 44 LD B,H */
X B = H;
X when 69: /* 45 LD B,L */
X B = L;
X when 70: /* 46 LD B, (HL) */
X B = ram[HL];
X when 71: /* 47 LD B,A */
X B = A;
X when 72: /* 48 LD C,B */
X C = B;
X when 73: /* 49 LD C,C */
X when 74: /* 4a LD C,D */
X C = D;
X when 75: /* 4b LD C,E */
X C = E;
X when 76: /* 4c LD C,H */
X C = H;
X when 77: /* 4d LD C,L */
X C = L;
X when 78: /* 4e LD C, (HL) */
X C = ram[HL];
X when 79: /* 4f LD C,A */
X C = A;
X when 80: /* 50 LD D,B */
X D = B;
X when 81: /* 51 LD D,C */
X D = C;
X when 82: /* 52 LD D,D */
X when 83: /* 53 LD D,E */
X D = E;
X when 84: /* 54 LD D,H */
X D = H;
X when 85: /* 55 LD D,L */
X D = L;
X when 86: /* 56 LD D, (HL) */
X D = ram[HL];
X when 87: /* 57 LD D,A */
X D = A;
X when 88: /* 58 LD E,B */
X E = B;
X when 89: /* 59 LD E,C */
X E = C;
X when 90: /* 5a LD E,D */
X E = D;
X when 91: /* 5b LD E,E */
X when 92: /* 5c LD E,H */
X E = H;
X when 93: /* 5d LD E,L */
X E = L;
X when 94: /* 5e LD E, (HL) */
X E = ram[HL];
X when 95: /* 5f LD E,A */
X E = A;
X when 96: /* 60 LD H,B */
X H = B;
X when 97: /* 61 LD H,C */
X H = C;
X when 98: /* 62 LD H,D */
X H = D;
X when 99: /* 63 LD H,E */
X H = E;
X when 100: /* 64 LD H,H */
X when 101: /* 65 LD H,L */
X H = L;
X when 102: /* 66 LD H, (HL) */
X H = ram[HL];
X when 103: /* 67 LD H,A */
X H = A;
X when 104: /* 68 LD L,B */
X L = B;
X when 105: /* 69 LD L,C */
X L = C;
X when 106: /* 6a LD L,D */
X L = D;
X when 107: /* 6b LD L,E */
X L = E;
X when 108: /* 6c LD L,H */
X L = H;
X when 109: /* 6d LD L,L */
X when 110: /* 6e LD L,(HL) */
X L = ram[HL];
X when 111: /* 6f LD L,A */
X L = A;
X when 112: /* 70 LD (HL),B */
X ram[HL] = B;
X when 113: /* 71 LD (HL),C */
X ram[HL] = C;
X when 114: /* 72 LD (HL),D */
X ram[HL] = D;
X when 115: /* 73 LD (HL),E */
X ram[HL] = E;
X when 116: /* 74 LD (HL),H */
X ram[HL] = H;
X when 117: /* 75 LD (HL),L */
X ram[HL] = L;
X when 118: /* 76 HALT */
X return(0x76);
X when 119: /* 77 LD (HL),A */
X ram[HL] = A;
X when 120: /* 78 LD A,B */
X A = B;
X when 121: /* 79 LD A,C */
X A = C;
X when 122: /* 7a LD A,D */
X A = D;
X when 123: /* 7b LD A,E */
X A = E;
X when 124: /* 7c LD A,H */
X A = H;
X when 125: /* 7d LD A,L */
X A = L;
X when 126: /* 7e LD A,(HL) */
X A = ram[HL];
X when 127: /* 7f LD A,A */
X when 128: /* 80 ADD A,B */
X s = B;
X goto add;
X case 129: /* 81 ADD A,C */
X s = C;
X goto add;
X case 130: /* 82 ADD A,D */
X s = D;
X goto add;
X case 131: /* 83 ADD A,E */
X s = E;
X goto add;
X case 132: /* 84 ADD A,H */
X s = H;
X goto add;
X case 133: /* 85 ADD A,L */
X s = L;
X goto add;
X case 134: /* 86 ADD A,(HL) */
X s = ram[HL];
X goto add;
X case 135: /* 87 ADD A,A */
X s = A;
X goto add;
X case 136: /* 88 ADC A,B */
X s = B;
X goto adc;
X case 137: /* 89 ADC A,C */
X s = C;
X goto adc;
X case 138: /* 8a ADC A,D */
X s = D;
X goto adc;
X case 139: /* 8b ADC A,E */
X s = E;
X goto adc;
X case 140: /* 8c ADC A,H */
X s = H;
X goto adc;
X case 141: /* 8d ADC A,L */
X s = L;
X goto adc;
X case 142: /* 8e ADC A,(HL) */
X s = ram[HL];
X goto adc;
X case 143: /* 8f ADC A,A */
X s = A;
X
adc:
X a = A & 0x0f;
X s1 = s & 0x0f;
X if (CARRY) { s++; a++; }
X goto add1;
X
add:
X a = A & 0x0f;
X s1 = s & 0x0f;
X
add1:
X BCD = 0;
X s += A;
X A = s;
X a += s1;
X
set_flags:
X CARRY = s >> 8;
X HALF_CARRY = a >> 4;
X SIGN = s >> 7;
X ZERO = s ? 0 : 1;
X PARITY = partab[A];
X
X when 144: /* 90 SUB A,B */
X s = B;
X goto sub;
X case 145: /* 91 SUB A,C */
X s = C;
X goto sub;
X case 146: /* 92 SUB A,D */
X s = D;
X goto sub;
X case 147: /* 93 SUB A,E */
X s = E;
X goto sub;
X case 148: /* 94 SUB A,H */
X s = H;
X goto sub;
X case 149: /* 95 SUB A,L */
X s = L;
X goto sub;
X case 150: /* 96 SUB A,(HL) */
X s = ram[HL];
X goto sub;
X case 151: /* 97 SUB A,A */
X s = A;
X goto sub;
X case 152: /* 98 SBC A,B */
X s = B;
X goto sbc;
X case 153: /* 99 SBC A,C */
X s = C;
X goto sbc;
X case 154: /* 9a SBC A,D */
X s = D;
X goto sbc;
X case 155: /* 9b SBC A,E */
X s = E;
X goto sbc;
X case 156: /* 9c SBC A,H */
X s = H;
X goto sbc;
X case 157: /* 9d SBC A,L */
X s = L;
X goto sbc;
X case 158: /* 9e SBC A,(HL) */
X s = ram[HL];
X goto sbc;
X when 159: /* 9f SBC A,A */
X s = A;
X
sbc:
X a = A & 0x0f;
X s1 = s & 0x0f;
X if (CARRY) { s--; a--; }
X goto sub1;
X
sub:
X a = A & 0x0f;
X s1 = s & 0x0f;
X
sub1:
X s = A - s;
X A = s;
X a -= s1;
X BCD = 1;
X goto set_flags;
X
X when 160: /* a0 AND A,B */
X s = B;
X goto and;
X case 161: /* a1 AND A,C */
X s = C;
X goto and;
X case 162: /* a2 AND A,D */
X s = D;
X goto and;
X case 163: /* a3 AND A,E */
X s = E;
X goto and;
X case 164: /* a4 AND A,H */
X s = H;
X goto and;
X case 165: /* a5 AND A,L */
X s = L;
X goto and;
X case 166: /* a6 AND A,(HL) */
X s = ram[HL];
X goto and;
X case 167: /* a7 AND A,A */
X s = A;
X
and:
X a = A & 0x0f;
X s1 = s & 0x0f;
X
X s &= A;
X A = s;
X a &= s;
X goto set_flags;
X
X when 168: /* a8 XOR A,B */
X s = B;
X goto xor;
X case 169: /* a9 XOR A,C */
X s = C;
X goto xor;
X case 170: /* aa XOR A,D */
X s = D;
X goto xor;
X case 171: /* ab XOR A,E */
X s = E;
X goto xor;
X case 172: /* ac XOR A,H */
X s = H;
X goto xor;
X case 173: /* ad XOR A,L */
X s = L;
X goto xor;
X case 174: /* ae XOR A,(HL) */
X s = ram[HL];
X goto xor;
X case 175: /* af XOR A,A */
X s = A;
X
xor:
X a = A & 0x0f;
X s1 = s & 0x0f;
X
X s ^= A;
X A = s;
X a ^= s;
X goto set_flags;
X
X when 176: /* b1 OR B */
X s = B;
X goto or;
X case 177: /* b1 OR C */
X s = C;
X goto or;
X case 178: /* b2 OR D */
X s = D;
X goto or;
X case 179: /* b3 OR E */
X s = E;
X goto or;
X case 180: /* b4 OR H */
X s = H;
X goto or;
X case 181: /* b5 OR L */
X s = L;
X goto or;
X case 182: /* b6 OR (HL) */
X s = ram[HL];
SHAR_EOF
true || echo 'restore of decode.c failed'
echo 'End of part 2, continue with part 3'
echo 3 > _shar_seq_.tmp
exit 0
--
D'Arcy J.M. Cain (darcy at druid) |
D'Arcy Cain Consulting | There's no government
West Hill, Ontario, Canada | like no government!
+1 416 281 6094 |
More information about the Alt.sources
mailing list