123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- // File copy tool
- // Currently not that efficient and reads entire file in memory
- // instead of doing it in chunks
- /*
- [x] check BDOS args for src and dst
- [x] check src file is valid
- [x] create dst file
- [x] open src
- [x] set cursor to start
- [x] read chunk into mem
- [x] close src
- [x] open dst
- [x] set cursor to start
- [x] write mem into dst
- [x] close dst
- */
- #define word char
- #include "lib/math.c"
- #include "lib/sys.c"
- #include "lib/stdlib.c"
- #include "lib/fs.c"
- char infilename[96]; // input filename
- char outfilename[96]; // output filename
- #define EOF -1
- #define FOPEN_FILENAME_LIMIT 32
- #define STDIO_FBUF_ADDR 0x420000
- #define STDIO_MEMBUF_ADDR 0x440000
- #define FOPEN_MAX_FILESIZE 0x200000 // 5 MiB
- // 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 32768
- 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
- word fileSize = 0; // size of input file
- char *memBuf = (char*) STDIO_MEMBUF_ADDR; // where the entire input file is written to
- // 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
- // get filesize
- fileSize = FS_getFileSize();
- word maxFileSize = FOPEN_MAX_FILESIZE;
- if (fileSize > maxFileSize)
- {
- BDOS_PrintConsole("E: File too large for memory\n");
- return 0;
- }
- 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)
- // increments the cursor
- word fgetc()
- {
- // 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;
- }
- }
- // reads all data from input file into memory
- void readInFileToMem()
- {
- word outputi = 0;
- char c = fgetc();
- // stop on EOF
- while (c != EOF)
- {
- memBuf[outputi] = c;
- outputi++;
- c = fgetc();
- }
- memBuf[outputi] = 0; // terminate
- }
- int main()
- {
- // output file
- BDOS_GetArgN(2, outfilename);
- if (outfilename[0] == 0)
- {
- BDOS_PrintConsole("E: Missing arguments\n");
- return 2;
- }
- // make full path if it is not already
- if (outfilename[0] != '/')
- {
- char bothPath[96];
- bothPath[0] = 0;
- strcat(bothPath, BDOS_GetPath());
- if (bothPath[strlen(bothPath)-1] != '/')
- {
- strcat(bothPath, "/");
- }
- strcat(bothPath, outfilename);
- strcpy(outfilename, bothPath);
- }
- // create output file, test if it can be created/opened
- if (!fopenWrite(outfilename))
- {
- BDOS_PrintConsole("Could not open outfile\n");
- return 0;
- }
- fclose();
- // input file
- BDOS_GetArgN(1, infilename);
- // Default to out.asm
- if (infilename[0] == 0)
- {
- BDOS_PrintConsole("E: Missing arguments\n");
- return 2;
- }
- // Make full path if it is not already
- if (infilename[0] != '/')
- {
- char bothPath[96];
- bothPath[0] = 0;
- strcat(bothPath, BDOS_GetPath());
- if (bothPath[strlen(bothPath)-1] != '/')
- {
- strcat(bothPath, "/");
- }
- strcat(bothPath, infilename);
- strcpy(infilename, bothPath);
- }
- // Open the input file
- if (!fopenRead(infilename))
- {
- BDOS_PrintConsole("Cannot open input file\n");
- return 1;
- }
- // read into memory
- readInFileToMem();
- // write into file
- // write binary to output file
- if (!fopenWrite(outfilename))
- {
- BDOS_PrintConsole("Could not open outfile\n");
- return 0;
- }
- fputData(memBuf, fileSize);
- fclose();
- return 'q';
- }
- void interrupt()
- {
- // Handle all interrupts
- word i = getIntID();
- switch(i)
- {
- case INTID_TIMER1:
- timer1Value = 1; // Notify ending of timer1
- break;
- }
- }
|