filetypes.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* sd2snes - SD card based universal cartridge for the SNES
  2. Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
  3. AVR firmware portion
  4. Inspired by and based on code from sd2iec, written by Ingo Korb et al.
  5. See sdcard.c|h, config.h.
  6. FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
  7. see ff.c|h.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; version 2 of the License only.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. filetypes.c: directory scanning and file type detection
  19. */
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <avr/pgmspace.h>
  23. #include <util/delay.h>
  24. #include "config.h"
  25. #include "uart.h"
  26. #include "filetypes.h"
  27. #include "ff.h"
  28. #include "smc.h"
  29. #include "fileops.h"
  30. #include "crc16.h"
  31. #include "memory.h"
  32. #include "led.h"
  33. uint16_t scan_flat(const char* path) {
  34. DIR dir;
  35. FRESULT res;
  36. FILINFO fno;
  37. fno.lfn = NULL;
  38. res = f_opendir(&dir, (unsigned char*)path);
  39. uint16_t numentries = 0;
  40. if (res == FR_OK) {
  41. for (;;) {
  42. res = f_readdir(&dir, &fno);
  43. if(res != FR_OK || fno.fname[0] == 0)break;
  44. numentries++;
  45. }
  46. }
  47. return numentries;
  48. }
  49. uint16_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
  50. DIR dir;
  51. FILINFO fno;
  52. FRESULT res;
  53. uint8_t len;
  54. unsigned char* fn;
  55. static unsigned char depth = 0;
  56. static uint16_t crc;
  57. static uint32_t db_tgt;
  58. static uint32_t next_subdir_tgt;
  59. static uint32_t parent_tgt;
  60. static uint32_t dir_end = 0;
  61. static uint8_t was_empty = 0;
  62. uint32_t dir_tgt;
  63. uint16_t numentries;
  64. uint32_t dirsize;
  65. uint8_t pass = 0;
  66. dir_tgt = this_dir_tgt;
  67. if(depth==0) {
  68. crc = 0;
  69. db_tgt = SRAM_DB_ADDR+0x10;
  70. dir_tgt = SRAM_DIR_ADDR;
  71. next_subdir_tgt = SRAM_DIR_ADDR;
  72. this_dir_tgt = SRAM_DIR_ADDR;
  73. parent_tgt = 0;
  74. dprintf("root dir @%lx\n", dir_tgt);
  75. }
  76. fno.lfn = file_lfn;
  77. numentries=0;
  78. for(pass = 0; pass < 2; pass++) {
  79. if(pass) {
  80. dirsize = 4*(numentries);
  81. // dir_tgt_next = dir_tgt + dirsize + 4; // number of entries + end marker
  82. next_subdir_tgt += dirsize + 4;
  83. if(parent_tgt) next_subdir_tgt += 4;
  84. if(next_subdir_tgt > dir_end) {
  85. dir_end = next_subdir_tgt;
  86. }
  87. dprintf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt /*dir_tgt_next*/);
  88. // _delay_ms(50);
  89. if(mkdb) {
  90. dprintf("d=%d Saving %lX to Address %lX [end]\n", depth, 0L, next_subdir_tgt - 4);
  91. // _delay_ms(50);
  92. sram_writelong(0L, next_subdir_tgt - 4);
  93. }
  94. }
  95. res = f_opendir(&dir, (unsigned char*)path);
  96. if (res == FR_OK) {
  97. if(pass && parent_tgt && mkdb) {
  98. // write backlink to parent dir
  99. // switch to next bank if record does not fit in current bank
  100. if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) {
  101. dprintf("switch! old=%lx ", db_tgt);
  102. db_tgt &= 0xffff0000;
  103. db_tgt += 0x00010000;
  104. dprintf("new=%lx\n", db_tgt);
  105. }
  106. sram_writelong((parent_tgt-SRAM_MENU_ADDR), db_tgt);
  107. sram_writebyte(0, db_tgt+sizeof(next_subdir_tgt));
  108. sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4);
  109. sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
  110. db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4;
  111. dir_tgt += 4;
  112. }
  113. len = strlen((char*)path);
  114. for (;;) {
  115. toggle_busy_led();
  116. res = f_readdir(&dir, &fno);
  117. if (res != FR_OK || fno.fname[0] == 0) {
  118. if(pass) {
  119. if(!numentries) was_empty=1;
  120. }
  121. break;
  122. }
  123. fn = *fno.lfn ? fno.lfn : fno.fname;
  124. // dprintf("%s\n", fn);
  125. // _delay_ms(100);
  126. if (*fn == '.') continue;
  127. if (fno.fattrib & AM_DIR) {
  128. numentries++;
  129. if(pass) {
  130. path[len]='/';
  131. strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
  132. depth++;
  133. if(mkdb) {
  134. uint16_t pathlen = strlen(path);
  135. // write element pointer to current dir structure
  136. dprintf("d=%d Saving %lX to Address %lX [dir]\n", depth, db_tgt, dir_tgt);
  137. // _delay_ms(50);
  138. sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
  139. // sram_writeblock((uint8_t*)&db_tgt, dir_tgt_save, sizeof(dir_tgt_save));
  140. // save element:
  141. // - path name
  142. // - pointer to sub dir structure
  143. if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) {
  144. dprintf("switch! old=%lx ", db_tgt);
  145. db_tgt &= 0xffff0000;
  146. db_tgt += 0x00010000;
  147. dprintf("new=%lx\n", db_tgt);
  148. }
  149. dprintf(" Saving dir descriptor to %lX, tgt=%lX, path=%s\n", db_tgt, next_subdir_tgt, path);
  150. // _delay_ms(100);
  151. sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
  152. sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
  153. sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
  154. sram_writeblock("/\0", db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2);
  155. // sram_writeblock((uint8_t*)&dir_tgt, db_tgt+256, sizeof(dir_tgt));
  156. db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2;
  157. }
  158. parent_tgt = this_dir_tgt;
  159. scan_dir(path, mkdb, next_subdir_tgt);
  160. dir_tgt += 4;
  161. // if(was_empty)dir_tgt_next += 4;
  162. was_empty = 0;
  163. depth--;
  164. path[len]=0;
  165. }
  166. } else {
  167. SNES_FTYPE type = determine_filetype((char*)fn);
  168. if(type != TYPE_UNKNOWN) {
  169. numentries++;
  170. if(pass) {
  171. if(mkdb) {
  172. snes_romprops_t romprops;
  173. path[len]='/';
  174. strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
  175. uint16_t pathlen = strlen(path);
  176. switch(type) {
  177. case TYPE_SMC:
  178. // XXX file_open_by_filinfo(&fno);
  179. // XXX if(file_res){
  180. // XXX dprintf("ZOMG NOOOO %d\n", file_res);
  181. // XXX _delay_ms(30);
  182. // XXX }
  183. // XXX smc_id(&romprops);
  184. // XXX file_close();
  185. // _delay_ms(30);
  186. // write element pointer to current dir structure
  187. // dprintf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt);
  188. // _delay_ms(50);
  189. if((db_tgt&0xffff) > ((0x10000-(sizeof(romprops) + sizeof(len) + pathlen + 1))&0xffff)) {
  190. dprintf("switch! old=%lx ", db_tgt);
  191. db_tgt &= 0xffff0000;
  192. db_tgt += 0x00010000;
  193. dprintf("new=%lx\n", db_tgt);
  194. }
  195. sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt);
  196. // sram_writeblock((uint8_t*)&db_tgt, dir_tgt, sizeof(db_tgt));
  197. dir_tgt += 4;
  198. // save element:
  199. // - SNES header information
  200. // - file name
  201. sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops));
  202. sram_writebyte(len+1, db_tgt + sizeof(romprops));
  203. sram_writeblock(path, db_tgt + sizeof(romprops) + sizeof(len), pathlen + 1);
  204. db_tgt += sizeof(romprops) + sizeof(len) + pathlen + 1;
  205. break;
  206. case TYPE_UNKNOWN:
  207. default:
  208. break;
  209. }
  210. path[len]=0;
  211. // dprintf("%s ", path);
  212. // _delay_ms(30);
  213. }
  214. } else {
  215. unsigned char* sfn = fno.fname;
  216. while(*sfn != 0) {
  217. crc += crc16_update(crc, sfn++, 1);
  218. }
  219. }
  220. }
  221. // dprintf("%s/%s\n", path, fn);
  222. // _delay_ms(50);
  223. }
  224. }
  225. } else uart_putc(0x30+res);
  226. }
  227. // dprintf("%x\n", crc);
  228. // _delay_ms(50);
  229. sram_writelong(db_tgt, SRAM_DB_ADDR+4);
  230. sram_writelong(dir_end, SRAM_DB_ADDR+8);
  231. return crc;
  232. }
  233. SNES_FTYPE determine_filetype(char* filename) {
  234. char* ext = strrchr(filename, '.');
  235. if(ext == NULL)
  236. return TYPE_UNKNOWN;
  237. if(!strcasecmp_P(ext+1, PSTR("SMC"))) {
  238. return TYPE_SMC;
  239. }/* later
  240. if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
  241. return TYPE_SRM;
  242. }
  243. if(!strcasecmp_P(ext+1, PSTR("SPC"))) {
  244. return TYPE_SPC;
  245. }*/
  246. return TYPE_UNKNOWN;
  247. }
  248. FRESULT get_db_id(uint16_t* id) {
  249. file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ);
  250. if(file_res == FR_OK) {
  251. file_readblock(id, 0, 2);
  252. /* XXX */// *id=0xdead;
  253. file_close();
  254. } else {
  255. *id=0xdead;
  256. }
  257. return file_res;
  258. }