From f3072000b5b76d1b8784aaca27f63aca1af5a959 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Mon, 19 Oct 2020 22:46:53 -0400 Subject: [PATCH] Added direct console I/O and fileio to stdin & stdout to run6502 --- lib6502/file6502.c | 64 ++++++++++++++++++++++++++++++++++------------ lib6502/file6502.h | 15 +++++++++++ lib6502/run6502.c | 30 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 16 deletions(-) diff --git a/lib6502/file6502.c b/lib6502/file6502.c index f1c514c..fad2b37 100644 --- a/lib6502/file6502.c +++ b/lib6502/file6502.c @@ -196,10 +196,11 @@ static int uniocb(void) { } /* Validate Channel */ -static int valchan(int chan, char valtype) { +static int valchan(int chan, char valtype, FILE *fp) { int errnum = 0; //Error (none) if (debug) fprintf(stderr, "validating channel %d\n", chan); - if (chan > MAXIOB) errnum = 44; //Channel number out of range + if (chan == 0) {if (fp) iocbs[chan].fp = fp; else errnum = 9; } + else if (chan > MAXIOB) errnum = 44; //Channel number out of range else if (iocbs[chan].opened == 0) errnum = 9; //Bad file descriptor else if (iocbs[chan].type != valtype) { if (debug) fprintf(stderr, "invalid channel type '%c'\n", iocbs[chan].type); @@ -326,7 +327,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { chan = y; m = p & 1; t = (m) ? TDIR : TFILE; if (debug) fprintf(stderr, "closing %s channel %d\n", fdesc[m], chan); - y = valchan(chan, t); if (y) break; + y = valchan(chan, t, NULL); if (y) break; if (m) e = closedir(iocbs[chan].dp); else e = fclose(iocbs[chan].fp); if (e) y = seterror(chan, errno); else initiocb(chan); if (debug) fprintf(stderr, "channel closed\n"); @@ -334,7 +335,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { case 'D': //Read Directory - Y = Channel, CC = Entry, CS = Header chan = y; x = 0; //Return Value (Read Failed) - y = valchan(chan, TDIR); if (y) break; + y = valchan(chan, TDIR, NULL); if (y) break; if (p & 1) { if (debug) fprintf(stderr, "retrieving directory name\n"); x = writestr(mpu, iocbs[chan].name, STRLEN); @@ -347,19 +348,19 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { break; case 'E': //EOF - Y = channel chan = y; - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, NULL); if (y) break; y = feof(iocbs[chan].fp); break; case 'F': //Flush File - Y = Channel chan = y; - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, NULL); if (y) break; x = fflush(iocbs[chan].fp); if (x) y = seterror(chan, errno); break; case 'G': //Get Character - Y = channel chan = y; x = 0; //Character read (none) - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, stdin); if (y) break; c = fgetc(iocbs[chan].fp); if (feof(iocbs[chan].fp)) {y = EOF; break;} if (c == EOF) {y = seterror(chan, errno); break;} @@ -368,7 +369,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { case 'H': //Get String - Y = channel chan = y; x = 0; //Number of Characters read - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, stdin); if (y) break; char *s = fgets(filebuff, STRLEN, iocbs[chan].fp); if (s == NULL) {y = seterror(chan, errno); break;} if (debug) fprintf(stderr, "read string '%s'\n", filebuff); @@ -380,7 +381,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { break; case 'J': //Get/Put Word - Y = Channel, Carry Set = Put, Clear = Get chan = y; - a = valchan(chan, TFILE); if (y) break; + a = valchan(chan, TFILE, NULL); if (y) break; if (p & 1) { y = fileaddr >> 8; x = fileaddr & 0xFF; e = fputc(x, iocbs[chan].fp); @@ -463,7 +464,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { c = x; if (debug) fprintf(stderr, "writing '%c' to channel %d\n", c, chan); x = 0xFF; //Character written (Error) - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, stdout); if (y) break; e = fputc(c, iocbs[chan].fp); if (e == EOF) {y = seterror(chan, errno); break;} x = e & 0xFF; @@ -471,7 +472,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { case 'Q': //Put String - Y = channel, Carry Set = putline chan = y; x = 0; //Number of characters written - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, stdout); if (y) break; for (i = 0; i<128; i++) { c = mpu->memory[fileaddr+i]; if (c) filebuff[i] = c; @@ -488,7 +489,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { m = p & 1; //Set Mode: 0 = fread, 1 = fgetr chan = y; if (m) { - a = valchan(chan, TFILE); if (a) break; + a = valchan(chan, TFILE, NULL); if (a) break; if (debug) fprintf(stderr, "selecting record #%d\n", fileindx); n = iocbs[chan].recsize; i = fileindx * n; @@ -496,7 +497,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { e = fseek(iocbs[chan].fp, i, SEEK_SET); if (e) {a = seterror(chan, errno); break;} } else { - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, NULL); if (y) break; n = x; } if (debug) fprintf(stderr, "reading %d bytes\n", n); @@ -552,7 +553,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { m = p & 1; //Set Mode: 0 = fread, 1 = fgetr chan = y; if (m) { - a = valchan(chan, TFILE); if (a) break; + a = valchan(chan, TFILE, NULL); if (a) break; if (debug) fprintf(stderr, "selecting record #%d\n", fileindx); n = iocbs[chan].recsize; i = fileindx * n; @@ -562,7 +563,7 @@ extern int filecmd(M6502 *mpu, word addr, byte data) { i = ftell(iocbs[chan].fp); if (debug) fprintf(stderr, "position set to %d\n", i); } else { - y = valchan(chan, TFILE); if (y) break; + y = valchan(chan, TFILE, NULL); if (y) break; n = x; } for (i = 0; iregisters->x = x; mpu->registers->y = y; } + +/* Read Keys Directly from Console, Eliminating getc() buffering */ +extern int getkey(M6502 *mpu, word addr, byte data) { + int a = 0, y=0, x=0; //Initialize Key Press to None + int p = mpu->registers->p; + if (_kbhit()) { + y = _getch(); + if (y == 0 || y == 0xE0) { + x = _getch(); //Get Extended Code + a = x | 0x80; //Convert to High ASCII + } else { + a = y; + } + } + if (a) p = p & 0xFD; else p = p | 0x02; //Set Z Flag + if (a > 127) p = p | 0x80; else p = p & 0x7F; //Set N Flag + mpu->registers->a = a; + mpu->registers->x = x; + mpu->registers->y = y; + mpu->registers->p = p; +} + +/* Write Character Directly to Console, Eliminating putc() buffering */ +extern int putcon(M6502 *mpu, word addr, byte data) { + byte a = mpu->registers->a; + switch (a) { + case 0xD6: a = _cputs("\e[2J"); break; + default: a = _putch(a); + } + mpu->registers->a = a; +} \ No newline at end of file diff --git a/lib6502/file6502.h b/lib6502/file6502.h index cc1d372..ebe9715 100644 --- a/lib6502/file6502.h +++ b/lib6502/file6502.h @@ -96,3 +96,18 @@ extern int filecmd(M6502 *mpu, word addr, byte data); * SETTM Set Date/Time Time (Carry Set Y,X = tm Address Y=Error * * **********************************************************************************************/ extern int syscmd(M6502 *mpu, word addr, byte data); + +/********************************************************************************************** + * Read Key Directly from Console * + * Bypasses getc() from stdin, eliminating input buffering * + * Returns ASCII key value in A, extended Key Code in Y and X * + * Cursor Control Keys produce an ASCII value with the high bit set * + **********************************************************************************************/ +extern int getkey(M6502 *mpu, word addr, byte data); + +/********************************************************************************************** + * Write Character Directly to Console * + * Bypasses putc() from stdout, eliminating output buffering * + * Character Code is passed in A * + **********************************************************************************************/ +extern int putcon(M6502 *mpu, word addr, byte data); diff --git a/lib6502/run6502.c b/lib6502/run6502.c index c546c06..61a0b34 100644 --- a/lib6502/run6502.c +++ b/lib6502/run6502.c @@ -248,11 +248,13 @@ static void usage(int status) fprintf(stream, " %s [option ...] -B [image ...]\n", program); fprintf(stream, " -B -- minimal Acorn 'BBC Model B' compatibility\n"); fprintf(stream, " -d addr last -- disassemble memory between addr and last\n"); + fprintf(stream, " -C addr -- emulate _putch at addr\n"); fprintf(stream, " -D -- print debug messages\n"); fprintf(stream, " -F addr -- emulate fileio at addr\n"); fprintf(stream, " -G addr -- emulate getchar(3) at addr\n"); fprintf(stream, " -h -- help (print this message)\n"); fprintf(stream, " -I addr -- set IRQ vector\n"); + fprintf(stream, " -K addr -- emulate _getch at addr\n"); fprintf(stream, " -l addr file -- load file at addr\n"); fprintf(stream, " -m addr last -- dump memory between addr and last\n"); fprintf(stream, " -M addr -- emulate memory-mapped stdio at addr\n"); @@ -421,6 +423,32 @@ static int doStrap(int argc, char **argv, M6502 *mpu) return 1; } + +/* Emulate _putch() at addr */ +static int cTrap(M6502 *mpu, word addr, byte data) { putcon(mpu, addr, data); rts; } + +static int doCtrap(int argc, char **argv, M6502 *mpu) +{ + unsigned addr; + if (argc < 2) usage(1); + addr= htol(argv[1]); + M6502_setCallback(mpu, call, addr, cTrap); + return 1; +} + +/* Emulate _getch() at addr */ +static int kTrap(M6502 *mpu, word addr, byte data) { getkey(mpu, addr, data); rts; } + +static int doKtrap(int argc, char **argv, M6502 *mpu) +{ + unsigned addr; + if (argc < 2) usage(1); + addr= htol(argv[1]); + M6502_setCallback(mpu, call, addr, kTrap); + return 1; +} + + /* Emulate getchar(3) at addr */ static int gTrap(M6502 *mpu, word addr, byte data) { mpu->registers->a= getchar(); rts; } @@ -533,12 +561,14 @@ int main(int argc, char **argv) int n= 0; if (!strcmp(*argv, "-B")) bTraps= 1; else if (!strcmp(*argv, "-d")) n= doDisassemble(argc, argv, mpu); + else if (!strcmp(*argv, "-C")) n= doCtrap(argc, argv, mpu); else if (!strcmp(*argv, "-D")) n= doDebug(argc, argv, mpu); else if (!strcmp(*argv, "-F")) n= doFtrap(argc, argv, mpu); else if (!strcmp(*argv, "-G")) n= doGtrap(argc, argv, mpu); else if (!strcmp(*argv, "-h")) n= doHelp(argc, argv, mpu); else if (!strcmp(*argv, "-i")) n= doLoadInterpreter(argc, argv, mpu); else if (!strcmp(*argv, "-I")) n= doIRQ(argc, argv, mpu); + else if (!strcmp(*argv, "-K")) n= doKtrap(argc, argv, mpu); else if (!strcmp(*argv, "-l")) n= doLoad(argc, argv, mpu); else if (!strcmp(*argv, "-m")) n= doDump(argc, argv, mpu); else if (!strcmp(*argv, "-M")) n= doMtrap(argc, argv, mpu);