940ctl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * Code for communication with ARM940 and control of it.
  3. * (C) notaz, 2006-2009
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <sys/mman.h>
  13. #include <sys/ioctl.h>
  14. #include <fcntl.h>
  15. #include <errno.h>
  16. #include "../libpicofe/input.h"
  17. #include "../libpicofe/gp2x/soc_mmsp2.h"
  18. #include "../libpicofe/gp2x/soc.h"
  19. #include "../common/mp3.h"
  20. #include "../common/arm_utils.h"
  21. #include "../common/menu_pico.h"
  22. #include "../common/emu.h"
  23. #include <pico/pico_int.h>
  24. #include <pico/sound/ym2612.h>
  25. #include <pico/sound/mix.h>
  26. #include "code940/940shared.h"
  27. #include "plat.h"
  28. #include "940ctl.h"
  29. static unsigned char *shared_mem = 0;
  30. static _940_data_t *shared_data = 0;
  31. _940_ctl_t *shared_ctl = 0;
  32. unsigned char *mp3_mem = 0;
  33. #define MP3_SIZE_MAX (0x400000 + 0x800000) // 12M
  34. #define CODE940_FILE "pico940_v3.bin"
  35. int crashed_940 = 0;
  36. static FILE *loaded_mp3 = 0;
  37. /***********************************************************/
  38. #define MAXOUT (+32767)
  39. #define MINOUT (-32768)
  40. /* limitter */
  41. #define Limit(val, max,min) { \
  42. if ( val > max ) val = max; \
  43. else if ( val < min ) val = min; \
  44. }
  45. /* these will be managed locally on our side */
  46. static UINT8 ST_address; /* address register */
  47. static INT32 addr_A1; /* address line A1 */
  48. static int writebuff_ptr = 0;
  49. /* YM2612 write */
  50. /* a = address */
  51. /* v = value */
  52. /* returns 1 if sample affecting state changed */
  53. int YM2612Write_940(unsigned int a, unsigned int v, int scanline)
  54. {
  55. int upd = 1; /* the write affects sample generation */
  56. a &= 3;
  57. //printf("%05i:%03i: ym w ([%i] %02x)\n", Pico.m.frame_count, Pico.m.scanline, a, v);
  58. switch (a)
  59. {
  60. case 0: /* address port 0 */
  61. if (addr_A1 == 0 && ST_address == v)
  62. return 0; /* address already selected, don't send this command to 940 */
  63. ST_address = v;
  64. addr_A1 = 0;
  65. /* don't send DAC or timer related address changes to 940 */
  66. if (v == 0x24 || v == 0x25 || v == 0x26 || v == 0x2a)
  67. return 0;
  68. upd = 0;
  69. break;
  70. case 2: /* address port 1 */
  71. if (addr_A1 == 1 && ST_address == v)
  72. return 0;
  73. ST_address = v;
  74. addr_A1 = 1;
  75. upd = 0;
  76. break;
  77. }
  78. //printf("ym pass\n");
  79. if (currentConfig.EmuOpt & 4)
  80. {
  81. UINT16 *writebuff = shared_ctl->writebuffsel ? shared_ctl->writebuff0 : shared_ctl->writebuff1;
  82. /* detect rapid ym updates */
  83. if (upd && !(writebuff_ptr & 0x80000000))
  84. {
  85. int mid = (Pico.m.pal ? 313 : 262) / 2;
  86. if (scanline >= mid) {
  87. //printf("%05i:%03i: rapid ym\n", Pico.m.frame_count, scanline);
  88. writebuff[writebuff_ptr++ & 0xffff] = 0xfffe;
  89. writebuff_ptr |= 0x80000000;
  90. //printf("%05i:%03i: ym w ([%02x] %02x, upd=%i)\n", Pico.m.frame_count, scanline, addr, v, upd);
  91. }
  92. }
  93. /* queue this write for 940 */
  94. if ((writebuff_ptr&0xffff) < 2047) {
  95. writebuff[writebuff_ptr++ & 0xffff] = (a<<8)|v;
  96. } else {
  97. printf("warning: writebuff_ptr > 2047 ([%i] %02x)\n", a, v);
  98. }
  99. }
  100. return 0; // cause the engine to do updates once per frame only
  101. }
  102. #define CHECK_BUSY(job) \
  103. (memregs[0x3b46>>1] & (1<<(job-1)))
  104. static void wait_busy_940(int job)
  105. {
  106. int i;
  107. job--;
  108. for (i = 0; (memregs[0x3b46>>1] & (1<<job)) && i < 0x10000; i++)
  109. spend_cycles(8*1024); // tested to be best for mp3 dec
  110. if (i < 0x10000) return;
  111. /* 940 crashed */
  112. printf("940 crashed (cnt: %i, ve: ", shared_ctl->loopc);
  113. for (i = 0; i < 8; i++)
  114. printf("%i ", shared_ctl->vstarts[i]);
  115. printf(")\n");
  116. printf("irq pending flags: DUALCPU %04x, SRCPND %08x (see 26), INTPND %08x\n",
  117. memregs[0x3b46>>1], memregl[0x4500>>2], memregl[0x4510>>2]);
  118. printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob);
  119. printf("trying to interrupt..\n");
  120. memregs[0x3B3E>>1] = 0xffff;
  121. for (i = 0; memregs[0x3b46>>1] && i < 0x10000; i++)
  122. spend_cycles(8*1024);
  123. printf("i = 0x%x\n", i);
  124. printf("irq pending flags: DUALCPU %04x, SRCPND %08x (see 26), INTPND %08x\n",
  125. memregs[0x3b46>>1], memregl[0x4500>>2], memregl[0x4510>>2]);
  126. printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob);
  127. menu_update_msg("940 crashed, too much overclock?");
  128. engineState = PGS_Menu;
  129. crashed_940 = 1;
  130. }
  131. static void add_job_940(int job)
  132. {
  133. if (job <= 0 || job > 16) {
  134. printf("add_job_940: bad job: %i\n", job);
  135. return;
  136. }
  137. // generate interrupt for this job
  138. job--;
  139. memregs[(0x3B20+job*2)>>1] = 1;
  140. // printf("added %i, pending %04x\n", job+1, memregs[0x3b46>>1]);
  141. }
  142. void YM2612PicoStateLoad_940(void)
  143. {
  144. UINT8 *REGS = YM2612GetRegs();
  145. /* make sure JOB940_PICOSTATELOAD gets done before next JOB940_YM2612UPDATEONE */
  146. add_job_940(JOB940_PICOSTATELOAD);
  147. if (CHECK_BUSY(JOB940_PICOSTATELOAD)) wait_busy_940(JOB940_PICOSTATELOAD);
  148. writebuff_ptr = 0;
  149. addr_A1 = *(INT32 *) (REGS + 0x200);
  150. }
  151. void YM2612PicoStateSave2_940(int tat, int tbt)
  152. {
  153. UINT8 *ym_remote_regs, *ym_local_regs;
  154. add_job_940(JOB940_PICOSTATESAVE2);
  155. if (CHECK_BUSY(JOB940_PICOSTATESAVE2)) wait_busy_940(JOB940_PICOSTATESAVE2);
  156. ym_remote_regs = (UINT8 *) shared_ctl->writebuff0;
  157. ym_local_regs = YM2612GetRegs();
  158. if (*(UINT32 *)(ym_remote_regs + 0x100) != 0x41534d59) {
  159. printf("code940 didn't return valid save data\n");
  160. return;
  161. }
  162. /* copy addin data only */
  163. memcpy(ym_local_regs, ym_remote_regs, 0x20);
  164. memcpy(ym_local_regs + 0x100, ym_remote_regs + 0x100, 0x30);
  165. memcpy(ym_local_regs + 0x0b8, ym_remote_regs + 0x0b8, 0x48);
  166. memcpy(ym_local_regs + 0x1b8, ym_remote_regs + 0x1b8, 0x48);
  167. *(INT32 *)(ym_local_regs + 0x108) = tat;
  168. *(INT32 *)(ym_local_regs + 0x10c) = tbt;
  169. }
  170. int YM2612PicoStateLoad2_940(int *tat, int *tbt)
  171. {
  172. UINT8 *ym_remote_regs, *ym_local_regs;
  173. ym_local_regs = YM2612GetRegs();
  174. ym_remote_regs = (UINT8 *) shared_ctl->writebuff0;
  175. if (*(UINT32 *)(ym_local_regs + 0x100) != 0x41534d59)
  176. return -1;
  177. *tat = *(INT32 *)(ym_local_regs + 0x108);
  178. *tbt = *(INT32 *)(ym_local_regs + 0x10c);
  179. if (CHECK_BUSY(JOB940_YM2612UPDATEONE)) wait_busy_940(JOB940_YM2612UPDATEONE);
  180. /* flush writes */
  181. if (shared_ctl->writebuffsel == 1) {
  182. shared_ctl->writebuff0[writebuff_ptr & 0xffff] = 0xffff;
  183. } else {
  184. shared_ctl->writebuff1[writebuff_ptr & 0xffff] = 0xffff;
  185. }
  186. shared_ctl->writebuffsel ^= 1;
  187. writebuff_ptr = 0;
  188. add_job_940(JOB940_PICOSTATELOAD2_PREP);
  189. if (CHECK_BUSY(JOB940_PICOSTATELOAD2_PREP)) wait_busy_940(JOB940_PICOSTATELOAD2_PREP);
  190. memcpy(ym_remote_regs, ym_local_regs, 0x200);
  191. add_job_940(JOB940_PICOSTATELOAD2);
  192. if (CHECK_BUSY(JOB940_PICOSTATELOAD2)) wait_busy_940(JOB940_PICOSTATELOAD2);
  193. return 0;
  194. }
  195. static void internal_reset(void)
  196. {
  197. writebuff_ptr = 0;
  198. ST_address = addr_A1 = -1;
  199. }
  200. /* this must be called after mmu hack, the allocated regions must not get cached */
  201. void sharedmem940_init(void)
  202. {
  203. if (shared_mem != NULL) return;
  204. shared_mem = (unsigned char *) mmap(0, 0x210000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2000000);
  205. if (shared_mem == MAP_FAILED)
  206. {
  207. printf("mmap(shared_data) failed with %i\n", errno);
  208. exit(1);
  209. }
  210. shared_data = (_940_data_t *) (shared_mem+0x100000);
  211. /* this area must not get buffered on either side */
  212. shared_ctl = (_940_ctl_t *) (shared_mem+0x200000);
  213. mp3_mem = (unsigned char *) mmap(0, MP3_SIZE_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2400000);
  214. if (mp3_mem == MAP_FAILED)
  215. {
  216. printf("mmap(mp3_mem) failed with %i\n", errno);
  217. exit(1);
  218. }
  219. crashed_940 = 1;
  220. }
  221. void sharedmem940_finish(void)
  222. {
  223. munmap(shared_mem, 0x210000);
  224. munmap(mp3_mem, MP3_SIZE_MAX);
  225. shared_mem = mp3_mem = NULL;
  226. shared_data = NULL;
  227. shared_ctl = NULL;
  228. }
  229. void YM2612Init_940(int baseclock, int rate, int ssg)
  230. {
  231. static int oldrate;
  232. // HACK
  233. if (Pico.m.frame_count > 0 && !crashed_940 && rate == oldrate)
  234. return;
  235. printf("YM2612Init_940()\n");
  236. printf("Mem usage: shared_data: %i, shared_ctl: %i\n", sizeof(*shared_data), sizeof(*shared_ctl));
  237. reset940(1, 2);
  238. pause940(1);
  239. memregs[0x3B40>>1] = 0; // disable DUALCPU interrupts for 920
  240. memregs[0x3B42>>1] = 1; // enable DUALCPU interrupts for 940
  241. memregl[0x4504>>2] = 0; // make sure no FIQs will be generated
  242. memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller
  243. if (crashed_940)
  244. {
  245. unsigned char ucData[1024];
  246. int nRead, nLen = 0;
  247. char binpath[512];
  248. FILE *fp;
  249. emu_make_path(binpath, CODE940_FILE, sizeof(binpath));
  250. fp = fopen(binpath, "rb");
  251. if(!fp)
  252. {
  253. memset(g_screen_ptr, 0, 320*240*2);
  254. text_out16(10, 100, "failed to open required file:");
  255. text_out16(10, 110, CODE940_FILE);
  256. gp2x_video_flip2();
  257. in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 100);
  258. printf("failed to open %s\n", binpath);
  259. exit(1);
  260. }
  261. while(1)
  262. {
  263. nRead = fread(ucData, 1, 1024, fp);
  264. if(nRead <= 0)
  265. break;
  266. memcpy(shared_mem + nLen, ucData, nRead);
  267. nLen += nRead;
  268. }
  269. fclose(fp);
  270. crashed_940 = 0;
  271. }
  272. memset(shared_data, 0, sizeof(*shared_data));
  273. memset(shared_ctl, 0, sizeof(*shared_ctl));
  274. /* cause local ym2612 to init REGS */
  275. YM2612Init_(baseclock, rate, ssg);
  276. internal_reset();
  277. loaded_mp3 = NULL;
  278. memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940
  279. memregl[0x4500>>2] = 0xffffffff; // clear pending IRQs in SRCPND
  280. memregl[0x4510>>2] = 0xffffffff; // clear pending IRQs in INTPND
  281. /* start the 940 */
  282. reset940(0, 2);
  283. pause940(0);
  284. // YM2612ResetChip_940(); // will be done on JOB940_YM2612INIT
  285. /* now cause 940 to init it's ym2612 stuff */
  286. shared_ctl->baseclock = baseclock;
  287. shared_ctl->rate = rate;
  288. add_job_940(JOB940_INITALL);
  289. oldrate = rate;
  290. }
  291. void YM2612ResetChip_940(void)
  292. {
  293. //printf("YM2612ResetChip_940()\n");
  294. if (shared_data == NULL) {
  295. printf("YM2612ResetChip_940: reset before init?\n");
  296. return;
  297. }
  298. YM2612ResetChip_();
  299. internal_reset();
  300. add_job_940(JOB940_YM2612RESETCHIP);
  301. }
  302. int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty)
  303. {
  304. int *ym_buf = shared_data->ym_buffer;
  305. int ym_active_chs;
  306. //printf("YM2612UpdateOne_940()\n");
  307. if (CHECK_BUSY(JOB940_YM2612UPDATEONE)) wait_busy_940(JOB940_YM2612UPDATEONE);
  308. ym_active_chs = shared_ctl->ym_active_chs;
  309. // mix in ym buffer. is_buf_empty means nobody mixed there anything yet and it may contain trash
  310. if (is_buf_empty && ym_active_chs) memcpy(buffer, ym_buf, length << (stereo + 2));
  311. else memset32(buffer, 0, length<<stereo);
  312. if (shared_ctl->writebuffsel == 1) {
  313. shared_ctl->writebuff0[writebuff_ptr & 0xffff] = 0xffff;
  314. } else {
  315. shared_ctl->writebuff1[writebuff_ptr & 0xffff] = 0xffff;
  316. }
  317. writebuff_ptr = 0;
  318. /* predict sample counter for next frame */
  319. if (Pico.snd.len_e_add) {
  320. length = Pico.snd.len;
  321. if (Pico.snd.len_e_cnt + Pico.snd.len_e_add >= 0x10000) length++;
  322. }
  323. /* give 940 ym job */
  324. shared_ctl->writebuffsel ^= 1;
  325. shared_ctl->length = length;
  326. shared_ctl->stereo = stereo;
  327. add_job_940(JOB940_YM2612UPDATEONE);
  328. return ym_active_chs;
  329. }
  330. /***********************************************************/
  331. // FIXME: double buffering no longer used..
  332. int mp3dec_decode(FILE *f, int *file_pos, int file_len)
  333. {
  334. if (!(PicoIn.opt & POPT_EXT_FM)) {
  335. return _mp3dec_decode(f, file_pos, file_len);
  336. }
  337. // check if playback was started, track not ended
  338. if (loaded_mp3 == NULL || shared_ctl->mp3_offs >= shared_ctl->mp3_len) {
  339. *file_pos = file_len;
  340. return 1;
  341. }
  342. /* do we have to wait? */
  343. if (CHECK_BUSY(JOB940_MP3DECODE))
  344. wait_busy_940(JOB940_MP3DECODE);
  345. memcpy(cdda_out_buffer,
  346. shared_data->mp3_buffer[shared_ctl->mp3_buffsel],
  347. sizeof(cdda_out_buffer));
  348. *file_pos = shared_ctl->mp3_offs;
  349. if (shared_ctl->mp3_offs < shared_ctl->mp3_len) {
  350. // ask to decode more
  351. //shared_ctl->mp3_buffsel ^= 1;
  352. add_job_940(JOB940_MP3DECODE);
  353. }
  354. return 0;
  355. }
  356. int mp3dec_start(FILE *f, int fpos_start)
  357. {
  358. if (!(PicoIn.opt & POPT_EXT_FM)) {
  359. return _mp3dec_start(f, fpos_start);
  360. }
  361. if (loaded_mp3 != f)
  362. {
  363. if (PicoIn.osdMessage != NULL)
  364. {
  365. fseek(f, 0, SEEK_END);
  366. if (ftell(f) > 2*1024*1024)
  367. PicoIn.osdMessage("Loading MP3...");
  368. }
  369. fseek(f, 0, SEEK_SET);
  370. fread(mp3_mem, 1, MP3_SIZE_MAX, f);
  371. if (!feof(f))
  372. printf("Warning: mp3 was too large, not all data loaded.\n");
  373. shared_ctl->mp3_len = ftell(f);
  374. loaded_mp3 = f;
  375. // as we are going to change 940's cacheable area,
  376. // we must invalidate it's cache..
  377. if (CHECK_BUSY(JOB940_MP3DECODE))
  378. wait_busy_940(JOB940_MP3DECODE);
  379. add_job_940(JOB940_INVALIDATE_DCACHE);
  380. reset_timing = 1;
  381. }
  382. shared_ctl->mp3_offs = fpos_start;
  383. shared_ctl->mp3_buffsel = 0;
  384. add_job_940(JOB940_MP3RESET);
  385. if (CHECK_BUSY(JOB940_MP3RESET))
  386. wait_busy_940(JOB940_MP3RESET);
  387. // because we decode ahea, need to start now
  388. if (shared_ctl->mp3_offs < shared_ctl->mp3_len) {
  389. add_job_940(JOB940_MP3DECODE);
  390. }
  391. return 0;
  392. }