memory.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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 "snesboot.h"
  37. #include "msu1.h"
  38. #include <string.h>
  39. char* hex = "0123456789ABCDEF";
  40. extern snes_romprops_t romprops;
  41. void sram_hexdump(uint32_t addr, uint32_t len) {
  42. static uint8_t buf[16];
  43. uint32_t ptr;
  44. for(ptr=0; ptr < len; ptr += 16) {
  45. sram_readblock((void*)buf, ptr+addr, 16);
  46. uart_trace(buf, 0, 16);
  47. }
  48. }
  49. void sram_writebyte(uint8_t val, uint32_t addr) {
  50. set_mcu_addr(addr);
  51. FPGA_SELECT();
  52. FPGA_TX_BYTE(0x98); /* WRITE */
  53. FPGA_TX_BYTE(val);
  54. FPGA_WAIT_RDY();
  55. FPGA_DESELECT();
  56. }
  57. uint8_t sram_readbyte(uint32_t addr) {
  58. set_mcu_addr(addr);
  59. FPGA_SELECT();
  60. FPGA_TX_BYTE(0x88); /* READ */
  61. FPGA_WAIT_RDY();
  62. uint8_t val = FPGA_RX_BYTE();
  63. FPGA_DESELECT();
  64. return val;
  65. }
  66. void sram_writeshort(uint16_t val, uint32_t addr) {
  67. set_mcu_addr(addr);
  68. FPGA_SELECT();
  69. FPGA_TX_BYTE(0x98); /* WRITE */
  70. FPGA_TX_BYTE(val&0xff);
  71. FPGA_WAIT_RDY();
  72. FPGA_TX_BYTE((val>>8)&0xff);
  73. FPGA_WAIT_RDY();
  74. FPGA_DESELECT();
  75. }
  76. void sram_writelong(uint32_t val, uint32_t addr) {
  77. set_mcu_addr(addr);
  78. FPGA_SELECT();
  79. FPGA_TX_BYTE(0x98); /* WRITE */
  80. FPGA_TX_BYTE(val&0xff);
  81. FPGA_WAIT_RDY();
  82. FPGA_TX_BYTE((val>>8)&0xff);
  83. FPGA_WAIT_RDY();
  84. FPGA_TX_BYTE((val>>16)&0xff);
  85. FPGA_WAIT_RDY();
  86. FPGA_TX_BYTE((val>>24)&0xff);
  87. FPGA_WAIT_RDY();
  88. FPGA_DESELECT();
  89. }
  90. uint16_t sram_readshort(uint32_t addr) {
  91. set_mcu_addr(addr);
  92. FPGA_SELECT();
  93. FPGA_TX_BYTE(0x88);
  94. FPGA_WAIT_RDY();
  95. uint32_t val = FPGA_RX_BYTE();
  96. FPGA_WAIT_RDY();
  97. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  98. FPGA_DESELECT();
  99. return val;
  100. }
  101. uint32_t sram_readlong(uint32_t addr) {
  102. set_mcu_addr(addr);
  103. FPGA_SELECT();
  104. FPGA_TX_BYTE(0x88);
  105. FPGA_WAIT_RDY();
  106. uint32_t val = FPGA_RX_BYTE();
  107. FPGA_WAIT_RDY();
  108. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  109. FPGA_WAIT_RDY();
  110. val |= ((uint32_t)FPGA_RX_BYTE()<<16);
  111. FPGA_WAIT_RDY();
  112. val |= ((uint32_t)FPGA_RX_BYTE()<<24);
  113. FPGA_DESELECT();
  114. return val;
  115. }
  116. void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
  117. set_mcu_addr(addr);
  118. FPGA_SELECT();
  119. FPGA_TX_BYTE(0x88);
  120. uint16_t i=0;
  121. while(i<count) {
  122. FPGA_WAIT_RDY();
  123. uint32_t val = (uint32_t)FPGA_RX_BYTE()<<24;
  124. FPGA_WAIT_RDY();
  125. val |= ((uint32_t)FPGA_RX_BYTE()<<16);
  126. FPGA_WAIT_RDY();
  127. val |= ((uint32_t)FPGA_RX_BYTE()<<8);
  128. FPGA_WAIT_RDY();
  129. val |= FPGA_RX_BYTE();
  130. buf[i++] = val;
  131. }
  132. FPGA_DESELECT();
  133. }
  134. void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
  135. uint16_t count=size;
  136. uint8_t* tgt = buf;
  137. set_mcu_addr(addr);
  138. FPGA_SELECT();
  139. FPGA_TX_BYTE(0x88); /* READ */
  140. while(count--) {
  141. FPGA_WAIT_RDY();
  142. *(tgt++) = FPGA_RX_BYTE();
  143. }
  144. FPGA_DESELECT();
  145. }
  146. void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
  147. uint16_t count=size;
  148. uint8_t* src = buf;
  149. set_mcu_addr(addr);
  150. FPGA_SELECT();
  151. FPGA_TX_BYTE(0x98); /* WRITE */
  152. while(count--) {
  153. FPGA_TX_BYTE(*src++);
  154. FPGA_WAIT_RDY();
  155. }
  156. FPGA_DESELECT();
  157. }
  158. uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
  159. UINT bytes_read;
  160. DWORD filesize;
  161. UINT count=0;
  162. tick_t ticksstart, ticks_total=0;
  163. ticksstart=getticks();
  164. printf("Loading: %s\n", filename);
  165. file_open(filename, FA_READ);
  166. if(file_res) {
  167. uart_putc('?');
  168. uart_putc(0x30+file_res);
  169. return 0;
  170. }
  171. filesize = file_handle.fsize;
  172. smc_id(&romprops);
  173. file_close();
  174. /* reconfigure FPGA if necessary */
  175. if(romprops.fpga_conf) {
  176. printf("reconfigure FPGA with %s...\n", romprops.fpga_conf);
  177. fpga_pgm((uint8_t*)romprops.fpga_conf);
  178. }
  179. set_mcu_addr(base_addr);
  180. file_open(filename, FA_READ);
  181. f_lseek(&file_handle, romprops.offset);
  182. for(;;) {
  183. ff_sd_offload=1;
  184. sd_offload_tgt=0;
  185. bytes_read = file_read();
  186. if (file_res || !bytes_read) break;
  187. if(!(count++ % 512)) {
  188. uart_putc('.');
  189. }
  190. }
  191. file_close();
  192. set_mapper(romprops.mapper_id);
  193. printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
  194. ticks_total=getticks()-ticksstart;
  195. printf("%u ticks total\n", ticks_total);
  196. if(romprops.mapper_id==3) {
  197. printf("BSX Flash cart image\n");
  198. printf("attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n");
  199. load_sram_offload((uint8_t*)"/sd2snes/bsxbios.bin", 0x800000);
  200. printf("Type: %02x\n", romprops.header.destcode);
  201. set_bsx_regs(0xc0, 0x3f);
  202. uint16_t rombase;
  203. if(romprops.header.ramsize & 1) {
  204. rombase = 0xff00;
  205. // set_bsx_regs(0x36, 0xc9);
  206. } else {
  207. rombase = 0x7f00;
  208. // set_bsx_regs(0x34, 0xcb);
  209. }
  210. sram_writebyte(0x33, rombase+0xda);
  211. sram_writebyte(0x00, rombase+0xd4);
  212. sram_writebyte(0xfc, rombase+0xd5);
  213. set_fpga_time(0x0220110301180530LL);
  214. }
  215. if(romprops.has_dspx || romprops.has_cx4) {
  216. printf("DSPx game. Loading firmware image %s...\n", romprops.dsp_fw);
  217. load_dspx(romprops.dsp_fw, romprops.fpga_features);
  218. /* fallback to DSP1B firmware if DSP1.bin is not present */
  219. if(file_res && romprops.dsp_fw == DSPFW_1) {
  220. load_dspx(DSPFW_1B, romprops.fpga_features);
  221. }
  222. if(file_res) {
  223. snes_menu_errmsg(MENU_ERR_NODSP, (void*)romprops.dsp_fw);
  224. }
  225. }
  226. uint32_t rammask;
  227. uint32_t rommask;
  228. while(filesize > (romprops.romsize_bytes + romprops.offset)) {
  229. romprops.romsize_bytes <<= 1;
  230. }
  231. if(romprops.header.ramsize == 0) {
  232. rammask = 0;
  233. } else {
  234. rammask = romprops.ramsize_bytes - 1;
  235. }
  236. rommask = romprops.romsize_bytes - 1;
  237. printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
  238. set_saveram_mask(rammask);
  239. set_rom_mask(rommask);
  240. readled(0);
  241. if(flags & LOADROM_WITH_SRAM) {
  242. if(romprops.ramsize_bytes) {
  243. strcpy(strrchr((char*)filename, (int)'.'), ".srm");
  244. printf("SRM file: %s\n", filename);
  245. load_sram(filename, SRAM_SAVE_ADDR);
  246. } else {
  247. printf("No SRAM\n");
  248. }
  249. }
  250. printf("check MSU...");
  251. if(msu1_check(filename)) {
  252. romprops.fpga_features |= FEAT_MSU1;
  253. romprops.has_msu1 = 1;
  254. } else {
  255. romprops.has_msu1 = 0;
  256. }
  257. printf("done\n");
  258. romprops.fpga_features |= FEAT_SRTC;
  259. romprops.fpga_features |= FEAT_213F;
  260. fpga_set_213f(romprops.region);
  261. fpga_set_features(romprops.fpga_features);
  262. if(flags & LOADROM_WITH_RESET) {
  263. fpga_dspx_reset(1);
  264. snes_reset(1);
  265. delay_ms(10);
  266. snes_reset(0);
  267. fpga_dspx_reset(0);
  268. }
  269. return (uint32_t)filesize;
  270. }
  271. uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) {
  272. set_mcu_addr(base_addr);
  273. UINT bytes_read;
  274. DWORD filesize;
  275. file_open(filename, FA_READ);
  276. filesize = file_handle.fsize;
  277. if(file_res) return 0;
  278. for(;;) {
  279. ff_sd_offload=1;
  280. sd_offload_tgt=0;
  281. bytes_read = file_read();
  282. if (file_res || !bytes_read) break;
  283. }
  284. file_close();
  285. return (uint32_t)filesize;
  286. }
  287. uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
  288. set_mcu_addr(base_addr);
  289. UINT bytes_read;
  290. DWORD filesize;
  291. file_open(filename, FA_READ);
  292. filesize = file_handle.fsize;
  293. if(file_res) {
  294. printf("load_sram: could not open %s, res=%d\n", filename, file_res);
  295. return 0;
  296. }
  297. for(;;) {
  298. bytes_read = file_read();
  299. if (file_res || !bytes_read) break;
  300. FPGA_SELECT();
  301. FPGA_TX_BYTE(0x98);
  302. for(int j=0; j<bytes_read; j++) {
  303. FPGA_TX_BYTE(file_buf[j]);
  304. FPGA_WAIT_RDY();
  305. }
  306. FPGA_DESELECT();
  307. }
  308. file_close();
  309. return (uint32_t)filesize;
  310. }
  311. uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
  312. uint8_t data;
  313. set_mcu_addr(base_addr);
  314. DWORD filesize;
  315. file_open(filename, FA_READ);
  316. filesize = file_handle.fsize;
  317. if(file_res) return 0;
  318. FPGA_SELECT();
  319. FPGA_TX_BYTE(0x98);
  320. for(;;) {
  321. data = rle_file_getc();
  322. if (file_res || file_status) break;
  323. FPGA_TX_BYTE(data);
  324. FPGA_WAIT_RDY();
  325. }
  326. FPGA_DESELECT();
  327. file_close();
  328. return (uint32_t)filesize;
  329. }
  330. uint32_t load_bootrle(uint32_t base_addr) {
  331. uint8_t data;
  332. set_mcu_addr(base_addr);
  333. DWORD filesize = 0;
  334. rle_mem_init(bootrle, sizeof(bootrle));
  335. FPGA_SELECT();
  336. FPGA_TX_BYTE(0x98);
  337. for(;;) {
  338. data = rle_mem_getc();
  339. if(rle_state) break;
  340. FPGA_TX_BYTE(data);
  341. FPGA_WAIT_RDY();
  342. filesize++;
  343. }
  344. FPGA_DESELECT();
  345. return (uint32_t)filesize;
  346. }
  347. void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
  348. uint32_t count = 0;
  349. uint32_t num = 0;
  350. FPGA_DESELECT();
  351. file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
  352. if(file_res) {
  353. uart_putc(0x30+file_res);
  354. }
  355. while(count<sram_size) {
  356. set_mcu_addr(base_addr+count);
  357. FPGA_SELECT();
  358. FPGA_TX_BYTE(0x88); /* read */
  359. for(int j=0; j<sizeof(file_buf); j++) {
  360. FPGA_WAIT_RDY();
  361. file_buf[j] = FPGA_RX_BYTE();
  362. count++;
  363. }
  364. FPGA_DESELECT();
  365. num = file_write();
  366. if(file_res) {
  367. uart_putc(0x30+file_res);
  368. }
  369. }
  370. file_close();
  371. }
  372. uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
  373. uint8_t data;
  374. uint32_t count;
  375. uint32_t crc;
  376. crc=0;
  377. crc_valid=1;
  378. set_mcu_addr(base_addr);
  379. FPGA_SELECT();
  380. FPGA_TX_BYTE(0x88);
  381. for(count=0; count<size; count++) {
  382. FPGA_WAIT_RDY();
  383. data = FPGA_RX_BYTE();
  384. if(get_snes_reset()) {
  385. crc_valid = 0;
  386. break;
  387. }
  388. crc += crc32_update(crc, data);
  389. }
  390. FPGA_DESELECT();
  391. return crc;
  392. }
  393. uint8_t sram_reliable() {
  394. uint16_t score=0;
  395. uint32_t val;
  396. uint8_t result = 0;
  397. /*while(score<SRAM_RELIABILITY_SCORE) {
  398. if(sram_readlong(SRAM_SCRATCHPAD)==val) {
  399. score++;
  400. } else {
  401. set_pwr_led(0);
  402. score=0;
  403. }
  404. } */
  405. for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
  406. val=sram_readlong(SRAM_SCRATCHPAD);
  407. if(val==0x12345678) {
  408. score++;
  409. } else {
  410. printf("i=%d val=%08lX\n", i, val);
  411. }
  412. }
  413. if(score<SRAM_RELIABILITY_SCORE) {
  414. result = 0;
  415. /* dprintf("score=%d\n", score); */
  416. } else {
  417. result = 1;
  418. }
  419. rdyled(result);
  420. return result;
  421. }
  422. void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
  423. set_mcu_addr(base_addr);
  424. FPGA_SELECT();
  425. FPGA_TX_BYTE(0x98);
  426. for(uint32_t i=0; i<len; i++) {
  427. FPGA_TX_BYTE(val);
  428. FPGA_WAIT_RDY();
  429. }
  430. FPGA_DESELECT();
  431. }
  432. /* memtest functions */
  433. uint8_t memtest_checkvalue(uint8_t value)
  434. {
  435. uint8_t ret = 0;
  436. uint32_t idx, lasterr = 0, errwas = 0, errcount = 0;
  437. uint8_t data;
  438. set_saveram_mask(0x0);
  439. set_rom_mask(0x0);
  440. printf("%s: Set memory to 0x%02X...\n", __func__, value);
  441. sram_memset(0x00000, 0x1000000, value);
  442. printf("Checking... [");
  443. set_mcu_addr(0x0);
  444. FPGA_SELECT();
  445. FPGA_WAIT_RDY();
  446. FPGA_TX_BYTE(0x88);
  447. for(idx = 0; idx < 0x1000000; idx++)
  448. {
  449. FPGA_WAIT_RDY();
  450. data = FPGA_RX_BYTE();
  451. if ((idx % 0x100000) == 0)
  452. uart_putc('.');
  453. if ((idx % 0x10000) == 0)
  454. toggle_read_led();
  455. if (data != value)
  456. {
  457. //printf("%06x [%02x],", idx, data);
  458. lasterr = idx;
  459. errwas = data;
  460. errcount++;
  461. writeled(1);
  462. ret = 0xFF;
  463. }
  464. }
  465. printf("]\n");
  466. if (errcount > 0)
  467. printf("Found %d error(s) - last @ %x [%02x]\n", errcount, lasterr, errwas);
  468. FPGA_DESELECT();
  469. return ret;
  470. }
  471. uint8_t fpga_check(uint8_t value)
  472. {
  473. uint8_t ret = 0, read;
  474. FPGA_SELECT();
  475. FPGA_WAIT_RDY();
  476. FPGA_TX_BYTE(0xFF);
  477. FPGA_TX_BYTE(value);
  478. FPGA_TX_BYTE(value);
  479. read = FPGA_RX_BYTE();
  480. if (read != value)
  481. {
  482. printf("%02x != %02x!!\n", value, read);
  483. ret = 0xFF;
  484. }
  485. FPGA_DESELECT();
  486. return ret;
  487. }
  488. uint8_t sram_memtest(void)
  489. {
  490. uint32_t ret;
  491. printf("%s: Start memory test...\n", __func__);
  492. writeled(0);
  493. printf("Check FPGA Communication..\n");
  494. printf("fpga_test = %02X\n", fpga_test());
  495. printf("fpga_status = %04X\n", fpga_status());
  496. ret = fpga_check(0x00);
  497. ret |= fpga_check(0xFF);
  498. ret |= fpga_check(0xAA);
  499. ret |= fpga_check(0x55);
  500. if (ret != 0x00)
  501. {
  502. printf("Error communicating with FPGA...\n");
  503. //return ret;
  504. }
  505. ret = memtest_checkvalue(0x00);
  506. ret |= memtest_checkvalue(0xFF);
  507. ret |= memtest_checkvalue(0xAA);
  508. ret |= memtest_checkvalue(0x55);
  509. return ret;
  510. }
  511. uint64_t sram_gettime(uint32_t base_addr) {
  512. set_mcu_addr(base_addr);
  513. FPGA_SELECT();
  514. FPGA_TX_BYTE(0x88);
  515. uint8_t data;
  516. uint64_t result = 0LL;
  517. /* 1st nibble is the century - 10 (binary)
  518. 4th nibble is the month (binary)
  519. all other fields are BCD */
  520. for(int i=0; i<12; i++) {
  521. FPGA_WAIT_RDY();
  522. data = FPGA_RX_BYTE();
  523. data &= 0xf;
  524. switch(i) {
  525. case 0:
  526. result = (result << 4) | ((data / 10) + 1);
  527. result = (result << 4) | (data % 10);
  528. break;
  529. case 3:
  530. result = (result << 4) | ((data / 10));
  531. result = (result << 4) | (data % 10);
  532. break;
  533. default:
  534. result = (result << 4) | data;
  535. }
  536. }
  537. FPGA_DESELECT();
  538. return result & 0x00ffffffffffffffLL;
  539. }
  540. void load_dspx(const uint8_t *filename, uint8_t coretype) {
  541. UINT bytes_read;
  542. DWORD filesize;
  543. uint16_t word_cnt;
  544. uint8_t wordsize_cnt = 0;
  545. uint16_t sector_remaining = 0;
  546. uint16_t sector_cnt = 0;
  547. uint16_t pgmsize = 0;
  548. uint16_t datsize = 0;
  549. uint32_t pgmdata = 0;
  550. uint16_t datdata = 0;
  551. if(coretype & FEAT_ST0010) {
  552. datsize = 1536;
  553. pgmsize = 2048;
  554. } else if (coretype & FEAT_DSPX) {
  555. datsize = 1024;
  556. pgmsize = 2048;
  557. } else if (coretype & FEAT_CX4) {
  558. datsize = 0;
  559. pgmsize = 1024; /* Cx4 data ROM */
  560. } else {
  561. printf("load_dspx: unknown core (%02x)!\n", coretype);
  562. }
  563. file_open((uint8_t*)filename, FA_READ);
  564. filesize = file_handle.fsize;
  565. if(file_res) {
  566. printf("Could not read %s: error %d\n", filename, file_res);
  567. return;
  568. }
  569. fpga_reset_dspx_addr();
  570. for(word_cnt = 0; word_cnt < pgmsize;) {
  571. if(!sector_remaining) {
  572. bytes_read = file_read();
  573. sector_remaining = bytes_read;
  574. sector_cnt = 0;
  575. }
  576. pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
  577. sector_cnt++;
  578. wordsize_cnt++;
  579. sector_remaining--;
  580. if(wordsize_cnt == 3){
  581. wordsize_cnt = 0;
  582. word_cnt++;
  583. fpga_write_dspx_pgm(pgmdata);
  584. }
  585. }
  586. wordsize_cnt = 0;
  587. if(coretype & FEAT_ST0010) {
  588. file_seek(0xc000);
  589. sector_remaining = 0;
  590. }
  591. for(word_cnt = 0; word_cnt < datsize;) {
  592. if(!sector_remaining) {
  593. bytes_read = file_read();
  594. sector_remaining = bytes_read;
  595. sector_cnt = 0;
  596. }
  597. datdata = (datdata << 8) | file_buf[sector_cnt];
  598. sector_cnt++;
  599. wordsize_cnt++;
  600. sector_remaining--;
  601. if(wordsize_cnt == 2){
  602. wordsize_cnt = 0;
  603. word_cnt++;
  604. fpga_write_dspx_dat(datdata);
  605. }
  606. }
  607. fpga_reset_dspx_addr();
  608. file_close();
  609. }