diff --git a/lib6502/file6502.c b/lib6502/file6502.c index fad2b37..c7a05ae 100644 --- a/lib6502/file6502.c +++ b/lib6502/file6502.c @@ -13,12 +13,16 @@ #include "lib6502.h" #include "file6502.h" - typedef uint8_t byte; typedef uint16_t word; int debug; +byte *xmemory[16]; //Extended Memory +byte xmembank; //Extended Memory Current Bank +word xmemaddr; //Extended Memory Current Address +word smemaddr; //System Memory Address + #define STRLEN 128 #define STRSIZ STRLEN+1 @@ -664,6 +668,106 @@ extern int syscmd(M6502 *mpu, word addr, byte data) { mpu->registers->y = y; } +/* Initialize Extended RAM */ +extern void initxmem(void) { + for (int i=0; i<16; i++) xmemory[i] = (byte *) malloc(0x10000); + xmembank = 0; + xmemaddr = 0; +} + +/* Increment Ext Memory Address and Page */ +static void xmemnext() { + xmemaddr++; + if (xmemaddr > 0xFFFF) {xmembank++; xmemaddr = 0;} + if (xmembank > 0x0F) xmembank = 0; +} + +/* Read/Write Extended Memory */ +static byte readxmem(int inc) { + byte b = xmemory[xmembank][xmemaddr]; + //if (debug) fprintf(stderr, "read byte %d from bank %02x address %04x\n", b, xmembank, xmemaddr); + if (inc) xmemnext(); + return b; +} +static void writexmem(byte b, int inc) { + //if (debug) fprintf(stderr, "writing byte %d to bank %02x address %04x\n", b, xmembank, xmemaddr); + xmemory[xmembank][xmemaddr] = b; + if (inc) xmemnext(); +} + +/* Emulate extended memory command dispatch at addr */ +extern int xmemcmd(M6502 *mpu, word addr, byte data) { + char mode[2][8] = {"reading", "writing"}; + byte a = mpu->registers->a; + byte x = mpu->registers->x; + byte y = mpu->registers->y; + byte p = mpu->registers->p; + word yx = y << 8 | x; + byte cs = (p & 1); + if (debug) fprintf(stderr, "executing ext memory command '%c' with options %02x,%02x,%02x\n", a, y, x, p); + switch(a) { + case 'A': //Get/Set Address - YX = address, CC = get, CS = set + if (cs) { + xmemaddr = yx; + if (debug) fprintf(stderr, "set extended memory address to $%04x\n", xmemaddr); + } else { + if (debug) fprintf(stderr, "returning extended memory address $%04x\n", xmemaddr); + y = xmemaddr >> 8; x = xmemaddr & 0xFF; + } + break; + case 'B': //Get/Set Bank - X/A = bank, CC = get, CS = set + if (cs) { + xmembank = x & 0x0F; + if (debug) fprintf(stderr, "set extended memory bank to $%02x\n", xmembank); + } else { + if (debug) fprintf(stderr, "returning extended memory bank $%02x\n", xmembank); + a = xmembank; + } + break; + case 'C': //Read/Write Byte w/o Increment - X/A = Byte, CC = Read, CS = Write + if (cs) writexmem(x,0); else a = readxmem(0); + break; + case 'M': //Read/Write Bytes to RAM - YX = Byte Count, CC = Read, CS = Write + if (debug) fprintf(stderr, "%s %d bytes: %02x-%04x <-> %04x\n{", mode[cs], yx, xmembank, xmemaddr, smemaddr); + for (int i=0; imemory[smemaddr], -1); + else mpu->memory[smemaddr] = readxmem(-1); + if (debug) {if (i) putc(',', stderr); fprintf(stderr, "%d", mpu->memory[smemaddr]);} + smemaddr++; if (smemaddr > 0xFFFF) smemaddr = 0; + } + if (debug) fprintf(stderr, "}\n"); + a = xmembank; y = xmemaddr >> 8; x = xmemaddr & 0xFF; + break; + case 'N': //Read/Write Next Byte - X/A = Byte, CC = Read, CS = Write + if (cs) writexmem(x,-1); else a = readxmem(-1); + break; + case 'S': //Set System RAM Address - YX = address + smemaddr = yx; + if (debug) fprintf(stderr, "set system memory address to $%04x\n", smemaddr); + break; + case 'W': //Read/Write Next Word - YX = Word, CC = Read, CS = Write + if (cs) {writexmem(x,-1); writexmem(y,-1);} + else {x = readxmem(-1); y = readxmem(-1);} + break; + case 'X': //Read/Write Bytes to RAM - YX = Byte Count, CC = Read, CS = Write + if (debug) fprintf(stderr, "swapping %d bytes: %02x-%04x <-> %04x\n{", yx, xmembank, xmemaddr, smemaddr); + for (int i=0; imemory[smemaddr]; + mpu->memory[smemaddr] = readxmem(-1); + writexmem(temp, -1); + smemaddr++; if (smemaddr > 0xFFFF) smemaddr = 0; + } + a = xmembank; y = xmemaddr >> 8; x = xmemaddr & 0xFF; + break; + default: + if (debug) fprintf(stderr, "invalid command '%x'\n", a); + } + if (debug) fprintf(stderr, "returning values %02x, %02x, %02x, %02x\n", a, y, x, p); + mpu->registers->a = a; + mpu->registers->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 @@ -693,4 +797,4 @@ extern int putcon(M6502 *mpu, word addr, byte data) { 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 ebe9715..f54cb28 100644 --- a/lib6502/file6502.h +++ b/lib6502/file6502.h @@ -7,7 +7,6 @@ typedef uint16_t word; extern void setdebug(int dbg); - /********************************************************************************************** * Process File Command * * Command passed in A and parameters in X, Y, and Carry * @@ -97,9 +96,41 @@ extern int filecmd(M6502 *mpu, word addr, byte data); **********************************************************************************************/ extern int syscmd(M6502 *mpu, word addr, byte data); +/* Initialize Extended RAM */ +extern void initxmem(void); + +/********************************************************************************************** + * Process Extended Memory Command * + * Extended Memory consists of 16 banks of 64KiB of memory, for a total of 1 MB of memory * + * not directly addressable by the 6502. * + * Memory is read and written a byte or word at a time to an 16 bit address within a bank. * + * After each read or write, the address is incremented, and at the end of a bank, the * + * address reset to zero and the next bank selected, wrapping around to bank 0 at the end. * * + * Command passed in A and parameters in X, Y, and Carry * + * 16-Bit values are passed with the MSB in Y and the LSB in X * + * Results returned in A, X, and Y * + * * + * A=Command Description Parameters Returns * + * A GETADDR Get Address (Carry Clear) Y,X=Address * + * SETADDR Set Address (Carry Set) Y,X=Address * + * B GETBANK Get Bank (Carry Clear) A=Bank * + * SETBANK Set Bank (Carry Set) X=Bank * + * C GETCHAR Read Byte (Carry Clear) A=Byte * + * PUTCHAR Write Byte (Carry Set) X=Byte * + * M GETMBLK Get Memory Block (Carry Clear) Y,X=Byte Count A,Y,X=Extended Address * + * SETMBLK Set Memory Block (Carry Set) Y,X=Byte Count A,Y,X=Extended Address * + * N GETNEXT Read Next Byte (Carry Clear) A=Byte * + * PUTNEXT Write Next Byte (Carry Set) X=Byte * + * S SYSADDR Set System RAM Address Y,X=Address * + * W GETWORD Read Next Word (Carry Clear) Y,X=Word * + * PUTWORD Write Next Word (Carry Set) Y,X=Word * + * X SWPMBLK Swap Memory Block Y,X=Byte Count A,Y,X=Extended Address * + **********************************************************************************************/ +extern int xmemcmd(M6502 *mpu, word addr, byte data); + /********************************************************************************************** * Read Key Directly from Console * - * Bypasses getc() from stdin, eliminating input buffering * + * 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 * **********************************************************************************************/ diff --git a/lib6502/run6502.c b/lib6502/run6502.c index 61a0b34..f49deab 100644 --- a/lib6502/run6502.c +++ b/lib6502/run6502.c @@ -250,6 +250,7 @@ static void usage(int status) 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, " -E addr maxpage -- emulate extended memory at addr\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"); @@ -265,7 +266,8 @@ static void usage(int status) fprintf(stream, " -s addr last file -- save memory from addr to last in file\n"); fprintf(stream, " -v -- print version number then exit\n"); fprintf(stream, " -X addr -- terminate emulation if PC reaches addr\n"); - fprintf(stream, " -x -- exit wihout further ado\n"); + fprintf(stream, " -w addr \"string\" -- write string to memory at addr\n"); + fprintf(stream, " -x -- exit without further ado\n"); fprintf(stream, " image -- '-l 8000 image' in available ROM slot\n"); fprintf(stream, "\n"); fprintf(stream, "'last' can be an address (non-inclusive) or '+size' (in bytes)\n"); @@ -380,6 +382,26 @@ static int doSave(int argc, char **argv, M6502 *mpu) /* -l addr size file */ return 3; } +static int doArgs(int argc, char **argv, M6502 *mpu) /* -a addr */ +{ + return 1; +} + +static int doWrite(int argc, char **argv, M6502 *mpu) /* -a addr "string" */ +{ + int addr = htol(argv[1]); + int size = strlen(argv[2]); + char *args = malloc(size); + strcpy(args, argv[1]); + write(mpu, addr, size, args); + return 2; +} + +static int write(M6502 *mpu, word address, int size, char *s) +{ + for (int i=0; imemory[address++] = s[i]; + return address; +} #define doVEC(VEC) \ static int do##VEC(int argc, char **argv, M6502 *mpu) \ @@ -397,6 +419,20 @@ doVEC(RST); #undef doVEC +static int eTrap(M6502 *mpu, word addr, byte data) { + xmemcmd(mpu, addr, data); + rts; +} +static int doEtrap(int argc, char **argv, M6502 *mpu) +{ + unsigned addr, page; + if (argc < 2) usage(1); + addr= htol(argv[1]); + initxmem(); + M6502_setCallback(mpu, call, addr, eTrap); + return 1; +} + static int fTrap(M6502 *mpu, word addr, byte data) { filecmd(mpu, addr, data); rts; @@ -559,10 +595,12 @@ int main(int argc, char **argv) while (++argv, --argc > 0) { int n= 0; - if (!strcmp(*argv, "-B")) bTraps= 1; + if (!strcmp(*argv, "-a")) n= doArgs(argc, argv, mpu); + else 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, "-E")) n= doEtrap(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); @@ -578,6 +616,7 @@ int main(int argc, char **argv) else if (!strcmp(*argv, "-S")) n= doStrap(argc, argv, mpu); else if (!strcmp(*argv, "-s")) n= doSave(argc, argv, mpu); else if (!strcmp(*argv, "-v")) n= doVersion(argc, argv, mpu); + else if (!strcmp(*argv, "-w")) n= doWrite(argc, argv, mpu); else if (!strcmp(*argv, "-X")) n= doXtrap(argc, argv, mpu); else if (!strcmp(*argv, "-x")) exit(0); else if ('-' == **argv) usage(1);