memory.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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. memory.c: RAM operations
  19. */
  20. #include "config.h"
  21. #include "uart.h"
  22. #include "fpga.h"
  23. #include "crc.h"
  24. #include "crc32.h"
  25. #include "ff.h"
  26. #include "fileops.h"
  27. #include "spi.h"
  28. #include "fpga_spi.h"
  29. #include "led.h"
  30. #include "smc.h"
  31. #include "memory.h"
  32. #include "snes.h"
  33. #include "timer.h"
  34. #include "rle.h"
  35. #include "diskio.h"
  36. #include "msu1.h"
  37. #include <string.h>
  38. char* hex = "0123456789ABCDEF";
  39. extern snes_romprops_t romprops;
  40. void sram_hexdump(uint32_t addr, uint32_t len) {
  41. static uint8_t buf[16];
  42. uint32_t ptr;
  43. for(ptr=0; ptr < len; ptr += 16) {
  44. sram_readblock((void*)buf, ptr+addr, 16);
  45. uart_trace(buf, 0, 16);
  46. }
  47. }
  48. void sram_writebyte(uint8_t val, uint32_t addr) {
  49. set_mcu_addr(addr);
  50. FPGA_SELECT();
  51. FPGA_TX_BYTE(0x98); /* WRITE */
  52. FPGA_TX_BYTE(val);
  53. FPGA_WAIT_RDY();
  54. FPGA_DESELECT();
  55. }
  56. uint8_t sram_readbyte(uint32_t addr) {
  57. set_mcu_addr(addr);
  58. FPGA_SELECT();
  59. FPGA_TX_BYTE(0x88); /* READ */
  60. FPGA_WAIT_RDY();
  61. uint8_t val = FPGA_RX_BYTE();
  62. FPGA_DESELECT();
  63. return val;
  64. }
  65. void sram_writeshort(uint16_t val, uint32_t addr) {
  66. set_mcu_addr(addr);
  67. FPGA_SELECT();
  68. FPGA_TX_BYTE(0x98); /* WRITE */
  69. FPGA_TX_BYTE(val&0xff);
  70. FPGA_WAIT_RDY();
  71. FPGA_TX_BYTE((val>>8)&0xff);
  72. FPGA_WAIT_RDY();
  73. FPGA_DESELECT();
  74. }
  75. void sram_writelong(uint32_t val, uint32_t addr) {
  76. set_mcu_addr(addr);
  77. FPGA_SELECT();
  78. FPGA_TX_BYTE(0x98); /* WRITE */
  79. FPGA_TX_BYTE(val&0xff);
  80. FPGA_WAIT_RDY();
  81. FPGA_TX_BYTE((val>>8)&0xff);
  82. FPGA_WAIT_RDY();
  83. FPGA_TX_BYTE((val>>16)&0xff);
  84. FPGA_WAIT_RDY();
  85. FPGA_TX_BYTE((val>>24)&0xff);
  86. FPGA_WAIT_RDY();
  87. FPGA_DESELECT();
  88. }
  89. uint16_t sram_readshort(uint32_t addr) {
  90. set_mcu_addr(addr);
  91. FPGA_SELECT();
  92. FPGA_TX_BYTE(0x88);
  93. FPGA_WAIT_RDY();
  94. uint32_t val = FPGA_RX_BYTE();
  95. FPGA_WAIT_RDY();
  96. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  97. FPGA_DESELECT();
  98. return val;
  99. }
  100. uint32_t sram_readlong(uint32_t addr) {
  101. set_mcu_addr(addr);
  102. FPGA_SELECT();
  103. FPGA_TX_BYTE(0x88);
  104. FPGA_WAIT_RDY();
  105. uint32_t val = FPGA_RX_BYTE();
  106. FPGA_WAIT_RDY();
  107. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  108. FPGA_WAIT_RDY();
  109. val |= ((uint32_t)FPGA_RX_BYTE()<<16);
  110. FPGA_WAIT_RDY();
  111. val |= ((uint32_t)FPGA_RX_BYTE()<<24);
  112. FPGA_DESELECT();
  113. return val;
  114. }
  115. void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
  116. set_mcu_addr(addr);
  117. FPGA_SELECT();
  118. FPGA_TX_BYTE(0x88);
  119. uint16_t i=0;
  120. while(i<count) {
  121. FPGA_WAIT_RDY();
  122. uint32_t val = (uint32_t)FPGA_RX_BYTE()<<24;
  123. FPGA_WAIT_RDY();
  124. val |= ((uint32_t)FPGA_RX_BYTE()<<16);
  125. FPGA_WAIT_RDY();
  126. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  127. FPGA_WAIT_RDY();
  128. val |= FPGA_RX_BYTE();
  129. buf[i++] = val;
  130. }
  131. FPGA_DESELECT();
  132. }
  133. void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
  134. uint16_t count=size;
  135. uint8_t* tgt = buf;
  136. set_mcu_addr(addr);
  137. FPGA_SELECT();
  138. FPGA_TX_BYTE(0x88); /* READ */
  139. while(count--) {
  140. FPGA_WAIT_RDY();
  141. *(tgt++) = FPGA_RX_BYTE();
  142. }
  143. FPGA_DESELECT();
  144. }
  145. void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
  146. uint16_t count=size;
  147. uint8_t* src = buf;
  148. set_mcu_addr(addr);
  149. FPGA_SELECT();
  150. FPGA_TX_BYTE(0x98); /* WRITE */
  151. while(count--) {
  152. FPGA_TX_BYTE(*src++);
  153. FPGA_WAIT_RDY();
  154. }
  155. FPGA_DESELECT();
  156. }
  157. uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
  158. UINT bytes_read;
  159. DWORD filesize;
  160. UINT count=0;
  161. tick_t ticksstart, ticks_total=0;
  162. ticksstart=getticks();
  163. printf("%s\n", filename);
  164. file_open(filename, FA_READ);
  165. if(file_res) {
  166. uart_putc('?');
  167. uart_putc(0x30+file_res);
  168. return 0;
  169. }
  170. filesize = file_handle.fsize;
  171. smc_id(&romprops);
  172. file_close();
  173. /* reconfigure FPGA if necessary */
  174. if(romprops.fpga_conf) {
  175. printf("reconfigure FPGA with %s...\n", romprops.fpga_conf);
  176. fpga_pgm((uint8_t*)romprops.fpga_conf);
  177. }
  178. set_mcu_addr(base_addr);
  179. file_open(filename, FA_READ);
  180. f_lseek(&file_handle, romprops.offset);
  181. for(;;) {
  182. ff_sd_offload=1;
  183. sd_offload_tgt=0;
  184. bytes_read = file_read();
  185. if (file_res || !bytes_read) break;
  186. if(!(count++ % 512)) {
  187. uart_putc('.');
  188. }
  189. }
  190. file_close();
  191. set_mapper(romprops.mapper_id);
  192. printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
  193. ticks_total=getticks()-ticksstart;
  194. printf("%u ticks total\n", ticks_total);
  195. if(romprops.mapper_id==3) {
  196. printf("BSX Flash cart image\n");
  197. printf("attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n");
  198. load_sram_offload((uint8_t*)"/sd2snes/bsxbios.bin", 0x800000);
  199. printf("Type: %02x\n", romprops.header.destcode);
  200. set_bsx_regs(0xc0, 0x3f);
  201. uint16_t rombase;
  202. if(romprops.header.ramsize & 1) {
  203. rombase = 0xff00;
  204. // set_bsx_regs(0x36, 0xc9);
  205. } else {
  206. rombase = 0x7f00;
  207. // set_bsx_regs(0x34, 0xcb);
  208. }
  209. sram_writebyte(0x33, rombase+0xda);
  210. sram_writebyte(0x00, rombase+0xd4);
  211. sram_writebyte(0xfc, rombase+0xd5);
  212. set_fpga_time(0x0220110301180530LL);
  213. }
  214. uint32_t rammask;
  215. uint32_t rommask;
  216. while(filesize > (romprops.romsize_bytes + romprops.offset)) {
  217. romprops.romsize_bytes <<= 1;
  218. }
  219. if(romprops.header.ramsize == 0) {
  220. rammask = 0;
  221. } else {
  222. rammask = romprops.ramsize_bytes - 1;
  223. }
  224. rommask = romprops.romsize_bytes - 1;
  225. printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
  226. set_saveram_mask(rammask);
  227. set_rom_mask(rommask);
  228. readled(0);
  229. if(flags & LOADROM_WITH_SRAM) {
  230. if(romprops.ramsize_bytes) {
  231. strcpy(strrchr((char*)filename, (int)'.'), ".srm");
  232. printf("SRM file: %s\n", filename);
  233. load_sram(filename, SRAM_SAVE_ADDR);
  234. } else {
  235. printf("No SRAM\n");
  236. }
  237. }
  238. printf("check MSU...");
  239. if(msu1_check(filename)) {
  240. romprops.fpga_features |= FEAT_MSU1;
  241. romprops.has_msu1 = 1;
  242. } else {
  243. romprops.has_msu1 = 0;
  244. }
  245. printf("done\n");
  246. romprops.fpga_features |= FEAT_SRTC;
  247. fpga_set_features(romprops.fpga_features);
  248. if(flags & LOADROM_WITH_RESET) {
  249. fpga_dspx_reset(1);
  250. snes_reset(1);
  251. delay_ms(10);
  252. snes_reset(0);
  253. fpga_dspx_reset(0);
  254. }
  255. return (uint32_t)filesize;
  256. }
  257. uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) {
  258. set_mcu_addr(base_addr);
  259. UINT bytes_read;
  260. DWORD filesize;
  261. file_open(filename, FA_READ);
  262. filesize = file_handle.fsize;
  263. if(file_res) return 0;
  264. for(;;) {
  265. ff_sd_offload=1;
  266. sd_offload_tgt=0;
  267. bytes_read = file_read();
  268. if (file_res || !bytes_read) break;
  269. }
  270. file_close();
  271. return (uint32_t)filesize;
  272. }
  273. uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
  274. set_mcu_addr(base_addr);
  275. UINT bytes_read;
  276. DWORD filesize;
  277. file_open(filename, FA_READ);
  278. filesize = file_handle.fsize;
  279. if(file_res) {
  280. printf("load_sram: could not open %s, res=%d\n", filename, file_res);
  281. return 0;
  282. }
  283. for(;;) {
  284. bytes_read = file_read();
  285. if (file_res || !bytes_read) break;
  286. FPGA_SELECT();
  287. FPGA_TX_BYTE(0x98);
  288. for(int j=0; j<bytes_read; j++) {
  289. FPGA_TX_BYTE(file_buf[j]);
  290. FPGA_WAIT_RDY();
  291. }
  292. FPGA_DESELECT();
  293. }
  294. file_close();
  295. return (uint32_t)filesize;
  296. }
  297. uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
  298. uint8_t data;
  299. set_mcu_addr(base_addr);
  300. DWORD filesize;
  301. file_open(filename, FA_READ);
  302. filesize = file_handle.fsize;
  303. if(file_res) return 0;
  304. FPGA_SELECT();
  305. FPGA_TX_BYTE(0x98);
  306. for(;;) {
  307. data = rle_file_getc();
  308. if (file_res || file_status) break;
  309. FPGA_TX_BYTE(data);
  310. FPGA_WAIT_RDY();
  311. }
  312. FPGA_DESELECT();
  313. file_close();
  314. return (uint32_t)filesize;
  315. }
  316. void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
  317. uint32_t count = 0;
  318. uint32_t num = 0;
  319. FPGA_DESELECT();
  320. file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
  321. if(file_res) {
  322. uart_putc(0x30+file_res);
  323. }
  324. while(count<sram_size) {
  325. set_mcu_addr(base_addr+count);
  326. FPGA_SELECT();
  327. FPGA_TX_BYTE(0x88); /* read */
  328. for(int j=0; j<sizeof(file_buf); j++) {
  329. FPGA_WAIT_RDY();
  330. file_buf[j] = FPGA_RX_BYTE();
  331. count++;
  332. }
  333. FPGA_DESELECT();
  334. num = file_write();
  335. if(file_res) {
  336. uart_putc(0x30+file_res);
  337. }
  338. }
  339. file_close();
  340. }
  341. uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
  342. uint8_t data;
  343. uint32_t count;
  344. uint32_t crc;
  345. crc=0;
  346. crc_valid=1;
  347. set_mcu_addr(base_addr);
  348. FPGA_SELECT();
  349. FPGA_TX_BYTE(0x88);
  350. for(count=0; count<size; count++) {
  351. FPGA_WAIT_RDY();
  352. data = FPGA_RX_BYTE();
  353. if(get_snes_reset()) {
  354. crc_valid = 0;
  355. break;
  356. }
  357. crc += crc32_update(crc, data);
  358. }
  359. FPGA_DESELECT();
  360. return crc;
  361. }
  362. uint8_t sram_reliable() {
  363. uint16_t score=0;
  364. uint32_t val;
  365. uint8_t result = 0;
  366. /*while(score<SRAM_RELIABILITY_SCORE) {
  367. if(sram_readlong(SRAM_SCRATCHPAD)==val) {
  368. score++;
  369. } else {
  370. set_pwr_led(0);
  371. score=0;
  372. }
  373. } */
  374. for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
  375. val=sram_readlong(SRAM_SCRATCHPAD);
  376. if(val==0x12345678) {
  377. score++;
  378. } else {
  379. printf("i=%d val=%08lX\n", i, val);
  380. }
  381. }
  382. if(score<SRAM_RELIABILITY_SCORE) {
  383. result = 0;
  384. /* dprintf("score=%d\n", score); */
  385. } else {
  386. result = 1;
  387. }
  388. rdyled(result);
  389. return result;
  390. }
  391. void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
  392. set_mcu_addr(base_addr);
  393. FPGA_SELECT();
  394. FPGA_TX_BYTE(0x98);
  395. for(uint32_t i=0; i<len; i++) {
  396. FPGA_TX_BYTE(val);
  397. FPGA_WAIT_RDY();
  398. }
  399. FPGA_DESELECT();
  400. }
  401. uint64_t sram_gettime(uint32_t base_addr) {
  402. set_mcu_addr(base_addr);
  403. FPGA_SELECT();
  404. FPGA_TX_BYTE(0x88);
  405. uint8_t data;
  406. uint64_t result = 0LL;
  407. /* 1st nibble is the century - 10 (binary)
  408. 4th nibble is the month (binary)
  409. all other fields are BCD */
  410. for(int i=0; i<12; i++) {
  411. FPGA_WAIT_RDY();
  412. data = FPGA_RX_BYTE();
  413. data &= 0xf;
  414. switch(i) {
  415. case 0:
  416. result = (result << 4) | ((data / 10) + 1);
  417. result = (result << 4) | (data % 10);
  418. break;
  419. case 3:
  420. result = (result << 4) | ((data / 10));
  421. result = (result << 4) | (data % 10);
  422. break;
  423. default:
  424. result = (result << 4) | data;
  425. }
  426. }
  427. FPGA_DESELECT();
  428. return result & 0x00ffffffffffffffLL;
  429. }
  430. void load_dspx(const uint8_t *filename, uint8_t coretype) {
  431. UINT bytes_read;
  432. DWORD filesize;
  433. uint16_t word_cnt;
  434. uint8_t wordsize_cnt = 0;
  435. uint16_t sector_remaining = 0;
  436. uint16_t sector_cnt = 0;
  437. uint16_t pgmsize = 0;
  438. uint16_t datsize = 0;
  439. uint32_t pgmdata = 0;
  440. uint16_t datdata = 0;
  441. if(coretype & FEAT_ST0010) {
  442. datsize = 1536;
  443. pgmsize = 2048;
  444. } else if (coretype & FEAT_DSPX) {
  445. datsize = 1024;
  446. pgmsize = 2048;
  447. } else if (coretype & FEAT_CX4) {
  448. datsize = 0;
  449. pgmsize = 1024; /* Cx4 data ROM */
  450. } else {
  451. printf("load_dspx: unknown core (%02x)!\n", coretype);
  452. }
  453. file_open((uint8_t*)filename, FA_READ);
  454. filesize = file_handle.fsize;
  455. if(file_res) {
  456. printf("Could not read %s: error %d\n", filename, file_res);
  457. return;
  458. }
  459. fpga_reset_dspx_addr();
  460. for(word_cnt = 0; word_cnt < pgmsize;) {
  461. if(!sector_remaining) {
  462. bytes_read = file_read();
  463. sector_remaining = bytes_read;
  464. sector_cnt = 0;
  465. }
  466. pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
  467. sector_cnt++;
  468. wordsize_cnt++;
  469. sector_remaining--;
  470. if(wordsize_cnt == 3){
  471. wordsize_cnt = 0;
  472. word_cnt++;
  473. fpga_write_dspx_pgm(pgmdata);
  474. }
  475. }
  476. wordsize_cnt = 0;
  477. if(coretype & FEAT_ST0010) {
  478. file_seek(0xc000);
  479. sector_remaining = 0;
  480. }
  481. for(word_cnt = 0; word_cnt < datsize;) {
  482. if(!sector_remaining) {
  483. bytes_read = file_read();
  484. sector_remaining = bytes_read;
  485. sector_cnt = 0;
  486. }
  487. datdata = (datdata << 8) | file_buf[sector_cnt];
  488. sector_cnt++;
  489. wordsize_cnt++;
  490. sector_remaining--;
  491. if(wordsize_cnt == 2){
  492. wordsize_cnt = 0;
  493. word_cnt++;
  494. fpga_write_dspx_dat(datdata);
  495. }
  496. }
  497. fpga_reset_dspx_addr();
  498. file_close();
  499. }