cdd.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  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 "cue.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. /* read CD image header + security code */
  279. pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
  280. /* Simulate audio tracks if none found */
  281. if (cdd.toc.last == 1)
  282. {
  283. /* Some games require exact TOC infos */
  284. if (strstr(header + 0x180,"T-95035") != NULL)
  285. {
  286. /* Snatcher */
  287. cdd.toc.last = cdd.toc.end = 0;
  288. do
  289. {
  290. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  291. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
  292. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  293. cdd.toc.last++;
  294. }
  295. while (cdd.toc.last < 21);
  296. }
  297. else if (strstr(header + 0x180,"T-127015") != NULL)
  298. {
  299. /* Lunar - The Silver Star */
  300. cdd.toc.last = cdd.toc.end = 0;
  301. do
  302. {
  303. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  304. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
  305. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  306. cdd.toc.last++;
  307. }
  308. while (cdd.toc.last < 52);
  309. }
  310. else if (strstr(header + 0x180,"T-113045") != NULL)
  311. {
  312. /* Shadow of the Beast II */
  313. cdd.toc.last = cdd.toc.end = 0;
  314. do
  315. {
  316. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  317. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
  318. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  319. cdd.toc.last++;
  320. }
  321. while (cdd.toc.last < 15);
  322. }
  323. else if (strstr(header + 0x180,"T-143025") != NULL)
  324. {
  325. /* Dungeon Explorer */
  326. cdd.toc.last = cdd.toc.end = 0;
  327. do
  328. {
  329. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  330. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
  331. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  332. cdd.toc.last++;
  333. }
  334. while (cdd.toc.last < 13);
  335. }
  336. else if (strstr(header + 0x180,"MK-4410") != NULL)
  337. {
  338. /* Final Fight CD (USA, Europe) */
  339. cdd.toc.last = cdd.toc.end = 0;
  340. do
  341. {
  342. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  343. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
  344. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  345. cdd.toc.last++;
  346. }
  347. while (cdd.toc.last < 26);
  348. }
  349. else if (strstr(header + 0x180,"G-6013") != NULL)
  350. {
  351. /* Final Fight CD (Japan) */
  352. cdd.toc.last = cdd.toc.end = 0;
  353. do
  354. {
  355. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  356. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
  357. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  358. cdd.toc.last++;
  359. }
  360. while (cdd.toc.last < 29);
  361. }
  362. #if 0
  363. else
  364. {
  365. /* default TOC (99 tracks & 2s per audio tracks) */
  366. do
  367. {
  368. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
  369. cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
  370. cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
  371. cdd.toc.last++;
  372. }
  373. while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
  374. }
  375. #endif
  376. }
  377. /* Lead-out */
  378. cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
  379. /* CD loaded */
  380. cdd.loaded = 1;
  381. /* disc not scanned yet */
  382. cdd.status = NO_DISC;
  383. return 0;
  384. }
  385. int cdd_unload(void)
  386. {
  387. int was_loaded = cdd.loaded;
  388. if (cdd.loaded)
  389. {
  390. int i;
  391. /* close CD tracks */
  392. if (cdd.toc.tracks[0].fd)
  393. {
  394. pm_close(cdd.toc.tracks[0].fd);
  395. cdd.toc.tracks[0].fd = NULL;
  396. }
  397. for (i = 1; i < cdd.toc.last; i++)
  398. {
  399. #ifdef USE_LIBTREMOR
  400. if (cdd.toc.tracks[i].vf.datasource)
  401. {
  402. /* close VORBIS file (if still opened) */
  403. ov_clear(&cdd.toc.tracks[i].vf);
  404. }
  405. else
  406. #endif
  407. if (cdd.toc.tracks[i].fd)
  408. {
  409. /* close file */
  410. if (Pico_mcd->cdda_type == CT_MP3)
  411. fclose(cdd.toc.tracks[i].fd);
  412. else
  413. pm_close(cdd.toc.tracks[0].fd);
  414. /* detect single file images */
  415. if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
  416. {
  417. /* exit loop */
  418. i = cdd.toc.last;
  419. }
  420. }
  421. }
  422. /* CD unloaded */
  423. cdd.loaded = 0;
  424. if (cdd.status != CD_OPEN)
  425. cdd.status = NO_DISC;
  426. }
  427. /* reset TOC */
  428. memset(&cdd.toc, 0x00, sizeof(cdd.toc));
  429. /* unknown CD image file format */
  430. cdd.sectorSize = 0;
  431. return was_loaded;
  432. }
  433. void cdd_read_data(uint8 *dst)
  434. {
  435. /* only read DATA track sectors */
  436. if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
  437. {
  438. /* BIN format ? */
  439. if (cdd.sectorSize == 2352)
  440. {
  441. /* skip 16-byte header */
  442. pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
  443. }
  444. /* read sector data (Mode 1 = 2048 bytes) */
  445. pm_read(dst, 2048, cdd.toc.tracks[0].fd);
  446. }
  447. }
  448. #if 0
  449. void cdd_read_audio(unsigned int samples)
  450. {
  451. /* previous audio outputs */
  452. int16 l = cdd.audio[0];
  453. int16 r = cdd.audio[1];
  454. /* get number of internal clocks (samples) needed */
  455. samples = blip_clocks_needed(blip[0], samples);
  456. /* audio track playing ? */
  457. if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
  458. {
  459. int i, mul, delta;
  460. /* current CD-DA fader volume */
  461. int curVol = cdd.volume;
  462. /* CD-DA fader volume setup (0-1024) */
  463. int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
  464. /* read samples from current block */
  465. #ifdef USE_LIBTREMOR
  466. if (cdd.toc.tracks[cdd.index].vf.datasource)
  467. {
  468. int len, done = 0;
  469. int16 *ptr = (int16 *) (cdc.ram);
  470. samples = samples * 4;
  471. while (done < samples)
  472. {
  473. len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
  474. if (len <= 0)
  475. {
  476. done = samples;
  477. break;
  478. }
  479. done += len;
  480. }
  481. samples = done / 4;
  482. /* process 16-bit (host-endian) stereo samples */
  483. for (i=0; i<samples; i++)
  484. {
  485. /* CD-DA fader multiplier (cf. LC7883 datasheet) */
  486. /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
  487. mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
  488. /* left channel */
  489. delta = ((ptr[0] * mul) / 1024) - l;
  490. ptr++;
  491. l += delta;
  492. blip_add_delta_fast(blip[0], i, delta);
  493. /* right channel */
  494. delta = ((ptr[0] * mul) / 1024) - r;
  495. ptr++;
  496. r += delta;
  497. blip_add_delta_fast(blip[1], i, delta);
  498. /* update CD-DA fader volume (one step/sample) */
  499. if (curVol < endVol)
  500. {
  501. /* fade-in */
  502. curVol++;
  503. }
  504. else if (curVol > endVol)
  505. {
  506. /* fade-out */
  507. curVol--;
  508. }
  509. else if (!curVol)
  510. {
  511. /* audio will remain muted until next setup */
  512. break;
  513. }
  514. }
  515. }
  516. else
  517. #endif
  518. {
  519. #ifdef LSB_FIRST
  520. int16 *ptr = (int16 *) (cdc.ram);
  521. #else
  522. uint8 *ptr = cdc.ram;
  523. #endif
  524. fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
  525. /* process 16-bit (little-endian) stereo samples */
  526. for (i=0; i<samples; i++)
  527. {
  528. /* CD-DA fader multiplier (cf. LC7883 datasheet) */
  529. /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
  530. mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
  531. /* left channel */
  532. #ifdef LSB_FIRST
  533. delta = ((ptr[0] * mul) / 1024) - l;
  534. ptr++;
  535. #else
  536. delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
  537. ptr += 2;
  538. #endif
  539. l += delta;
  540. blip_add_delta_fast(blip[0], i, delta);
  541. /* right channel */
  542. #ifdef LSB_FIRST
  543. delta = ((ptr[0] * mul) / 1024) - r;
  544. ptr++;
  545. #else
  546. delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
  547. ptr += 2;
  548. #endif
  549. r += delta;
  550. blip_add_delta_fast(blip[1], i, delta);
  551. /* update CD-DA fader volume (one step/sample) */
  552. if (curVol < endVol)
  553. {
  554. /* fade-in */
  555. curVol++;
  556. }
  557. else if (curVol > endVol)
  558. {
  559. /* fade-out */
  560. curVol--;
  561. }
  562. else if (!curVol)
  563. {
  564. /* audio will remain muted until next setup */
  565. break;
  566. }
  567. }
  568. }
  569. /* save current CD-DA fader volume */
  570. cdd.volume = curVol;
  571. /* save last audio output for next frame */
  572. cdd.audio[0] = l;
  573. cdd.audio[1] = r;
  574. }
  575. else
  576. {
  577. /* no audio output */
  578. if (l) blip_add_delta_fast(blip[0], 0, -l);
  579. if (r) blip_add_delta_fast(blip[1], 0, -r);
  580. /* save audio output for next frame */
  581. cdd.audio[0] = 0;
  582. cdd.audio[1] = 0;
  583. }
  584. /* end of Blip Buffer timeframe */
  585. blip_end_frame(blip[0], samples);
  586. blip_end_frame(blip[1], samples);
  587. }
  588. #endif
  589. void cdd_update(void)
  590. {
  591. #ifdef LOG_CDD
  592. error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
  593. #endif
  594. /* drive latency */
  595. if (cdd.latency > 0)
  596. {
  597. cdd.latency--;
  598. return;
  599. }
  600. /* reading disc */
  601. if (cdd.status == CD_PLAY)
  602. {
  603. /* track type */
  604. if (!cdd.index)
  605. {
  606. /* DATA sector header (CD-ROM Mode 1) */
  607. uint8 header[4];
  608. uint32 msf = cdd.lba + 150;
  609. header[0] = lut_BCD_8[(msf / 75) / 60];
  610. header[1] = lut_BCD_8[(msf / 75) % 60];
  611. header[2] = lut_BCD_8[(msf % 75)];
  612. header[3] = 0x01;
  613. /* data track sector read is controlled by CDC */
  614. cdd.lba += cdc_decoder_update(header);
  615. }
  616. else if (cdd.index < cdd.toc.last)
  617. {
  618. uint8 header[4] = { 0, };
  619. /* check against audio track start index */
  620. if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
  621. {
  622. /* audio track playing */
  623. Pico_mcd->s68k_regs[0x36+0] = 0x00;
  624. }
  625. /* audio blocks are still sent to CDC as well as CD DAC/Fader */
  626. cdc_decoder_update(header);
  627. /* next audio block is automatically read */
  628. cdd.lba++;
  629. }
  630. else
  631. {
  632. /* end of disc */
  633. cdd.status = CD_END;
  634. return;
  635. }
  636. /* check end of current track */
  637. if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
  638. {
  639. #ifdef USE_LIBTREMOR
  640. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  641. /* close previous track VORBIS file structure to save memory */
  642. if (cdd.toc.tracks[cdd.index].vf.datasource)
  643. {
  644. ogg_free(cdd.index);
  645. }
  646. #endif
  647. #endif
  648. /* play next track */
  649. cdd.index++;
  650. /* PAUSE between tracks */
  651. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  652. /* seek to next audio track start */
  653. #ifdef USE_LIBTREMOR
  654. if (cdd.toc.tracks[cdd.index].vf.seekable)
  655. {
  656. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  657. /* VORBIS file need to be opened first */
  658. ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
  659. #endif
  660. ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
  661. }
  662. else
  663. #endif
  664. #if 0
  665. if (cdd.toc.tracks[cdd.index].fd)
  666. {
  667. fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  668. }
  669. #else
  670. {
  671. cdd_change_track(cdd.index, cdd.lba);
  672. }
  673. #endif
  674. }
  675. }
  676. /* scanning disc */
  677. else if (cdd.status == CD_SCAN)
  678. {
  679. /* fast-forward or fast-rewind */
  680. cdd.lba += cdd.scanOffset;
  681. /* check current track limits */
  682. if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
  683. {
  684. #ifdef USE_LIBTREMOR
  685. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  686. /* close previous track VORBIS file structure to save memory */
  687. if (cdd.toc.tracks[cdd.index].vf.datasource)
  688. {
  689. ogg_free(cdd.index);
  690. }
  691. #endif
  692. #endif
  693. /* next track */
  694. cdd.index++;
  695. /* skip directly to track start position */
  696. cdd.lba = cdd.toc.tracks[cdd.index].start;
  697. /* AUDIO track playing ? */
  698. if (cdd.status == CD_PLAY)
  699. {
  700. Pico_mcd->s68k_regs[0x36+0] = 0x00;
  701. }
  702. }
  703. else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
  704. {
  705. #ifdef USE_LIBTREMOR
  706. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  707. /* close previous track VORBIS file structure to save memory */
  708. if (cdd.toc.tracks[cdd.index].vf.datasource)
  709. {
  710. ogg_free(cdd.index);
  711. }
  712. #endif
  713. #endif
  714. /* previous track */
  715. cdd.index--;
  716. /* skip directly to track end position */
  717. cdd.lba = cdd.toc.tracks[cdd.index].end;
  718. }
  719. /* check disc limits */
  720. if (cdd.index < 0)
  721. {
  722. cdd.index = 0;
  723. cdd.lba = 0;
  724. }
  725. else if (cdd.index >= cdd.toc.last)
  726. {
  727. /* no AUDIO track playing */
  728. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  729. /* end of disc */
  730. cdd.index = cdd.toc.last;
  731. cdd.lba = cdd.toc.end;
  732. cdd.status = CD_END;
  733. return;
  734. }
  735. /* seek to current block */
  736. if (!cdd.index)
  737. {
  738. /* no AUDIO track playing */
  739. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  740. /* DATA track */
  741. pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
  742. }
  743. #ifdef USE_LIBTREMOR
  744. else if (cdd.toc.tracks[cdd.index].vf.seekable)
  745. {
  746. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  747. /* check if a new track is being played */
  748. if (!cdd.toc.tracks[cdd.index].vf.datasource)
  749. {
  750. /* VORBIS file need to be opened first */
  751. ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
  752. }
  753. #endif
  754. /* VORBIS AUDIO track */
  755. ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
  756. }
  757. #endif
  758. #if 0
  759. else if (cdd.toc.tracks[cdd.index].fd)
  760. {
  761. /* PCM AUDIO track */
  762. fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
  763. }
  764. #else
  765. else
  766. {
  767. cdd_change_track(cdd.index, cdd.lba);
  768. }
  769. #endif
  770. }
  771. }
  772. #define set_reg16(r, v) { \
  773. uint16 _v = v; \
  774. Pico_mcd->s68k_regs[(r)] = _v >> 8; \
  775. Pico_mcd->s68k_regs[(r)+1] = _v; \
  776. }
  777. void cdd_process(void)
  778. {
  779. /* Process CDD command */
  780. switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f)
  781. {
  782. case 0x00: /* Drive Status */
  783. {
  784. if (cdd.latency <= 3) {
  785. /* RS1-RS8 normally unchanged */
  786. Pico_mcd->s68k_regs[0x38+0] = cdd.status;
  787. /* unless RS1 indicated invalid track infos */
  788. if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
  789. {
  790. /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */
  791. Pico_mcd->s68k_regs[0x38+1] = 0x02;
  792. set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
  793. }
  794. }
  795. break;
  796. }
  797. case 0x01: /* Stop Drive */
  798. {
  799. /* update status */
  800. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  801. /* no audio track playing */
  802. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  803. /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
  804. set_reg16(0x38, 0x0000);
  805. set_reg16(0x3a, 0x0000);
  806. set_reg16(0x3c, 0x0000);
  807. set_reg16(0x3e, 0x0000);
  808. set_reg16(0x40, 0x000f);
  809. return;
  810. }
  811. case 0x02: /* Read TOC */
  812. {
  813. if (cdd.status == NO_DISC)
  814. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  815. /* Infos automatically retrieved by CDD processor from Q-Channel */
  816. /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
  817. switch (Pico_mcd->s68k_regs[0x44+1])
  818. {
  819. case 0x00: /* Current Absolute Time (MM:SS:FF) */
  820. {
  821. int lba = cdd.lba + 150;
  822. set_reg16(0x38, cdd.status << 8);
  823. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  824. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  825. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  826. 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) */
  827. break;
  828. }
  829. case 0x01: /* Current Track Relative Time (MM:SS:FF) */
  830. {
  831. int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
  832. set_reg16(0x38, (cdd.status << 8) | 0x01);
  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 0x02: /* Current Track Number */
  840. {
  841. set_reg16(0x38, (cdd.status << 8) | 0x02);
  842. set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
  843. set_reg16(0x3c, 0x0000);
  844. set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
  845. Pico_mcd->s68k_regs[0x40+0] = 0x00;
  846. break;
  847. }
  848. case 0x03: /* Total length (MM:SS:FF) */
  849. {
  850. int lba = cdd.toc.end + 150;
  851. set_reg16(0x38, (cdd.status << 8) | 0x03);
  852. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  853. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  854. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  855. Pico_mcd->s68k_regs[0x40+0] = 0x00;
  856. break;
  857. }
  858. case 0x04: /* First & Last Track Numbers */
  859. {
  860. set_reg16(0x38, (cdd.status << 8) | 0x04);
  861. set_reg16(0x3a, 0x0001);
  862. set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
  863. set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */
  864. Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
  865. break;
  866. }
  867. case 0x05: /* Track Start Time (MM:SS:FF) */
  868. {
  869. int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1];
  870. int lba = cdd.toc.tracks[track-1].start + 150;
  871. set_reg16(0x38, (cdd.status << 8) | 0x05);
  872. set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
  873. set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
  874. set_reg16(0x3e, lut_BCD_16[(lba%75)]);
  875. Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */
  876. if (track == 1)
  877. {
  878. /* RS6 bit 3 is set for the first (DATA) track */
  879. Pico_mcd->s68k_regs[0x3e + 0] |= 0x08;
  880. }
  881. break;
  882. }
  883. default:
  884. {
  885. #ifdef LOG_ERROR
  886. error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc);
  887. #endif
  888. return;
  889. }
  890. }
  891. break;
  892. }
  893. case 0x03: /* Play */
  894. {
  895. /* reset track index */
  896. int index = 0;
  897. /* new LBA position */
  898. int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
  899. (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
  900. (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
  901. /* CD drive latency */
  902. if (!cdd.latency)
  903. {
  904. /* Fixes a few games hanging during intro because they expect data to be read with some delay */
  905. /* Radical Rex needs at least one interrupt delay */
  906. /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
  907. /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */
  908. /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */
  909. cdd.latency = 10;
  910. }
  911. /* CD drive seek time */
  912. /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
  913. /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
  914. /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
  915. /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
  916. if (lba > cdd.lba)
  917. {
  918. cdd.latency += (((lba - cdd.lba) * 120) / 270000);
  919. }
  920. else
  921. {
  922. cdd.latency += (((cdd.lba - lba) * 120) / 270000);
  923. }
  924. /* update current LBA */
  925. cdd.lba = lba;
  926. /* get track index */
  927. while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
  928. #ifdef USE_LIBTREMOR
  929. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  930. /* check if track index has changed */
  931. if (index != cdd.index)
  932. {
  933. /* close previous track VORBIS file structure to save memory */
  934. if (cdd.toc.tracks[cdd.index].vf.datasource)
  935. {
  936. ogg_free(cdd.index);
  937. }
  938. /* open current track VORBIS file */
  939. if (cdd.toc.tracks[index].vf.seekable)
  940. {
  941. ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
  942. }
  943. }
  944. #endif
  945. #endif
  946. /* update current track index */
  947. cdd.index = index;
  948. /* stay within track limits when seeking files */
  949. if (lba < cdd.toc.tracks[index].start)
  950. {
  951. lba = cdd.toc.tracks[index].start;
  952. }
  953. /* seek to current block */
  954. if (!index)
  955. {
  956. /* DATA track */
  957. pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
  958. }
  959. #ifdef USE_LIBTREMOR
  960. else if (cdd.toc.tracks[index].vf.seekable)
  961. {
  962. /* VORBIS AUDIO track */
  963. ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
  964. }
  965. #endif
  966. #if 0
  967. else if (cdd.toc.tracks[index].fd)
  968. {
  969. /* PCM AUDIO track */
  970. fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
  971. }
  972. #else
  973. else
  974. {
  975. cdd_change_track(index, lba);
  976. }
  977. #endif
  978. /* no audio track playing (yet) */
  979. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  980. /* update status */
  981. cdd.status = CD_PLAY;
  982. /* return track index in RS2-RS3 */
  983. set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
  984. set_reg16(0x3a, 0x0000);
  985. set_reg16(0x3c, 0x0000);
  986. set_reg16(0x3e, 0x0000);
  987. set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
  988. break;
  989. }
  990. case 0x04: /* Seek */
  991. {
  992. /* reset track index */
  993. int index = 0;
  994. /* new LBA position */
  995. int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
  996. (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
  997. (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
  998. /* CD drive seek time */
  999. /* We are using similar linear model as above, although still not exactly accurate, */
  1000. /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
  1001. /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
  1002. if (lba > cdd.lba)
  1003. {
  1004. cdd.latency = ((lba - cdd.lba) * 120) / 270000;
  1005. }
  1006. else
  1007. {
  1008. cdd.latency = ((cdd.lba - lba) * 120) / 270000;
  1009. }
  1010. /* update current LBA */
  1011. cdd.lba = lba;
  1012. /* get current track index */
  1013. while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
  1014. #ifdef USE_LIBTREMOR
  1015. #ifdef DISABLE_MANY_OGG_OPEN_FILES
  1016. /* check if track index has changed */
  1017. if (index != cdd.index)
  1018. {
  1019. /* close previous track VORBIS file structure to save memory */
  1020. if (cdd.toc.tracks[cdd.index].vf.datasource)
  1021. {
  1022. ogg_free(cdd.index);
  1023. }
  1024. /* open current track VORBIS file */
  1025. if (cdd.toc.tracks[index].vf.seekable)
  1026. {
  1027. ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
  1028. }
  1029. }
  1030. #endif
  1031. #endif
  1032. /* update current track index */
  1033. cdd.index = index;
  1034. /* stay within track limits */
  1035. if (lba < cdd.toc.tracks[index].start)
  1036. {
  1037. lba = cdd.toc.tracks[index].start;
  1038. }
  1039. /* seek to current block */
  1040. if (!index)
  1041. {
  1042. /* DATA track */
  1043. pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
  1044. }
  1045. #ifdef USE_LIBTREMOR
  1046. else if (cdd.toc.tracks[index].vf.seekable)
  1047. {
  1048. /* VORBIS AUDIO track */
  1049. ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
  1050. }
  1051. #endif
  1052. #if 0
  1053. else if (cdd.toc.tracks[index].fd)
  1054. {
  1055. /* PCM AUDIO track */
  1056. fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
  1057. }
  1058. #else
  1059. else
  1060. {
  1061. cdd_change_track(index, lba);
  1062. }
  1063. #endif
  1064. /* no audio track playing */
  1065. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1066. /* update status */
  1067. cdd.status = CD_READY;
  1068. /* 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) */
  1069. set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
  1070. set_reg16(0x3a, 0x0000);
  1071. set_reg16(0x3c, 0x0000);
  1072. set_reg16(0x3e, 0x0000);
  1073. set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
  1074. return;
  1075. }
  1076. case 0x06: /* Pause */
  1077. {
  1078. /* no audio track playing */
  1079. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1080. /* update status (RS1-RS8 unchanged) */
  1081. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
  1082. break;
  1083. }
  1084. case 0x07: /* Resume */
  1085. {
  1086. /* update status (RS1-RS8 unchanged) */
  1087. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY;
  1088. break;
  1089. }
  1090. case 0x08: /* Forward Scan */
  1091. {
  1092. /* reset scanning direction / speed */
  1093. cdd.scanOffset = CD_SCAN_SPEED;
  1094. /* update status (RS1-RS8 unchanged) */
  1095. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
  1096. break;
  1097. }
  1098. case 0x09: /* Rewind Scan */
  1099. {
  1100. /* reset scanning direction / speed */
  1101. cdd.scanOffset = -CD_SCAN_SPEED;
  1102. /* update status (RS1-RS8 unchanged) */
  1103. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
  1104. break;
  1105. }
  1106. case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
  1107. {
  1108. /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
  1109. /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */
  1110. /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */
  1111. /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
  1112. /* no audio track playing */
  1113. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1114. /* update status (RS1-RS8 unchanged) */
  1115. cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
  1116. break;
  1117. }
  1118. case 0x0c: /* Close Tray */
  1119. {
  1120. /* no audio track playing */
  1121. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1122. /* update status */
  1123. cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
  1124. /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
  1125. set_reg16(0x38, 0x0000);
  1126. set_reg16(0x3a, 0x0000);
  1127. set_reg16(0x3c, 0x0000);
  1128. set_reg16(0x3e, 0x0000);
  1129. set_reg16(0x40, 0x000f);
  1130. if (PicoIn.mcdTrayClose)
  1131. PicoIn.mcdTrayClose();
  1132. return;
  1133. }
  1134. case 0x0d: /* Open Tray */
  1135. {
  1136. /* no audio track playing */
  1137. Pico_mcd->s68k_regs[0x36+0] = 0x01;
  1138. /* update status (RS1-RS8 ignored) */
  1139. cdd.status = CD_OPEN;
  1140. set_reg16(0x38, CD_OPEN << 8);
  1141. set_reg16(0x3a, 0x0000);
  1142. set_reg16(0x3c, 0x0000);
  1143. set_reg16(0x3e, 0x0000);
  1144. set_reg16(0x40, ~CD_OPEN & 0x0f);
  1145. if (PicoIn.mcdTrayOpen)
  1146. PicoIn.mcdTrayOpen();
  1147. return;
  1148. }
  1149. default: /* Unknown command */
  1150. #ifdef LOG_CDD
  1151. error("Unknown CDD Command !!!\n");
  1152. #endif
  1153. Pico_mcd->s68k_regs[0x38+0] = cdd.status;
  1154. break;
  1155. }
  1156. /* only compute checksum when necessary */
  1157. Pico_mcd->s68k_regs[0x40 + 1] =
  1158. ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] +
  1159. Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] +
  1160. Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] +
  1161. Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] +
  1162. Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f;
  1163. }
  1164. // vim:shiftwidth=2:ts=2:expandtab