diff --git a/examples/pgztest/pgztest.c b/examples/pgztest/pgztest.c index 363a1bf..fe66bde 100644 --- a/examples/pgztest/pgztest.c +++ b/examples/pgztest/pgztest.c @@ -29,17 +29,13 @@ void dirtest(void) { DIR *dir; struct dirent *dirent; - textPrint("Starting directory test.\n"); + //textPrint("Starting directory test.\n"); if ((dir = opendir("0:"))) { - textPrint("Directory opened.\n"); + //textPrint("Directory opened.\n"); for (;;) { if ((dirent = readdir(dir))) { - textPrint("dirent type="); - textPrintInt(dirent->d_type); - textPrint("\n"); - if (_DE_ISREG(dirent->d_type)) { textPrint(dirent->d_name); textPrint(" ("); @@ -63,7 +59,7 @@ void dirtest(void) { } break; } - textPrint("Closing.\n"); + //textPrint("Closing.\n"); closedir(dir); } else { textPrint("Failed to open directory.\n"); @@ -74,7 +70,8 @@ void dirtest(void) { int main(void) { f256Init(); - dirtest(); +// dirtest(); + printf("Int = %d\n", sizeof(int)); return 0; } diff --git a/f256lib/api.h b/f256lib/api.h index b82611d..7729a84 100644 --- a/f256lib/api.h +++ b/f256lib/api.h @@ -13,6 +13,9 @@ #include +#pragma push_macro("EOF") +#undef EOF + struct call { // Mount at $ff00 long NextEvent; // Copy the next event into user-space. @@ -85,6 +88,7 @@ struct call { // Mount at $ff00 long Reject; // Reply to a received TCP packet with a REJECT message. long Send; // Accept some new data and send an ACK along with any unACK'd data. long Recv; // Copy any new TCP bytes into the user's buf and update the socket state. + long Close; } TCP; }; @@ -98,8 +102,10 @@ struct call { // Mount at $ff00 struct { long GetTime; // Get the date+time in BCD: YY,YY,MM,DD,HH,MM,SS,cS long SetTime; // - long GetSysInfo; // - long SetBPS; // + long vectors816_1; + long vectors816_2; // 12 bytes skipped here. + long vectors816_3; + long SetTimer; // } Config; }; @@ -408,4 +414,8 @@ struct event_t { struct event_dir_t directory; }; }; + + +#pragma pop_macro("EOF") + #endif diff --git a/f256lib/f256.h b/f256lib/f256.h index 5587e62..a1b1759 100644 --- a/f256lib/f256.h +++ b/f256lib/f256.h @@ -32,6 +32,8 @@ extern "C" #include +#include + #include "stddclmr.h" #include "api.h" diff --git a/f256lib/file.c b/f256lib/file.c index 40b3ac0..df6bbdc 100644 --- a/f256lib/file.c +++ b/f256lib/file.c @@ -32,9 +32,35 @@ static char _dirStream[MAX_DRIVES]; -static char *pathWithoutDrive(char *path, char *drive); +static bool findName(const char *name, int16_t *offset); +static char getIn(void); // This isn't the best place for this. +static int16_t kernelRead(uint8_t fd, void *buf, uint16_t nbytes); +static int16_t kernelWrite(uint8_t fd, void *buf, uint16_t nbytes); +static char *pathWithoutDrive(char *path, char *drive); +#pragma push_macro("close") +#undef close +void fileClose(uint8_t fd) { + kernelArgs->file.close.stream = fd; + kernelCall(File.Close); + + for (;;) { + kernelNextEvent(); + switch (kernelEventData.type) { + case kernelEvent(file.CLOSED): + case kernelEvent(file.ERROR): + return; + default: + continue; + } + } +} +#pragma pop_macro("close") + + +#pragma push_macro("close") +#undef close int16_t fileCloseDir(fileDirT *dir) { if (!dir) return -1; @@ -54,6 +80,44 @@ int16_t fileCloseDir(fileDirT *dir) { } } } +#pragma pop_macro("close") + + +int16_t fileOpen(char *fname, char *mode) { + int16_t ret = 0; + uint8_t m = 0; // Default to READ. + char drive; + char *c; + + fname = pathWithoutDrive(fname, &drive); + + c = mode; + while (*c != 0) { + if (*c == 'w') m = 1; // WRITE + if (*c == 'a') m = 2; // APPEND + c++; + } + + kernelArgs->common.buf = (uint8_t *)fname; + kernelArgs->common.buflen = strlen(fname); + kernelArgs->file.open.drive = drive; + kernelArgs->file.open.mode = m; + ret = kernelCall(File.Open); + if (kernelError) return -1; + + for (;;) { + kernelNextEvent(); + switch (kernelEventData.type) { + case kernelEvent(file.OPENED): + return ret; + case kernelEvent(file.NOT_FOUND): + case kernelEvent(file.ERROR): + return -1; + default: + continue; + } + } +} fileDirT *fileOpenDir(char *name) { @@ -69,21 +133,11 @@ fileDirT *fileOpenDir(char *name) { kernelArgs->common.buf = name; kernelArgs->common.buflen = strlen(name); stream = kernelCall(Directory.Open); - - textPrint("kernelError = "); textPrintInt(kernelError); textPrint("\n"); - textPrint("kernelReturn = "); textPrintInt(kernelReturn); textPrint("\n"); - textPrint("stream = "); textPrintInt(stream); textPrint("\n"); - if (kernelError) return NULL; for (;;) { kernelNextEvent(); - if (kernelEventData.type != 0) { - textPrintInt(kernelEventData.type); - textPrint(" "); - } - if (kernelEventData.type == kernelEvent(directory.OPENED)) break; if (kernelEventData.type == kernelEvent(directory.ERROR)) return NULL; } @@ -96,30 +150,40 @@ fileDirT *fileOpenDir(char *name) { } +int16_t fileRead(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t fd) { + char *data = (char *)buf; + int16_t gathered = 0; + int16_t returned; + uint16_t bytes = nbytes * nmemb; + + while (gathered < bytes) { + returned = kernelRead(fd, data + gathered, bytes - gathered); + if (returned <= 0) break; + gathered += returned; + } + + return gathered; +} + + +#pragma push_macro("EOF") +#pragma push_macro("FILE") +#undef EOF +#undef FILE fileDirEntT *fileReadDir(fileDirT *dir) { static fileDirEntT dirent; - unsigned len; + uint16_t len; if (!dir) return NULL; - textPrint("Calling Directory.Read.\n"); - textPrint("stream = "); textPrintInt(*dir->stream); textPrint("\n"); - kernelArgs->directory.read.stream = *dir->stream; kernelCall(Directory.Read); if (kernelError) return NULL; - textPrint("Directory.Read called.\n"); - for (;;) { - kernelNextEvent(); switch (kernelEventData.type) { - - textPrintInt(kernelEventData.type); - textPrint(" "); - case kernelEvent(directory.VOLUME): dirent.d_blocks = 0; dirent.d_type = 2; @@ -163,6 +227,49 @@ fileDirEntT *fileReadDir(fileDirT *dir) { return &dirent; } } +#pragma pop_macro("FILE") +#pragma pop_macro("EOF") + + +int16_t fileRename(char *name, char *to) { + char drive; + char drive2; + char stream; + int16_t path1; + int16_t path2; + + name = pathWithoutDrive(name, &drive); + to = pathWithoutDrive(to, &drive2); + + // ensure that the paths match + if (false + || (drive != drive2) + || !findName(name, &path1) + || !findName(to, &path2) + || (path1 != path2) + || (strncmp(name, to, path1) != 0) + ) { + return -1; + } + + to += path2; + + kernelArgs->file.delete.drive = drive; + kernelArgs->common.buf = name; + kernelArgs->common.buflen = strlen(name); + kernelArgs->common.ext = to; + kernelArgs->common.extlen = strlen(to); + stream = kernelCall(File.Rename); + if (kernelError) return -1; + + for (;;) { + kernelNextEvent(); + if (kernelEventData.type == kernelEvent(file.RENAMED)) break; + if (kernelEventData.type == kernelEvent(file.ERROR)) return -1; + } + + return 0; +} void fileReset(void) { @@ -172,6 +279,152 @@ void fileReset(void) { } +int16_t fileUnlink(char *name) { + char drive; + char stream; + + name = pathWithoutDrive(name, &drive); + kernelArgs->file.delete.drive = drive; + kernelArgs->common.buf = name; + kernelArgs->common.buflen = strlen(name); + stream = kernelCall(File.Delete); + if (kernelError) return -1; + + for (;;) { + kernelNextEvent(); + if (kernelEventData.type == kernelEvent(file.DELETED)) break; + if (kernelEventData.type == kernelEvent(file.ERROR)) return -1; + } + + return 0; +} + + +int16_t fileWrite(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t fd) { + uint8_t *data = (uint8_t *)buf; + int16_t total = 0; + int16_t bytes = nbytes * nmemb; + uint8_t writing; + int16_t written; + int16_t i; + char *text; + + if (fd == 1) { + text = (char *)buf; + for (i = 0; i < bytes; i++) { + __putchar(text[i]); + } + return i; + } + + while (bytes) { + + if (bytes > 254) { + writing = 254; + } else { + writing = bytes; + } + + written = kernelWrite(fd, data + total, writing); + if (written <= 0) { + return -1; + } + + total += written; + bytes -= written; + } + + return total; +} + + +static bool findName(const char *name, int16_t *offset) { + int16_t i; + int16_t pos; + + for (i = pos = 0; name[i]; i++) { + if (name[i] == '/') { + pos = i+1; + if (!name[pos]) { + // No base name found! + return false; + } + } + } + + *offset = pos; + return true; +} + + +static char getIn(void) { + while (1) { + kernelNextEvent(); + if (kernelError) { + kernelCall(Yield); + continue; + } + + if (kernelEventData.type != kernelEvent(key.PRESSED)) continue; + if (kernelEventData.key.flags) continue; // Meta key. + + return kernelEventData.key.ascii; + } +} + + +#pragma push_macro("EOF") +#undef EOF +static int16_t kernelRead(uint8_t fd, void *buf, uint16_t nbytes) { + + if (fd == 0) { + // stdin + *(char *)buf = getIn(); + return 1; + } + + if (nbytes > 256) nbytes = 256; + + kernelArgs->file.read.stream = fd; + kernelArgs->file.read.buflen = nbytes; + kernelCall(File.Read); + if (kernelError) return -1; + + for(;;) { + kernelNextEvent(); + switch (kernelEventData.type) { + case kernelEvent(file.DATA): + kernelArgs->common.buf = buf; + kernelArgs->common.buflen = kernelEventData.file.data.delivered; + kernelCall(ReadData); + if (!kernelEventData.file.data.delivered) return 256; + return kernelEventData.file.data.delivered; + case kernelEvent(file.EOF): + return 0; + case kernelEvent(file.ERROR): + return -1; + default: + continue; + } + } +} +#pragma pop_macro("EOF") + + +static int16_t kernelWrite(uint8_t fd, void *buf, uint16_t nbytes) { + kernelArgs->file.read.stream = fd; + kernelArgs->common.buf = buf; + kernelArgs->common.buflen = nbytes; + kernelCall(File.Write); + if (kernelError) return -1; + + for (;;) { + kernelNextEvent(); + if (kernelEventData.type == kernelEvent(file.WROTE)) return kernelEventData.file.data.delivered; + if (kernelEventData.type == kernelEvent(file.ERROR)) return -1; + } +} + static char *pathWithoutDrive(char *path, char *drive) { *drive = 0; diff --git a/f256lib/file.h b/f256lib/file.h index 30cdda8..2a6e980 100644 --- a/f256lib/file.h +++ b/f256lib/file.h @@ -45,10 +45,16 @@ typedef struct fileDirEntS { } fileDirEntT; +void fileClose(uint8_t fd); int16_t fileCloseDir(fileDirT *dir); +int16_t fileOpen(char *fname, char *mode); fileDirT *fileOpenDir(char *name); +int16_t fileRead(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t fd); fileDirEntT *fileReadDir(fileDirT *dir); +int16_t fileRename(char *name, char *to); void fileReset(void); +int16_t fileUnlink(char *name); +int16_t fileWrite(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t fd); #define _DE_ISREG(t) (t == 0) @@ -59,11 +65,18 @@ void fileReset(void); // Aliases to the standard names if they don't exist. #ifndef DIR +#define close fileClose +#define closedir fileCloseDir #define DIR fileDirT #define dirent fileDirEntS +#define FILE uint8_t +#define fopen fileOpen +#define fread fileRead +#define fwrite fileWrite #define opendir fileOpenDir -#define closedir fileCloseDir #define readdir fileReadDir +#define rename fileRename +#define unlink fileUnlink #endif diff --git a/f256lib/kernel.h b/f256lib/kernel.h index ff9ca9b..72714eb 100644 --- a/f256lib/kernel.h +++ b/f256lib/kernel.h @@ -38,13 +38,33 @@ extern "C" #define kernelEvent(member) (size_t)(&((struct events *)0)->member) #define kernelVector(member) (size_t)(&((struct call *)0xff00)->member) #define kernelCall(fn) \ - ({ asm("jsr %[addy] \n" \ - "stz %[err] \n" \ - "ror %[err] \n" \ - "sta %[ret]" \ - : [err] "+m"(kernelError), [ret] "+m"(kernelReturn) \ - : [addy] "i"(kernelVector(fn)) \ - : "a", "x", "y", "c", "v"); kernelReturn; }) + ({ asm( \ + "jsr %[addy] \n" \ + "sta (%[ret]) \n" \ + "lda #0 \n" \ + "ror a \n" \ + "sta (%[err]) \n" \ + : [err] "=m"(kernelError), [ret] "=m"(kernelReturn) \ + : [addy] "i"(kernelVector(fn)) \ + : "a", "c", "v"); \ + kernelReturn; }) +/* +asm ( + ".text\n" + ".global kernelwrapper\n" + "kernelwrapper: \n" + " jsr 1f \n" + " tax \n" + " lda #0 \n" + " ror a \n" + " sta (__rs2) \n" + " txa \n" + " rts \n" + "1: jmp (__rs1) \n" + ); +unsigned char kernelwrapper(void *vector, char *error); +#define kernelCall(fn) kernelwrapper((void*)kernelVector(fn), &kernelError) +*/ typedef struct event_t kernelEventT; diff --git a/f256lib/text.c b/f256lib/text.c index 4f788c4..eaf524c 100644 --- a/f256lib/text.c +++ b/f256lib/text.c @@ -54,6 +54,14 @@ static byte _bcolor = 0; static byte _ccolor = 240; +// printf() support. +void __putchar(char c) { + static char s[2] = { 0, 0 }; + s[0] = c; + textPrint(s); +} + + // Clear screen to current text attributes. void textClear(void) { byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state. diff --git a/f256lib/text.h b/f256lib/text.h index c1c119c..05f8ca2 100644 --- a/f256lib/text.h +++ b/f256lib/text.h @@ -59,6 +59,8 @@ typedef enum textColorsE { extern colorT textColors[16]; +void __putchar(char c); // Allows printf(). + void textClear(void); void textDefineColor(byte slot, byte fr, byte fg, byte fb, byte br, byte bg, byte bb); void textGetXY(byte *x, byte *y);