memory.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  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("%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. ff_sd_offload=1;
  182. sd_offload_tgt=0;
  183. f_lseek(&file_handle, romprops.offset);
  184. for(;;) {
  185. ff_sd_offload=1;
  186. sd_offload_tgt=0;
  187. bytes_read = file_read();
  188. if (file_res || !bytes_read) break;
  189. if(!(count++ % 512)) {
  190. uart_putc('.');
  191. }
  192. }
  193. file_close();
  194. set_mapper(romprops.mapper_id);
  195. printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id);
  196. ticks_total=getticks()-ticksstart;
  197. printf("%u ticks total\n", ticks_total);
  198. if(romprops.mapper_id==3) {
  199. printf("BSX Flash cart image\n");
  200. printf("attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n");
  201. load_sram_offload((uint8_t*)"/sd2snes/bsxbios.bin", 0x800000);
  202. printf("attempting to load BS data file /sd2snes/bsxpage.bin...\n");
  203. load_sram_offload((uint8_t*)"/sd2snes/bsxpage.bin", 0x900000);
  204. printf("Type: %02x\n", romprops.header.destcode);
  205. set_bsx_regs(0xc0, 0x3f);
  206. uint16_t rombase;
  207. if(romprops.header.ramsize & 1) {
  208. rombase = 0xff00;
  209. // set_bsx_regs(0x36, 0xc9);
  210. } else {
  211. rombase = 0x7f00;
  212. // set_bsx_regs(0x34, 0xcb);
  213. }
  214. sram_writebyte(0x33, rombase+0xda);
  215. sram_writebyte(0x00, rombase+0xd4);
  216. sram_writebyte(0xfc, rombase+0xd5);
  217. set_fpga_time(0x0220110301180530LL);
  218. }
  219. if(romprops.has_dspx || romprops.has_cx4) {
  220. printf("DSPx game. Loading firmware image %s...\n", romprops.dsp_fw);
  221. load_dspx(romprops.dsp_fw, romprops.fpga_features);
  222. /* fallback to DSP1B firmware if DSP1.bin is not present */
  223. if(file_res && romprops.dsp_fw == DSPFW_1) {
  224. load_dspx(DSPFW_1B, romprops.fpga_features);
  225. }
  226. if(file_res) {
  227. snes_menu_errmsg(MENU_ERR_NODSP, (void*)romprops.dsp_fw);
  228. }
  229. }
  230. uint32_t rammask;
  231. uint32_t rommask;
  232. while(filesize > (romprops.romsize_bytes + romprops.offset)) {
  233. romprops.romsize_bytes <<= 1;
  234. }
  235. if(romprops.header.ramsize == 0) {
  236. rammask = 0;
  237. } else {
  238. rammask = romprops.ramsize_bytes - 1;
  239. }
  240. rommask = romprops.romsize_bytes - 1;
  241. printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
  242. set_saveram_mask(rammask);
  243. set_rom_mask(rommask);
  244. readled(0);
  245. if(flags & LOADROM_WITH_SRAM) {
  246. if(romprops.ramsize_bytes) {
  247. strcpy(strrchr((char*)filename, (int)'.'), ".srm");
  248. printf("SRM file: %s\n", filename);
  249. load_sram(filename, SRAM_SAVE_ADDR);
  250. } else {
  251. printf("No SRAM\n");
  252. }
  253. }
  254. printf("check MSU...");
  255. if(msu1_check(filename)) {
  256. romprops.fpga_features |= FEAT_MSU1;
  257. romprops.has_msu1 = 1;
  258. } else {
  259. romprops.has_msu1 = 0;
  260. }
  261. printf("done\n");
  262. romprops.fpga_features |= FEAT_SRTC;
  263. romprops.fpga_features |= FEAT_213F;
  264. fpga_set_213f(romprops.region);
  265. fpga_set_features(romprops.fpga_features);
  266. if(flags & LOADROM_WITH_RESET) {
  267. fpga_dspx_reset(1);
  268. snes_reset_pulse();
  269. fpga_dspx_reset(0);
  270. }
  271. return (uint32_t)filesize;
  272. }
  273. uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header_addr) {
  274. DWORD filesize;
  275. UINT bytes_read;
  276. uint8_t data;
  277. UINT j;
  278. printf("%s\n", filename);
  279. file_open(filename, FA_READ); /* Open SPC file */
  280. if(file_res) return 0;
  281. filesize = file_handle.fsize;
  282. if (filesize < 65920) { /* At this point, we care about filesize only */
  283. file_close(); /* since SNES decides if it is an SPC file */
  284. sram_writebyte(0, spc_header_addr); /* If file is too small, destroy previous SPC header */
  285. return 0;
  286. }
  287. set_mcu_addr(spc_data_addr);
  288. f_lseek(&file_handle, 0x100L); /* Load 64K data segment */
  289. for(;;) {
  290. bytes_read = file_read();
  291. if (file_res || !bytes_read) break;
  292. FPGA_SELECT();
  293. FPGA_TX_BYTE(0x98);
  294. for(j=0; j<bytes_read; j++) {
  295. FPGA_TX_BYTE(file_buf[j]);
  296. FPGA_WAIT_RDY();
  297. }
  298. FPGA_DESELECT();
  299. }
  300. file_close();
  301. file_open(filename, FA_READ); /* Reopen SPC file to reset file_getc state*/
  302. set_mcu_addr(spc_header_addr);
  303. f_lseek(&file_handle, 0x0L); /* Load 256 bytes header */
  304. FPGA_SELECT();
  305. FPGA_TX_BYTE(0x98);
  306. for (j = 0; j < 256; j++) {
  307. data = file_getc();
  308. FPGA_TX_BYTE(data);
  309. FPGA_WAIT_RDY();
  310. }
  311. FPGA_DESELECT();
  312. file_close();
  313. file_open(filename, FA_READ); /* Reopen SPC file to reset file_getc state*/
  314. set_mcu_addr(spc_header_addr+0x100);
  315. f_lseek(&file_handle, 0x10100L); /* Load 128 DSP registers */
  316. FPGA_SELECT();
  317. FPGA_TX_BYTE(0x98);
  318. for (j = 0; j < 128; j++) {
  319. data = file_getc();
  320. FPGA_TX_BYTE(data);
  321. FPGA_WAIT_RDY();
  322. }
  323. FPGA_DESELECT();
  324. file_close(); /* Done ! */
  325. /* clear echo buffer to avoid artifacts */
  326. uint8_t esa = sram_readbyte(spc_header_addr+0x100+0x6d);
  327. uint8_t edl = sram_readbyte(spc_header_addr+0x100+0x7d);
  328. uint8_t flg = sram_readbyte(spc_header_addr+0x100+0x6c);
  329. if(!(flg & 0x20) && (edl & 0x0f)) {
  330. int echo_start = esa << 8;
  331. int echo_length = (edl & 0x0f) << 11;
  332. printf("clearing echo buffer %04x-%04x...\n", echo_start, echo_start+echo_length-1);
  333. sram_memset(spc_data_addr+echo_start, echo_length, 0);
  334. }
  335. return (uint32_t)filesize;
  336. }
  337. uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) {
  338. set_mcu_addr(base_addr);
  339. UINT bytes_read;
  340. DWORD filesize;
  341. file_open(filename, FA_READ);
  342. filesize = file_handle.fsize;
  343. if(file_res) return 0;
  344. for(;;) {
  345. ff_sd_offload=1;
  346. sd_offload_tgt=0;
  347. bytes_read = file_read();
  348. if (file_res || !bytes_read) break;
  349. }
  350. file_close();
  351. return (uint32_t)filesize;
  352. }
  353. uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
  354. set_mcu_addr(base_addr);
  355. UINT bytes_read;
  356. DWORD filesize;
  357. file_open(filename, FA_READ);
  358. filesize = file_handle.fsize;
  359. if(file_res) {
  360. printf("load_sram: could not open %s, res=%d\n", filename, file_res);
  361. return 0;
  362. }
  363. for(;;) {
  364. bytes_read = file_read();
  365. if (file_res || !bytes_read) break;
  366. FPGA_SELECT();
  367. FPGA_TX_BYTE(0x98);
  368. for(int j=0; j<bytes_read; j++) {
  369. FPGA_TX_BYTE(file_buf[j]);
  370. FPGA_WAIT_RDY();
  371. }
  372. FPGA_DESELECT();
  373. }
  374. file_close();
  375. return (uint32_t)filesize;
  376. }
  377. uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
  378. uint8_t data;
  379. set_mcu_addr(base_addr);
  380. DWORD filesize;
  381. file_open(filename, FA_READ);
  382. filesize = file_handle.fsize;
  383. if(file_res) return 0;
  384. FPGA_SELECT();
  385. FPGA_TX_BYTE(0x98);
  386. for(;;) {
  387. data = rle_file_getc();
  388. if (file_res || file_status) break;
  389. FPGA_TX_BYTE(data);
  390. FPGA_WAIT_RDY();
  391. }
  392. FPGA_DESELECT();
  393. file_close();
  394. return (uint32_t)filesize;
  395. }
  396. uint32_t load_bootrle(uint32_t base_addr) {
  397. uint8_t data;
  398. set_mcu_addr(base_addr);
  399. DWORD filesize = 0;
  400. rle_mem_init(bootrle, sizeof(bootrle));
  401. FPGA_SELECT();
  402. FPGA_TX_BYTE(0x98);
  403. for(;;) {
  404. data = rle_mem_getc();
  405. if(rle_state) break;
  406. FPGA_TX_BYTE(data);
  407. FPGA_WAIT_RDY();
  408. filesize++;
  409. }
  410. FPGA_DESELECT();
  411. return (uint32_t)filesize;
  412. }
  413. void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
  414. uint32_t count = 0;
  415. uint32_t num = 0;
  416. FPGA_DESELECT();
  417. file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
  418. if(file_res) {
  419. uart_putc(0x30+file_res);
  420. }
  421. while(count<sram_size) {
  422. set_mcu_addr(base_addr+count);
  423. FPGA_SELECT();
  424. FPGA_TX_BYTE(0x88); /* read */
  425. for(int j=0; j<sizeof(file_buf); j++) {
  426. FPGA_WAIT_RDY();
  427. file_buf[j] = FPGA_RX_BYTE();
  428. count++;
  429. }
  430. FPGA_DESELECT();
  431. num = file_write();
  432. if(file_res) {
  433. uart_putc(0x30+file_res);
  434. }
  435. }
  436. file_close();
  437. }
  438. uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
  439. uint8_t data;
  440. uint32_t count;
  441. uint32_t crc;
  442. crc=0;
  443. crc_valid=1;
  444. set_mcu_addr(base_addr);
  445. FPGA_SELECT();
  446. FPGA_TX_BYTE(0x88);
  447. for(count=0; count<size; count++) {
  448. FPGA_WAIT_RDY();
  449. data = FPGA_RX_BYTE();
  450. if(get_snes_reset()) {
  451. crc_valid = 0;
  452. break;
  453. }
  454. crc += crc32_update(crc, data);
  455. }
  456. FPGA_DESELECT();
  457. return crc;
  458. }
  459. uint8_t sram_reliable() {
  460. uint16_t score=0;
  461. uint32_t val;
  462. uint8_t result = 0;
  463. /*while(score<SRAM_RELIABILITY_SCORE) {
  464. if(sram_readlong(SRAM_SCRATCHPAD)==val) {
  465. score++;
  466. } else {
  467. set_pwr_led(0);
  468. score=0;
  469. }
  470. } */
  471. for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
  472. val=sram_readlong(SRAM_SCRATCHPAD);
  473. if(val==0x12345678) {
  474. score++;
  475. } else {
  476. printf("i=%d val=%08lX\n", i, val);
  477. }
  478. }
  479. if(score<SRAM_RELIABILITY_SCORE) {
  480. result = 0;
  481. /* dprintf("score=%d\n", score); */
  482. } else {
  483. result = 1;
  484. }
  485. rdyled(result);
  486. return result;
  487. }
  488. void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
  489. set_mcu_addr(base_addr);
  490. FPGA_SELECT();
  491. FPGA_TX_BYTE(0x98);
  492. for(uint32_t i=0; i<len; i++) {
  493. FPGA_TX_BYTE(val);
  494. FPGA_WAIT_RDY();
  495. }
  496. FPGA_DESELECT();
  497. }
  498. uint64_t sram_gettime(uint32_t base_addr) {
  499. set_mcu_addr(base_addr);
  500. FPGA_SELECT();
  501. FPGA_TX_BYTE(0x88);
  502. uint8_t data;
  503. uint64_t result = 0LL;
  504. /* 1st nibble is the century - 10 (binary)
  505. 4th nibble is the month (binary)
  506. all other fields are BCD */
  507. for(int i=0; i<12; i++) {
  508. FPGA_WAIT_RDY();
  509. data = FPGA_RX_BYTE();
  510. data &= 0xf;
  511. switch(i) {
  512. case 0:
  513. result = (result << 4) | ((data / 10) + 1);
  514. result = (result << 4) | (data % 10);
  515. break;
  516. case 3:
  517. result = (result << 4) | ((data / 10));
  518. result = (result << 4) | (data % 10);
  519. break;
  520. default:
  521. result = (result << 4) | data;
  522. }
  523. }
  524. FPGA_DESELECT();
  525. return result & 0x00ffffffffffffffLL;
  526. }
  527. void load_dspx(const uint8_t *filename, uint8_t coretype) {
  528. UINT bytes_read;
  529. DWORD filesize;
  530. uint16_t word_cnt;
  531. uint8_t wordsize_cnt = 0;
  532. uint16_t sector_remaining = 0;
  533. uint16_t sector_cnt = 0;
  534. uint16_t pgmsize = 0;
  535. uint16_t datsize = 0;
  536. uint32_t pgmdata = 0;
  537. uint16_t datdata = 0;
  538. if(coretype & FEAT_ST0010) {
  539. datsize = 1536;
  540. pgmsize = 2048;
  541. } else if (coretype & FEAT_DSPX) {
  542. datsize = 1024;
  543. pgmsize = 2048;
  544. } else if (coretype & FEAT_CX4) {
  545. datsize = 0;
  546. pgmsize = 1024; /* Cx4 data ROM */
  547. } else {
  548. printf("load_dspx: unknown core (%02x)!\n", coretype);
  549. }
  550. file_open((uint8_t*)filename, FA_READ);
  551. filesize = file_handle.fsize;
  552. if(file_res) {
  553. printf("Could not read %s: error %d\n", filename, file_res);
  554. return;
  555. }
  556. fpga_reset_dspx_addr();
  557. for(word_cnt = 0; word_cnt < pgmsize;) {
  558. if(!sector_remaining) {
  559. bytes_read = file_read();
  560. sector_remaining = bytes_read;
  561. sector_cnt = 0;
  562. }
  563. pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
  564. sector_cnt++;
  565. wordsize_cnt++;
  566. sector_remaining--;
  567. if(wordsize_cnt == 3){
  568. wordsize_cnt = 0;
  569. word_cnt++;
  570. fpga_write_dspx_pgm(pgmdata);
  571. }
  572. }
  573. wordsize_cnt = 0;
  574. if(coretype & FEAT_ST0010) {
  575. file_seek(0xc000);
  576. sector_remaining = 0;
  577. }
  578. for(word_cnt = 0; word_cnt < datsize;) {
  579. if(!sector_remaining) {
  580. bytes_read = file_read();
  581. sector_remaining = bytes_read;
  582. sector_cnt = 0;
  583. }
  584. datdata = (datdata << 8) | file_buf[sector_cnt];
  585. sector_cnt++;
  586. wordsize_cnt++;
  587. sector_remaining--;
  588. if(wordsize_cnt == 2){
  589. wordsize_cnt = 0;
  590. word_cnt++;
  591. fpga_write_dspx_dat(datdata);
  592. }
  593. }
  594. fpga_reset_dspx_addr();
  595. file_close();
  596. }