stdio.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Very simple stdio library to read from or write to a single file
  3. * implements a buffer for reading the input file
  4. * Specially made for ASM, so it is kept very simple:
  5. * only one file can be open at the same time
  6. */
  7. #define EOF -1
  8. #define FOPEN_FILENAME_LIMIT 32
  9. // Buffers for reading
  10. // Length of buffer always should be less than 65536, since this is the maximum FS_readFile can do in a single call
  11. #define STDIO_FBUF_LEN 4096
  12. char *inputBuffer = (char*) STDIO_FBUF_ADDR; //inputBuffer[STDIO_FBUF_LEN];
  13. word inbufStartPos = 0; // where in the file the buffer starts
  14. word inbufCursor = 0; // where in the buffer we currently are working
  15. // Opens file for reading
  16. // requires full paths
  17. // returns 1 on success
  18. word fopenRead(const char* fname)
  19. {
  20. if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
  21. {
  22. BDOS_PrintConsole("E: Path too large\n");
  23. return 0;
  24. }
  25. if (fname[0] != '/')
  26. {
  27. BDOS_PrintConsole("E: Filename should be a full path\n");
  28. return 0;
  29. }
  30. FS_close(); // to be sure
  31. // convert to uppercase
  32. strToUpper(fname);
  33. // init read buffer
  34. inbufStartPos = 0; // start at 0
  35. inbufCursor = 0; // start at 0
  36. // if the resulting path is correct (can be file or directory)
  37. if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
  38. {
  39. // if we can successfully open the file (not directory)
  40. if (FS_open() == FS_ANSW_USB_INT_SUCCESS)
  41. {
  42. FS_setCursor(0); // set cursor to start
  43. return 1;
  44. }
  45. else
  46. {
  47. return 0;
  48. }
  49. }
  50. else
  51. {
  52. return 0;
  53. }
  54. return 0;
  55. }
  56. // Opens file for writing
  57. // requires full paths
  58. // returns 1 on success
  59. word fopenWrite(const char* fname)
  60. {
  61. if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
  62. {
  63. BDOS_PrintConsole("E: Path too large\n");
  64. return 0;
  65. }
  66. if (fname[0] != '/')
  67. {
  68. BDOS_PrintConsole("E: Filename should be a full path\n");
  69. return 0;
  70. }
  71. FS_close(); // to be sure
  72. // convert to uppercase
  73. strToUpper(fname);
  74. // if current path is correct (can be file or directory)
  75. if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
  76. {
  77. // create the file
  78. if (FS_createFile() == FS_ANSW_USB_INT_SUCCESS)
  79. {
  80. //BDOS_PrintConsole("File created\n");
  81. // open again and start at 0
  82. FS_sendFullPath(fname);
  83. FS_open();
  84. FS_setCursor(0); // set cursor to start
  85. return 1;
  86. }
  87. else
  88. {
  89. BDOS_PrintConsole("E: Could not create file\n");
  90. return 0;
  91. }
  92. }
  93. else
  94. {
  95. BDOS_PrintConsole("E: Invalid path\n");
  96. return 0;
  97. }
  98. return 0;
  99. }
  100. // closes currently opened file
  101. void fclose()
  102. {
  103. FS_close();
  104. }
  105. // returns the current char at cursor (EOF if end of file)
  106. // increments the cursor
  107. word fgetc()
  108. {
  109. // workaround for missing compiler check for ALU constants > 11 bit
  110. word stdioBufLen = STDIO_FBUF_LEN;
  111. if (inbufCursor >= STDIO_FBUF_LEN || inbufCursor == 0) // we are at the end of the buffer (or it is not initialized yet)
  112. {
  113. // get filesize
  114. word sizeOfFile = FS_getFileSize();
  115. // if we cannot completely fill the buffer:
  116. if (inbufStartPos + stdioBufLen > sizeOfFile)
  117. {
  118. // fill the buffer, and append with EOF token
  119. FS_readFile(inputBuffer, sizeOfFile - inbufStartPos, 0);
  120. inputBuffer[sizeOfFile - inbufStartPos] = EOF;
  121. }
  122. else
  123. {
  124. // Fill buffer again
  125. FS_readFile(inputBuffer, STDIO_FBUF_LEN, 0);
  126. }
  127. inbufStartPos += stdioBufLen; // for the next fill
  128. inbufCursor = 0; // start at the beginning of the buffer again
  129. }
  130. // return from the buffer, and increment
  131. char gotchar = inputBuffer[inbufCursor];
  132. inbufCursor++;
  133. // BDOS_PrintcConsole(gotchar); // useful for debugging
  134. return gotchar;
  135. }
  136. word fputData(char* outbufAddr, word lenOfData)
  137. {
  138. word bytesWritten = 0;
  139. // loop until all bytes are sent
  140. while (bytesWritten != lenOfData)
  141. {
  142. word partToSend = lenOfData - bytesWritten;
  143. // send in parts of 0xFFFF
  144. if (partToSend > 0xFFFF)
  145. partToSend = 0xFFFF;
  146. // write away
  147. if (FS_writeFile((outbufAddr +bytesWritten), partToSend) != FS_ANSW_USB_INT_SUCCESS)
  148. BDOS_PrintConsole("write error\n");
  149. // Update the amount of bytes sent
  150. bytesWritten += partToSend;
  151. }
  152. }
  153. /*
  154. Prints a single char c by writing it to UART_TX_ADDR
  155. */
  156. void uprintc(char c)
  157. {
  158. word *p = (word *)UART_TX_ADDR; // address of UART TX
  159. *p = (word)c; // write char over UART
  160. }
  161. /*
  162. Sends each character from str over UART
  163. by writing them to UART_TX_ADDR
  164. until a 0 value is found.
  165. Does not send a newline afterwards.
  166. */
  167. void uprint(char* str)
  168. {
  169. word *p = (word *)UART_TX_ADDR; // address of UART TX
  170. char chr = *str; // first character of str
  171. while (chr != 0) // continue until null value
  172. {
  173. *p = (word)chr; // write char over UART
  174. str++; // go to next character address
  175. chr = *str; // get character from address
  176. }
  177. }
  178. /*
  179. Same as uprint(char* str),
  180. except it sends a newline afterwards.
  181. */
  182. void uprintln(char* str)
  183. {
  184. uprint(str);
  185. uprintc('\n');
  186. }
  187. void exit(word i)
  188. {
  189. asm("jump Return_BDOS\n");
  190. }