Bläddra i källkod

Assembler for BCC updated to new cpu arch and brfs. Seems to work on a few programs but not fully tested yet. Current fgetc is very slow without buffer. Same goes for BCC

bart 7 månader sedan
förälder
incheckning
42f0174d60

+ 107 - 117
BCC/FPGCbuildTools/asm/asm.c

@@ -20,12 +20,10 @@
 
 #define word char
 
-#define STDIO_FBUF_ADDR 0x440000
-
 #include "lib/math.c"
 #include "lib/sys.c"
 #include "lib/stdlib.c"
-#include "lib/fs.c"
+#include "lib/brfs.c"
 #include "lib/stdio.c"
 
 #define USERBDOS_OFFSET 0x400000 // applied offset to all labels
@@ -39,7 +37,13 @@
 #define LABELLIST_ADDR 0x660000
 
 #define LINEBUFFER_ADDR 0x4C0000
-char infilename[96];
+
+word fd_input = -1;
+word fd_output = -1;
+
+char absolute_path_in[MAX_PATH_LENGTH];
+word filesize_input = 0;
+
 char *lineBuffer = (char*) LINEBUFFER_ADDR;
 
 word memCursor = 0; // cursor for readMemLine
@@ -65,7 +69,7 @@ word readFileLine()
 
     word outputi = 0;
 
-    char c = fgetc();
+    char c = fgetc(fd_input, filesize_input);
     char cprev = c;
     // stop on EOF or newline
     while (c != EOF && c != '\n')
@@ -108,7 +112,7 @@ word readFileLine()
             
         
         cprev = c;
-        c = fgetc();
+        c = fgetc(fd_input, filesize_input);
     }
 
     lineBuffer[outputi] = 0; // terminate
@@ -118,9 +122,9 @@ word readFileLine()
         if (lineBuffer[0] != 0)
         {
             // all code after the last \n is ignored!
-            BDOS_PrintConsole("Skipped: ");
-            BDOS_PrintConsole(lineBuffer);
-            BDOS_PrintConsole("\n");
+            bdos_print("Skipped: ");
+            bdos_print(lineBuffer);
+            bdos_print("\n");
         }
         return EOF;
     }
@@ -167,7 +171,7 @@ word readMemLine(char* memAddr)
     // if empty line, read next line
     if (outputi == 0)
     {
-        BDOS_PrintConsole("Empty string in readMemLine!!!\n");
+        bdos_print("Empty string in readMemLine!!!\n");
         return EOF;
     }
 
@@ -192,7 +196,7 @@ void getArgPos(word argi, char* bufOut)
     }
     if (linei == 0)
     {
-        BDOS_PrintConsole("getArgPos error");
+        bdos_print("getArgPos error");
         exit(1);
     }
     // copy until space or \n
@@ -227,7 +231,7 @@ word getNumberAtArg(word argi)
     }
     if (linei == 0)
     {
-        BDOS_PrintConsole("NumberAtArg error");
+        bdos_print("NumberAtArg error");
         exit(1);
     }
 
@@ -463,7 +467,7 @@ word Pass1Dw(char* outputAddr, char* outputCursor)
 
 void Pass1Db(char* outputAddr, char* outputCursor)
 {
-    BDOS_PrintConsole(".db is not yet implemented!\n");
+    bdos_print(".db is not yet implemented!\n");
     exit(1);
 }
 
@@ -524,7 +528,7 @@ void LinePass1(char* outputAddr, char* outputCursor)
 
 void doPass1()
 {
-    BDOS_PrintConsole("Doing pass 1\n");
+    bdos_print("Doing pass 1\n");
 
     memCursor = 0; // reset cursor for readMemLine
     globalLineCursor = 0; // keep track of the line number for the labels
@@ -534,9 +538,10 @@ void doPass1()
     word filePass1Cursor = 0;
 
     // add userBDOS header instructions
-    memcpy(outfilePass1Addr, "jump Main\njump Int\njump Main\njump Main\n", 39);
-    filePass1Cursor += 39;
-    globalLineCursor += 5;
+    char* userBDOSHeader = "jump Main\njump Int\njump Main\njump Main\n";
+    memcpy(outfilePass1Addr, userBDOSHeader, strlen(userBDOSHeader));
+    filePass1Cursor += strlen(userBDOSHeader);
+    globalLineCursor += 4;
 
     while (readMemLine(outfileCodeAddr) != EOF)
     {
@@ -596,6 +601,8 @@ void LinePass2(char* outputAddr, char* outputCursor)
         pass2Savpc(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "reti", 4))
         pass2Reti(outputAddr, outputCursor);
+    else if (memcmp(lineBuffer, "ccache", 6))
+        pass2Ccache(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "or ", 3))
         pass2Or(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "and ", 4))
@@ -618,6 +625,8 @@ void LinePass2(char* outputAddr, char* outputCursor)
         pass2Mults(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "multu ", 6))
         pass2Multu(outputAddr, outputCursor);
+    else if (memcmp(lineBuffer, "multfp ", 7))
+        pass2Multfp(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "slt ", 4))
         pass2Slt(outputAddr, outputCursor);
     else if (memcmp(lineBuffer, "sltu ", 5))
@@ -638,9 +647,9 @@ void LinePass2(char* outputAddr, char* outputCursor)
         pass2Dl(outputAddr, outputCursor);
     else
     {
-        BDOS_PrintConsole("Unknown instruction!\n");
-        BDOS_PrintConsole(lineBuffer);
-        BDOS_PrintConsole("\n");
+        bdos_print("Unknown instruction!\n");
+        bdos_print(lineBuffer);
+        bdos_print("\n");
         exit(1);
     }
 }
@@ -649,7 +658,7 @@ void LinePass2(char* outputAddr, char* outputCursor)
 // returns the length of the binary
 word doPass2()
 {
-    BDOS_PrintConsole("Doing pass 2\n");
+    bdos_print("Doing pass 2\n");
 
     memCursor = 0; // reset cursor for readMemLine
 
@@ -676,7 +685,15 @@ void moveDataDown()
     *outfileCodeAddr = 0; // initialize to 0
     word fileCodeCursor = 0;
 
-    BDOS_PrintConsole("Looking for .data and .code sections\n");
+    bdos_print("Looking for .data and .code sections\n");
+
+    // Open file
+    fd_input = fs_open(absolute_path_in);
+    if (fd_input == -1)
+    {
+        bdos_print("UNEXPECTED: Could not open input file.\n");
+        exit(1);
+    }
 
     // .data, also do pass one on the code
     word inDataSection = 0;
@@ -735,11 +752,16 @@ void moveDataDown()
     *(outfileCodeAddr+fileCodeCursor) = 0; // terminate code section
     // do not increment the codeCursor, because we will append the data section
 
-    BDOS_PrintConsole("Looking for .rdata and .bss sections\n");
+    bdos_print("Looking for .rdata and .bss sections\n");
 
     // reopen file to reiterate
-    fclose();
-    fopenRead(infilename);
+    fs_close(fd_input);
+    fd_input = fs_open(absolute_path_in);
+    if (fd_input == -1)
+    {
+        bdos_print("UNEXPECTED: Could not open input file.\n");
+        exit(1);
+    }
 
     //.rdata and .bss at the same time
     inDataSection = 0;
@@ -781,145 +803,113 @@ void moveDataDown()
     *(outfileDataAddr+fileDataCursor) = 0; // terminate data section
     fileDataCursor++;
 
-    BDOS_PrintConsole("Appending all to .code section\n");
+    bdos_print("Appending all to .code section\n");
 
     // append data section to code section, including \0
     memcpy((outfileCodeAddr+fileCodeCursor), outfileDataAddr, fileDataCursor);
+
+    fs_close(fd_input);
 }
 
 
 int main() 
 {
-    BDOS_PrintConsole("B322 Assembler\n");
+    bdos_print("B322 Assembler\n");
 
-    // output file
+    // Read number of arguments
+    word argc = shell_argc();
+    if (argc < 3)
+    {
+        bdos_print("Usage: asm <source file> <output file>\n");
+        return 1;
+    }
 
-    char outfilename[96];
-    BDOS_GetArgN(2, outfilename);
+    // Get input filename
+    char** args = shell_argv();
+    char* filename = args[1];
 
-    // Default to a.out
-    if (outfilename[0] == 0)
+    // Check if absolute path
+    if (filename[0] != '/')
     {
-        strcat(outfilename, BDOS_GetPath());
-        if (outfilename[strlen(outfilename)-1] != '/')
-        {
-            strcat(outfilename, "/");
-        }
-        strcat(outfilename, "A.OUT");
+        strcpy(absolute_path_in, fs_getcwd());
+        strcat(absolute_path_in, "/");
+        strcat(absolute_path_in, filename);
     }
-
-    // Make full path if it is not already
-    if (outfilename[0] != '/')
+    else
     {
-        char bothPath[96];
-        bothPath[0] = 0;
-        strcat(bothPath, BDOS_GetPath());
-        if (bothPath[strlen(bothPath)-1] != '/')
-        {
-            strcat(bothPath, "/");
-        }
-        strcat(bothPath, outfilename);
-        strcpy(outfilename, bothPath);
+        strcpy(absolute_path_in, filename);
     }
 
-    // create output file, test if it can be created/opened
-    if (!fopenWrite(outfilename))
+    fd_input = fs_open(absolute_path_in);
+    if (fd_input == -1)
     {
-        BDOS_PrintConsole("Could not open outfile\n");
-        return 0;
+        bdos_print("Could not open input file.\n");
+        return 1;
     }
-    fclose();
-
-
+    // Get file size
+    struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(absolute_path_in);
+    filesize_input = entry->filesize;
+    fs_close(fd_input); // Close so we can reopen it later when needed
 
-    // input file
+    // Get output filename
+    args = shell_argv();
+    filename = args[2];
 
-    BDOS_GetArgN(1, infilename);
-
-    // Default to out.asm
-    if (infilename[0] == 0)
+    char absolute_path_out[MAX_PATH_LENGTH];
+    // Check if absolute path
+    if (filename[0] != '/')
     {
-        strcat(infilename, BDOS_GetPath());
-        if (infilename[strlen(infilename)-1] != '/')
-        {
-            strcat(infilename, "/");
-        }
-        strcat(infilename, "OUT.ASM");
+        strcpy(absolute_path_out, fs_getcwd());
+        strcat(absolute_path_out, "/");
+        strcat(absolute_path_out, filename);
     }
-
-    // Make full path if it is not already
-    if (infilename[0] != '/')
+    else
     {
-        char bothPath[96];
-        bothPath[0] = 0;
-        strcat(bothPath, BDOS_GetPath());
-        if (bothPath[strlen(bothPath)-1] != '/')
-        {
-            strcat(bothPath, "/");
-        }
-        strcat(bothPath, infilename);
-        strcpy(infilename, bothPath);
+        strcpy(absolute_path_out, filename);
     }
 
-    // Open the input file
-    if (!fopenRead(infilename))
+    // (re)create file for output
+    fs_delete(absolute_path_out);
+    fs_mkfile(absolute_path_out);
+    fd_output = fs_open(absolute_path_out);
+    if (fd_output == -1)
     {
-        BDOS_PrintConsole("Cannot open input file\n");
+        bdos_print("Could not create/open output file.\n");
         return 1;
     }
+    fs_close(fd_output); // Close so we can reopen it later when needed
 
-    moveDataDown(); // move all data sections below the code sections
 
-    fclose(); // done reading file, everything else can be done in memory
 
+    moveDataDown(); // Move all data sections below the code sections
+    // done reading file, everything else can be done in memory
     doPass1();
-
     word pass2Length = doPass2();
 
-    BDOS_PrintConsole("Writing to file\n");
 
-    // write binary to output file
-    if (!fopenWrite(outfilename))
+    bdos_print("Writing to file\n");
+    fd_output = fs_open(absolute_path_out);
+    if (fd_output == -1)
     {
-        BDOS_PrintConsole("Could not open outfile\n");
-        return 0;
+        bdos_print("UNEXPECTED: Could not open output file.\n");
+        return 1;
     }
+    
     char* outfilePass2Addr = (char*) OUTFILE_PASS2_ADDR;
-    fputData(outfilePass2Addr, pass2Length-1);
-    fclose();
+    fs_write(fd_output, outfilePass2Addr, pass2Length);
+    fs_close(fd_output);
     
     return 0;
 }
 
 void interrupt()
 {
-  // handle all interrupts
-  word i = getIntID();
+  // Handle all interrupts
+  word i = get_int_id();
   switch(i)
   {
     case INTID_TIMER1:
-      timer1Value = 1; // notify ending of timer1
-      break;
-
-    case INTID_TIMER2:
-      break;
-
-    case INTID_UART0:
-      break;
-
-    case INTID_GPU:
-      break;
-
-    case INTID_TIMER3:
-      break;
-
-    case INTID_PS2:
-      break;
-
-    case INTID_UART1:
-      break;
-
-    case INTID_UART2:
+      timer1Value = 1;  // Notify ending of timer1
       break;
   }
 }

+ 15 - 0
BCC/FPGCbuildTools/asm/lib/brfs.c

@@ -0,0 +1,15 @@
+/**
+ * User library for file system operations
+*/
+
+#define MAX_DIR_ENTRIES 128 // Safe bound on max number of entries in a directory (128 -> full dir on block size of 512 words)
+#define MAX_PATH_LENGTH 127
+
+struct brfs_dir_entry
+{
+  word filename[4];       // 4 chars per word
+  word modify_date;       // TBD when RTC added to FPGC
+  word flags;             // 32 flags, from right to left: directory, hidden 
+  word fat_idx;           // idx of first FAT block
+  word filesize;          // file size in words, not bytes
+};

+ 0 - 549
BCC/FPGCbuildTools/asm/lib/fs.c

@@ -1,549 +0,0 @@
-/*
-* Filesystem library
-* Handles all filesystem related work for userBDOS programs using CH376.
-* Uses only bottom USB port (SPI1 CH376), 
-*  allowing top USB top to be used for other USB devices (like HID).
-* Uses blocking delays for now.
-*/
-
-// uses stdlib.c
-
-#define FS_INTERRUPT_ADDR 0xC0272D
-
-//CH376 Codes
-#define FS_CMD_GET_IC_VER           0x01
-#define FS_CMD_SET_BAUDRATE         0x02
-#define FS_CMD_ENTER_SLEEP          0x03
-#define FS_CMD_SET_USB_SPEED        0x04
-#define FS_CMD_RESET_ALL            0x05
-#define FS_CMD_CHECK_EXIST          0x06
-#define FS_CMD_SET_SD0_INT          0x0b
-#define FS_CMD_SET_RETRY            0x0b
-#define FS_CMD_GET_FILE_SIZE        0x0c
-#define FS_CMD_SET_FILE_SIZE        0x0d
-#define FS_CMD_SET_USB_ADDRESS      0x13
-#define FS_CMD_SET_USB_MODE         0x15
-#define FS_MODE_HOST_0              0x05
-#define FS_MODE_HOST_1              0x07
-#define FS_MODE_HOST_2              0x06
-#define FS_CMD_GET_STATUS           0x22
-#define FS_CMD_RD_USB_DATA0         0x27
-#define FS_CMD_WR_USB_DATA          0x2c
-#define FS_CMD_WR_REQ_DATA          0x2d
-#define FS_CMD_WR_OFS_DATA          0x2e
-#define FS_CMD_SET_FILE_NAME        0x2f
-#define FS_CMD_DISK_CONNECT         0x30
-#define FS_CMD_DISK_MOUNT           0x31
-#define FS_CMD_FILE_OPEN            0x32
-#define FS_CMD_FILE_ENUM_GO         0x33
-#define FS_CMD_FILE_CREATE          0x34
-#define FS_CMD_FILE_ERASE           0x35
-#define FS_CMD_FILE_CLOSE           0x36
-#define FS_CMD_DIR_INFO_READ        0x37
-#define FS_CMD_DIR_INFO_SAVE        0x38
-#define FS_CMD_BYTE_LOCATE          0x39
-#define FS_CMD_BYTE_READ            0x3a
-#define FS_CMD_BYTE_RD_GO           0x3b
-#define FS_CMD_BYTE_WRITE           0x3c
-#define FS_CMD_BYTE_WR_GO           0x3d
-#define FS_CMD_DISK_CAPACITY        0x3e
-#define FS_CMD_DISK_QUERY           0x3f
-#define FS_CMD_DIR_CREATE           0x40
-#define FS_CMD_SET_ADDRESS          0x45
-#define FS_CMD_GET_DESCR            0x46
-#define FS_CMD_SET_CONFIG           0x49
-#define FS_CMD_AUTO_CONFIG          0x4D
-#define FS_CMD_ISSUE_TKN_X          0x4E
-
-#define FS_ANSW_RET_SUCCESS         0x51
-#define FS_ANSW_USB_INT_SUCCESS     0x14
-#define FS_ANSW_USB_INT_CONNECT     0x15
-#define FS_ANSW_USB_INT_DISCONNECT  0x16
-#define FS_ANSW_USB_INT_USB_READY   0x18
-#define FS_ANSW_USB_INT_DISK_READ   0x1d
-#define FS_ANSW_USB_INT_DISK_WRITE  0x1e
-#define FS_ANSW_RET_ABORT           0x5F
-#define FS_ANSW_USB_INT_DISK_ERR    0x1f
-#define FS_ANSW_USB_INT_BUF_OVER    0x17
-#define FS_ANSW_ERR_OPEN_DIR        0x41
-#define FS_ANSW_ERR_MISS_FILE       0x42
-#define FS_ANSW_ERR_FOUND_NAME      0x43
-#define FS_ANSW_ERR_DISK_DISCON     0x82
-#define FS_ANSW_ERR_LARGE_SECTOR    0x84
-#define FS_ANSW_ERR_TYPE_ERROR      0x92
-#define FS_ANSW_ERR_BPB_ERROR       0xa1
-#define FS_ANSW_ERR_DISK_FULL       0xb1
-#define FS_ANSW_ERR_FDT_OVER        0xb2
-#define FS_ANSW_ERR_FILE_CLOSE      0xb4
-#define FS_ERR_LONGFILENAME         0x01
-#define FS_ATTR_READ_ONLY           0x01
-#define FS_ATTR_HIDDEN              0x02
-#define FS_ATTR_SYSTEM              0x04
-#define FS_ATTR_VOLUME_ID           0x08
-#define FS_ATTR_DIRECTORY           0x10 
-#define FS_ATTR_ARCHIVE             0x20
-
-// Sets SPI1_CS low
-void FS_spiBeginTransfer()
-{
-    asm(
-        "; backup regs\n"
-        "push r1\n"
-        "push r2\n"
-
-        "load32 0xC0272C r2          ; r2 = 0xC0272C\n"
-
-        "load 0 r1                          ; r1 = 0 (enable)\n"
-        "write 0 r2 r1                      ; write to SPI1_CS\n"
-
-        "; restore regs\n"
-        "pop r2\n"
-        "pop r1\n"
-        );
-}
-
-// Sets SPI1_CS high
-void FS_spiEndTransfer()
-{
-    asm(
-        "; backup regs\n"
-        "push r1\n"
-        "push r2\n"
-
-        "load32 0xC0272C r2          ; r2 = 0xC0272C\n"
-
-        "load 1 r1                          ; r1 = 1 (disable)\n"
-        "write 0 r2 r1                      ; write to SPI1_CS\n"
-
-        "; restore regs\n"
-        "pop r2\n"
-        "pop r1\n"
-        );
-}
-
-// write dataByte and return read value
-// write 0x00 for a read
-// Writes byte over SPI1 to CH376
-word FS_spiTransfer(word dataByte)
-{
-    word retval = 0;
-    asm(
-        "load32 0xC0272B r2             ; r2 = 0xC0272B\n"
-        "write 0 r2 r4                      ; write r4 over SPI1\n"
-        "read 0 r2 r2                       ; read return value\n"
-        "write -4 r14 r2                    ; write to stack to return\n"
-        );
-
-    return retval;
-}
-
-
-
-
-// Get status after waiting for an interrupt
-word FS_WaitGetStatus()
-{
-    word intValue = 1;
-    while(intValue)
-    {
-        word *i = (word *) FS_INTERRUPT_ADDR;
-        intValue = *i;
-    }
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_GET_STATUS);
-    FS_spiEndTransfer(); 
-    //delay(1);
-
-    FS_spiBeginTransfer();
-    word retval = FS_spiTransfer(0x00);
-    FS_spiEndTransfer(); 
-
-    return retval;
-}
-
-// Function to send a string (without terminating 0)
-void FS_sendString(char* str)
-{
-    char chr = *str;            // first character of str
-
-    while (chr != 0)            // continue until null value
-    {
-        FS_spiTransfer(chr);
-        str++;                  // go to next character address
-        chr = *str;             // get character from address
-    }
-}
-
-
-// Function to send data d of size s
-void FS_sendData(char* d, word s)
-{
-    char chr = *d;          // first byte of data
-
-    word i;
-    for(i = 0; (unsigned int) i < (unsigned int)s; i++)  // write s bytes
-    {
-        FS_spiTransfer(chr);
-        d++;                    // go to next data address
-        chr = *d;           // get data from address
-    }
-}
-
-// Returns file size of currently opened file (32 bits)
-word FS_getFileSize()
-{
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_GET_FILE_SIZE);
-    FS_spiTransfer(0x68);
-    word retval = FS_spiTransfer(0);
-    retval = retval + (FS_spiTransfer(0) << 8);
-    retval = retval + (FS_spiTransfer(0) << 16);
-    retval = retval + (FS_spiTransfer(0) << 24);
-    FS_spiEndTransfer();
-
-    return retval;
-}
-
-
-// Sets cursor to position s
-// Returns FS_ANSW_USB_INT_SUCCESS on success
-word FS_setCursor(word s) 
-{
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_BYTE_LOCATE);
-    FS_spiTransfer(s);
-    FS_spiTransfer(s >> 8);
-    FS_spiTransfer(s >> 16);
-    FS_spiTransfer(s >> 24);
-    FS_spiEndTransfer();
-
-    return FS_WaitGetStatus();
-}
-
-
-// Reads s bytes into buf
-// If bytesToWord is true, four bytes will be stored in one address/word
-// Can read 65536 bytes per call
-// Returns FS_ANSW_USB_INT_SUCCESS on success
-// TODO: this surely can be optimized for speed in some way!
-word FS_readFile(char* buf, word s, word bytesToWord) 
-{
-    if (s == 0)
-        return FS_ANSW_USB_INT_SUCCESS;
-
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_BYTE_READ);
-    FS_spiTransfer(s);
-    FS_spiTransfer(s >> 8);
-    FS_spiEndTransfer();
-
-    word retval = FS_WaitGetStatus();
-    // Return on error or EOF
-    if (retval == FS_ANSW_USB_INT_SUCCESS) // eof
-        return 0;
-    if (retval != FS_ANSW_USB_INT_DISK_READ)
-        return retval;
-
-
-    word bytesRead = 0; 
-    word wordsRead = 0;
-    word doneReading = 0;
-
-    // clear first address
-    buf[wordsRead] = 0;
-
-    // used for shifting bytes to word
-    word currentByteShift = 24;
-
-    while (doneReading == 0)
-    {
-        // Read set of bytes (max 255)
-        FS_spiBeginTransfer();
-        FS_spiTransfer(FS_CMD_RD_USB_DATA0);
-        word readLen = FS_spiTransfer(0x00);
-
-        word readByte;
-
-        word i;
-        for (i = 0; i < readLen; i++) 
-        {
-            readByte = FS_spiTransfer(0x00);
-
-            // Read 4 bytes into one word, from left to right
-            if (bytesToWord)
-            {
-                readByte = readByte << currentByteShift;
-                buf[wordsRead] = buf[wordsRead] + readByte;
-
-
-                if (currentByteShift == 0)
-                {
-                    currentByteShift = 24;
-                    wordsRead++;
-                    buf[wordsRead] = 0;
-                }
-                else
-                {
-                    currentByteShift -= 8;
-                }
-
-            }
-            else
-            {
-                buf[bytesRead] = (char)readByte;
-                bytesRead = bytesRead + 1;
-            }
-        }
-        FS_spiEndTransfer();
-
-        // requesting another set of data
-        FS_spiBeginTransfer();
-        FS_spiTransfer(FS_CMD_BYTE_RD_GO);
-        FS_spiEndTransfer();
-
-        retval = FS_WaitGetStatus();
-        if (retval == FS_ANSW_USB_INT_SUCCESS)
-            doneReading = 1;
-        else if (retval == FS_ANSW_USB_INT_DISK_READ)
-        {
-            // read another block
-        }
-        else
-        {
-            uprintln("E: Error while reading data");
-            return retval;
-        }
-    }
-
-    return retval;
-}
-
-
-// Writes data d of size s
-// Can only write 65536 bytes at a time
-// returns FS_ANSW_USB_INT_SUCCESS on success
-// TODO: optimize for speed
-word FS_writeFile(char* d, word s) 
-{
-    if (s == 0)
-        return FS_ANSW_USB_INT_SUCCESS;
-
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_BYTE_WRITE);
-    FS_spiTransfer(s);
-    FS_spiTransfer(s >> 8);
-    FS_spiEndTransfer();
-
-    word retval = FS_WaitGetStatus();
-    // Return on error
-    if (retval != FS_ANSW_USB_INT_DISK_WRITE)
-        return retval;
-
-
-    word bytesWritten = 0;
-    word doneWriting = 0;
-
-    while (doneWriting == 0)
-    {
-        // Write set of bytes (max 255)
-        FS_spiBeginTransfer();
-        FS_spiTransfer(FS_CMD_WR_REQ_DATA);
-        word wrLen = FS_spiTransfer(0x00);
-
-        FS_sendData(d + bytesWritten, wrLen);
-        bytesWritten = bytesWritten + wrLen;
-        FS_spiEndTransfer();
-
-        // update file size
-        FS_spiBeginTransfer();
-        FS_spiTransfer(FS_CMD_BYTE_WR_GO);
-        FS_spiEndTransfer();
-
-
-        retval = FS_WaitGetStatus();
-        if (retval == FS_ANSW_USB_INT_SUCCESS)
-            doneWriting = 1;
-        else if (retval == FS_ANSW_USB_INT_DISK_WRITE)
-        {
-            // write another block
-        }
-        else
-        {
-            uprintln("E: Error while writing data");
-            return retval;
-        }
-
-    }
-    
-    return retval;
-}
-
-
-// returns status of opening a file/directory
-// Usually the successful status codes are:
-//  FS_ANSW_USB_INT_SUCCESS || FS_ANSW_ERR_OPEN_DIR || FS_ANSW_USB_INT_DISK_READ
-word FS_open() 
-{
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_FILE_OPEN);
-    FS_spiEndTransfer();
-
-    return FS_WaitGetStatus();
-}
-
-
-
-
-// returns FS_ANSW_USB_INT_SUCCESS on success
-word FS_close() 
-{  
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_FILE_CLOSE);
-    FS_spiTransfer(0x01); //0x01 if update filesize, else 0x00
-    FS_spiEndTransfer();
-
-    return FS_WaitGetStatus();
-}
-
-
-
-
-// Creates file (recreates if exists)
-// New files are 1 byte long
-// Have not found a way to set it to 0 bytes, 
-// since FS_CMD_SET_FILE_SIZE does not work
-// Automatically closes file
-// returns FS_ANSW_USB_INT_SUCCESS on success
-word FS_createFile() 
-{
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_FILE_CREATE);
-    FS_spiEndTransfer();
-
-    word retval = FS_WaitGetStatus();
-    // Return on error
-    if (retval != FS_ANSW_USB_INT_SUCCESS)
-        return retval;
-
-    // open and close file
-    FS_open();
-    FS_close();
-
-    return FS_ANSW_USB_INT_SUCCESS;
-}
-
-
-// Sends single path f
-// No processing of f is done, it is directly sent
-// This means no error checking on file length!
-void FS_sendSinglePath(char* f) 
-{
-
-    // send buf
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_SET_FILE_NAME);
-    FS_sendString(f);      // send file name
-    FS_spiTransfer(0);       // close with null
-    FS_spiEndTransfer();
-}
-
-
-// Sends path f
-// Can be relative or absolute file or directory
-// REQUIRES CAPITAL LETTERS and must conform the 8.3 filename standard
-// Function can handle folders with forward slashes
-// returns FS_ANSW_USB_INT_SUCCESS on success
-word FS_sendFullPath(char* f) 
-{
-    // path to uppercase and replace backslash by slash
-    word i = 0;
-    while (f[i] != 0)
-    {
-        f[i] = toUpper(f[i]);
-        if (f[i] == '\\')
-            f[i] = '/';
-        i++;
-    }
-
-    word removedSlash = 0; // to restore removed slash
-    // remove (single) trailing slash if exists
-    // we reuse i here since it points to the end of the path
-    if (i > 1) // ignore the root path
-    {
-        if (f[i-1] == '/')
-        {
-            f[i-1] = 0;
-            removedSlash = 1;
-        }
-    }
-
-    // if first char is a /, then we go back to root
-    if (f[0] == '/')
-    {
-        FS_sendSinglePath("/");
-        FS_open();
-    }
-
-    i = 0;
-    char buf[16]; // buffer for single folder/file name
-    word bufi = 0;
-
-    while (f[i] != 0)
-    {
-        // handle all directories
-        if (f[i] == 47) // forward slash
-        {
-            // return error on opening folders containing a single or double dot
-            if ((bufi == 1 && buf[0] == '.') || (bufi == 2 && buf[0] == '.' && buf[1] == '.'))
-                return FS_ANSW_ERR_OPEN_DIR;
-
-            // add null to end of buf
-            buf[bufi] = 0;
-            // send buf
-            FS_spiBeginTransfer();
-            FS_spiTransfer(FS_CMD_SET_FILE_NAME);
-            FS_sendString(buf);      // send folder name
-            FS_spiTransfer(0);       // close with null
-            FS_spiEndTransfer();
-            // reset bufi
-            bufi = 0;
-            // open folder
-            word retval = FS_open();
-            // Return on if failure / folder not found
-            if (retval != FS_ANSW_USB_INT_SUCCESS && retval != FS_ANSW_ERR_OPEN_DIR)
-                return retval;
-        }
-        else
-        {
-            buf[bufi] = f[i];
-            bufi++;
-            if (bufi > 13)
-                return FS_ERR_LONGFILENAME; // exit if folder/file name is too long
-        }
-        i++;
-    }
-    if (removedSlash) // restore removed slash if there
-    {
-        f[i] = '/';
-        f[i+1] = 0;
-    }
-
-    // handle filename itself (if any)
-    // add null to end of buf
-    buf[bufi] = 0;
-    if (bufi == 0)
-        return FS_ANSW_USB_INT_SUCCESS; // exit if there is no filename after the folder
-
-    // return error on opening folders containing a single or double dot
-    if ((bufi == 1 && buf[0] == '.') || (bufi == 2 && buf[0] == '.' && buf[1] == '.'))
-        return FS_ANSW_ERR_OPEN_DIR;
-
-    // send buf (last part of string)
-    FS_spiBeginTransfer();
-    FS_spiTransfer(FS_CMD_SET_FILE_NAME);
-    FS_sendString(buf);      // send file name
-    FS_spiTransfer(0);       // close with null
-    FS_spiEndTransfer();
-
-    return FS_ANSW_USB_INT_SUCCESS;
-}

+ 9 - 219
BCC/FPGCbuildTools/asm/lib/stdio.c

@@ -1,230 +1,20 @@
 /*
-* Very simple stdio library to read from or write to a single file
-* implements a buffer for reading the input file
-* Specially made for ASM, so it is kept very simple:
-*  only one file can be open at the same time
+* Very simple stdio library for mapping stdio functions to brfs.
 */
 
 #define EOF -1
 
-#define FOPEN_FILENAME_LIMIT 32
-
-// Buffers for reading
-// Length of buffer always should be less than 65536, since this is the maximum FS_readFile can do in a single call
-#define STDIO_FBUF_LEN 4096
-char *inputBuffer = (char*) STDIO_FBUF_ADDR; //inputBuffer[STDIO_FBUF_LEN];
-word inbufStartPos = 0; // where in the file the buffer starts
-word inbufCursor = 0; // where in the buffer we currently are working
-
-
-// Opens file for reading
-// requires full paths
-// returns 1 on success
-word fopenRead(const char* fname)
-{
-    if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
-    {
-        BDOS_PrintConsole("E: Path too large\n");
-        return 0;
-    }
-
-    if (fname[0] != '/')
-    {
-        BDOS_PrintConsole("E: Filename should be a full path\n");
-        return 0;
-    }
-
-    FS_close(); // to be sure
-
-    // convert to uppercase
-    strToUpper(fname);
-
-    // init read buffer
-    inbufStartPos = 0; // start at 0
-    inbufCursor = 0; // start at 0
-
-    // if the resulting path is correct (can be file or directory)
-    if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
-    {
-
-        // if we can successfully open the file (not directory)
-        if (FS_open() == FS_ANSW_USB_INT_SUCCESS)
-        {
-            FS_setCursor(0); // set cursor to start
-            return 1;
-        }
-        else
-        {
-            return 0;
-        }
-    }
-    else
-    {
-        return 0;
-    }
-
-    return 0;
-}
-
-// Opens file for writing
-// requires full paths
-// returns 1 on success
-word fopenWrite(const char* fname)
-{
-    if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
-    {
-        BDOS_PrintConsole("E: Path too large\n");
-        return 0;
-    }
-
-    if (fname[0] != '/')
-    {
-        BDOS_PrintConsole("E: Filename should be a full path\n");
-        return 0;
-    }
-
-    FS_close(); // to be sure
-
-    // convert to uppercase
-    strToUpper(fname);
-
-    // if current path is correct (can be file or directory)
-    if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
-    {
-        // create the file
-        
-        if (FS_createFile() == FS_ANSW_USB_INT_SUCCESS)
-        {
-            //BDOS_PrintConsole("File created\n");
-            // open again and start at 0
-            FS_sendFullPath(fname);
-            FS_open();
-            FS_setCursor(0); // set cursor to start
-            return 1;
-        }
-        else
-        {
-            BDOS_PrintConsole("E: Could not create file\n");
-            return 0;
-        }
-    }
-    else
-    {
-        BDOS_PrintConsole("E: Invalid path\n");
-        return 0;
-    }
-
-    return 0;
-}
-
-// closes currently opened file
-void fclose()
-{
-
-    FS_close();
-}
-
-
-// returns the current char at cursor (EOF if end of file)
+// returns the current char at cursor within the opened file (EOF if end of file)
 // increments the cursor
-word fgetc()
+word fgetc(word fd, word filesize)
 {
-    // workaround for missing compiler check for ALU constants > 11 bit
-    word stdioBufLen = STDIO_FBUF_LEN;
-
-    if (inbufCursor >= STDIO_FBUF_LEN || inbufCursor == 0)  // we are at the end of the buffer (or it is not initialized yet)
-    {
-        // get filesize
-        word sizeOfFile = FS_getFileSize();
-        
-        // if we cannot completely fill the buffer:
-        if (inbufStartPos + stdioBufLen > sizeOfFile)
-        {
-            //  fill the buffer, and append with EOF token
-            FS_readFile(inputBuffer, sizeOfFile - inbufStartPos, 0);
-            inputBuffer[sizeOfFile - inbufStartPos] = EOF;
-        }
-        else
-        {
-            //  Fill buffer again
-            FS_readFile(inputBuffer, STDIO_FBUF_LEN, 0);
-        }
-        
-        inbufStartPos += stdioBufLen; // for the next fill
-
-        inbufCursor = 0; // start at the beginning of the buffer again
-    }
-
-    // return from the buffer, and increment
-    char gotchar = inputBuffer[inbufCursor];
-    inbufCursor++;
-    // BDOS_PrintcConsole(gotchar); // useful for debugging
-    return gotchar;
-}
-
-word fputData(char* outbufAddr, word lenOfData)
-{
-    word bytesWritten = 0;
-
-    // loop until all bytes are sent
-    while (bytesWritten != lenOfData)
-    {
-        word partToSend = lenOfData - bytesWritten;
-        // send in parts of 0xFFFF
-        if (partToSend > 0xFFFF)
-            partToSend = 0xFFFF;
-
-        // write away
-        if (FS_writeFile((outbufAddr +bytesWritten), partToSend) != FS_ANSW_USB_INT_SUCCESS)
-            BDOS_PrintConsole("write error\n");
-
-        // Update the amount of bytes sent
-        bytesWritten += partToSend;
-    }
-}
-
-
-/*
-Prints a single char c by writing it to UART_TX_ADDR
-*/
-void uprintc(char c) 
-{
-  word *p = (word *)UART_TX_ADDR; // address of UART TX
-  *p = (word)c;           // write char over UART
-}
-
-
-/*
-Sends each character from str over UART
-by writing them to UART_TX_ADDR
-until a 0 value is found.
-Does not send a newline afterwards.
-*/
-void uprint(char* str) 
-{
-  word *p = (word *)UART_TX_ADDR; // address of UART TX
-  char chr = *str;        // first character of str
-
-  while (chr != 0)        // continue until null value
+  word cursor = fs_getcursor(fd);
+  if (cursor == filesize)
   {
-    *p = (word)chr;       // write char over UART
-    str++;            // go to next character address
-    chr = *str;         // get character from address
+    return EOF;
   }
-}
 
-
-/*
-Same as uprint(char* str),
-except it sends a newline afterwards.
-*/
-void uprintln(char* str) 
-{
-  uprint(str);
-  uprintc('\n');
+  char c;
+  fs_read(fd, &c, 1);
+  return c;
 }
-
-void exit(word i)
-{
-    asm("jump Return_BDOS\n");
-}

+ 135 - 1
BCC/FPGCbuildTools/asm/lib/stdlib.c

@@ -144,6 +144,56 @@ word getIntID()
   return retval;
 }
 
+/*
+Recursive helper function for itoa
+Eventually returns the number of digits in n
+s is the output buffer
+*/
+word itoahr(word n, char *s)
+{
+  word digit = MATH_modU(n, 16);
+  word i = 0;
+
+  n = MATH_divU(n,16);
+  if ((unsigned int) n > 0)
+    i += itoahr(n, s);
+
+  char c;
+  if (digit > 9)
+  {
+    c = digit + 'A' - 10;
+  }
+  else
+  {
+    c = digit + '0';
+  }
+  s[i++] = c;
+
+  return i;
+}
+
+
+/*
+Converts integer n to hex string characters.
+The characters are placed in the buffer s.
+A prefix of 0x is added.
+The buffer is terminated with a 0 value.
+Uses recursion, division and mod to compute.
+*/
+void itoah(word n, char *s)
+{
+  // add prefix
+  s[0] = '0';
+  s[1] = 'x';
+  s+=2;
+
+  // compute and fill the buffer
+  word i = itoahr(n, s);
+
+  // end with terminator
+  s[i] = 0;
+}
+
 /*
 Converts string into int.
 Assumes the string is valid.
@@ -254,7 +304,7 @@ word binToInt(char *binStr) {
         }
         else if (c != '0')
         {
-            BDOS_PrintConsole("Invalid binary number\n");
+            bdos_print("Invalid binary number\n");
             exit(1);
         }
     }
@@ -284,3 +334,87 @@ void strToUpper(char* str)
         chr = *str;             // get character from address
     }
 }
+
+/*
+Prints a single char c by writing it to UART_TX_ADDR
+*/
+void uprintc(char c) 
+{
+  word *p = (word *)UART_TX_ADDR; // address of UART TX
+  *p = (word)c;           // write char over UART
+}
+
+
+/*
+Sends each character from str over UART
+by writing them to UART_TX_ADDR
+until a 0 value is found.
+Does not send a newline afterwards.
+*/
+void uprint(char* str) 
+{
+  word *p = (word *)UART_TX_ADDR; // address of UART TX
+  char chr = *str;        // first character of str
+
+  while (chr != 0)        // continue until null value
+  {
+    *p = (word)chr;       // write char over UART
+    str++;            // go to next character address
+    chr = *str;         // get character from address
+  }
+}
+
+
+/*
+Same as uprint(char* str),
+except it sends a newline afterwards.
+*/
+void uprintln(char* str) 
+{
+  uprint(str);
+  uprintc('\n');
+}
+
+
+/*
+Prints decimal integer over UART
+*/
+void uprintDec(word i) 
+{
+  char buffer[11];
+  itoa(i, buffer);
+  uprint(buffer);
+}
+
+/*
+Prints hex integer over UART
+*/
+void uprintHex(word i) 
+{
+  char buffer[11];
+  itoah(i, buffer);
+  uprint(buffer);
+}
+
+
+/*
+Prints decimal integer over UART, with newline
+*/
+void uprintlnDec(word i) 
+{
+  char buffer[11];
+  itoa(i, buffer);
+  uprint(buffer);
+  uprintc('\n');
+}
+
+/*
+Prints hex integer over UART, with newline
+*/
+void uprintlnHex(word i) 
+{
+  char buffer[11];
+  itoah(i, buffer);
+  uprint(buffer);
+  uprintc('\n');
+}

+ 359 - 107
BCC/FPGCbuildTools/asm/lib/sys.c

@@ -1,9 +1,8 @@
-/*
-Contains System Call functions
+/**
+ * Contains system functions for user programs
+ * Contains code for system calls and interrupt handling
 */
 
-#define SYSCALL_RETVAL_ADDR 0x200000
-
 // Interrupt IDs for interrupt handler
 #define INTID_TIMER1  0x1
 #define INTID_TIMER2  0x2
@@ -14,123 +13,376 @@ Contains System Call functions
 #define INTID_UART1   0x7
 #define INTID_UART2   0x8
 
+#define SYSCALL_RETVAL_ADDR 0x200000
+
+// System call IDs
+#define SYS_HID_CHECKFIFO 1
+#define SYS_HID_READFIFO 2
+#define SYS_BDOS_PRINTC 3
+#define SYS_BDOS_PRINT 4
+#define SYS_FS_OPEN 5
+#define SYS_FS_CLOSE 6
+#define SYS_FS_READ 7
+#define SYS_FS_WRITE 8
+#define SYS_FS_SETCURSOR 9
+#define SYS_FS_GETCURSOR 10
+#define SYS_FS_DELETE 11
+#define SYS_FS_MKDIR 12
+#define SYS_FS_MKFILE 13
+#define SYS_FS_STAT 14
+#define SYS_FS_READDIR 15
+#define SYS_FS_GETCWD 16
+#define SYS_FS_SYNCFLASH 17
+// Syscalls 18-19 are reserved for future use
+#define SYS_SHELL_ARGC 20
+#define SYS_SHELL_ARGV 21
+#define SYS_USB_KB_BUF 99
+
+
+/**
+ * Returns the interrupt ID
+*/
+word get_int_id()
+{
+  word retval = 0;
+
+  asm(
+    "readintid r2     ;reads interrupt id to r2\n"
+    "write -4 r14 r2  ;write to stack to return\n"
+    );
+
+  return retval;
+}
 
-// executes system call to BDOS
-// ID is written to the same location as the output of the system call
-//  at address SYSCALL_RETVAL_ADDR
-// This address is also returned
+/**
+ * Executes system call to BDOS
+ * Argument specifies the system call ID
+ * Returns the address of the return value
+*/
 word* syscall(word ID)
 {
-    word* p = (word*) SYSCALL_RETVAL_ADDR;
-    *p = ID;
-
-    asm("push r1\n"
-        "push r2\n"
-        "push r3\n"
-        "push r4\n"
-        "push r5\n"
-        "push r6\n"
-        "push r7\n"
-        "push r8\n"
-        "push r9\n"
-        "push r10\n"
-        "push r11\n"
-        "push r12\n"
-        "push r13\n"
-        "push r14\n"
-        "push r15\n"
-        "savpc r1\n"
-        "push r1\n"
-        "jump 4\n"
-        "pop r15\n"
-        "pop r14\n"
-        "pop r13\n"
-        "pop r12\n"
-        "pop r11\n"
-        "pop r10\n"
-        "pop r9\n"
-        "pop r8\n"
-        "pop r7\n"
-        "pop r6\n"
-        "pop r5\n"
-        "pop r4\n"
-        "pop r3\n"
-        "pop r2\n"
-        "pop r1\n");
-
-    return p;
-}
-
-
-void BDOS_PrintcConsole(char c)
-{
-    char* p = (char*) SYSCALL_RETVAL_ADDR;
-    p[1] = c;
-    syscall(3);
-}
-
-// Prints string on BDOS console untill terminator
-// Does not add newline at end
-void BDOS_PrintConsole(char* str)
-{
-    char chr = *str;            // first character of str
-
-    while (chr != 0)            // continue until null value
-    {
-        BDOS_PrintcConsole(chr);
-        str++;                  // go to next character address
-        chr = *str;             // get character from address
-    }
+  word* p = (word*) SYSCALL_RETVAL_ADDR;
+  *p = ID;
+
+  asm("push r1\n"
+    "push r2\n"
+    "push r3\n"
+    "push r4\n"
+    "push r5\n"
+    "push r6\n"
+    "push r7\n"
+    "push r8\n"
+    "push r9\n"
+    "push r10\n"
+    "push r11\n"
+    "push r12\n"
+    "push r13\n"
+    "push r14\n"
+    "push r15\n"
+    "savpc r1\n"
+    "push r1\n"
+    "jump 4\n"
+    "pop r15\n"
+    "pop r14\n"
+    "pop r13\n"
+    "pop r12\n"
+    "pop r11\n"
+    "pop r10\n"
+    "pop r9\n"
+    "pop r8\n"
+    "pop r7\n"
+    "pop r6\n"
+    "pop r5\n"
+    "pop r4\n"
+    "pop r3\n"
+    "pop r2\n"
+    "pop r1\n");
+
+  return p;
 }
 
+/**
+ * Exits the user program and returns to BDOS in a somewhat controlled way
+*/
+void exit(int n)
+{
+  asm("ccache\n");
+  asm("jump Return_BDOS\n");
+}
 
-// Returns command line args
-char* BDOS_GetArgs()
+/**
+ * Returns 1 if the HID buffer is not empty
+*/
+word hid_checkfifo()
 {
-    char* p = syscall(4);
-    return (char*) p[0];
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_HID_CHECKFIFO);
+  return p[0];
 }
 
+/**
+ * Reads a character from the HID buffer
+*/
+word hid_fiforead()
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_HID_READFIFO);
+  return p[0];
+}
 
-// Writes command line argument n into buf
-// Arg 0 is the command itself
-void BDOS_GetArgN(word n, char* buf)
+/**
+ * Prints a character on the BDOS console
+*/
+void bdos_printc(char c)
 {
-    char* args = BDOS_GetArgs();
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = c;
+  syscall(SYS_BDOS_PRINTC);
+}
 
-    word i = 0;
-    word bufi = 0;
-    word currentArg = 0;
-    char prevChar = 0;
-    buf[0] = 0;
-    while (args[i] != 0)
-    {
-        // new argument
-        if (args[i] == ' ' && prevChar != ' ')
-        {
-            currentArg++;
-        }
-
-        if (args[i] != ' ')
-        {
-            if (currentArg == n)
-            {
-                buf[bufi] = args[i];
-                bufi++;
-            }
-        }
-
-        prevChar = args[i];
-        i++;
-    }
+/**
+ * Prints a string on the BDOS console
+*/
+void bdos_print(char* c)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char)c;
+  syscall(SYS_BDOS_PRINT);
+}
+
+/**
+ * Prints a string with newline on the BDOS console
+*/
+void bdos_println(char* str)
+{
+  bdos_print(str);
+  bdos_printc('\n');
+}
+
+/**
+ * Prints a decimal on the BDOS console
+*/
+void bdos_printdec(word i)
+{
+  char buffer[12];
+
+  if (i < 0)
+  {
+    buffer[0] = '-';
+    itoa(MATH_abs(i), &buffer[1]);
+  }
+  else
+  {
+    itoa(i, buffer);
+  }
+  bdos_print(buffer);
+}
+
+/**
+ * Prints a decimal with newline on the BDOS console
+*/
+void bdos_printdecln(word i)
+{
+  bdos_printdec(i);
+  bdos_printc('\n');
+}
+
+/**
+ * Prints a hexadecimal on the BDOS console
+*/
+void bdos_printhex(word i)
+{
+  char buffer[11];
+  itoah(i, buffer);
+  bdos_print(buffer);
+}
+
+/**
+ * Opens a file in the filesystem
+*/
+word fs_open(char* filename)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) filename;
+  syscall(SYS_FS_OPEN);
+  return p[0];
+}
+
+/**
+ * Closes a file in the filesystem
+*/
+word fs_close(word fp)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = fp;
+  syscall(SYS_FS_CLOSE);
+  return p[0];
+}
+
+/**
+ * Reads from a file in the filesystem
+*/
+word fs_read(word fp, char* buffer, word len)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = fp;
+  p[2] = (char) buffer;
+  p[3] = len;
+  syscall(SYS_FS_READ);
+  return p[0];
+}
+
+/**
+ * Writes to a file in the filesystem
+*/
+word fs_write(word fp, char* buffer, word len)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = fp;
+  p[2] = (char) buffer;
+  p[3] = len;
+  syscall(SYS_FS_WRITE);
+  return p[0];
+}
+
+/**
+ * Sets the cursor position in the filesystem
+*/
+word fs_setcursor(word fp, word pos)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = fp;
+  p[2] = pos;
+  syscall(SYS_FS_SETCURSOR);
+  return p[0];
+}
+
+/**
+ * Gets the cursor position in the filesystem
+*/
+word fs_getcursor(word fp)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = fp;
+  syscall(SYS_FS_GETCURSOR);
+  return p[0];
+}
+
+/**
+ * Deletes a file in the filesystem
+*/
+word fs_delete(char* filename)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) filename;
+  syscall(SYS_FS_DELETE);
+  return p[0];
+}
+
+/**
+ * Creates a directory in the filesystem
+*/
+word fs_mkdir(char* dirname)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) dirname;
+  syscall(SYS_FS_MKDIR);
+  return p[0];
+}
+
+/**
+ * Creates a file in the filesystem
+*/
+word fs_mkfile(char* filename)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) filename;
+  syscall(SYS_FS_MKFILE);
+  return p[0];
+}
 
-    buf[bufi] = 0; // terminate
+/**
+ * Gets the status of a file in the filesystem
+*/
+word fs_stat(char* filename)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) filename;
+  syscall(SYS_FS_STAT);
+  return p[0];
+}
+
+/**
+ * Lists the contents of a directory in the filesystem
+ * Returns the number of entries in the directory
+*/
+word fs_readdir(char* dirname, char* buffer)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  p[1] = (char) dirname;
+  p[2] = (char) buffer;  
+  syscall(SYS_FS_READDIR);
+  return p[0];
 }
 
+/**
+ * Gets the current working directory in the filesystem
+ * Note: The pointer returned is only valid until the next syscall
+*/
+char* fs_getcwd()
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_FS_GETCWD);
+  return p;
+}
 
-// Returns BDOS current path
-char* BDOS_GetPath()
+/**
+ * Synchronizes the filesystem with the flash memory
+*/
+word fs_syncflash()
 {
-    word* p = syscall(5);
-    return (char*) p[0];
-}
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_FS_SYNCFLASH);
+  return p[0];
+}
+
+/**
+ * Returns the number of command line arguments
+*/
+word shell_argc()
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_SHELL_ARGC);
+  return p[0];
+}
+
+/**
+ * Returns the command line arguments
+ * Note: The pointer returned is only valid until the next syscall
+*/
+char* shell_argv()
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_SHELL_ARGV);
+  return p;
+}
+
+/**
+ * Returns 1 if key is being held on USB keyboard
+*/
+word bdos_usbkey_held(word c)
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_USB_KB_BUF);
+  word* usbKeyBuffer = (char*) p[0];
+  
+  word i;
+  for (i = 0; i < 8; i++)
+  {
+    if (usbKeyBuffer[i] == c)
+    {
+      return 1;
+    }
+  }
+  return 0;
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 183 - 389
BCC/FPGCbuildTools/asm/pass2.c


+ 10 - 1
BCC/FPGCbuildTools/bcc/bcc.c

@@ -944,6 +944,9 @@ void IncludeFile(word quot)
     strcat(cFileDir, FileNames[FileCnt]);
     Files[FileCnt] = fs_open(cFileDir);
 
+    bdos_print("- Compiling: ");
+    bdos_println(cFileDir);
+
     // Get file size
     struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(cFileDir);
     word filesize = entry->filesize;
@@ -978,6 +981,8 @@ void IncludeFile(word quot)
           FileNames[FileCnt][plen] = '/';
           if ((Files[FileCnt] = fs_open(FileNames[FileCnt])) != NULL)
           {
+            bdos_print("- Compiling: ");
+            bdos_println(FileNames[FileCnt]);
             // Get file size
             struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(FileNames[FileCnt]);
             word filesize = entry->filesize;
@@ -7786,7 +7791,7 @@ int main()
 
   // Read number of arguments
   word argc = shell_argc();
-  if (argc < 2)
+  if (argc < 3)
   {
     printf("Usage: BCC <source file> <output file>\n");
     return 1;
@@ -7864,6 +7869,10 @@ int main()
     }
     strcpy(FileNames[0], absolute_path_in);
     Files[0] = fs_open(FileNames[0]);
+
+    bdos_print("Compiling: ");
+    bdos_println(FileNames[0]);
+
     // Get file size
     struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(FileNames[0]);
     word filesize = entry->filesize;

+ 26 - 0
BCC/userBDOS/webserv.c

@@ -44,6 +44,32 @@ void write_file_from_fs(word s, char* path, word filesize)
 
   // Read file in chunks of WIZNET_MAX_TBUF
   word file_buffer[WIZNET_MAX_RBUF];
+
+  /* // Program download mode
+  word file_buffer[WIZNET_MAX_RBUF];
+  word file_buffer2[WIZNET_MAX_RBUF>>2];
+  word chunk_to_read;
+
+  char dbuf[10]; // Percentage done for progress indication
+  dbuf[0] = 0;
+
+  while (filesize > 0)
+  {
+    chunk_to_read = filesize > WIZNET_MAX_RBUF>>2 ? WIZNET_MAX_RBUF>>2 : filesize;
+    fs_read(fd, (char*)file_buffer2, chunk_to_read);
+
+    // Convert each 32-bit word into 4 8-bit words
+    word x;
+    for (x = 0; x < chunk_to_read; x++)
+    {
+      word w = file_buffer2[x];
+      file_buffer[(x << 2) + 3] = (w >> 0) & 0xFF;
+      file_buffer[(x << 2) + 2] = (w >> 8) & 0xFF;
+      file_buffer[(x << 2) + 1] = (w >> 16) & 0xFF;
+      file_buffer[(x << 2) + 0] = (w >> 24) & 0xFF;
+    }
+  */
+
   word chunk_to_read;
 
   char dbuf[10]; // Percentage done for progress indication

Vissa filer visades inte eftersom för många filer har ändrats