diff --git a/lib6502/file6502.c b/lib6502/file6502.c new file mode 100644 index 0000000..f390544 --- /dev/null +++ b/lib6502/file6502.c @@ -0,0 +1,460 @@ +/* file6502.c - File I/O Command Processor for run6502.c */ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "lib6502.h" +#include "file6502.h" + + +typedef uint8_t byte; +typedef uint16_t word; + +int debug; + +/* I/O Blocks for File I/O */ +#define MAXIOB 15 +#define STRLEN 128 +struct iocb +{ + int opened; //Flag: file opened + char type; //Channel Type: 'F', 'D' + char mode; //File Mode: 'R', 'W' + int recsize; //Record Size (0=None) + FILE *fp; //File Pointer + DIR *dp; //Directory Pointer + int errnum; //Last Error Number + char name[STRLEN]; //File/Directory Name +}; + +static struct iocb iocbs[MAXIOB]; +static char filename[STRLEN]; //File name for open +static char filebuff[256]; //File I/O Buffer +static word fileaddr; //File Read/Write Address +static word fileindx; //File Record Size/Number + +extern void setdebug(int dbg) { + debug = dbg; +} + +static int save(M6502 *mpu, word address, unsigned length, const char *path) +{ + FILE *file= 0; + int count= 0; + if (!(file= fopen(path, "wb"))) + return 0; + while ((count= fwrite(mpu->memory + address, 1, length, file))) + { + address += count; + length -= count; + } + fclose(file); + return address; +} + + +static int load(M6502 *mpu, word address, const char *path) +{ + FILE *file= 0; + int count= 0; + size_t max= 0x10000 - address; + if (!(file= fopen(path, "rb"))) + return 0; + if (debug) fprintf(stderr, "loading %s\nstart address %04x\n", path, address); + while ((count= fread(mpu->memory + address, 1, max, file)) > 0) + { + address += count; + max -= count; + } + fclose(file); + if (debug) fprintf(stderr, "end address %04x\n", address); + return address; +} + +int setiocb(int chan, int opened, char type, char mode, int recsize, FILE *fp, DIR *dp, char *name) { + iocbs[chan].opened = opened; + iocbs[chan].type = type; + iocbs[chan].mode = mode; + iocbs[chan].recsize = recsize; + iocbs[chan].fp = fp; + iocbs[chan].dp = dp; + iocbs[chan].errnum = 0; + strcpy(iocbs[chan].name, name); + return 0; +} + +void initiocb(int chan) { + setiocb(chan, 0, ' ', ' ', 0, NULL, NULL, ""); +} + +void initiocbs(void) +{ + filename[0] = 0; //Set filename to "" + for (int chan=0; chan<=MAXIOB; chan++) + initiocb(chan); +} + +/* Set Error Number and Error Message */ +static int seterror(int chan, int errnum) { + if (debug) fprintf(stderr, "setting channel %d error to %d\n", chan, errnum); + iocbs[chan].errnum = errnum; + return errnum; +} + +/* Set File Name */ +static int setname(M6502 *mpu, word addr, char *name) { + int i; + if (debug) fprintf(stderr, "copying name from address $%04x\n", addr); + for (i=0; imemory[addr + i & 0xFFFF]; + if (c) name[i] = c; + else break; + } + name[i] = 0; //Terminate String + if (debug) fprintf(stderr, "copied %d characters\n", i); + return i; +} + +/* Find Unused IOCB */ +static int uniocb(void) { + int chan; + for (chan=1; chan<=MAXIOB; chan++) { + if (iocbs[chan].opened == 0) break; + if (chan > MAXIOB) {chan = -24; break;} + } + return chan; +} + +/* Validate Channel */ +static int valchan(int chan, char valtype) { + int errnum = 0; //Error (none) + if (debug) fprintf(stderr, "validating channel %d\n", chan); + 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); + switch (iocbs[chan].type) { + case 'D': errnum = 21; //Is a directory + case 'F': errnum = 20; //Not a directory + default: errnum = 77; //File descriptor in bad state + } + } + return errnum; +} + +/* Write Buffer to Memory */ +static int writemem(M6502 *mpu, char* buffer, int count) { + int i; + for (i = 0; imemory[fileaddr+i] = buffer[i]; + return i; +} + +/* Write String to Memory */ +static int writestr(M6502 *mpu, char* buffer, int count) { + int i; + if (debug) fprintf(stderr, "writing '%s' to address %04x\n", buffer, fileaddr); + for (i = 0; imemory[fileaddr+i] = c; + } + mpu->memory[fileaddr+i] = 0; //Terminate String + if (debug) fprintf(stderr, "wrote %d characters\n", i); + return i; +} + +/* Emulate fileio at addr */ +extern int filecmd(M6502 *mpu, word addr, byte data) { + const char modes[8][4] = {"r", "rb", "w", "wb", "a", "ab", "r+", "rb+"}; + const char qdesc[2][7] = {"string", "line"}; + int chan, e, i; + char c, m, n, mode[4]; + char *name; + struct dirent *de; + 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; + char drive = y & 0x1f; + if (debug) fprintf(stderr, "executing '%c' with options %02x,%02x,%02x\n", a, y, x, p); + switch (a) { //File I/O Command + case 'A': //Set filebuffer address - Y.X = address + if (p & 1) { + fileindx = yx; + if (debug) fprintf(stderr, "file index set to %04x\n", fileaddr); + } else { + fileaddr = yx; + if (debug) fprintf(stderr, "file address set to %04x\n", fileaddr); + } + break; + case 'B': //Close Directory - Y = channel + chan = y; + if (debug) fprintf(stderr, "closing directory channel %d\n", chan); + y = valchan(chan, 'D'); if (y) break; + if (closedir(iocbs[chan].dp)) y = seterror(chan, errno); + else initiocb(chan); + break; + case 'C': //Close file - Y = channel + chan = y; + if (debug) fprintf(stderr, "closing file channel %d\n", chan); + y = valchan(chan, 'F'); if (y) break; + if (fclose(iocbs[chan].fp)) y = seterror(chan, errno); + else initiocb(chan); + break; + case 'D': //Open Directory - Y,X = Directory Name + x = 0; //File channel (none) + y = 0; //Error code (none) + chan = uniocb(); if (chan <0) {y = -chan; break;} + setname(mpu, yx, filename); + if (strlen(filename) == 0) strcpy(filename, "."); + if (debug) fprintf(stderr, "opening directory '%s'\n", filename, mode); + DIR *dp = opendir(filename); + if (dp == NULL) { y = seterror(0, errno); break;} + if (debug) fprintf(stderr, "directory opened on channel %d\n", chan); + y = setiocb(chan, -1, 'D', ' ', 0, NULL, dp, filename); //Setup IOCB + if (y == 0) x = chan; + break; + case 'E': //EOF - Y = channel + chan = y; + y = valchan(chan, 'F'); if (y) break; + y = feof(iocbs[chan].fp); + break; + case 'F': //Flush File - Y = Channel + chan = y; + y = valchan(chan, 'F'); if (y) break; + if (fflush(iocbs[chan].fp)) y = seterror(chan, errno); + break; + case 'G': //Get character - Y = channel + chan = y; + x = 0; //Character read (none) + y = valchan(chan, 'F'); if (y) break; + c = fgetc(iocbs[chan].fp); + if (feof(iocbs[chan].fp)) {y = 255; break;} + if (c == EOF) {y = seterror(chan, errno); break;} + x = c & 0xFF; + break; + case 'H': //Get String - Y = channel + chan = y; + x = 0; //Number of Characters read + y = valchan(chan, 'F'); 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); + writestr(mpu, filebuff, STRLEN); + x = strlen(s); fprintf(stderr, "returning %d bytes read\n", x); + break; + case 'I': //Init File System + initiocbs(); //Initialize I/O Control Blocks + break; + case 'J': //Read Directory Entry + chan = y; + x = 0; //Return Value (Read Failed) + y = valchan(chan, 'D'); if (y) break; + if (p & 1) { + if (debug) fprintf(stdout, "retrieving directory name\n"); + x = writestr(mpu, iocbs[chan].name, STRLEN); + } else { + if (debug) fprintf(stdout, "reading directory entry\n"); + de = readdir(iocbs[chan].dp); + if (de) { + if (debug) fprintf(stdout, "read entry '%s'\n", de->d_name); + x = writestr(mpu, de->d_name, STRLEN); + } + else if (errno != 2) y = seterror(chan, errno); + } + break; + case 'K': //REMOVE - Delete File - Y,X = Filename + setname(mpu, yx, filename); + if (debug) fprintf(stderr, "removing file '%s'\n", filename); + x = remove(filename); + if (x) y=seterror(0, errno); else y=0; + break; + case 'L': //Load file + a = 0; //Error (none) + if (debug) fprintf(stderr, "loading file at %04h\n", fileaddr); + e = load(mpu, fileaddr, filename); + if (!e) {a = seterror(0, errno); break;} + y = e >> 8; x = e & 0xff; + break; + case 'M': //MOVE - Rename File - Y,X = Filename + setname(mpu, yx, filebuff); + if (debug) fprintf(stderr, "renaming file '%s' to '%s'\n", filename, filebuff); + x = rename(filename, filebuff); + if (x) y=seterror(0, errno); else y=0; + break; + case 'N': //Set filename - Y,X = string address + x = setname(mpu, yx, filename); //Set filename and Return Length + if (debug) fprintf(stderr, "filename set to '%s'\n", filename); + break; + case 'O': //Open file - Y = Drive#, X = Mode (Bits 7,6 = RWA, Bit 5 = Binary) + m = x >> 5 & 7; //Get Mode Index + x = 0; //File channel (none) + y = 0; //Error code (none) + strcpy(mode, modes[m]); //Set Mode from Mode Index + chan = uniocb(); if (chan <0) {y = seterror(0, -chan); break;} + if (debug) fprintf(stderr, "opening file '%s' with mode '%s'\n", filename, mode); + FILE *fp = fopen(filename, mode); + if (fp == NULL) { y = seterror(0, errno); break;} + if (debug) fprintf(stderr, "file opened on channel %d\n", chan); + i = (m == 3) ? fileindx : 0; //Set Records Size if Mode RECORD + y = setiocb(chan, -1, 'F', mode[0], i, fp, NULL, filename); //Setup IOCB + if (y == 0) x = chan; + break; + case 'P': //Put character - Y = channel; X = character + chan = y; + c = x; + if (debug) fprintf(stderr, "writing '%c' to channel %d\n", c, chan); + a = 0; //Character written (none) + y = valchan(chan, 'F'); if (y) break; + e = fputc(c, iocbs[chan].fp); + if (e == EOF) {y = seterror(chan, errno); break;} + a = e & 0xFF; + break; + case 'Q': //Put String - Y = channel + chan = y; + x = 0; //Number of characters written + y = valchan(chan, 'F'); if (y) break; + for (i = 0; i<128; i++) { + c = mpu->memory[fileaddr+i]; + if (c) filebuff[i] = c; + else break; + } + filebuff[i] = 0; + if (debug) fprintf(stderr, "writing %s '%s'\n", qdesc[p&1], filebuff); + if (p & 1) strcat(filebuff, "\n"); + e = fputs(filebuff, iocbs[chan].fp); + if (e == EOF) {y = seterror(chan, errno); break;} + x = strlen(filebuff); + break; + case 'R': //Read bytes - Y = channel, X=Number of Bytes + m = p & 1; //Set Mode: 0 = fread, 1 = fgetr + chan = y; + if (m) { + a = valchan(chan, 'F'); if (a) break; + if (debug) fprintf(stderr, "selecting record #%d\n", fileindx); + n = iocbs[chan].recsize; + i = fileindx * n; + if (debug) fprintf(stderr, "setting position to %d\n", i); + e = fseek(iocbs[chan].fp, i, SEEK_SET); + if (e) {a = seterror(chan, errno); break;} + } else { + y = valchan(chan, 'F'); if (y) break; + n = x; + } + if (debug) fprintf(stderr, "reading %d bytes\n", n); + x = fread(filebuff, 1, n, iocbs[chan].fp); + if (debug) fprintf(stderr, "read %d bytes\n", x); + e = ferror(iocbs[chan].fp); + if (e) {seterror(chan, errno); if (m) a = e; else y = e; break; } + writemem(mpu, filebuff, x); + if (m) { + fileindx++; y = fileindx >> 8; x = fileindx & 0xff; + if (debug) fprintf(stderr, "returning record #%d\n", fileindx); + } + break; + case 'S': //Save file Y,X = end address + a = 0; //Error (none) + if (debug) fprintf(stderr, "saving file from %04x to %04x\n", fileaddr, yx); + e = save(mpu, fileaddr, yx-fileaddr-1, filename); + if (!e) {a = seterror(0, errno); break;} + y = e >> 8; x = e & 0xff; + break; + case 'T': //Get Current Directory - YX = String Address + x = 0; //Directory Name Length + y = 0; //Error (None) + if (debug) fprintf(stderr, "getting current working directory\n"); + if (_getcwd(filename, STRLEN)) { + if (debug) fprintf(stderr, "cwd: %s\n", filename); + for (i = 0; imemory[yx+i] = c; + } + mpu->memory[yx+i] = 0; + x = i; + } + else y = seterror(0, errno); + break; + case 'U': //Change Directory - YX = Directory Name + x = 0; //Result (Success) + y = 0; //Error (None) + setname(mpu, yx, filename); //Set filename to Directory Name + if (debug) fprintf(stderr, "changing directory to '%s'\n", filename); + if (_chdir(filename)) {x = 0xFF; y = seterror(0, errno);} + break; + case 'V': //Get or Set Current Drive, Y=Drive, Carry=Get/Set + if (p & 1) { + if (debug) fprintf(stderr, "changing drive to %c\n", y+'@'); + x = _chdrive(y); + if (x) y=seterror(0, errno); else y=0; + } else { + x = _getdrive(); + if (x) y=0; else y=seterror(0, errno); + if (debug) fprintf(stderr, "current drive is %c\n", x+'@'); + } + break; + case 'W': //Write bytes - Y = channel, X=Number of Bytes + chan = y; + y = valchan(chan, 'F'); if (y) break; + for (i = 0; imemory[fileaddr+i]; + if (debug) fprintf(stderr, "writing %d bytes\n", x); + e = fwrite(filebuff, x, 1, iocbs[chan].fp); + if (e != 1) {y = seterror(chan, errno); break;} + break; + case 'X': //Make/Remove Directory - YX = Directory Name + setname(mpu, yx, filename); + if (p & 1) { + if (debug) fprintf(stderr, "removing directory '%s'\n", filename); + x = _rmdir(filename); + } else { + if (debug) fprintf(stderr, "creating directory '%s'\n", filename); + x = _mkdir(filename); + } + if (x) y=seterror(0, errno); else y=0; + break; + case 'Y': //Get Last Error: Y=chan + chan = y; + y = 0; //Set Error to None + x = 0xFF; //Set Result to Invalid + if (chan > MAXIOB) {y = 44; break;} + if (debug) fprintf(stderr, "getting last error for channel %d\n", chan); + x = iocbs[chan].errnum; + char *msg = strerror(x); + if (debug) fprintf(stderr, "retrieved error %d, '%s'\n", x, msg); + writestr(mpu, msg, STRLEN); + break; + case 'Z': //File Position: Y=chan, fileaddr = position, Carry = seek/tell + chan = y; + y = valchan(chan, 'F'); if (y) break; + if (p & 1) { + e = ftell(iocbs[chan].fp); + if (e < 0) {a = seterror(chan, errno);} + else { + if (debug) fprintf(stderr, "returning position %d\n", e); + a = 0; y = e >> 8; x = e & 0xff; + } + } else { + if (fileindx == 0xFFFF) {i = 0; m = SEEK_END;} + else {i = fileindx, m = SEEK_SET;} + if (debug) fprintf(stderr, "seeking position %d\n", i); + x = fseek(iocbs[chan].fp, i, m); + if (x) y = seterror(chan, errno); + } + break; + default: + y = 22; //Error - invalid argument + } + if (debug) fprintf(stderr, "returning values %02x, %02x, %02x\n", a, y, x); + mpu->registers->a = a; + mpu->registers->x = x; + mpu->registers->y = y; +} diff --git a/lib6502/file6502.h b/lib6502/file6502.h new file mode 100644 index 0000000..5d95bdf --- /dev/null +++ b/lib6502/file6502.h @@ -0,0 +1,9 @@ +/* file6502.h - File I/O Command Processor Header File */ + +#include "lib6502.h" + +typedef uint8_t byte; +typedef uint16_t word; + +extern void setdebug(int dbg); +extern int filecmd(M6502 *mpu, word addr, byte data); diff --git a/lib6502/lib6502.c b/lib6502/lib6502.c index 84549fb..5709825 100644 --- a/lib6502/lib6502.c +++ b/lib6502/lib6502.c @@ -1,4 +1,4 @@ -/* lib6502.c -- MOS Technology 6502 emulator -*- C -*- */ +/* lib6502.c -- MOS Technology 6502 emulator -*- C -*- */ /* Copyright (c) 2005 Ian Piumarta * @@ -36,606 +36,606 @@ typedef uint8_t byte; typedef uint16_t word; enum { - flagN= (1<<7), /* negative */ - flagV= (1<<6), /* overflow */ - flagX= (1<<5), /* unused */ - flagB= (1<<4), /* irq from brk */ - flagD= (1<<3), /* decimal mode */ - flagI= (1<<2), /* irq disable */ - flagZ= (1<<1), /* zero */ - flagC= (1<<0) /* carry */ + flagN= (1<<7), /* negative */ + flagV= (1<<6), /* overflow */ + flagX= (1<<5), /* unused */ + flagB= (1<<4), /* irq from brk */ + flagD= (1<<3), /* decimal mode */ + flagI= (1<<2), /* irq disable */ + flagZ= (1<<1), /* zero */ + flagC= (1<<0) /* carry */ }; -#define getN() (P & flagN) -#define getV() (P & flagV) -#define getB() (P & flagB) -#define getD() (P & flagD) -#define getI() (P & flagI) -#define getZ() (P & flagZ) -#define getC() (P & flagC) +#define getN() (P & flagN) +#define getV() (P & flagV) +#define getB() (P & flagB) +#define getD() (P & flagD) +#define getI() (P & flagI) +#define getZ() (P & flagZ) +#define getC() (P & flagC) -#define setNVZC(N,V,Z,C) (P= (P & ~(flagN | flagV | flagZ | flagC)) | (N) | ((V)<<6) | ((Z)<<1) | (C)) -#define setNZC(N,Z,C) (P= (P & ~(flagN | flagZ | flagC)) | (N) | ((Z)<<1) | (C)) -#define setNZ(N,Z) (P= (P & ~(flagN | flagZ )) | (N) | ((Z)<<1) ) -#define setZ(Z) (P= (P & ~( flagZ )) | ((Z)<<1) ) -#define setC(C) (P= (P & ~( flagC)) | (C)) +#define setNVZC(N,V,Z,C) (P= (P & ~(flagN | flagV | flagZ | flagC)) | (N) | ((V)<<6) | ((Z)<<1) | (C)) +#define setNZC(N,Z,C) (P= (P & ~(flagN | flagZ | flagC)) | (N) | ((Z)<<1) | (C)) +#define setNZ(N,Z) (P= (P & ~(flagN | flagZ )) | (N) | ((Z)<<1) ) +#define setZ(Z) (P= (P & ~( flagZ )) | ((Z)<<1) ) +#define setC(C) (P= (P & ~( flagC)) | (C)) -#define NAND(P, Q) (!((P) & (Q))) +#define NAND(P, Q) (!((P) & (Q))) #define tick(n) #define tickIf(p) /* memory access (indirect if callback installed) -- ARGUMENTS ARE EVALUATED MORE THAN ONCE! */ -#define putMemory(ADDR, BYTE) \ - ( writeCallback[ADDR] \ - ? writeCallback[ADDR](mpu, ADDR, BYTE) \ +#define putMemory(ADDR, BYTE) \ + ( writeCallback[ADDR] \ + ? writeCallback[ADDR](mpu, ADDR, BYTE) \ : (memory[ADDR]= BYTE) ) -#define getMemory(ADDR) \ - ( readCallback[ADDR] \ - ? readCallback[ADDR](mpu, ADDR, 0) \ +#define getMemory(ADDR) \ + ( readCallback[ADDR] \ + ? readCallback[ADDR](mpu, ADDR, 0) \ : memory[ADDR] ) /* stack access (always direct) */ -#define push(BYTE) (memory[0x0100 + S--]= (BYTE)) -#define pop() (memory[++S + 0x0100]) +#define push(BYTE) (memory[0x0100 + S--]= (BYTE)) +#define pop() (memory[++S + 0x0100]) /* adressing modes (memory access direct) */ -#define implied(ticks) \ +#define implied(ticks) \ tick(ticks); -#define immediate(ticks) \ - tick(ticks); \ +#define immediate(ticks) \ + tick(ticks); \ ea= PC++; -#define abs(ticks) \ - tick(ticks); \ - ea= memory[PC] + (memory[PC + 1] << 8); \ +#define abs(ticks) \ + tick(ticks); \ + ea= memory[PC] + (memory[PC + 1] << 8); \ PC += 2; -#define relative(ticks) \ - tick(ticks); \ - ea= memory[PC++]; \ - if (ea & 0x80) ea -= 0x100; \ +#define relative(ticks) \ + tick(ticks); \ + ea= memory[PC++]; \ + if (ea & 0x80) ea -= 0x100; \ tickIf((ea >> 8) != (PC >> 8)); -#define indirect(ticks) \ - tick(ticks); \ - { \ - word tmp; \ - tmp= memory[PC] + (memory[PC + 1] << 8); \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ - PC += 2; \ +#define indirect(ticks) \ + tick(ticks); \ + { \ + word tmp; \ + tmp= memory[PC] + (memory[PC + 1] << 8); \ + ea = memory[tmp] + (memory[tmp + 1] << 8); \ + PC += 2; \ } -#define absx(ticks) \ - tick(ticks); \ - ea= memory[PC] + (memory[PC + 1] << 8); \ - PC += 2; \ - tickIf((ticks == 4) && ((ea >> 8) != ((ea + X) >> 8))); \ +#define absx(ticks) \ + tick(ticks); \ + ea= memory[PC] + (memory[PC + 1] << 8); \ + PC += 2; \ + tickIf((ticks == 4) && ((ea >> 8) != ((ea + X) >> 8))); \ ea += X; -#define absy(ticks) \ - tick(ticks); \ - ea= memory[PC] + (memory[PC + 1] << 8); \ - PC += 2; \ - tickIf((ticks == 4) && ((ea >> 8) != ((ea + Y) >> 8))); \ +#define absy(ticks) \ + tick(ticks); \ + ea= memory[PC] + (memory[PC + 1] << 8); \ + PC += 2; \ + tickIf((ticks == 4) && ((ea >> 8) != ((ea + Y) >> 8))); \ ea += Y -#define zp(ticks) \ - tick(ticks); \ +#define zp(ticks) \ + tick(ticks); \ ea= memory[PC++]; -#define zpx(ticks) \ - tick(ticks); \ - ea= memory[PC++] + X; \ +#define zpx(ticks) \ + tick(ticks); \ + ea= memory[PC++] + X; \ ea &= 0x00ff; -#define zpy(ticks) \ - tick(ticks); \ - ea= memory[PC++] + Y; \ +#define zpy(ticks) \ + tick(ticks); \ + ea= memory[PC++] + Y; \ ea &= 0x00ff; -#define indx(ticks) \ - tick(ticks); \ - { \ - byte tmp= memory[PC++] + X; \ - ea= memory[tmp] + (memory[tmp + 1] << 8); \ +#define indx(ticks) \ + tick(ticks); \ + { \ + byte tmp= memory[PC++] + X; \ + ea= memory[tmp] + (memory[tmp + 1] << 8); \ } -#define indy(ticks) \ - tick(ticks); \ - { \ - byte tmp= memory[PC++]; \ - ea= memory[tmp] + (memory[tmp + 1] << 8); \ - tickIf((ticks == 5) && ((ea >> 8) != ((ea + Y) >> 8))); \ - ea += Y; \ +#define indy(ticks) \ + tick(ticks); \ + { \ + byte tmp= memory[PC++]; \ + ea= memory[tmp] + (memory[tmp + 1] << 8); \ + tickIf((ticks == 5) && ((ea >> 8) != ((ea + Y) >> 8))); \ + ea += Y; \ } -#define indabsx(ticks) \ - tick(ticks); \ - { \ - word tmp; \ - tmp= memory[PC ] + (memory[PC + 1] << 8) + X; \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ +#define indabsx(ticks) \ + tick(ticks); \ + { \ + word tmp; \ + tmp= memory[PC ] + (memory[PC + 1] << 8) + X; \ + ea = memory[tmp] + (memory[tmp + 1] << 8); \ } -#define indzp(ticks) \ - tick(ticks); \ - { \ - byte tmp; \ - tmp= memory[PC++]; \ - ea = memory[tmp] + (memory[tmp + 1] << 8); \ +#define indzp(ticks) \ + tick(ticks); \ + { \ + byte tmp; \ + tmp= memory[PC++]; \ + ea = memory[tmp] + (memory[tmp + 1] << 8); \ } /* insns */ -#define adc(ticks, adrmode) \ - adrmode(ticks); \ - { \ - byte B= getMemory(ea); \ - if (!getD()) \ - { \ - int c= A + B + getC(); \ - int v= (int8_t)A + (int8_t)B + getC(); \ - fetch(); \ - A= c; \ - setNVZC((A & 0x80), (((A & 0x80) > 0) ^ (v < 0)), (A == 0), ((c & 0x100) > 0)); \ - next(); \ - } \ - else \ - { \ - int l, h, s; \ - /* inelegant & slow, but consistent with the hw for illegal digits */ \ - l= (A & 0x0F) + (B & 0x0F) + getC(); \ - h= (A & 0xF0) + (B & 0xF0); \ - if (l >= 0x0A) { l -= 0x0A; h += 0x10; } \ - if (h >= 0xA0) { h -= 0xA0; } \ - fetch(); \ - s= h | (l & 0x0F); \ - /* only C is valid on NMOS 6502 */ \ - setNVZC(s & 0x80, !(((A ^ B) & 0x80) && ((A ^ s) & 0x80)), !s, !!(h & 0x80)); \ - A= s; \ - tick(1); \ - next(); \ - } \ +#define adc(ticks, adrmode) \ + adrmode(ticks); \ + { \ + byte B= getMemory(ea); \ + if (!getD()) \ + { \ + int c= A + B + getC(); \ + int v= (int8_t)A + (int8_t)B + getC(); \ + fetch(); \ + A= c; \ + setNVZC((A & 0x80), (((A & 0x80) > 0) ^ (v < 0)), (A == 0), ((c & 0x100) > 0)); \ + next(); \ + } \ + else \ + { \ + int l, h, s; \ + /* inelegant & slow, but consistent with the hw for illegal digits */ \ + l= (A & 0x0F) + (B & 0x0F) + getC(); \ + h= (A & 0xF0) + (B & 0xF0); \ + if (l >= 0x0A) { l -= 0x0A; h += 0x10; } \ + if (h >= 0xA0) { h -= 0xA0; } \ + fetch(); \ + s= h | (l & 0x0F); \ + /* only C is valid on NMOS 6502 */ \ + setNVZC(s & 0x80, !(((A ^ B) & 0x80) && ((A ^ s) & 0x80)), !s, !!(h & 0x80)); \ + A= s; \ + tick(1); \ + next(); \ + } \ } -#define sbc(ticks, adrmode) \ - adrmode(ticks); \ - { \ - byte B= getMemory(ea); \ - if (!getD()) \ - { \ - int b= 1 - (P &0x01); \ - int c= A - B - b; \ - int v= (int8_t)A - (int8_t) B - b; \ - fetch(); \ - A= c; \ - setNVZC(A & 0x80, ((A & 0x80) > 0) ^ ((v & 0x100) != 0), A == 0, c >= 0); \ - next(); \ - } \ - else \ - { \ - /* this is verbatim ADC, with a 10's complemented operand */ \ - int l, h, s; \ - B= 0x99 - B; \ - l= (A & 0x0F) + (B & 0x0F) + getC(); \ - h= (A & 0xF0) + (B & 0xF0); \ - if (l >= 0x0A) { l -= 0x0A; h += 0x10; } \ - if (h >= 0xA0) { h -= 0xA0; } \ - fetch(); \ - s= h | (l & 0x0F); \ - /* only C is valid on NMOS 6502 */ \ - setNVZC(s & 0x80, !(((A ^ B) & 0x80) && ((A ^ s) & 0x80)), !s, !!(h & 0x80)); \ - A= s; \ - tick(1); \ - next(); \ - } \ +#define sbc(ticks, adrmode) \ + adrmode(ticks); \ + { \ + byte B= getMemory(ea); \ + if (!getD()) \ + { \ + int b= 1 - (P &0x01); \ + int c= A - B - b; \ + int v= (int8_t)A - (int8_t) B - b; \ + fetch(); \ + A= c; \ + setNVZC(A & 0x80, ((A & 0x80) > 0) ^ ((v & 0x100) != 0), A == 0, c >= 0); \ + next(); \ + } \ + else \ + { \ + /* this is verbatim ADC, with a 10's complemented operand */ \ + int l, h, s; \ + B= 0x99 - B; \ + l= (A & 0x0F) + (B & 0x0F) + getC(); \ + h= (A & 0xF0) + (B & 0xF0); \ + if (l >= 0x0A) { l -= 0x0A; h += 0x10; } \ + if (h >= 0xA0) { h -= 0xA0; } \ + fetch(); \ + s= h | (l & 0x0F); \ + /* only C is valid on NMOS 6502 */ \ + setNVZC(s & 0x80, !(((A ^ B) & 0x80) && ((A ^ s) & 0x80)), !s, !!(h & 0x80)); \ + A= s; \ + tick(1); \ + next(); \ + } \ } -#define cmpR(ticks, adrmode, R) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte B= getMemory(ea); \ - byte d= R - B; \ - setNZC(d & 0x80, !d, R >= B); \ - } \ +#define cmpR(ticks, adrmode, R) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte B= getMemory(ea); \ + byte d= R - B; \ + setNZC(d & 0x80, !d, R >= B); \ + } \ next(); -#define cmp(ticks, adrmode) cmpR(ticks, adrmode, A) -#define cpx(ticks, adrmode) cmpR(ticks, adrmode, X) -#define cpy(ticks, adrmode) cmpR(ticks, adrmode, Y) +#define cmp(ticks, adrmode) cmpR(ticks, adrmode, A) +#define cpx(ticks, adrmode) cmpR(ticks, adrmode, X) +#define cpy(ticks, adrmode) cmpR(ticks, adrmode, Y) -#define dec(ticks, adrmode) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte B= getMemory(ea); \ - --B; \ - putMemory(ea, B); \ - setNZ(B & 0x80, !B); \ - } \ +#define dec(ticks, adrmode) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte B= getMemory(ea); \ + --B; \ + putMemory(ea, B); \ + setNZ(B & 0x80, !B); \ + } \ next(); -#define decR(ticks, adrmode, R) \ - fetch(); \ - tick(ticks); \ - --R; \ - setNZ(R & 0x80, !R); \ +#define decR(ticks, adrmode, R) \ + fetch(); \ + tick(ticks); \ + --R; \ + setNZ(R & 0x80, !R); \ next(); -#define dea(ticks, adrmode) decR(ticks, adrmode, A) -#define dex(ticks, adrmode) decR(ticks, adrmode, X) -#define dey(ticks, adrmode) decR(ticks, adrmode, Y) +#define dea(ticks, adrmode) decR(ticks, adrmode, A) +#define dex(ticks, adrmode) decR(ticks, adrmode, X) +#define dey(ticks, adrmode) decR(ticks, adrmode, Y) -#define inc(ticks, adrmode) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte B= getMemory(ea); \ - ++B; \ - putMemory(ea, B); \ - setNZ(B & 0x80, !B); \ - } \ +#define inc(ticks, adrmode) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte B= getMemory(ea); \ + ++B; \ + putMemory(ea, B); \ + setNZ(B & 0x80, !B); \ + } \ next(); -#define incR(ticks, adrmode, R) \ - fetch(); \ - tick(ticks); \ - ++R; \ - setNZ(R & 0x80, !R); \ +#define incR(ticks, adrmode, R) \ + fetch(); \ + tick(ticks); \ + ++R; \ + setNZ(R & 0x80, !R); \ next(); -#define ina(ticks, adrmode) incR(ticks, adrmode, A) -#define inx(ticks, adrmode) incR(ticks, adrmode, X) -#define iny(ticks, adrmode) incR(ticks, adrmode, Y) +#define ina(ticks, adrmode) incR(ticks, adrmode, A) +#define inx(ticks, adrmode) incR(ticks, adrmode, X) +#define iny(ticks, adrmode) incR(ticks, adrmode, Y) -#define bit(ticks, adrmode) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte B= getMemory(ea); \ - P= (P & ~(flagN | flagV | flagZ)) \ - | (B & (0xC0)) | (((A & B) == 0) << 1); \ - } \ +#define bit(ticks, adrmode) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte B= getMemory(ea); \ + P= (P & ~(flagN | flagV | flagZ)) \ + | (B & (0xC0)) | (((A & B) == 0) << 1); \ + } \ next(); -#define tsb(ticks, adrmode) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte b= getMemory(ea); \ - b |= A; \ - putMemory(ea, b); \ - setZ(!b); \ - } \ +#define tsb(ticks, adrmode) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte b= getMemory(ea); \ + b |= A; \ + putMemory(ea, b); \ + setZ(!b); \ + } \ next(); -#define trb(ticks, adrmode) \ - adrmode(ticks); \ - fetch(); \ - { \ - byte b= getMemory(ea); \ - b |= (A ^ 0xFF); \ - putMemory(ea, b); \ - setZ(!b); \ - } \ +#define trb(ticks, adrmode) \ + adrmode(ticks); \ + fetch(); \ + { \ + byte b= getMemory(ea); \ + b |= (A ^ 0xFF); \ + putMemory(ea, b); \ + setZ(!b); \ + } \ next(); -#define bitwise(ticks, adrmode, op) \ - adrmode(ticks); \ - fetch(); \ - A op##= getMemory(ea); \ - setNZ(A & 0x80, !A); \ +#define bitwise(ticks, adrmode, op) \ + adrmode(ticks); \ + fetch(); \ + A op##= getMemory(ea); \ + setNZ(A & 0x80, !A); \ next(); -#define and(ticks, adrmode) bitwise(ticks, adrmode, &) -#define eor(ticks, adrmode) bitwise(ticks, adrmode, ^) -#define ora(ticks, adrmode) bitwise(ticks, adrmode, |) +#define and(ticks, adrmode) bitwise(ticks, adrmode, &) +#define eor(ticks, adrmode) bitwise(ticks, adrmode, ^) +#define ora(ticks, adrmode) bitwise(ticks, adrmode, |) -#define asl(ticks, adrmode) \ - adrmode(ticks); \ - { \ - unsigned int i= getMemory(ea) << 1; \ - putMemory(ea, i); \ - fetch(); \ - setNZC(i & 0x80, !i, i >> 8); \ - } \ +#define asl(ticks, adrmode) \ + adrmode(ticks); \ + { \ + unsigned int i= getMemory(ea) << 1; \ + putMemory(ea, i); \ + fetch(); \ + setNZC(i & 0x80, !i, i >> 8); \ + } \ next(); -#define asla(ticks, adrmode) \ - tick(ticks); \ - fetch(); \ - { \ - int c= A >> 7; \ - A <<= 1; \ - setNZC(A & 0x80, !A, c); \ - } \ +#define asla(ticks, adrmode) \ + tick(ticks); \ + fetch(); \ + { \ + int c= A >> 7; \ + A <<= 1; \ + setNZC(A & 0x80, !A, c); \ + } \ next(); -#define lsr(ticks, adrmode) \ - adrmode(ticks); \ - { \ - byte b= getMemory(ea); \ - int c= b & 1; \ - fetch(); \ - b >>= 1; \ - putMemory(ea, b); \ - setNZC(0, !b, c); \ - } \ +#define lsr(ticks, adrmode) \ + adrmode(ticks); \ + { \ + byte b= getMemory(ea); \ + int c= b & 1; \ + fetch(); \ + b >>= 1; \ + putMemory(ea, b); \ + setNZC(0, !b, c); \ + } \ next(); -#define lsra(ticks, adrmode) \ - tick(ticks); \ - fetch(); \ - { \ - int c= A & 1; \ - A >>= 1; \ - setNZC(0, !A, c); \ - } \ +#define lsra(ticks, adrmode) \ + tick(ticks); \ + fetch(); \ + { \ + int c= A & 1; \ + A >>= 1; \ + setNZC(0, !A, c); \ + } \ next(); -#define rol(ticks, adrmode) \ - adrmode(ticks); \ - { \ - word b= (getMemory(ea) << 1) | getC(); \ - fetch(); \ - putMemory(ea, b); \ - setNZC(b & 0x80, !(b & 0xFF), b >> 8); \ - } \ +#define rol(ticks, adrmode) \ + adrmode(ticks); \ + { \ + word b= (getMemory(ea) << 1) | getC(); \ + fetch(); \ + putMemory(ea, b); \ + setNZC(b & 0x80, !(b & 0xFF), b >> 8); \ + } \ next(); -#define rola(ticks, adrmode) \ - tick(ticks); \ - fetch(); \ - { \ - word b= (A << 1) | getC(); \ - A= b; \ - setNZC(A & 0x80, !A, b >> 8); \ - } \ +#define rola(ticks, adrmode) \ + tick(ticks); \ + fetch(); \ + { \ + word b= (A << 1) | getC(); \ + A= b; \ + setNZC(A & 0x80, !A, b >> 8); \ + } \ next(); -#define ror(ticks, adrmode) \ - adrmode(ticks); \ - { \ - int c= getC(); \ - byte m= getMemory(ea); \ - byte b= (c << 7) | (m >> 1); \ - fetch(); \ - putMemory(ea, b); \ - setNZC(b & 0x80, !b, m & 1); \ - } \ +#define ror(ticks, adrmode) \ + adrmode(ticks); \ + { \ + int c= getC(); \ + byte m= getMemory(ea); \ + byte b= (c << 7) | (m >> 1); \ + fetch(); \ + putMemory(ea, b); \ + setNZC(b & 0x80, !b, m & 1); \ + } \ next(); -#define rora(ticks, adrmode) \ - adrmode(ticks); \ - { \ - int ci= getC(); \ - int co= A & 1; \ - fetch(); \ - A= (ci << 7) | (A >> 1); \ - setNZC(A & 0x80, !A, co); \ - } \ +#define rora(ticks, adrmode) \ + adrmode(ticks); \ + { \ + int ci= getC(); \ + int co= A & 1; \ + fetch(); \ + A= (ci << 7) | (A >> 1); \ + setNZC(A & 0x80, !A, co); \ + } \ next(); -#define tRS(ticks, adrmode, R, S) \ - fetch(); \ - tick(ticks); \ - S= R; \ - setNZ(S & 0x80, !S); \ +#define tRS(ticks, adrmode, R, S) \ + fetch(); \ + tick(ticks); \ + S= R; \ + setNZ(S & 0x80, !S); \ next(); -#define tax(ticks, adrmode) tRS(ticks, adrmode, A, X) -#define txa(ticks, adrmode) tRS(ticks, adrmode, X, A) -#define tay(ticks, adrmode) tRS(ticks, adrmode, A, Y) -#define tya(ticks, adrmode) tRS(ticks, adrmode, Y, A) -#define tsx(ticks, adrmode) tRS(ticks, adrmode, S, X) +#define tax(ticks, adrmode) tRS(ticks, adrmode, A, X) +#define txa(ticks, adrmode) tRS(ticks, adrmode, X, A) +#define tay(ticks, adrmode) tRS(ticks, adrmode, A, Y) +#define tya(ticks, adrmode) tRS(ticks, adrmode, Y, A) +#define tsx(ticks, adrmode) tRS(ticks, adrmode, S, X) -#define txs(ticks, adrmode) \ - fetch(); \ - tick(ticks); \ - S= X; \ +#define txs(ticks, adrmode) \ + fetch(); \ + tick(ticks); \ + S= X; \ next(); -#define ldR(ticks, adrmode, R) \ - adrmode(ticks); \ - fetch(); \ - R= getMemory(ea); \ - setNZ(R & 0x80, !R); \ +#define ldR(ticks, adrmode, R) \ + adrmode(ticks); \ + fetch(); \ + R= getMemory(ea); \ + setNZ(R & 0x80, !R); \ next(); -#define lda(ticks, adrmode) ldR(ticks, adrmode, A) -#define ldx(ticks, adrmode) ldR(ticks, adrmode, X) -#define ldy(ticks, adrmode) ldR(ticks, adrmode, Y) +#define lda(ticks, adrmode) ldR(ticks, adrmode, A) +#define ldx(ticks, adrmode) ldR(ticks, adrmode, X) +#define ldy(ticks, adrmode) ldR(ticks, adrmode, Y) -#define stR(ticks, adrmode, R) \ - adrmode(ticks); \ - fetch(); \ - putMemory(ea, R); \ +#define stR(ticks, adrmode, R) \ + adrmode(ticks); \ + fetch(); \ + putMemory(ea, R); \ next(); -#define sta(ticks, adrmode) stR(ticks, adrmode, A) -#define stx(ticks, adrmode) stR(ticks, adrmode, X) -#define sty(ticks, adrmode) stR(ticks, adrmode, Y) -#define stz(ticks, adrmode) stR(ticks, adrmode, 0) +#define sta(ticks, adrmode) stR(ticks, adrmode, A) +#define stx(ticks, adrmode) stR(ticks, adrmode, X) +#define sty(ticks, adrmode) stR(ticks, adrmode, Y) +#define stz(ticks, adrmode) stR(ticks, adrmode, 0) -#define branch(ticks, adrmode, cond) \ - if (cond) \ - { \ - adrmode(ticks); \ - PC += ea; \ - tick(1); \ - } \ - else \ - { \ - tick(ticks); \ - PC++; \ - } \ - fetch(); \ +#define branch(ticks, adrmode, cond) \ + if (cond) \ + { \ + adrmode(ticks); \ + PC += ea; \ + tick(1); \ + } \ + else \ + { \ + tick(ticks); \ + PC++; \ + } \ + fetch(); \ next(); -#define bcc(ticks, adrmode) branch(ticks, adrmode, !getC()) -#define bcs(ticks, adrmode) branch(ticks, adrmode, getC()) -#define bne(ticks, adrmode) branch(ticks, adrmode, !getZ()) -#define beq(ticks, adrmode) branch(ticks, adrmode, getZ()) -#define bpl(ticks, adrmode) branch(ticks, adrmode, !getN()) -#define bmi(ticks, adrmode) branch(ticks, adrmode, getN()) -#define bvc(ticks, adrmode) branch(ticks, adrmode, !getV()) -#define bvs(ticks, adrmode) branch(ticks, adrmode, getV()) +#define bcc(ticks, adrmode) branch(ticks, adrmode, !getC()) +#define bcs(ticks, adrmode) branch(ticks, adrmode, getC()) +#define bne(ticks, adrmode) branch(ticks, adrmode, !getZ()) +#define beq(ticks, adrmode) branch(ticks, adrmode, getZ()) +#define bpl(ticks, adrmode) branch(ticks, adrmode, !getN()) +#define bmi(ticks, adrmode) branch(ticks, adrmode, getN()) +#define bvc(ticks, adrmode) branch(ticks, adrmode, !getV()) +#define bvs(ticks, adrmode) branch(ticks, adrmode, getV()) -#define bra(ticks, adrmode) \ - adrmode(ticks); \ - PC += ea; \ - fetch(); \ - tick(1); \ +#define bra(ticks, adrmode) \ + adrmode(ticks); \ + PC += ea; \ + fetch(); \ + tick(1); \ next(); -#define jmp(ticks, adrmode) \ - adrmode(ticks); \ - PC= ea; \ - if (mpu->callbacks->call[ea]) \ - { \ - word addr; \ - externalise(); \ - if ((addr= mpu->callbacks->call[ea](mpu, ea, 0))) \ - { \ - internalise(); \ - PC= addr; \ - } \ - } \ - fetch(); \ +#define jmp(ticks, adrmode) \ + adrmode(ticks); \ + PC= ea; \ + if (mpu->callbacks->call[ea]) \ + { \ + word addr; \ + externalise(); \ + if ((addr= mpu->callbacks->call[ea](mpu, ea, 0))) \ + { \ + internalise(); \ + PC= addr; \ + } \ + } \ + fetch(); \ next(); -#define jsr(ticks, adrmode) \ - PC++; \ - push(PC >> 8); \ - push(PC & 0xff); \ - PC--; \ - adrmode(ticks); \ - if (mpu->callbacks->call[ea]) \ - { \ - word addr; \ - externalise(); \ - if ((addr= mpu->callbacks->call[ea](mpu, ea, 0))) \ - { \ - internalise(); \ - PC= addr; \ - fetch(); \ - next(); \ - } \ - } \ - PC=ea; \ - fetch(); \ +#define jsr(ticks, adrmode) \ + PC++; \ + push(PC >> 8); \ + push(PC & 0xff); \ + PC--; \ + adrmode(ticks); \ + if (mpu->callbacks->call[ea]) \ + { \ + word addr; \ + externalise(); \ + if ((addr= mpu->callbacks->call[ea](mpu, ea, 0))) \ + { \ + internalise(); \ + PC= addr; \ + fetch(); \ + next(); \ + } \ + } \ + PC=ea; \ + fetch(); \ next(); -#define rts(ticks, adrmode) \ - tick(ticks); \ - PC = pop(); \ - PC |= (pop() << 8); \ - PC++; \ - fetch(); \ +#define rts(ticks, adrmode) \ + tick(ticks); \ + PC = pop(); \ + PC |= (pop() << 8); \ + PC++; \ + fetch(); \ next(); -#define brk(ticks, adrmode) \ - tick(ticks); \ - PC++; \ - push(PC >> 8); \ - push(PC & 0xff); \ - P |= flagB; \ - push(P | flagX); \ - P |= flagI; \ - { \ - word hdlr= getMemory(0xfffe) + (getMemory(0xffff) << 8); \ - if (mpu->callbacks->call[hdlr]) \ - { \ - word addr; \ - externalise(); \ - if ((addr= mpu->callbacks->call[hdlr](mpu, PC - 2, 0))) \ - { \ - internalise(); \ - hdlr= addr; \ - } \ - } \ - PC= hdlr; \ - } \ - fetch(); \ +#define brk(ticks, adrmode) \ + tick(ticks); \ + PC++; \ + push(PC >> 8); \ + push(PC & 0xff); \ + P |= flagB; \ + push(P | flagX); \ + P |= flagI; \ + { \ + word hdlr= getMemory(0xfffe) + (getMemory(0xffff) << 8); \ + if (mpu->callbacks->call[hdlr]) \ + { \ + word addr; \ + externalise(); \ + if ((addr= mpu->callbacks->call[hdlr](mpu, PC - 2, 0))) \ + { \ + internalise(); \ + hdlr= addr; \ + } \ + } \ + PC= hdlr; \ + } \ + fetch(); \ next(); -#define rti(ticks, adrmode) \ - tick(ticks); \ - P= pop(); \ - PC= pop(); \ - PC |= (pop() << 8); \ - fetch(); \ +#define rti(ticks, adrmode) \ + tick(ticks); \ + P= pop(); \ + PC= pop(); \ + PC |= (pop() << 8); \ + fetch(); \ next(); -#define nop(ticks, adrmode) \ - fetch(); \ - tick(ticks); \ +#define nop(ticks, adrmode) \ + fetch(); \ + tick(ticks); \ next(); -#define ill(ticks, adrmode) \ - fetch(); \ - tick(ticks); \ - fflush(stdout); \ - fprintf(stderr, "\nundefined instruction %02X\n", memory[PC-1]); \ +#define ill(ticks, adrmode) \ + fetch(); \ + tick(ticks); \ + fflush(stdout); \ + fprintf(stderr, "\nundefined instruction %02X\n", memory[PC-1]); \ return; -#define phR(ticks, adrmode, R) \ - fetch(); \ - tick(ticks); \ - push(R); \ +#define phR(ticks, adrmode, R) \ + fetch(); \ + tick(ticks); \ + push(R); \ next(); -#define pha(ticks, adrmode) phR(ticks, adrmode, A) -#define phx(ticks, adrmode) phR(ticks, adrmode, X) -#define phy(ticks, adrmode) phR(ticks, adrmode, Y) -#define php(ticks, adrmode) phR(ticks, adrmode, P | flagX | flagB) +#define pha(ticks, adrmode) phR(ticks, adrmode, A) +#define phx(ticks, adrmode) phR(ticks, adrmode, X) +#define phy(ticks, adrmode) phR(ticks, adrmode, Y) +#define php(ticks, adrmode) phR(ticks, adrmode, P | flagX | flagB) -#define plR(ticks, adrmode, R) \ - fetch(); \ - tick(ticks); \ - R= pop(); \ - setNZ(R & 0x80, !R); \ +#define plR(ticks, adrmode, R) \ + fetch(); \ + tick(ticks); \ + R= pop(); \ + setNZ(R & 0x80, !R); \ next(); -#define pla(ticks, adrmode) plR(ticks, adrmode, A) -#define plx(ticks, adrmode) plR(ticks, adrmode, X) -#define ply(ticks, adrmode) plR(ticks, adrmode, Y) +#define pla(ticks, adrmode) plR(ticks, adrmode, A) +#define plx(ticks, adrmode) plR(ticks, adrmode, X) +#define ply(ticks, adrmode) plR(ticks, adrmode, Y) -#define plp(ticks, adrmode) \ - fetch(); \ - tick(ticks); \ - P= pop(); \ +#define plp(ticks, adrmode) \ + fetch(); \ + tick(ticks); \ + P= pop(); \ next(); -#define clF(ticks, adrmode, F) \ - fetch(); \ - tick(ticks); \ - P &= ~F; \ +#define clF(ticks, adrmode, F) \ + fetch(); \ + tick(ticks); \ + P &= ~F; \ next(); -#define clc(ticks, adrmode) clF(ticks, adrmode, flagC) -#define cld(ticks, adrmode) clF(ticks, adrmode, flagD) -#define cli(ticks, adrmode) clF(ticks, adrmode, flagI) -#define clv(ticks, adrmode) clF(ticks, adrmode, flagV) +#define clc(ticks, adrmode) clF(ticks, adrmode, flagC) +#define cld(ticks, adrmode) clF(ticks, adrmode, flagD) +#define cli(ticks, adrmode) clF(ticks, adrmode, flagI) +#define clv(ticks, adrmode) clF(ticks, adrmode, flagV) -#define seF(ticks, adrmode, F) \ - fetch(); \ - tick(ticks); \ - P |= F; \ +#define seF(ticks, adrmode, F) \ + fetch(); \ + tick(ticks); \ + P |= F; \ next(); -#define sec(ticks, adrmode) seF(ticks, adrmode, flagC) -#define sed(ticks, adrmode) seF(ticks, adrmode, flagD) -#define sei(ticks, adrmode) seF(ticks, adrmode, flagI) +#define sec(ticks, adrmode) seF(ticks, adrmode, flagC) +#define sed(ticks, adrmode) seF(ticks, adrmode, flagD) +#define sei(ticks, adrmode) seF(ticks, adrmode, flagI) -#define do_insns(_) \ +#define do_insns(_) \ _(00, brk, implied, 7); _(01, ora, indx, 6); _(02, ill, implied, 2); _(03, ill, implied, 2); \ _(04, tsb, zp, 3); _(05, ora, zp, 3); _(06, asl, zp, 5); _(07, ill, implied, 2); \ _(08, php, implied, 3); _(09, ora, immediate, 3); _(0a, asla,implied, 2); _(0b, ill, implied, 2); \ @@ -749,50 +749,50 @@ void M6502_run(M6502 *mpu) #if defined(__GNUC__) && !defined(__STRICT_ANSI__) static void *itab[256]= { &&_00, &&_01, &&_02, &&_03, &&_04, &&_05, &&_06, &&_07, &&_08, &&_09, &&_0a, &&_0b, &&_0c, &&_0d, &&_0e, &&_0f, - &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, &&_1a, &&_1b, &&_1c, &&_1d, &&_1e, &&_1f, - &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, &&_2a, &&_2b, &&_2c, &&_2d, &&_2e, &&_2f, - &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, &&_3a, &&_3b, &&_3c, &&_3d, &&_3e, &&_3f, - &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, &&_4a, &&_4b, &&_4c, &&_4d, &&_4e, &&_4f, - &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, &&_5a, &&_5b, &&_5c, &&_5d, &&_5e, &&_5f, - &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, &&_6a, &&_6b, &&_6c, &&_6d, &&_6e, &&_6f, - &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, &&_7a, &&_7b, &&_7c, &&_7d, &&_7e, &&_7f, - &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, &&_8a, &&_8b, &&_8c, &&_8d, &&_8e, &&_8f, - &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, &&_9a, &&_9b, &&_9c, &&_9d, &&_9e, &&_9f, - &&_a0, &&_a1, &&_a2, &&_a3, &&_a4, &&_a5, &&_a6, &&_a7, &&_a8, &&_a9, &&_aa, &&_ab, &&_ac, &&_ad, &&_ae, &&_af, - &&_b0, &&_b1, &&_b2, &&_b3, &&_b4, &&_b5, &&_b6, &&_b7, &&_b8, &&_b9, &&_ba, &&_bb, &&_bc, &&_bd, &&_be, &&_bf, - &&_c0, &&_c1, &&_c2, &&_c3, &&_c4, &&_c5, &&_c6, &&_c7, &&_c8, &&_c9, &&_ca, &&_cb, &&_cc, &&_cd, &&_ce, &&_cf, - &&_d0, &&_d1, &&_d2, &&_d3, &&_d4, &&_d5, &&_d6, &&_d7, &&_d8, &&_d9, &&_da, &&_db, &&_dc, &&_dd, &&_de, &&_df, - &&_e0, &&_e1, &&_e2, &&_e3, &&_e4, &&_e5, &&_e6, &&_e7, &&_e8, &&_e9, &&_ea, &&_eb, &&_ec, &&_ed, &&_ee, &&_ef, - &&_f0, &&_f1, &&_f2, &&_f3, &&_f4, &&_f5, &&_f6, &&_f7, &&_f8, &&_f9, &&_fa, &&_fb, &&_fc, &&_fd, &&_fe, &&_ff }; + &&_10, &&_11, &&_12, &&_13, &&_14, &&_15, &&_16, &&_17, &&_18, &&_19, &&_1a, &&_1b, &&_1c, &&_1d, &&_1e, &&_1f, + &&_20, &&_21, &&_22, &&_23, &&_24, &&_25, &&_26, &&_27, &&_28, &&_29, &&_2a, &&_2b, &&_2c, &&_2d, &&_2e, &&_2f, + &&_30, &&_31, &&_32, &&_33, &&_34, &&_35, &&_36, &&_37, &&_38, &&_39, &&_3a, &&_3b, &&_3c, &&_3d, &&_3e, &&_3f, + &&_40, &&_41, &&_42, &&_43, &&_44, &&_45, &&_46, &&_47, &&_48, &&_49, &&_4a, &&_4b, &&_4c, &&_4d, &&_4e, &&_4f, + &&_50, &&_51, &&_52, &&_53, &&_54, &&_55, &&_56, &&_57, &&_58, &&_59, &&_5a, &&_5b, &&_5c, &&_5d, &&_5e, &&_5f, + &&_60, &&_61, &&_62, &&_63, &&_64, &&_65, &&_66, &&_67, &&_68, &&_69, &&_6a, &&_6b, &&_6c, &&_6d, &&_6e, &&_6f, + &&_70, &&_71, &&_72, &&_73, &&_74, &&_75, &&_76, &&_77, &&_78, &&_79, &&_7a, &&_7b, &&_7c, &&_7d, &&_7e, &&_7f, + &&_80, &&_81, &&_82, &&_83, &&_84, &&_85, &&_86, &&_87, &&_88, &&_89, &&_8a, &&_8b, &&_8c, &&_8d, &&_8e, &&_8f, + &&_90, &&_91, &&_92, &&_93, &&_94, &&_95, &&_96, &&_97, &&_98, &&_99, &&_9a, &&_9b, &&_9c, &&_9d, &&_9e, &&_9f, + &&_a0, &&_a1, &&_a2, &&_a3, &&_a4, &&_a5, &&_a6, &&_a7, &&_a8, &&_a9, &&_aa, &&_ab, &&_ac, &&_ad, &&_ae, &&_af, + &&_b0, &&_b1, &&_b2, &&_b3, &&_b4, &&_b5, &&_b6, &&_b7, &&_b8, &&_b9, &&_ba, &&_bb, &&_bc, &&_bd, &&_be, &&_bf, + &&_c0, &&_c1, &&_c2, &&_c3, &&_c4, &&_c5, &&_c6, &&_c7, &&_c8, &&_c9, &&_ca, &&_cb, &&_cc, &&_cd, &&_ce, &&_cf, + &&_d0, &&_d1, &&_d2, &&_d3, &&_d4, &&_d5, &&_d6, &&_d7, &&_d8, &&_d9, &&_da, &&_db, &&_dc, &&_dd, &&_de, &&_df, + &&_e0, &&_e1, &&_e2, &&_e3, &&_e4, &&_e5, &&_e6, &&_e7, &&_e8, &&_e9, &&_ea, &&_eb, &&_ec, &&_ed, &&_ee, &&_ef, + &&_f0, &&_f1, &&_f2, &&_f3, &&_f4, &&_f5, &&_f6, &&_f7, &&_f8, &&_f9, &&_fa, &&_fb, &&_fc, &&_fd, &&_fe, &&_ff }; register void **itabp= &itab[0]; register void *tpc; -# define begin() fetch(); next() -# define fetch() tpc= itabp[memory[PC++]] -# define next() goto *tpc -# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) oops(); next() +# define begin() fetch(); next() +# define fetch() tpc= itabp[memory[PC++]] +# define next() goto *tpc +# define dispatch(num, name, mode, cycles) _##num: name(cycles, mode) oops(); next() # define end() #else /* (!__GNUC__) || (__STRICT_ANSI__) */ -# define begin() for (;;) switch (memory[PC++]) { +# define begin() for (;;) switch (memory[PC++]) { # define fetch() -# define next() break -# define dispatch(num, name, mode, cycles) case 0x##num: name(cycles, mode); next() -# define end() } +# define next() break +# define dispatch(num, name, mode, cycles) case 0x##num: name(cycles, mode); next() +# define end() } #endif register byte *memory= mpu->memory; register word PC; - word ea; - byte A, X, Y, P, S; + word ea; + byte A, X, Y, P, S; M6502_Callback *readCallback= mpu->callbacks->read; M6502_Callback *writeCallback= mpu->callbacks->write; -# define internalise() A= mpu->registers->a; X= mpu->registers->x; Y= mpu->registers->y; P= mpu->registers->p; S= mpu->registers->s; PC= mpu->registers->pc -# define externalise() mpu->registers->a= A; mpu->registers->x= X; mpu->registers->y= Y; mpu->registers->p= P; mpu->registers->s= S; mpu->registers->pc= PC +# define internalise() A= mpu->registers->a; X= mpu->registers->x; Y= mpu->registers->y; P= mpu->registers->p; S= mpu->registers->s; PC= mpu->registers->pc +# define externalise() mpu->registers->a= A; mpu->registers->x= X; mpu->registers->y= Y; mpu->registers->p= P; mpu->registers->s= S; mpu->registers->pc= PC internalise(); @@ -819,20 +819,20 @@ int M6502_disassemble(M6502 *mpu, word ip, char buffer[64]) switch (b[0]) { -# define _implied return 1; -# define _immediate sprintf(s, "#%02X", b[1]); return 2; -# define _zp sprintf(s, "%02X", b[1]); return 2; -# define _zpx sprintf(s, "%02X,X", b[1]); return 2; -# define _zpy sprintf(s, "%02X,Y", b[1]); return 2; -# define _abs sprintf(s, "%02X%02X", b[2], b[1]); return 3; -# define _absx sprintf(s, "%02X%02X,X", b[2], b[1]); return 3; -# define _absy sprintf(s, "%02X%02X,Y", b[2], b[1]); return 3; -# define _relative sprintf(s, "%04X", ip + 2 + (int8_t)b[1]); return 2; -# define _indirect sprintf(s, "(%02X%02X)", b[2], b[1]); return 3; -# define _indzp sprintf(s, "(%02X)", b[1]); return 2; -# define _indx sprintf(s, "(%02X,X)", b[1]); return 2; -# define _indy sprintf(s, "(%02X),Y", b[1]); return 2; -# define _indabsx sprintf(s, "(%02X%02X,X)", b[2], b[1]); return 3; +# define _implied return 1; +# define _immediate sprintf(s, "#%02X", b[1]); return 2; +# define _zp sprintf(s, "%02X", b[1]); return 2; +# define _zpx sprintf(s, "%02X,X", b[1]); return 2; +# define _zpy sprintf(s, "%02X,Y", b[1]); return 2; +# define _abs sprintf(s, "%02X%02X", b[2], b[1]); return 3; +# define _absx sprintf(s, "%02X%02X,X", b[2], b[1]); return 3; +# define _absy sprintf(s, "%02X%02X,Y", b[2], b[1]); return 3; +# define _relative sprintf(s, "%04X", ip + 2 + (int8_t)b[1]); return 2; +# define _indirect sprintf(s, "(%02X%02X)", b[2], b[1]); return 3; +# define _indzp sprintf(s, "(%02X)", b[1]); return 2; +# define _indx sprintf(s, "(%02X,X)", b[1]); return 2; +# define _indy sprintf(s, "(%02X),Y", b[1]); return 2; +# define _indabsx sprintf(s, "(%02X%02X,X)", b[2], b[1]); return 3; # define disassemble(num, name, mode, cycles) case 0x##num: s += sprintf(s, "%s ", #name); _##mode do_insns(disassemble); @@ -849,9 +849,9 @@ void M6502_dump(M6502 *mpu, char buffer[64]) uint8_t p= r->p; # define P(N,C) (p & (1 << (N)) ? (C) : '-') sprintf(buffer, "PC=%04X SP=%04X A=%02X X=%02X Y=%02X P=%02X %c%c%c%c%c%c%c%c", - r->pc, 0x0100 + r->s, - r->a, r->x, r->y, r->p, - P(7,'N'), P(6,'V'), P(5,'?'), P(4,'B'), P(3,'D'), P(2,'I'), P(1,'Z'), P(0,'C')); + r->pc, 0x0100 + r->s, + r->a, r->x, r->y, r->p, + P(7,'N'), P(6,'V'), P(5,'?'), P(4,'B'), P(3,'D'), P(2,'I'), P(1,'Z'), P(0,'C')); # undef P } diff --git a/lib6502/run6502.c b/lib6502/run6502.c index a7594c0..98a606b 100644 --- a/lib6502/run6502.c +++ b/lib6502/run6502.c @@ -25,16 +25,13 @@ #include #include #include -#include -#include #include "config.h" #include "lib6502.h" +#include "file6502.h" #define VERSION PACKAGE_NAME " " PACKAGE_VERSION " " PACKAGE_COPYRIGHT -#define DEBUG 0 - typedef uint8_t byte; typedef uint16_t word; @@ -42,25 +39,6 @@ static char *program= 0; static byte bank[0x10][0x4000]; -/* I/O Blocks for File I/O */ -#define MAXIOB 15 -#define STRLEN 128 -struct iocb -{ - int opened; //Flag: file opened - char type; //Channel Type: 'F', 'D' - char mode; //File Mode: 'R', 'W' - FILE *fp; //File Pointer - DIR *dp; //Directory Pointer - int errnum; //Last Error Number - char name[STRLEN]; //File/Directory Name -}; - -static struct iocb iocbs[MAXIOB]; -static char filename[STRLEN]; //File name for open -static char filebuff[256]; //File I/O Buffer -static word fileaddr; //File Read/Write Address - void fail(const char *fmt, ...) { va_list ap; @@ -270,6 +248,7 @@ 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, " -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"); @@ -290,6 +269,12 @@ static void usage(int status) exit(status); } +static int doDebug(int argc, char **argv, M6502 *mpu) +{ + setdebug(-1); + return 0; +} + static int doHelp(int argc, char **argv, M6502 *mpu) { @@ -360,14 +345,12 @@ static int load(M6502 *mpu, word address, const char *path) size_t max= 0x10000 - address; if (!(file= fopen(path, "rb"))) return 0; - if (DEBUG) fprintf(stderr, "loading %s\nstart address %04x\n", path, address); while ((count= fread(mpu->memory + address, 1, max, file)) > 0) { address += count; max -= count; } fclose(file); - if (DEBUG) fprintf(stderr, "end address %04x\n", address); return address; } @@ -411,342 +394,10 @@ doVEC(RST); #undef doVEC -int setiocb(int chan, int opened, char type, char mode, FILE *fp, DIR *dp, char *name) { - iocbs[chan].opened = opened; - iocbs[chan].type = type; - iocbs[chan].mode = mode; - iocbs[chan].fp = fp; - iocbs[chan].dp = dp; - iocbs[chan].errnum = 0; - strcpy(iocbs[chan].name, name); - return 0; -} - -void initiocb(int chan) { - setiocb(chan, 0, ' ', ' ', NULL, NULL, ""); -} - -void initiocbs(void) -{ - filename[0] = 0; //Set filename to "" - for (int chan=0; chan<=MAXIOB; chan++) - initiocb(chan); -} - -/* Set Error Number and Error Message */ -static int seterror(int chan) { - int errnum = errno; - if (DEBUG) fprintf(stderr, "setting channel %d error to %d\n", chan, errnum); - iocbs[chan].errnum = errnum; - return errnum; -} - -/* Set File Name */ -static int setname(M6502 *mpu, word addr, char *name) { - int i; - if (DEBUG) fprintf(stderr, "copying name from address $%04x\n", addr); - for (i=0; imemory[addr + i & 0xFFFF]; - if (c) name[i] = c; - else break; - } - name[i] = 0; //Terminate String - if (DEBUG) fprintf(stderr, "copied %d characters\n", i); - return i; -} - -/* Find Unused IOCB */ -static int uniocb(void) { - int chan; - for (chan=1; chan<=MAXIOB; chan++) { - if (iocbs[chan].opened == 0) break; - if (chan > MAXIOB) {chan = -24; break;} - } - return chan; -} - -/* Validate Channel */ -static int valchan(int chan, char valtype) { - int errnum = 0; //Error (none) - if (DEBUG) fprintf(stderr, "validating channel %d\n", chan); - 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); - switch (iocbs[chan].type) { - case 'D': errnum = 21; //Is a directory - case 'F': errnum = 20; //Not a directory - default: errnum = 77; //File descriptor in bad state - } - } - return errnum; -} - -/* Write Buffer to Memory */ -static int writemem(M6502 *mpu, char* buffer, int count) { - int i; - for (i = 0; imemory[fileaddr+i] = buffer[i]; - return i; -} - -/* Write String to Memory */ -static int writestr(M6502 *mpu, char* buffer, int count) { - int i; - if (DEBUG) fprintf(stderr, "writing '%s' to address %04x\n", buffer, fileaddr); - for (i = 0; imemory[fileaddr+i] = c; - } - mpu->memory[fileaddr+i] = 0; //Terminate String - if (DEBUG) fprintf(stderr, "wrote %d characters\n", i); - return i; -} - -/* Emulate fileio at addr */ static int fTrap(M6502 *mpu, word addr, byte data) { - const char modes[2][3] = {"r", "w"}; - int chan, e, i; - char c, mode[3]; - char *name; - struct dirent *de; - 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; - char drive = y & 0x1f; - if (DEBUG) fprintf(stderr, "executing '%c' with options %02x,%02x,%02x\n", a, y, x, p); - switch (a) { //File I/O Command - case 'A': //Set filebuffer address - Y.X = address - fileaddr = yx; - if (DEBUG) fprintf(stdout, "file address set to %04x\n", fileaddr); - break; - case 'B': //Close Directory - Y = channel - chan = y; - if (DEBUG) fprintf(stderr, "closing directory channel %d\n", chan); - y = valchan(chan, 'D'); if (y) break; - if (closedir(iocbs[chan].dp)) y = seterror(chan); - else initiocb(chan); - break; - case 'C': //Close file - Y = channel - chan = y; - if (DEBUG) fprintf(stderr, "closing file channel %d\n", chan); - y = valchan(chan, 'F'); if (y) break; - if (fclose(iocbs[chan].fp)) y = seterror(chan); - else initiocb(chan); - break; - case 'D': //Open Directory - Y,X = Directory Name - x = 0; //File channel (none) - y = 0; //Error code (none) - chan = uniocb(); if (chan <0) {y = -chan; break;} - setname(mpu, yx, filename); - if (strlen(filename) == 0) strcpy(filename, "."); - if (DEBUG) fprintf(stderr, "opening directory '%s'\n", filename, mode); - DIR *dp = opendir(filename); - if (dp == NULL) { y = seterror(0); break;} - if (DEBUG) fprintf(stderr, "directory opened on channel %d\n", chan); - y = setiocb(chan, -1, 'D', ' ', NULL, dp, filename); //Setup IOCB - if (y == 0) x = chan; - break; - case 'E': //EOF - Y = channel - chan = y; - y = valchan(chan, 'F'); if (y) break; - y = feof(iocbs[chan].fp); - break; - case 'F': //Flush File - Y = Channel - chan = y; - y = valchan(chan, 'F'); if (y) break; - if (fflush(iocbs[chan].fp)) y = seterror(chan); - break; - case 'G': //Get character - Y = channel - chan = y; - x = 0; //Character read (none) - y = valchan(chan, 'F'); if (y) break; - c = fgetc(iocbs[chan].fp); - if (feof(iocbs[chan].fp)) {y = 255; break;} - if (c == EOF) {y = seterror(chan); break;} - x = c & 0xFF; - break; - case 'H': //Get String - Y = channel - chan = y; - x = 0; //Number of Characters read - y = valchan(chan, 'F'); if (y) break; - char *s = fgets(filebuff, STRLEN, iocbs[chan].fp); - if (s == NULL) {y = seterror(chan); break;} - if (DEBUG) fprintf(stderr, "read string '%s'\n", filebuff); - writestr(mpu, filebuff, STRLEN); - break; - case 'I': //Init File System - initiocbs(); //Initialize I/O Control Blocks - break; - case 'J': //Read Directory Entry - chan = y; - x = 0; //Return Value (Read Failed) - y = valchan(chan, 'D'); if (y) break; - if (p & 1) { - if (DEBUG) fprintf(stdout, "retrieving directory name\n"); - x = writestr(mpu, iocbs[chan].name, STRLEN); - } else { - if (DEBUG) fprintf(stdout, "reading directory entry\n"); - de = readdir(iocbs[chan].dp); - if (de) { - if (DEBUG) fprintf(stdout, "read entry '%s'\n", de->d_name); - x = writestr(mpu, de->d_name, STRLEN); - } - else if (errno != 2) y = seterror(chan); - } - break; - case 'K': //REMOVE - Delete File - Y,X = Filename - setname(mpu, yx, filename); - if (DEBUG) fprintf(stderr, "removing file '%s'\n", filename); - x = remove(filename); - if (x) y=seterror(0); else y=0; - break; - case 'L': //Load file - a = 0; //Error (none) - if (DEBUG) fprintf(stderr, "loading file at %04h\n", fileaddr); - e = load(mpu, fileaddr, filename); - if (!e) {a = seterror(0); break;} - y = e >> 8; x = e & 0xff; - break; - case 'M': //MOVE - Rename File - Y,X = Filename - setname(mpu, yx, filebuff); - if (DEBUG) fprintf(stderr, "renaming file '%s' to '%s'\n", filename, filebuff); - x = rename(filename, filebuff); - if (x) y=seterror(0); else y=0; - break; - case 'N': //Set filename - Y,X = string address - x = setname(mpu, yx, filename); //Set filename and Return Length - if (DEBUG) fprintf(stderr, "filename set to '%s'\n", filename); - break; - case 'O': //Open file - Y = Drive#, X = Mode (0x80 = Write) - strcpy(mode, modes[x >> 7]); //Set Mode based on Negative Flag - x = 0; //File channel (none) - y = 0; //Error code (none) - chan = uniocb(); if (chan <0) {y = -chan; break;} - if (DEBUG) fprintf(stderr, "opening file '%s' with mode '%s'\n", filename, mode); - FILE *fp = fopen(filename, mode); - if (fp == NULL) { y = seterror(0); break;} - if (DEBUG) fprintf(stderr, "file opened on channel %d\n", chan); - y = setiocb(chan, -1, 'F', mode[0], fp, NULL, filename); //Setup IOCB - if (y == 0) x = chan; - break; - case 'P': //Put character - Y = channel; X = character - chan = y; - c = x; - if (DEBUG) fprintf(stderr, "writing '%c' to channel %d\n", c, chan); - a = 0; //Character written (none) - y = valchan(chan, 'F'); if (y) break; - e = fputc(c, iocbs[chan].fp); - if (e == EOF) {y = seterror(chan); break;} - a = e & 0xFF; - break; - case 'Q': //Put String - Y = channel - chan = y; - x = 0; //Number of characters written - y = valchan(chan, 'F'); if (y) break; - for (i = 0; i<128; i++) { - c = mpu->memory[fileaddr+i]; - if (c) filebuff[i] = c; - else break; - } - filebuff[i] = 0; - if (DEBUG) fprintf(stderr, "writing string '%s'\n", filebuff); - if (p & 1) strcat(filebuff, "\n"); - e = fputs(filebuff, iocbs[chan].fp); - if (e == EOF) {y = seterror(chan); break;} - break; - case 'R': //Read bytes - Y = channel, X=Number of Bytes - chan = y; - y = valchan(chan, 'F'); if (y) break; - if (DEBUG) fprintf(stderr, "reading %d bytes\n", x); - e = fread(filebuff, x, 1, iocbs[chan].fp); - if (e != 1) {y = seterror(chan); break;} - writemem(mpu, filebuff, x); - break; - case 'S': //Save file Y,X = end address - a = 0; //Error (none) - if (DEBUG) fprintf(stderr, "saving file from %04x to %04x\n", fileaddr, yx); - e = save(mpu, fileaddr, yx-fileaddr-1, filename); - if (!e) {a = seterror(0); break;} - y = e >> 8; x = e & 0xff; - break; - case 'T': //Get Current Directory - YX = String Address - x = 0; //Directory Name Length - y = 0; //Error (None) - if (DEBUG) fprintf(stderr, "getting current working directory\n"); - if (_getcwd(filename, STRLEN)) { - if (DEBUG) fprintf(stderr, "cwd: %s\n", filename); - for (i = 0; imemory[yx+i] = c; - } - mpu->memory[yx+i] = 0; - x = i; - } - else y = seterror(0); - break; - case 'U': //Change Directory - YX = Directory Name - x = 0; //Result (Success) - y = 0; //Error (None) - setname(mpu, yx, filename); //Set filename to Directory Name - if (DEBUG) fprintf(stderr, "changing directory to '%s'\n", filename); - if (_chdir(filename)) {x = 0xFF; y = seterror(0);} - break; - case 'V': //Get or Set Current Drive, Y=Drive, Carry=Get/Set - if (p & 1) { - if (DEBUG) fprintf(stderr, "changing drive to %c\n", y+'@'); - x = _chdrive(y); - if (x) y=seterror(0); else y=0; - } else { - x = _getdrive(); - if (x) y=0; else y=seterror(0); - if (DEBUG) fprintf(stderr, "current drive is %c\n", x+'@'); - } - break; - case 'W': //Write bytes - Y = channel, X=Number of Bytes - chan = y; - y = valchan(chan, 'F'); if (y) break; - for (i = 0; imemory[fileaddr+i]; - if (DEBUG) fprintf(stderr, "writing %d bytes\n", x); - e = fwrite(filebuff, x, 1, iocbs[chan].fp); - if (e != 1) {y = seterror(chan); break;} - break; - case 'X': //Make/Remove Directory - YX = Directory Name - setname(mpu, yx, filename); - if (p & 1) { - if (DEBUG) fprintf(stderr, "removing directory '%s'\n", filename); - x = _rmdir(filename); - } else { - if (DEBUG) fprintf(stderr, "creating directory '%s'\n", filename); - x = _mkdir(filename); - } - if (x) y=seterror(0); else y=0; - break; - case 'Y': //Get Last Error, Y=chan - chan = y; - y = 0; //Set Error to None - x = 0xFF; //Set Result to Invalid - if (chan > MAXIOB) {y = 44; break;} - if (DEBUG) fprintf(stderr, "getting last error for channel %d\n", chan); - x = iocbs[chan].errnum; - char *msg = strerror(x); - if (DEBUG) fprintf(stderr, "retrieved error %d, '%s'\n", x, msg); - writestr(mpu, msg, STRLEN); - break; - default: - y = 22; //Error - invalid argument - } - mpu->registers->a = a; - mpu->registers->x = x; - mpu->registers->y = y; - rts; + filecmd(mpu, addr, data); + rts; } - static int doFtrap(int argc, char **argv, M6502 *mpu) { unsigned addr; @@ -853,6 +504,7 @@ int main(int argc, char **argv) { M6502 *mpu= M6502_new(0, 0, 0); int bTraps= 0; + setdebug(0); program= argv[0]; @@ -868,6 +520,7 @@ 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, "-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); diff --git a/lib6502/tcc6502.bat b/lib6502/tcc6502.bat index 6d73387..9abbb62 100644 --- a/lib6502/tcc6502.bat +++ b/lib6502/tcc6502.bat @@ -1 +1 @@ -tcc -o run6502.exe -I . dirent.c lib6502.c run6502.c +tcc -o run6502.exe -I . lib6502.c dirent.c file6502.c run6502.c