cdd.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. /***************************************************************************************
  2. * Genesis Plus
  3. * CD drive processor & CD-DA fader
  4. *
  5. * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX)
  6. *
  7. * Redistribution and use of this code or any derivative works are permitted
  8. * provided that the following conditions are met:
  9. *
  10. * - Redistributions may not be sold, nor may they be used in a commercial
  11. * product or activity.
  12. *
  13. * - Redistributions that are modified from the original source must include the
  14. * complete source code, including the source code for all components used by a
  15. * binary built from the modified sources. However, as a special exception, the
  16. * source code distributed need not include anything that is normally distributed
  17. * (in either source or binary form) with the major components (compiler, kernel,
  18. * and so on) of the operating system on which the executable runs, unless that
  19. * component itself accompanies the executable.
  20. *
  21. * - Redistributions must reproduce the above copyright notice, this list of
  22. * conditions and the following disclaimer in the documentation and/or other
  23. * materials provided with the distribution.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. ****************************************************************************************/
  38. #include "../pico_int.h"
  39. #include "genplus_macros.h"
  40. #include "cd_parse.h"
  41. #include "cdd.h"
  42. #ifdef USE_LIBTREMOR
  43. #define SUPPORTED_EXT 20
  44. #else
  45. #define SUPPORTED_EXT 10
  46. #endif
  47. cdd_t cdd;
  48. /* BCD conversion lookup tables */
  49. static const uint8 lut_BCD_8[100] =
  50. {
  51. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
  52. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
  53. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
  54. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
  55. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  56. 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  57. 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
  58. 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
  59. 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
  60. 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
  61. };
  62. static const uint16 lut_BCD_16[100] =
  63. {
  64. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
  65. 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
  66. 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
  67. 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
  68. 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
  69. 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
  70. 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609,
  71. 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
  72. 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
  73. 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
  74. };
  75. /* pre-build TOC */
  76. static const uint16 toc_snatcher[21] =
  77. {
  78. 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681,
  79. 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485,
  80. 31380
  81. };
  82. static const uint16 toc_lunar[52] =
  83. {
  84. 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870,
  85. 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263,
  86. 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205,
  87. 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549,
  88. 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132,
  89. 685, 3167
  90. };
  91. static const uint32 toc_shadow[15] =
  92. {
  93. 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792,
  94. 11637, 2547, 2521, 3856, 900
  95. };
  96. static const uint32 toc_dungeon[13] =
  97. {
  98. 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
  99. 3325, 6825, 25275
  100. };
  101. static const uint32 toc_ffight[26] =
  102. {
  103. 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764,
  104. 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024,
  105. 14562, 10320, 8627, 3795, 3047
  106. };
  107. static const uint32 toc_ffightj[29] =
  108. {
  109. 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763,
  110. 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026,
  111. 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052
  112. };
  113. #if 0
  114. /* supported WAVE file header (16-bit stereo samples @44.1kHz) */
  115. static const unsigned char waveHeader[32] =
  116. {
  117. 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
  118. 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61
  119. };
  120. #endif
  121. #ifdef USE_LIBTREMOR
  122. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  123. static void ogg_free(int i)
  124. {
  125. /* clear OGG file descriptor to prevent file from being closed */
  126. cdd.toc.tracks[i].vf.datasource = NULL;
  127. /* close VORBIS file structure */
  128. ov_clear(&cdd.toc.tracks[i].vf);
  129. /* indicates that the track is a seekable VORBIS file */
  130. cdd.toc.tracks[i].vf.seekable = 1;
  131. /* reset file reading position */
  132. fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET);
  133. }
  134. #endif
  135. #endif
  136. void cdd_reset(void)
  137. {
  138. /* reset cycle counter */
  139. cdd.cycles = 0;
  140. /* reset drive access latency */
  141. cdd.latency = 0;
  142. /* reset track index */
  143. cdd.index = 0;
  144. /* reset logical block address */
  145. cdd.lba = 0;
  146. /* reset status */
  147. cdd.status = NO_DISC;
  148. /* reset CD-DA fader (full volume) */
  149. cdd.volume = 0x400;
  150. /* clear CD-DA output */
  151. cdd.audio[0] = cdd.audio[1] = 0;
  152. }
  153. /* FIXME: use cdd_read_audio() instead */
  154. static void cdd_change_track(int index, int lba)
  155. {
  156. int i, base, lba_offset, lb_len;
  157. for (i = index; i > 0; i--)
  158. if (cdd.toc.tracks[i].fd != NULL)
  159. break;
  160. Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd;
  161. base = cdd.toc.tracks[index].offset;
  162. lba_offset = lba - cdd.toc.tracks[index].start;
  163. lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start;
  164. elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base);
  165. cdda_start_play(base, lba_offset, lb_len);
  166. }
  167. int cdd_context_save(uint8 *state)
  168. {
  169. int bufferptr = 0;
  170. save_param(&cdd.cycles, sizeof(cdd.cycles));
  171. save_param(&cdd.latency, sizeof(cdd.latency));
  172. save_param(&cdd.index, sizeof(cdd.index));
  173. save_param(&cdd.lba, sizeof(cdd.lba));
  174. save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
  175. save_param(&cdd.volume, sizeof(cdd.volume));
  176. save_param(&cdd.status, sizeof(cdd.status));
  177. return bufferptr;
  178. }
  179. int cdd_context_load(uint8 *state)
  180. {
  181. int lba;
  182. int bufferptr = 0;
  183. #ifdef USE_LIBTREMOR
  184. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  185. /* close previous track VORBIS file structure to save memory */
  186. if (cdd.toc.tracks[cdd.index].vf.datasource)
  187. {
  188. ogg_free(cdd.index);
  189. }
  190. #endif
  191. #endif
  192. load_param(&cdd.cycles, sizeof(cdd.cycles));
  193. load_param(&cdd.latency, sizeof(cdd.latency));
  194. load_param(&cdd.index, sizeof(cdd.index));
  195. load_param(&cdd.lba, sizeof(cdd.lba));
  196. load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
  197. load_param(&cdd.volume, sizeof(cdd.volume));
  198. load_param(&cdd.status, sizeof(cdd.status));
  199. /* adjust current LBA within track limit */
  200. lba = cdd.lba;
  201. if (lba < cdd.toc.tracks[cdd.index].start)
  202. {
  203. lba = cdd.toc.tracks[cdd.index].start;
  204. }
  205. /* seek to current track position */
  206. if (!cdd.index)
  207. {
  208. /* DATA track */
  209. if (cdd.toc.tracks[0].fd)
  210. {
  211. pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
  212. }
  213. }
  214. #ifdef USE_LIBTREMOR
  215. else if (cdd.toc.tracks[cdd.index].vf.seekable)
  216. {
  217. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  218. /* VORBIS file need to be opened first */
  219. ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
  220. #endif
  221. /* VORBIS AUDIO track */
  222. ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
  223. }
  224. #endif
  225. #if 0
  226. else if (cdd.toc.tracks[cdd.index].fd)
  227. {
  228. /* PCM AUDIO track */
  229. fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  230. }
  231. #else
  232. else
  233. {
  234. cdd_change_track(cdd.index, lba);
  235. }
  236. #endif
  237. return bufferptr;
  238. }
  239. int cdd_context_load_old(uint8 *state)
  240. {
  241. memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
  242. return 12 * 4;
  243. }
  244. int cdd_load(const char *filename, int type)
  245. {
  246. char header[0x210];
  247. int ret;
  248. /* first unmount any loaded disc */
  249. cdd_unload();
  250. /* genplus parses cue here, in PD we use our own parser */
  251. ret = load_cd_image(filename, &type);
  252. if (ret != 0)
  253. return ret;
  254. /* read first 16 bytes */
  255. pm_read(header, 0x10, cdd.toc.tracks[0].fd);
  256. /* look for valid CD image ID string */
  257. if (memcmp("SEGADISCSYSTEM", header, 14))
  258. {
  259. /* if not found, read next 16 bytes */
  260. pm_read(header, 0x10, cdd.toc.tracks[0].fd);
  261. /* look again for valid CD image ID string */
  262. if (memcmp("SEGADISCSYSTEM", header, 14))
  263. {
  264. elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
  265. /* assume bin without security code */
  266. }
  267. /* BIN format (2352 bytes data blocks) */
  268. cdd.sectorSize = 2352;
  269. }
  270. else
  271. {
  272. /* ISO format (2048 bytes data blocks) */
  273. cdd.sectorSize = 2048;
  274. }
  275. ret = (type == CT_BIN) ? 2352 : 2048;
  276. if (ret != cdd.sectorSize)
  277. elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
  278. pm_sectorsize(cdd.sectorSize, cdd.toc.tracks[0].fd);
  279. /* read CD image header + security code */
  280. pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
  281. /* Simulate audio tracks if none found */
  282. if (cdd.toc.last == 1)
  283. {
  284. /* Some games require exact TOC infos */
  285. if (strstr(header + 0x180,"T-95035") != NULL)
  286. {
  287. /* Snatcher */
  288. cdd.toc.last = cdd.toc.end = 0;
  289. do
  290. {
  291. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  292. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
  293. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  294. cdd.toc.last++;
  295. }
  296. while (cdd.toc.last < 21);
  297. }
  298. else if (strstr(header + 0x180,"T-127015") != NULL)
  299. {
  300. /* Lunar - The Silver Star */
  301. cdd.toc.last = cdd.toc.end = 0;
  302. do
  303. {
  304. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  305. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
  306. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  307. cdd.toc.last++;
  308. }
  309. while (cdd.toc.last < 52);
  310. }
  311. else if (strstr(header + 0x180,"T-113045") != NULL)
  312. {
  313. /* Shadow of the Beast II */
  314. cdd.toc.last = cdd.toc.end = 0;
  315. do
  316. {
  317. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  318. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
  319. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  320. cdd.toc.last++;
  321. }
  322. while (cdd.toc.last < 15);
  323. }
  324. else if (strstr(header + 0x180,"T-143025") != NULL)
  325. {
  326. /* Dungeon Explorer */
  327. cdd.toc.last = cdd.toc.end = 0;
  328. do
  329. {
  330. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  331. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
  332. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  333. cdd.toc.last++;
  334. }
  335. while (cdd.toc.last < 13);
  336. }
  337. else if (strstr(header + 0x180,"MK-4410") != NULL)
  338. {
  339. /* Final Fight CD (USA, Europe) */
  340. cdd.toc.last = cdd.toc.end = 0;
  341. do
  342. {
  343. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  344. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
  345. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  346. cdd.toc.last++;
  347. }
  348. while (cdd.toc.last < 26);
  349. }
  350. else if (strstr(header + 0x180,"G-6013") != NULL)
  351. {
  352. /* Final Fight CD (Japan) */
  353. cdd.toc.last = cdd.toc.end = 0;
  354. do
  355. {
  356. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  357. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
  358. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  359. cdd.toc.last++;
  360. }
  361. while (cdd.toc.last < 29);
  362. }
  363. #if 0
  364. else
  365. {
  366. /* default TOC (99 tracks & 2s per audio tracks) */
  367. do
  368. {
  369. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
  370. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
  371. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  372. cdd.toc.last++;
  373. }
  374. while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
  375. }
  376. #endif
  377. }
  378. /* Lead-out */
  379. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  380. /* CD loaded */
  381. cdd.loaded = 1;
  382. /* disc not scanned yet */
  383. cdd.status = NO_DISC;
  384. return 0;
  385. }
  386. int cdd_unload(void)
  387. {
  388. int was_loaded = cdd.loaded;
  389. if (cdd.loaded)
  390. {
  391. int i;
  392. /* stop audio streaming */
  393. Pico_mcd->cdda_stream = NULL;
  394. /* close CD tracks */
  395. if (cdd.toc.tracks[0].fd)
  396. {
  397. pm_close(cdd.toc.tracks[0].fd);
  398. cdd.toc.tracks[0].fd = NULL;
  399. if (cdd.toc.tracks[0].fname)
  400. free(cdd.toc.tracks[0].fname);
  401. cdd.toc.tracks[0].fname = NULL;
  402. }
  403. for (i = 1; i < cdd.toc.last; i++)
  404. {
  405. #ifdef USE_LIBTREMOR
  406. if (cdd.toc.tracks[i].vf.datasource)
  407. {
  408. /* close VORBIS file (if still opened) */
  409. ov_clear(&cdd.toc.tracks[i].vf);
  410. }
  411. else
  412. #endif
  413. if (cdd.toc.tracks[i].fd)
  414. {
  415. /* close file */
  416. if (Pico_mcd->cdda_type == CT_MP3)
  417. fclose(cdd.toc.tracks[i].fd);
  418. else
  419. pm_close(cdd.toc.tracks[i].fd);
  420. cdd.toc.tracks[i].fd = NULL;
  421. if (cdd.toc.tracks[i].fname)
  422. free(cdd.toc.tracks[i].fname);
  423. cdd.toc.tracks[i].fname = NULL;
  424. /* detect single file images */
  425. if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
  426. {
  427. /* exit loop */
  428. i = cdd.toc.last;
  429. }
  430. }
  431. }
  432. /* CD unloaded */
  433. cdd.loaded = 0;
  434. if (cdd.status != CD_OPEN)
  435. cdd.status = NO_DISC;
  436. }
  437. /* reset TOC */
  438. memset(&cdd.toc, 0x00, sizeof(cdd.toc));
  439. /* unknown CD image file format */
  440. cdd.sectorSize = 0;
  441. return was_loaded;
  442. }
  443. void cdd_read_data(uint8 *dst)
  444. {
  445. /* only read DATA track sectors */
  446. if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
  447. {
  448. /* BIN format ? */
  449. if (cdd.sectorSize == 2352)
  450. {
  451. /* skip 16-byte header */
  452. pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
  453. }
  454. /* read sector data (Mode 1 = 2048 bytes) */
  455. pm_read(dst, 2048, cdd.toc.tracks[0].fd);
  456. }
  457. }
  458. #if 0
  459. void cdd_read_audio(unsigned int samples)
  460. {
  461. /* previous audio outputs */
  462. int16 l = cdd.audio[0];
  463. int16 r = cdd.audio[1];
  464. /* get number of internal clocks (samples) needed */
  465. samples = blip_clocks_needed(blip[0], samples);
  466. /* audio track playing ? */
  467. if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
  468. {
  469. int i, mul, delta;
  470. /* current CD-DA fader volume */
  471. int curVol = cdd.volume;
  472. /* CD-DA fader volume setup (0-1024) */
  473. int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
  474. /* read samples from current block */
  475. #ifdef USE_LIBTREMOR
  476. if (cdd.toc.tracks[cdd.index].vf.datasource)
  477. {
  478. int len, done = 0;
  479. int16 *ptr = (int16 *) (cdc.ram);
  480. samples = samples * 4;
  481. while (done < samples)
  482. {
  483. len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
  484. if (len <= 0)
  485. {
  486. done = samples;
  487. break;
  488. }
  489. done += len;
  490. }
  491. samples = done / 4;
  492. /* process 16-bit (host-endian) stereo samples */
  493. for (i=0; i<samples; i++)
  494. {
  495. /* CD-DA fader multiplier (cf. LC7883 datasheet) */
  496. /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
  497. mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
  498. /* left channel */
  499. delta = ((ptr[0] * mul) / 1024) - l;
  500. ptr++;
  501. l += delta;
  502. blip_add_delta_fast(blip[0], i, delta);
  503. /* right channel */
  504. delta = ((ptr[0] * mul) / 1024) - r;
  505. ptr++;
  506. r += delta;
  507. blip_add_delta_fast(blip[1], i, delta);
  508. /* update CD-DA fader volume (one step/sample) */
  509. if (curVol < endVol)
  510. {
  511. /* fade-in */
  512. curVol++;
  513. }
  514. else if (curVol > endVol)
  515. {
  516. /* fade-out */
  517. curVol--;
  518. }
  519. else if (!curVol)
  520. {
  521. /* audio will remain muted until next setup */
  522. break;
  523. }
  524. }
  525. }
  526. else
  527. #endif
  528. {
  529. #ifdef LSB_FIRST
  530. int16 *ptr = (int16 *) (cdc.ram);
  531. #else
  532. uint8 *ptr = cdc.ram;
  533. #endif
  534. fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
  535. /* process 16-bit (little-endian) stereo samples */
  536. for (i=0; i<samples; i++)
  537. {
  538. /* CD-DA fader multiplier (cf. LC7883 datasheet) */
  539. /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
  540. mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
  541. /* left channel */
  542. #ifdef LSB_FIRST
  543. delta = ((ptr[0] * mul) / 1024) - l;
  544. ptr++;
  545. #else
  546. delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
  547. ptr += 2;
  548. #endif
  549. l += delta;
  550. blip_add_delta_fast(blip[0], i, delta);
  551. /* right channel */
  552. #ifdef LSB_FIRST
  553. delta = ((ptr[0] * mul) / 1024) - r;
  554. ptr++;
  555. #else
  556. delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
  557. ptr += 2;
  558. #endif
  559. r += delta;
  560. blip_add_delta_fast(blip[1], i, delta);
  561. /* update CD-DA fader volume (one step/sample) */
  562. if (curVol < endVol)
  563. {
  564. /* fade-in */
  565. curVol++;
  566. }
  567. else if (curVol > endVol)
  568. {
  569. /* fade-out */
  570. curVol--;
  571. }
  572. else if (!curVol)
  573. {
  574. /* audio will remain muted until next setup */
  575. break;
  576. }
  577. }
  578. }
  579. /* save current CD-DA fader volume */
  580. cdd.volume = curVol;
  581. /* save last audio output for next frame */
  582. cdd.audio[0] = l;
  583. cdd.audio[1] = r;
  584. }
  585. else
  586. {
  587. /* no audio output */
  588. if (l) blip_add_delta_fast(blip[0], 0, -l);
  589. if (r) blip_add_delta_fast(blip[1], 0, -r);
  590. /* save audio output for next frame */
  591. cdd.audio[0] = 0;
  592. cdd.audio[1] = 0;
  593. }
  594. /* end of Blip Buffer timeframe */
  595. blip_end_frame(blip[0], samples);
  596. blip_end_frame(blip[1], samples);
  597. }
  598. #endif
  599. void cdd_update(void)
  600. {
  601. #ifdef LOG_CDD
  602. error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
  603. #endif
  604. /* drive latency */
  605. if (cdd.latency > 0)
  606. {
  607. cdd.latency--;
  608. return;
  609. }
  610. /* reading disc */
  611. if (cdd.status == CD_PLAY)
  612. {
  613. /* track type */
  614. if (!cdd.index)
  615. {
  616. /* DATA sector header (CD-ROM Mode 1) */
  617. uint8 header[4];
  618. uint32 msf = cdd.lba + 150;
  619. header[0] = lut_BCD_8[(msf / 75) / 60];
  620. header[1] = lut_BCD_8[(msf / 75) % 60];
  621. header[2] = lut_BCD_8[(msf % 75)];
  622. header[3] = 0x01;
  623. /* data track sector read is controlled by CDC */
  624. cdd.lba += cdc_decoder_update(header);
  625. }
  626. else if (cdd.index < cdd.toc.last)
  627. {
  628. uint8 header[4] = { 0, };
  629. /* check against audio track start index */
  630. if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
  631. {
  632. /* audio track playing */
  633. Pico_mcd->s68k_regs[0x36+0] = 0x00;
  634. }
  635. /* audio blocks are still sent to CDC as well as CD DAC/Fader */
  636. cdc_decoder_update(header);
  637. /* next audio block is automatically read */
  638. cdd.lba++;
  639. }
  640. else
  641. {
  642. /* end of disc */
  643. cdd.status = CD_END;
  644. return;
  645. }
  646. /* check end of current track */
  647. if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
  648. {
  649. #ifdef USE_LIBTREMOR
  650. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  651. /* close previous track VORBIS file structure to save memory */
  652. if (cdd.toc.tracks[cdd.index].vf.datasource)
  653. {
  654. ogg_free(cdd.index);
  655. }
  656. #endif
  657. #endif
  658. /* play next track */
  659. cdd.index++;
  660. /* PAUSE between tracks */
  661. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  662. /* seek to next audio track start */
  663. #ifdef USE_LIBTREMOR
  664. if (cdd.toc.tracks[cdd.index].vf.seekable)
  665. {
  666. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  667. /* VORBIS file need to be opened first */
  668. ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
  669. #endif
  670. ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
  671. }
  672. else
  673. #endif
  674. #if 0
  675. if (cdd.toc.tracks[cdd.index].fd)
  676. {
  677. fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  678. }
  679. #else
  680. {
  681. cdd_change_track(cdd.index, cdd.lba);
  682. }
  683. #endif
  684. }
  685. }
  686. /* scanning disc */
  687. else if (cdd.status == CD_SCAN)
  688. {
  689. /* fast-forward or fast-rewind */
  690. cdd.lba += cdd.scanOffset;
  691. /* check current track limits */
  692. if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
  693. {
  694. #ifdef USE_LIBTREMOR
  695. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  696. /* close previous track VORBIS file structure to save memory */
  697. if (cdd.toc.tracks[cdd.index].vf.datasource)
  698. {
  699. ogg_free(cdd.index);
  700. }
  701. #endif
  702. #endif
  703. /* next track */
  704. cdd.index++;
  705. /* skip directly to track start position */
  706. cdd.lba = cdd.toc.tracks[cdd.index].start;
  707. /* AUDIO track playing ? */
  708. if (cdd.status == CD_PLAY)
  709. {
  710. Pico_mcd->s68k_regs[0x36+0] = 0x00;
  711. }
  712. }
  713. else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
  714. {
  715. #ifdef USE_LIBTREMOR
  716. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  717. /* close previous track VORBIS file structure to save memory */
  718. if (cdd.toc.tracks[cdd.index].vf.datasource)
  719. {
  720. ogg_free(cdd.index);
  721. }
  722. #endif
  723. #endif
  724. /* previous track */
  725. cdd.index--;
  726. /* skip directly to track end position */
  727. cdd.lba = cdd.toc.tracks[cdd.index].end;
  728. }
  729. /* check disc limits */
  730. if (cdd.index < 0)
  731. {
  732. cdd.index = 0;
  733. cdd.lba = 0;
  734. }
  735. else if (cdd.index >= cdd.toc.last)
  736. {
  737. /* no AUDIO track playing */
  738. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  739. /* end of disc */
  740. cdd.index = cdd.toc.last;
  741. cdd.lba = cdd.toc.end;
  742. cdd.status = CD_END;
  743. return;
  744. }
  745. /* seek to current block */
  746. if (!cdd.index)
  747. {
  748. /* no AUDIO track playing */
  749. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  750. /* DATA track */
  751. pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
  752. }
  753. #ifdef USE_LIBTREMOR
  754. else if (cdd.toc.tracks[cdd.index].vf.seekable)
  755. {
  756. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  757. /* check if a new track is being played */
  758. if (!cdd.toc.tracks[cdd.index].vf.datasource)
  759. {
  760. /* VORBIS file need to be opened first */
  761. ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
  762. }
  763. #endif
  764. /* VORBIS AUDIO track */
  765. ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
  766. }
  767. #endif
  768. #if 0
  769. else if (cdd.toc.tracks[cdd.index].fd)
  770. {
  771. /* PCM AUDIO track */
  772. fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  773. }
  774. #else
  775. else
  776. {
  777. cdd_change_track(cdd.index, cdd.lba);
  778. }
  779. #endif
  780. }
  781. }
  782. #define set_reg16(r, v) { \
  783. uint16 _v = v; \
  784. Pico_mcd->s68k_regs[(r)] = _v >> 8; \
  785. Pico_mcd->s68k_regs[(r)+1] = _v; \
  786. }
  787. void cdd_process(void)
  788. {
  789. /* Process CDD command */
  790. switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f)
  791. {
  792. case 0x00: /* Drive Status */
  793. {
  794. if (cdd.latency <= 3) {
  795. /* RS1-RS8 normally unchanged */
  796. Pico_mcd->s68k_regs[0x38+0] = cdd.status;
  797. /* unless RS1 indicated invalid track infos */
  798. if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
  799. {
  800. /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */
  801. Pico_mcd->s68k_regs[0x38+1] = 0x02;
  802. set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
  803. }
  804. }
  805. break;
  806. }
  807. case 0x01: /* Stop Drive */
  808. {
  809. /* update status */
  810. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  811. /* no audio track playing */
  812. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  813. /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
  814. set_reg16(0x38, 0x0000);
  815. set_reg16(0x3a, 0x0000);
  816. set_reg16(0x3c, 0x0000);
  817. set_reg16(0x3e, 0x0000);
  818. set_reg16(0x40, 0x000f);
  819. return;
  820. }
  821. case 0x02: /* Read TOC */
  822. {
  823. if (cdd.status == NO_DISC)
  824. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  825. /* Infos automatically retrieved by CDD processor from Q-Channel */
  826. /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
  827. switch (Pico_mcd->s68k_regs[0x44+1])
  828. {
  829. case 0x00: /* Current Absolute Time (MM:SS:FF) */
  830. {
  831. int lba = cdd.lba + 150;
  832. set_reg16(0x38, cdd.status << 8);
  833. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  834. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  835. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  836. Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
  837. break;
  838. }
  839. case 0x01: /* Current Track Relative Time (MM:SS:FF) */
  840. {
  841. int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
  842. if (lba < 0) lba = 0;
  843. set_reg16(0x38, (cdd.status << 8) | 0x01);
  844. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  845. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  846. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  847. Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
  848. break;
  849. }
  850. case 0x02: /* Current Track Number */
  851. {
  852. set_reg16(0x38, (cdd.status << 8) | 0x02);
  853. set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
  854. set_reg16(0x3c, 0x0000);
  855. set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
  856. Pico_mcd->s68k_regs[0x40+0] = 0x00;
  857. break;
  858. }
  859. case 0x03: /* Total length (MM:SS:FF) */
  860. {
  861. int lba = cdd.toc.end + 150;
  862. set_reg16(0x38, (cdd.status << 8) | 0x03);
  863. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  864. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  865. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  866. Pico_mcd->s68k_regs[0x40+0] = 0x00;
  867. break;
  868. }
  869. case 0x04: /* First & Last Track Numbers */
  870. {
  871. set_reg16(0x38, (cdd.status << 8) | 0x04);
  872. set_reg16(0x3a, 0x0001);
  873. set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
  874. set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */
  875. Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
  876. break;
  877. }
  878. case 0x05: /* Track Start Time (MM:SS:FF) */
  879. {
  880. int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1];
  881. int lba = cdd.toc.tracks[track-1].start + 150;
  882. set_reg16(0x38, (cdd.status << 8) | 0x05);
  883. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  884. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  885. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  886. Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */
  887. if (track == 1)
  888. {
  889. /* RS6 bit 3 is set for the first (DATA) track */
  890. Pico_mcd->s68k_regs[0x3e + 0] |= 0x08;
  891. }
  892. break;
  893. }
  894. default:
  895. {
  896. #ifdef LOG_ERROR
  897. error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc);
  898. #endif
  899. return;
  900. }
  901. }
  902. break;
  903. }
  904. case 0x03: /* Play */
  905. {
  906. /* reset track index */
  907. int index = 0;
  908. /* new LBA position */
  909. int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
  910. (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
  911. (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
  912. /* CD drive latency */
  913. if (!cdd.latency)
  914. {
  915. /* Fixes a few games hanging during intro because they expect data to be read with some delay */
  916. /* Radical Rex needs at least one interrupt delay */
  917. /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
  918. /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */
  919. /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */
  920. cdd.latency = 10;
  921. }
  922. /* CD drive seek time */
  923. /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
  924. /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
  925. /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
  926. /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
  927. if (lba > cdd.lba)
  928. {
  929. cdd.latency += (((lba - cdd.lba) * 120) / 270000);
  930. }
  931. else
  932. {
  933. cdd.latency += (((cdd.lba - lba) * 120) / 270000);
  934. }
  935. /* update current LBA */
  936. cdd.lba = lba;
  937. /* get track index */
  938. while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
  939. #ifdef USE_LIBTREMOR
  940. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  941. /* check if track index has changed */
  942. if (index != cdd.index)
  943. {
  944. /* close previous track VORBIS file structure to save memory */
  945. if (cdd.toc.tracks[cdd.index].vf.datasource)
  946. {
  947. ogg_free(cdd.index);
  948. }
  949. /* open current track VORBIS file */
  950. if (cdd.toc.tracks[index].vf.seekable)
  951. {
  952. ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
  953. }
  954. }
  955. #endif
  956. #endif
  957. /* update current track index */
  958. cdd.index = index;
  959. /* stay within track limits when seeking files */
  960. if (lba < cdd.toc.tracks[index].start)
  961. {
  962. lba = cdd.toc.tracks[index].start;
  963. }
  964. /* seek to current block */
  965. if (!index)
  966. {
  967. /* DATA track */
  968. pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
  969. }
  970. #ifdef USE_LIBTREMOR
  971. else if (cdd.toc.tracks[index].vf.seekable)
  972. {
  973. /* VORBIS AUDIO track */
  974. ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
  975. }
  976. #endif
  977. #if 0
  978. else if (cdd.toc.tracks[index].fd)
  979. {
  980. /* PCM AUDIO track */
  981. fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
  982. }
  983. #else
  984. else
  985. {
  986. cdd_change_track(index, lba);
  987. }
  988. #endif
  989. /* no audio track playing (yet) */
  990. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  991. /* update status */
  992. cdd.status = CD_PLAY;
  993. /* return track index in RS2-RS3 */
  994. set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
  995. set_reg16(0x3a, 0x0000);
  996. set_reg16(0x3c, 0x0000);
  997. set_reg16(0x3e, 0x0000);
  998. set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
  999. break;
  1000. }
  1001. case 0x04: /* Seek */
  1002. {
  1003. /* reset track index */
  1004. int index = 0;
  1005. /* new LBA position */
  1006. int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
  1007. (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
  1008. (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
  1009. /* CD drive seek time */
  1010. /* We are using similar linear model as above, although still not exactly accurate, */
  1011. /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
  1012. /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
  1013. if (lba > cdd.lba)
  1014. {
  1015. cdd.latency = ((lba - cdd.lba) * 120) / 270000;
  1016. }
  1017. else
  1018. {
  1019. cdd.latency = ((cdd.lba - lba) * 120) / 270000;
  1020. }
  1021. /* update current LBA */
  1022. cdd.lba = lba;
  1023. /* get current track index */
  1024. while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
  1025. #ifdef USE_LIBTREMOR
  1026. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  1027. /* check if track index has changed */
  1028. if (index != cdd.index)
  1029. {
  1030. /* close previous track VORBIS file structure to save memory */
  1031. if (cdd.toc.tracks[cdd.index].vf.datasource)
  1032. {
  1033. ogg_free(cdd.index);
  1034. }
  1035. /* open current track VORBIS file */
  1036. if (cdd.toc.tracks[index].vf.seekable)
  1037. {
  1038. ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
  1039. }
  1040. }
  1041. #endif
  1042. #endif
  1043. /* update current track index */
  1044. cdd.index = index;
  1045. /* stay within track limits */
  1046. if (lba < cdd.toc.tracks[index].start)
  1047. {
  1048. lba = cdd.toc.tracks[index].start;
  1049. }
  1050. /* seek to current block */
  1051. if (!index)
  1052. {
  1053. /* DATA track */
  1054. pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
  1055. }
  1056. #ifdef USE_LIBTREMOR
  1057. else if (cdd.toc.tracks[index].vf.seekable)
  1058. {
  1059. /* VORBIS AUDIO track */
  1060. ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
  1061. }
  1062. #endif
  1063. #if 0
  1064. else if (cdd.toc.tracks[index].fd)
  1065. {
  1066. /* PCM AUDIO track */
  1067. fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
  1068. }
  1069. #else
  1070. else
  1071. {
  1072. cdd_change_track(index, lba);
  1073. }
  1074. #endif
  1075. /* no audio track playing */
  1076. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1077. /* update status */
  1078. cdd.status = CD_READY;
  1079. /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */
  1080. set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
  1081. set_reg16(0x3a, 0x0000);
  1082. set_reg16(0x3c, 0x0000);
  1083. set_reg16(0x3e, 0x0000);
  1084. set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
  1085. return;
  1086. }
  1087. case 0x06: /* Pause */
  1088. {
  1089. /* no audio track playing */
  1090. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1091. /* update status (RS1-RS8 unchanged) */
  1092. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
  1093. break;
  1094. }
  1095. case 0x07: /* Resume */
  1096. {
  1097. /* update status (RS1-RS8 unchanged) */
  1098. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY;
  1099. break;
  1100. }
  1101. case 0x08: /* Forward Scan */
  1102. {
  1103. /* reset scanning direction / speed */
  1104. cdd.scanOffset = CD_SCAN_SPEED;
  1105. /* update status (RS1-RS8 unchanged) */
  1106. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
  1107. break;
  1108. }
  1109. case 0x09: /* Rewind Scan */
  1110. {
  1111. /* reset scanning direction / speed */
  1112. cdd.scanOffset = -CD_SCAN_SPEED;
  1113. /* update status (RS1-RS8 unchanged) */
  1114. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
  1115. break;
  1116. }
  1117. case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
  1118. {
  1119. /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
  1120. /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */
  1121. /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */
  1122. /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
  1123. /* no audio track playing */
  1124. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1125. /* update status (RS1-RS8 unchanged) */
  1126. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
  1127. break;
  1128. }
  1129. case 0x0c: /* Close Tray */
  1130. {
  1131. /* no audio track playing */
  1132. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1133. /* update status */
  1134. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  1135. /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
  1136. set_reg16(0x38, 0x0000);
  1137. set_reg16(0x3a, 0x0000);
  1138. set_reg16(0x3c, 0x0000);
  1139. set_reg16(0x3e, 0x0000);
  1140. set_reg16(0x40, 0x000f);
  1141. if (PicoIn.mcdTrayClose)
  1142. PicoIn.mcdTrayClose();
  1143. return;
  1144. }
  1145. case 0x0d: /* Open Tray */
  1146. {
  1147. /* no audio track playing */
  1148. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1149. /* update status (RS1-RS8 ignored) */
  1150. cdd.status = CD_OPEN;
  1151. set_reg16(0x38, CD_OPEN << 8);
  1152. set_reg16(0x3a, 0x0000);
  1153. set_reg16(0x3c, 0x0000);
  1154. set_reg16(0x3e, 0x0000);
  1155. set_reg16(0x40, ~CD_OPEN & 0x0f);
  1156. if (PicoIn.mcdTrayOpen)
  1157. PicoIn.mcdTrayOpen();
  1158. return;
  1159. }
  1160. default: /* Unknown command */
  1161. #ifdef LOG_CDD
  1162. error("Unknown CDD Command !!!\n");
  1163. #endif
  1164. Pico_mcd->s68k_regs[0x38+0] = cdd.status;
  1165. break;
  1166. }
  1167. /* only compute checksum when necessary */
  1168. Pico_mcd->s68k_regs[0x40 + 1] =
  1169. ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] +
  1170. Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] +
  1171. Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] +
  1172. Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] +
  1173. Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f;
  1174. }
  1175. // vim:shiftwidth=2:ts=2:expandtab