msu1.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include <string.h>
  2. #include "config.h"
  3. #include "uart.h"
  4. #include "ff.h"
  5. #include "diskio.h"
  6. #include "spi.h"
  7. #include "fpga_spi.h"
  8. #include "cli.h"
  9. #include "fileops.h"
  10. #include "msu1.h"
  11. #include "snes.h"
  12. #include "timer.h"
  13. #include "smc.h"
  14. FIL msufile;
  15. FRESULT msu_res;
  16. DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
  17. DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM;
  18. UINT msu_audio_bytes_read = 1024;
  19. UINT msu_data_bytes_read = 1;
  20. extern snes_romprops_t romprops;
  21. uint32_t msu_loop_point = 0;
  22. uint32_t msu_page1_start = 0x0000;
  23. uint32_t msu_page2_start = 0x2000;
  24. uint32_t msu_page_size = 0x2000;
  25. uint16_t fpga_status_prev;
  26. uint16_t fpga_status_now;
  27. enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG };
  28. void prepare_audio_track(uint16_t msu_track) {
  29. /* open file, fill buffer */
  30. char suffix[11];
  31. f_close(&file_handle);
  32. snprintf(suffix, sizeof(suffix), "-%d.pcm", msu_track);
  33. strcpy((char*)file_buf, (char*)file_lfn);
  34. strcpy(strrchr((char*)file_buf, (int)'.'), suffix);
  35. DBG_MSU1 printf("filename: %s\n", file_buf);
  36. if(f_open(&file_handle, (const TCHAR*)file_buf, FA_READ) == FR_OK) {
  37. file_handle.cltbl = pcm_cltbl;
  38. pcm_cltbl[0] = CLTBL_SIZE;
  39. f_lseek(&file_handle, CREATE_LINKMAP);
  40. f_lseek(&file_handle, 4L);
  41. f_read(&file_handle, &msu_loop_point, 4, &msu_audio_bytes_read);
  42. DBG_MSU1 printf("loop point: %ld samples\n", msu_loop_point);
  43. ff_sd_offload=1;
  44. sd_offload_tgt=1;
  45. f_lseek(&file_handle, 8L);
  46. set_dac_addr(0);
  47. dac_pause();
  48. dac_reset();
  49. ff_sd_offload=1;
  50. sd_offload_tgt=1;
  51. f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read);
  52. /* clear busy bit */
  53. set_msu_status(0x00, 0x28); /* set no bits, reset audio_busy + audio_error */
  54. } else {
  55. f_close(&file_handle);
  56. set_msu_status(0x08, 0x20); /* reset audio_busy, set audio_error */
  57. }
  58. }
  59. void prepare_data(uint32_t msu_offset) {
  60. DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
  61. if( ((msu_offset < msu_page1_start)
  62. || (msu_offset >= msu_page1_start + msu_page_size))
  63. && ((msu_offset < msu_page2_start)
  64. || (msu_offset >= msu_page2_start + msu_page_size))) {
  65. DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
  66. msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1);
  67. /* "cache miss" */
  68. /* fill buffer */
  69. set_msu_addr(0x0);
  70. sd_offload_tgt=2;
  71. ff_sd_offload=1;
  72. msu_res = f_lseek(&msufile, msu_offset);
  73. DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, msu_res);
  74. sd_offload_tgt=2;
  75. ff_sd_offload=1;
  76. msu_res = f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
  77. DBG_MSU1 printf("read res = %d\n", msu_res);
  78. DBG_MSU1 printf("read %d bytes\n", msu_data_bytes_read);
  79. msu_reset(0x0);
  80. msu_page1_start = msu_offset;
  81. msu_page2_start = msu_offset + msu_page_size;
  82. } else {
  83. if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) {
  84. msu_reset(0x0000 + msu_offset - msu_page1_start);
  85. DBG_MSU1 printf("inside page1, new offset: %08lx\n", 0x0000 + msu_offset-msu_page1_start);
  86. if(!(msu_page2_start == msu_page1_start + msu_page_size)) {
  87. set_msu_addr(0x2000);
  88. sd_offload_tgt=2;
  89. ff_sd_offload=1;
  90. f_read(&msufile, file_buf, 8192, &msu_data_bytes_read);
  91. DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start);
  92. msu_page2_start = msu_page1_start + msu_page_size;
  93. DBG_MSU1 printf("%08lx)\n", msu_page2_start);
  94. }
  95. } else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) {
  96. DBG_MSU1 printf("inside page2, new offset: %08lx\n", 0x2000 + msu_offset-msu_page2_start);
  97. msu_reset(0x2000 + msu_offset - msu_page2_start);
  98. if(!(msu_page1_start == msu_page2_start + msu_page_size)) {
  99. set_msu_addr(0x0);
  100. sd_offload_tgt=2;
  101. ff_sd_offload=1;
  102. f_read(&msufile, file_buf, 8192, &msu_data_bytes_read);
  103. DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start);
  104. msu_page1_start = msu_page2_start + msu_page_size;
  105. DBG_MSU1 printf("%08lx)\n", msu_page1_start);
  106. }
  107. } else printf("!!!WATWATWAT!!!\n");
  108. }
  109. /* clear bank bit to mask bank reset artifact */
  110. fpga_status_now &= ~0x2000;
  111. fpga_status_prev &= ~0x2000;
  112. /* clear busy bit */
  113. set_msu_status(0x00, 0x10);
  114. }
  115. int msu1_check_reset(void) {
  116. static tick_t rising_ticks;
  117. static uint8_t resbutton=0, resbutton_prev=0;
  118. int result = MSU_RESET_NONE;
  119. resbutton = get_snes_reset();
  120. if(resbutton && !resbutton_prev) { /* push */
  121. rising_ticks = getticks();
  122. } else if(resbutton && resbutton_prev) { /* hold */
  123. if(getticks() > rising_ticks + 99) {
  124. result = MSU_RESET_LONG;
  125. }
  126. } else if(!resbutton && resbutton_prev) { /* release */
  127. if(getticks() < rising_ticks + 99) {
  128. result = MSU_RESET_SHORT;
  129. }
  130. } else {
  131. result = MSU_RESET_NONE;
  132. }
  133. resbutton_prev = resbutton;
  134. return result;
  135. }
  136. int msu1_check(uint8_t* filename) {
  137. /* open MSU file */
  138. strcpy((char*)file_buf, (char*)filename);
  139. strcpy(strrchr((char*)file_buf, (int)'.'), ".msu");
  140. printf("MSU datafile: %s\n", file_buf);
  141. if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) {
  142. printf("MSU datafile not found\n");
  143. return 0;
  144. }
  145. msufile.cltbl = msu_cltbl;
  146. msu_cltbl[0] = CLTBL_SIZE;
  147. if(f_lseek(&msufile, CREATE_LINKMAP)) {
  148. printf("Error creating FF linkmap for MSU file!\n");
  149. }
  150. romprops.fpga_features |= FEAT_MSU1;
  151. return 1;
  152. }
  153. int msu1_loop() {
  154. /* it is assumed that the MSU file is already opened by calling msu1_check(). */
  155. while(fpga_status() & 0x4000);
  156. uint16_t dac_addr = 0;
  157. uint16_t msu_addr = 0;
  158. uint8_t msu_repeat = 0;
  159. uint16_t msu_track = 0;
  160. uint32_t msu_offset = 0;
  161. fpga_status_prev = fpga_status();
  162. fpga_status_now = fpga_status();
  163. int msu_res;
  164. /* set_msu_addr(0x0);
  165. msu_reset(0x0);
  166. ff_sd_offload=1;
  167. sd_offload_tgt=2;
  168. f_lseek(&msufile, 0L);
  169. ff_sd_offload=1;
  170. sd_offload_tgt=2;
  171. f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
  172. */
  173. set_dac_addr(dac_addr);
  174. dac_pause();
  175. dac_reset();
  176. set_msu_addr(0x0);
  177. msu_reset(0x0);
  178. ff_sd_offload=1;
  179. sd_offload_tgt=2;
  180. f_lseek(&msufile, 0L);
  181. ff_sd_offload=1;
  182. sd_offload_tgt=2;
  183. f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
  184. prepare_audio_track(0);
  185. prepare_data(0);
  186. /* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
  187. while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){
  188. cli_entrycheck();
  189. fpga_status_now = fpga_status();
  190. /* Data buffer refill */
  191. if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) {
  192. DBG_MSU1 printf("data\n");
  193. if(fpga_status_now & 0x2000) {
  194. msu_addr = 0x0;
  195. msu_page1_start = msu_page2_start + msu_page_size;
  196. } else {
  197. msu_addr = 0x2000;
  198. msu_page2_start = msu_page1_start + msu_page_size;
  199. }
  200. set_msu_addr(msu_addr);
  201. sd_offload_tgt=2;
  202. ff_sd_offload=1;
  203. msu_res = f_read(&msufile, file_buf, 8192, &msu_data_bytes_read);
  204. DBG_MSU1 printf("data buffer refilled. page=%d res=%d page1=%08lx page2=%08lx\n", pageno, msu_res, msu_page1_start, msu_page2_start);
  205. }
  206. /* Audio buffer refill */
  207. if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) {
  208. if(fpga_status_now & 0x4000) {
  209. dac_addr = 0;
  210. } else {
  211. dac_addr = MSU_DAC_BUFSIZE/2;
  212. }
  213. set_dac_addr(dac_addr);
  214. sd_offload_tgt=1;
  215. ff_sd_offload=1;
  216. f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &msu_audio_bytes_read);
  217. }
  218. if(fpga_status_now & 0x0020) {
  219. /* get trackno */
  220. msu_track = get_msu_track();
  221. DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track);
  222. prepare_audio_track(msu_track);
  223. }
  224. if(fpga_status_now & 0x0010) {
  225. /* get address */
  226. msu_offset=get_msu_offset();
  227. prepare_data(msu_offset);
  228. }
  229. if(fpga_status_now & 0x0001) {
  230. if(fpga_status_now & 0x0004) {
  231. msu_repeat = 1;
  232. set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */
  233. DBG_MSU1 printf("Repeat set!\n");
  234. } else {
  235. msu_repeat = 0;
  236. set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */
  237. DBG_MSU1 printf("Repeat clear!\n");
  238. }
  239. if(fpga_status_now & 0x0002) {
  240. DBG_MSU1 printf("PLAY!\n");
  241. set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */
  242. dac_play();
  243. } else {
  244. DBG_MSU1 printf("PAUSE!\n");
  245. set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */
  246. dac_pause();
  247. }
  248. }
  249. fpga_status_prev = fpga_status_now;
  250. /* handle loop / end */
  251. if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) {
  252. ff_sd_offload=0;
  253. sd_offload=0;
  254. if(msu_repeat) {
  255. DBG_MSU1 printf("loop\n");
  256. ff_sd_offload=1;
  257. sd_offload_tgt=1;
  258. f_lseek(&file_handle, 8L+msu_loop_point*4);
  259. ff_sd_offload=1;
  260. sd_offload_tgt=1;
  261. f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - msu_audio_bytes_read, &msu_audio_bytes_read);
  262. } else {
  263. set_msu_status(0x00, 0x02); /* clear play bit */
  264. dac_pause();
  265. }
  266. msu_audio_bytes_read = MSU_DAC_BUFSIZE;
  267. }
  268. }
  269. f_close(&file_handle);
  270. DBG_MSU1 printf("Reset ");
  271. if(msu_res == MSU_RESET_LONG) {
  272. f_close(&msufile);
  273. DBG_MSU1 printf("to menu\n");
  274. return 1;
  275. }
  276. DBG_MSU1 printf("game\n");
  277. return 0;
  278. }
  279. /* END OF MSU1 STUFF */