1
0

cp.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // File copy tool
  2. // Currently not that efficient and reads entire file in memory
  3. // instead of doing it in chunks
  4. /*
  5. [x] check BDOS args for src and dst
  6. [x] check src file is valid
  7. [x] create dst file
  8. [x] open src
  9. [x] set cursor to start
  10. [x] read chunk into mem
  11. [x] close src
  12. [x] open dst
  13. [x] set cursor to start
  14. [x] write mem into dst
  15. [x] close dst
  16. */
  17. #define word char
  18. #include "lib/math.c"
  19. #include "lib/sys.c"
  20. #include "lib/stdlib.c"
  21. #include "lib/fs.c"
  22. char infilename[96]; // input filename
  23. char outfilename[96]; // output filename
  24. #define EOF -1
  25. #define FOPEN_FILENAME_LIMIT 32
  26. #define STDIO_FBUF_ADDR 0x420000
  27. #define STDIO_MEMBUF_ADDR 0x440000
  28. #define FOPEN_MAX_FILESIZE 0x200000 // 5 MiB
  29. // Buffers for reading
  30. // Length of buffer always should be less than 65536, since this is the maximum FS_readFile can do in a single call
  31. #define STDIO_FBUF_LEN 32768
  32. char *inputBuffer = (char*) STDIO_FBUF_ADDR; //inputBuffer[STDIO_FBUF_LEN];
  33. word inbufStartPos = 0; // where in the file the buffer starts
  34. word inbufCursor = 0; // where in the buffer we currently are working
  35. word fileSize = 0; // size of input file
  36. char *memBuf = (char*) STDIO_MEMBUF_ADDR; // where the entire input file is written to
  37. // Opens file for reading
  38. // requires full paths
  39. // returns 1 on success
  40. word fopenRead(const char* fname)
  41. {
  42. if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
  43. {
  44. BDOS_PrintConsole("E: Path too large\n");
  45. return 0;
  46. }
  47. if (fname[0] != '/')
  48. {
  49. BDOS_PrintConsole("E: Filename should be a full path\n");
  50. return 0;
  51. }
  52. FS_close(); // to be sure
  53. // convert to uppercase
  54. strToUpper(fname);
  55. // init read buffer
  56. inbufStartPos = 0; // start at 0
  57. inbufCursor = 0; // start at 0
  58. // if the resulting path is correct (can be file or directory)
  59. if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
  60. {
  61. // if we can successfully open the file (not directory)
  62. if (FS_open() == FS_ANSW_USB_INT_SUCCESS)
  63. {
  64. FS_setCursor(0); // set cursor to start
  65. // get filesize
  66. fileSize = FS_getFileSize();
  67. word maxFileSize = FOPEN_MAX_FILESIZE;
  68. if (fileSize > maxFileSize)
  69. {
  70. BDOS_PrintConsole("E: File too large for memory\n");
  71. return 0;
  72. }
  73. return 1;
  74. }
  75. else
  76. {
  77. return 0;
  78. }
  79. }
  80. else
  81. {
  82. return 0;
  83. }
  84. return 0;
  85. }
  86. // Opens file for writing
  87. // requires full paths
  88. // returns 1 on success
  89. word fopenWrite(const char* fname)
  90. {
  91. if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
  92. {
  93. BDOS_PrintConsole("E: Path too large\n");
  94. return 0;
  95. }
  96. if (fname[0] != '/')
  97. {
  98. BDOS_PrintConsole("E: Filename should be a full path\n");
  99. return 0;
  100. }
  101. FS_close(); // to be sure
  102. // convert to uppercase
  103. strToUpper(fname);
  104. // if current path is correct (can be file or directory)
  105. if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
  106. {
  107. // create the file
  108. if (FS_createFile() == FS_ANSW_USB_INT_SUCCESS)
  109. {
  110. //BDOS_PrintConsole("File created\n");
  111. // open again and start at 0
  112. FS_sendFullPath(fname);
  113. FS_open();
  114. FS_setCursor(0); // set cursor to start
  115. return 1;
  116. }
  117. else
  118. {
  119. BDOS_PrintConsole("E: Could not create file\n");
  120. return 0;
  121. }
  122. }
  123. else
  124. {
  125. BDOS_PrintConsole("E: Invalid path\n");
  126. return 0;
  127. }
  128. return 0;
  129. }
  130. // closes currently opened file
  131. void fclose()
  132. {
  133. FS_close();
  134. }
  135. // returns the current char at cursor (EOF if end of file)
  136. // increments the cursor
  137. word fgetc()
  138. {
  139. // workaround for missing compiler check for ALU constants > 11 bit
  140. word stdioBufLen = STDIO_FBUF_LEN;
  141. if (inbufCursor >= STDIO_FBUF_LEN || inbufCursor == 0) // we are at the end of the buffer (or it is not initialized yet)
  142. {
  143. // get filesize
  144. word sizeOfFile = FS_getFileSize();
  145. // if we cannot completely fill the buffer:
  146. if (inbufStartPos + stdioBufLen > sizeOfFile)
  147. {
  148. // fill the buffer, and append with EOF token
  149. FS_readFile(inputBuffer, sizeOfFile - inbufStartPos, 0);
  150. inputBuffer[sizeOfFile - inbufStartPos] = EOF;
  151. }
  152. else
  153. {
  154. // Fill buffer again
  155. FS_readFile(inputBuffer, STDIO_FBUF_LEN, 0);
  156. }
  157. inbufStartPos += stdioBufLen; // for the next fill
  158. inbufCursor = 0; // start at the beginning of the buffer again
  159. }
  160. // return from the buffer, and increment
  161. char gotchar = inputBuffer[inbufCursor];
  162. inbufCursor++;
  163. // BDOS_PrintcConsole(gotchar); // useful for debugging
  164. return gotchar;
  165. }
  166. word fputData(char* outbufAddr, word lenOfData)
  167. {
  168. word bytesWritten = 0;
  169. // loop until all bytes are sent
  170. while (bytesWritten != lenOfData)
  171. {
  172. word partToSend = lenOfData - bytesWritten;
  173. // send in parts of 0xFFFF
  174. if (partToSend > 0xFFFF)
  175. partToSend = 0xFFFF;
  176. // write away
  177. if (FS_writeFile((outbufAddr +bytesWritten), partToSend) != FS_ANSW_USB_INT_SUCCESS)
  178. BDOS_PrintConsole("write error\n");
  179. // Update the amount of bytes sent
  180. bytesWritten += partToSend;
  181. }
  182. }
  183. // reads all data from input file into memory
  184. void readInFileToMem()
  185. {
  186. word outputi = 0;
  187. char c = fgetc();
  188. // stop on EOF
  189. while (c != EOF)
  190. {
  191. memBuf[outputi] = c;
  192. outputi++;
  193. c = fgetc();
  194. }
  195. memBuf[outputi] = 0; // terminate
  196. }
  197. int main()
  198. {
  199. // output file
  200. BDOS_GetArgN(2, outfilename);
  201. if (outfilename[0] == 0)
  202. {
  203. BDOS_PrintConsole("E: Missing arguments\n");
  204. return 2;
  205. }
  206. // make full path if it is not already
  207. if (outfilename[0] != '/')
  208. {
  209. char bothPath[96];
  210. bothPath[0] = 0;
  211. strcat(bothPath, BDOS_GetPath());
  212. if (bothPath[strlen(bothPath)-1] != '/')
  213. {
  214. strcat(bothPath, "/");
  215. }
  216. strcat(bothPath, outfilename);
  217. strcpy(outfilename, bothPath);
  218. }
  219. // create output file, test if it can be created/opened
  220. if (!fopenWrite(outfilename))
  221. {
  222. BDOS_PrintConsole("Could not open outfile\n");
  223. return 0;
  224. }
  225. fclose();
  226. // input file
  227. BDOS_GetArgN(1, infilename);
  228. // Default to out.asm
  229. if (infilename[0] == 0)
  230. {
  231. BDOS_PrintConsole("E: Missing arguments\n");
  232. return 2;
  233. }
  234. // Make full path if it is not already
  235. if (infilename[0] != '/')
  236. {
  237. char bothPath[96];
  238. bothPath[0] = 0;
  239. strcat(bothPath, BDOS_GetPath());
  240. if (bothPath[strlen(bothPath)-1] != '/')
  241. {
  242. strcat(bothPath, "/");
  243. }
  244. strcat(bothPath, infilename);
  245. strcpy(infilename, bothPath);
  246. }
  247. // Open the input file
  248. if (!fopenRead(infilename))
  249. {
  250. BDOS_PrintConsole("Cannot open input file\n");
  251. return 1;
  252. }
  253. // read into memory
  254. readInFileToMem();
  255. // write into file
  256. // write binary to output file
  257. if (!fopenWrite(outfilename))
  258. {
  259. BDOS_PrintConsole("Could not open outfile\n");
  260. return 0;
  261. }
  262. fputData(memBuf, fileSize);
  263. fclose();
  264. return 'q';
  265. }
  266. void interrupt()
  267. {
  268. // Handle all interrupts
  269. word i = getIntID();
  270. switch(i)
  271. {
  272. case INTID_TIMER1:
  273. timer1Value = 1; // Notify ending of timer1
  274. break;
  275. }
  276. }