diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs index 43c153f1ab..dab7c82b84 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs @@ -17,7 +17,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive public int Buttons; } + [UnmanagedFunctionPointer(CC)] + public delegate void CDReadCallback(int lba, IntPtr dest, bool audio); + [BizImport(CC)] - public abstract bool Init(); + public abstract bool Init(bool cd); + + [BizImport(CC)] + public abstract void SetCDReadCallback(CDReadCallback callback); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs index 4996ef7671..feaf8ad0dd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs @@ -1,21 +1,35 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; +using BizHawk.Emulation.DiscSystem; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using System.IO; namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive { [CoreAttributes("PicoDrive", "notaz", true, false, "0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)] - public class PicoDrive : WaterboxCore + public class PicoDrive : WaterboxCore, IDriveLight { private LibPicoDrive _core; + private LibPicoDrive.CDReadCallback _cdcallback; + private Disc _cd; + private DiscSectorReader _cdReader; [CoreConstructor("GEN")] public PicoDrive(CoreComm comm, byte[] rom, bool deterministic) + :this(comm, rom, null, deterministic) + { } + + public PicoDrive(CoreComm comm, Disc cd, bool deterministic) + :this(comm, null, cd, deterministic) + { } + + private PicoDrive(CoreComm comm, byte[] rom, Disc cd, bool deterministic) : base(comm, new Configuration { MaxSamples = 2048, @@ -51,12 +65,38 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive _exe.AddReadonlyFile(bioss, "32x.s"); Console.WriteLine("Using supplied 32x BIOS files"); } - _exe.AddReadonlyFile(rom, "romfile.md"); + if (cd != null) + { + _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_EU", true), "cd.eu"); + _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_US", true), "cd.us"); + _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_JP", true), "cd.jp"); + _exe.AddReadonlyFile(gpgx64.GPGX.GetCDData(cd), "toc"); + _cd = cd; + _cdReader = new DiscSectorReader(_cd); + _cdcallback = CDRead; + _core.SetCDReadCallback(_cdcallback); + DriveLightEnabled = true; + } + else + { + _exe.AddReadonlyFile(rom, "romfile.md"); + } - if (!_core.Init()) - throw new InvalidOperationException("Core rejected the rom!"); + if (!_core.Init(cd != null)) + throw new InvalidOperationException("Core rejected the file!"); - _exe.RemoveReadonlyFile("romfile.md"); + if (cd != null) + { + _exe.RemoveReadonlyFile("cd.eu"); + _exe.RemoveReadonlyFile("cd.us"); + _exe.RemoveReadonlyFile("cd.jp"); + _exe.RemoveReadonlyFile("toc"); + _core.SetCDReadCallback(null); + } + else + { + _exe.RemoveReadonlyFile("romfile.md"); + } if (has32xBios) { _exe.RemoveReadonlyFile("32x.g"); @@ -67,6 +107,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive PostInit(); ControllerDefinition = PicoDriveController; DeterministicEmulation = deterministic; + _core.SetCDReadCallback(_cdcallback); } public static readonly ControllerDefinition PicoDriveController = new ControllerDefinition @@ -97,7 +138,40 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive b |= v; v <<= 1; } + DriveLightOn = false; return new LibPicoDrive.FrameInfo { Buttons = b }; } + + private void CDRead(int lba, IntPtr dest, bool audio) + { + if (audio) + { + byte[] data = new byte[2352]; + if (lba < _cd.Session1.LeadoutLBA) + { + _cdReader.ReadLBA_2352(lba, data, 0); + } + Marshal.Copy(data, 0, dest, 2352); + } + else + { + byte[] data = new byte[2048]; + _cdReader.ReadLBA_2048(lba, data, 0); + Marshal.Copy(data, 0, dest, 2048); + DriveLightOn = true; + } + } + + protected override void LoadStateBinaryInternal(BinaryReader reader) + { + _core.SetCDReadCallback(_cdcallback); + } + + #region IDriveLight + + public bool DriveLightEnabled { get; private set; } + public bool DriveLightOn { get; private set; } + + #endregion } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs index 6b0b1fae64..16e5ad0eea 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs @@ -6,6 +6,7 @@ using BizHawk.Common.BizInvoke; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Common; +using BizHawk.Emulation.DiscSystem; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 { @@ -221,7 +222,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename); return 0; } - srcdata = GetCDData(); + srcdata = GetCDData(CD); if (srcdata.Length != maxsize) { Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename); @@ -308,12 +309,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 LibGPGX.cd_read_cb cd_callback_handle; - unsafe byte[] GetCDData() + public static unsafe byte[] GetCDData(Disc cd) { LibGPGX.CDData ret = new LibGPGX.CDData(); int size = Marshal.SizeOf(ret); - var ses = CD.Session1; + var ses = cd.Session1; int ntrack = ses.InformationTrackCount; // bet you a dollar this is all wrong diff --git a/waterbox/picodrive/bizhawk.c b/waterbox/picodrive/bizhawk.c index f07bb09850..a3b9e710f8 100644 --- a/waterbox/picodrive/bizhawk.c +++ b/waterbox/picodrive/bizhawk.c @@ -6,7 +6,7 @@ #include "../emulibc/emulibc.h" #include "../emulibc/waterboxcore.h" #include "pico/pico.h" -#include "pico/cd/cue.h" +#include "pico/cd/cdd.h" void lprintf(const char *fmt, ...) { @@ -24,12 +24,41 @@ int PicoCartResize(int newsize) int PicoCdCheck(const char *fname_in, int *pregion) { - return CIT_NOT_CD; + uint8_t buff[2048]; + CDReadSector(0, buff, 0); + int region; + switch (buff[0x20b]) + { + case 0x64: + region = 8; // EU + printf("Detected CD region EU\n"); + break; + case 0xa1: + region = 1; // JP + printf("Detected CD region JP\n"); + break; + default: + region = 4; // US + printf("Detected CD region US\n"); + break; + } + if (pregion) + *pregion = region; + + return CIT_BIN; } -cue_data_t *cue_parse(const char *fname) +static const char *GetBiosFilename(int *region, const char *cd_fname) { - return NULL; + switch (*region) + { + case 8: // EU + return "cd.eu"; + case 1: // JP + return "cd.jp"; + default: // US? + return "cd.us"; + } } pm_file *pm_open(const char *path) @@ -97,21 +126,21 @@ int mp3_get_bitrate(void *f, int size) { return 0; } void mp3_start_play(void *f, int pos) {} void mp3_update(int *buffer, int length, int stereo) {} -static const uint8_t* TryLoadBios(const char* name) +static const uint8_t *TryLoadBios(const char *name) { FILE *f = fopen(name, "rb"); if (!f) return NULL; fseek(f, 0, SEEK_END); int size = ftell(f); - uint8_t* ret = alloc_sealed(size); + uint8_t *ret = alloc_sealed(size); fseek(f, 0, SEEK_SET); fread(ret, 1, size, f); fclose(f); return ret; } -ECL_EXPORT int Init(void) +ECL_EXPORT int Init(int cd) { p32x_bios_g = TryLoadBios("32x.g"); p32x_bios_m = TryLoadBios("32x.m"); @@ -120,8 +149,16 @@ ECL_EXPORT int Init(void) PicoOpt = POPT_EN_FM | POPT_EN_PSG | POPT_EN_Z80 | POPT_EN_STEREO | POPT_ACC_SPRITES | POPT_DIS_32C_BORDER | POPT_EN_MCD_PCM | POPT_EN_MCD_CDDA | POPT_EN_MCD_GFX | POPT_EN_32X | POPT_EN_PWM; PicoInit(); - if (PicoLoadMedia("romfile.md", NULL, NULL, NULL, PM_MD_CART) != PM_MD_CART) - return 0; + if (cd) + { + if (PicoLoadMedia(NULL, NULL, GetBiosFilename, NULL, PM_CD) != PM_CD) + return 0; + } + else + { + if (PicoLoadMedia("romfile.md", NULL, NULL, NULL, PM_MD_CART) != PM_MD_CART) + return 0; + } PicoLoopPrepare(); video_buffer = alloc_invisible(512 * 512 * sizeof(uint16_t)); @@ -189,6 +226,10 @@ ECL_EXPORT void SetInputCallback(void (*callback)(void)) { PicoInputCallback = callback; } +ECL_EXPORT void SetCDReadCallback(void (*callback)(int lba, void *dest, int audio)) +{ + CDReadSector = callback; +} int main(void) { diff --git a/waterbox/picodrive/pico/carthw/svp/svp.c b/waterbox/picodrive/pico/carthw/svp/svp.c index 811a515d8d..423a771afe 100644 --- a/waterbox/picodrive/pico/carthw/svp/svp.c +++ b/waterbox/picodrive/pico/carthw/svp/svp.c @@ -107,14 +107,6 @@ void PicoSVPInit(void) #endif } -static void PicoSVPExit(void) -{ -#ifdef _SVP_DRC - ssp1601_dyn_exit(); -#endif -} - - void PicoSVPStartup(void) { int ret; diff --git a/waterbox/picodrive/pico/cd/cd_image.c b/waterbox/picodrive/pico/cd/cd_image.c deleted file mode 100644 index 07b55ceb06..0000000000 --- a/waterbox/picodrive/pico/cd/cd_image.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * CD image handler - * (C) notaz, 2007,2013 - * - * This work is licensed under the terms of MAME license. - * See COPYING file in the top-level directory. - */ - -#include "../pico_int.h" -#include "genplus_macros.h" -#include "cdd.h" -#include "cue.h" - -static int handle_mp3(const char *fname, int index) -{ - track_t *track = &cdd.toc.tracks[index]; - FILE *tmp_file; - int kBps; - int fs, ret; - - tmp_file = fopen(fname, "rb"); - if (tmp_file == NULL) - return -1; - - ret = fseek(tmp_file, 0, SEEK_END); - fs = ftell(tmp_file); - fseek(tmp_file, 0, SEEK_SET); - -#ifdef _PSP_FW_VERSION - // some systems (like PSP) can't have many open files at a time, - // so we work with their names instead. - fclose(tmp_file); - tmp_file = (void *) strdup(fname); -#endif - - kBps = mp3_get_bitrate(tmp_file, fs) / 8; - if (ret != 0 || kBps <= 0) - { - elprintf(EL_STATUS, "track %2i: mp3 bitrate %i", index+1, kBps); -#ifdef _PSP_FW_VERSION - free(tmp_file); -#else - fclose(tmp_file); -#endif - return -1; - } - - track->fd = tmp_file; - track->offset = 0; - - fs *= 75; - fs /= kBps * 1000; - return fs; -} - -static void to_upper(char *d, const char *s) -{ - for (; *s != 0; d++, s++) { - if ('a' <= *s && *s <= 'z') - *d = *s - 'a' + 'A'; - else - *d = *s; - } -} - -// cdd.c uses lba - 150 -static void sprintf_lba(char *buf, size_t size, int lba) -{ - lba += 150; - snprintf(buf, size, "%02d:%02d:%02d", lba / 60 / 75, - (lba / 75) % 60, lba % 75); -} - -int load_cd_image(const char *cd_img_name, int *type) -{ - static const char *exts[] = { - "%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3", - "%d.mp3", " %d.mp3", "-%d.mp3", "_%d.mp3", " - %d.mp3", - }; - int i, j, n, lba, index, length, ret; - int iso_name_len, missed, cd_img_sectors; - char tmp_name[256], tmp_ext[10], tmp_ext_u[10]; - track_t *tracks = cdd.toc.tracks; - cue_data_t *cue_data = NULL; - pm_file *pmf; - - if (PicoCDLoadProgressCB != NULL) - PicoCDLoadProgressCB(cd_img_name, 1); - - Pico_mcd->cdda_type = CT_UNKNOWN; - - /* is this a .cue? */ - cue_data = cue_parse(cd_img_name); - if (cue_data != NULL) { - cd_img_name = cue_data->tracks[1].fname; - *type = cue_data->tracks[1].type; - } - - pmf = pm_open(cd_img_name); - if (pmf == NULL) - { - if (cue_data != NULL) - cue_destroy(cue_data); - return -1; - } - tracks[0].fd = pmf; - - if (*type == CT_ISO) - cd_img_sectors = pmf->size >>= 11; // size in sectors - else cd_img_sectors = pmf->size /= 2352; - - // cdd.c operates with lba - 150 - tracks[0].start = 0; - tracks[0].end = cd_img_sectors; - tracks[0].offset = 0; - - sprintf_lba(tmp_ext, sizeof(tmp_ext), 0); - elprintf(EL_STATUS, "Track 1: %s %9i DATA %s", - tmp_ext, tracks[0].end, cd_img_name); - - lba = cd_img_sectors; - - if (cue_data != NULL) - { - if (cue_data->tracks[2].fname == NULL) { - // NULL fname means track2 is in same file as track1 - lba = tracks[0].end = cue_data->tracks[2].sector_offset; - } - i = 100 / cue_data->track_count + 1; // progress display - - for (n = 2; n <= cue_data->track_count; n++) - { - if (PicoCDLoadProgressCB != NULL) - PicoCDLoadProgressCB(cd_img_name, i * n); - - index = n - 1; - lba += cue_data->tracks[n].pregap; - if (cue_data->tracks[n].type == CT_MP3) { - ret = handle_mp3(cue_data->tracks[n].fname, index); - if (ret < 0) - break; - length = ret; - } - else if (cue_data->tracks[n].fname != NULL) - { - pm_file *f = pm_open(cue_data->tracks[n].fname); - if (f != NULL) - { - // assume raw, ignore header for wav.. - tracks[index].fd = f; - tracks[index].offset = cue_data->tracks[n].sector_offset; - length = f->size / 2352; - } - else - { - elprintf(EL_STATUS, "track %2i (%s): can't determine length", - n, cue_data->tracks[n].fname); - tracks[index].offset = 0; - length = 2*75; - } - } - else - { - if (n < cue_data->track_count) - length = cue_data->tracks[n+1].sector_offset - - cue_data->tracks[n].sector_offset; - else - length = cd_img_sectors - cue_data->tracks[n].sector_offset; - tracks[index].offset = cue_data->tracks[n].sector_offset; - } - - if (cue_data->tracks[n].sector_xlength != 0) - // overriden by custom cue command - length = cue_data->tracks[n].sector_xlength; - - Pico_mcd->cdda_type = cue_data->tracks[n].type; - - tracks[index].start = lba; - lba += length; - tracks[index].end = lba; - - sprintf_lba(tmp_ext, sizeof(tmp_ext), tracks[index].start); - elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO %s", - n, tmp_ext, length, cue_data->tracks[n].fname); - } - goto finish; - } - - /* mp3 track autosearch, Gens-like */ - iso_name_len = strlen(cd_img_name); - if (iso_name_len >= sizeof(tmp_name)) - iso_name_len = sizeof(tmp_name) - 1; - - for (n = 2, i = 0, missed = 0; i < 100 && missed < 4; i++) - { - if (PicoCDLoadProgressCB != NULL && i > 1) - PicoCDLoadProgressCB(cd_img_name, i + (100-i)*missed/4); - - for (j = 0; j < sizeof(exts)/sizeof(char *); j++) - { - int ext_len; - char *p; - - index = n - 1; - - snprintf(tmp_ext, sizeof(tmp_ext), exts[j], i); - ext_len = strlen(tmp_ext); - to_upper(tmp_ext_u, tmp_ext); - - memcpy(tmp_name, cd_img_name, iso_name_len + 1); - p = tmp_name + iso_name_len - 4; - - strcpy(p, tmp_ext); - ret = handle_mp3(tmp_name, index); - if (ret <= 0) { - strcpy(p, tmp_ext_u); - ret = handle_mp3(tmp_name, index); - } - - if (ret <= 0 && i > 1 && iso_name_len > ext_len) { - p = tmp_name + iso_name_len - ext_len; - strcpy(p, tmp_ext); - ret = handle_mp3(tmp_name, index); - if (ret <= 0) { - strcpy(p, tmp_ext_u); - ret = handle_mp3(tmp_name, index); - } - } - - if (ret > 0) - { - length = ret; - tracks[index].start = lba; - lba += length; - tracks[index].end = lba; - - Pico_mcd->cdda_type = CT_MP3; - - sprintf_lba(tmp_ext, sizeof(tmp_ext), tracks[index].start); - elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO - %s", - n, tmp_ext, length, tmp_name); - - n++; - missed = 0; - break; - } - } - if (ret <= 0 && i > 1) - missed++; - } - -finish: - cdd.toc.last = n - 1; - cdd.toc.end = lba; - - sprintf_lba(tmp_ext, sizeof(tmp_ext), cdd.toc.end); - elprintf(EL_STATUS, "End CD - %s\n", tmp_ext); - - if (PicoCDLoadProgressCB != NULL) - PicoCDLoadProgressCB(cd_img_name, 100); - - if (cue_data != NULL) - cue_destroy(cue_data); - - return 0; -} - -// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdc.c b/waterbox/picodrive/pico/cd/cdc.c index bf688f5792..75d979b8dc 100644 --- a/waterbox/picodrive/pico/cd/cdc.c +++ b/waterbox/picodrive/pico/cd/cdc.c @@ -130,120 +130,6 @@ void cdc_reset(void) cdc.dma_w = 0; } -int cdc_context_save(uint8 *state) -{ - uint8 tmp8; - int bufferptr = 0; - - if (cdc.dma_w == pcm_ram_dma_w) - { - tmp8 = 1; - } - else if (cdc.dma_w == prg_ram_dma_w) - { - tmp8 = 2; - } - else if (cdc.dma_w == word_ram_0_dma_w) - { - tmp8 = 3; - } - else if (cdc.dma_w == word_ram_1_dma_w) - { - tmp8 = 4; - } - else if (cdc.dma_w == word_ram_2M_dma_w) - { - tmp8 = 5; - } - else - { - tmp8 = 0; - } - - save_param(&cdc, sizeof(cdc)); - save_param(&tmp8, 1); - - return bufferptr; -} - -int cdc_context_load(uint8 *state) -{ - uint8 tmp8; - int bufferptr = 0; - - load_param(&cdc, sizeof(cdc)); - load_param(&tmp8, 1); - - switch (tmp8) - { - case 1: - cdc.dma_w = pcm_ram_dma_w; - break; - case 2: - cdc.dma_w = prg_ram_dma_w; - break; - case 3: - cdc.dma_w = word_ram_0_dma_w; - break; - case 4: - cdc.dma_w = word_ram_1_dma_w; - break; - case 5: - cdc.dma_w = word_ram_2M_dma_w; - break; - default: - cdc.dma_w = 0; - break; - } - - return bufferptr; -} - -int cdc_context_load_old(uint8 *state) -{ -#define old_load(v, ofs) \ - memcpy(&cdc.v, state + ofs, sizeof(cdc.v)) - - memcpy(cdc.ram, state, 0x4000); - old_load(ifstat, 67892); - old_load(ifctrl, 67924); - old_load(dbc, 67896); - old_load(dac, 67900); - old_load(pt, 67908); - old_load(wa, 67912); - old_load(ctrl, 67928); - old_load(head[0], 67904); - old_load(stat, 67916); - - cdc.dma_w = 0; - switch (Pico_mcd->s68k_regs[0x04+0] & 0x07) - { - case 4: /* PCM RAM DMA */ - cdc.dma_w = pcm_ram_dma_w; - break; - case 5: /* PRG-RAM DMA */ - cdc.dma_w = prg_ram_dma_w; - break; - case 7: /* WORD-RAM DMA */ - if (Pico_mcd->s68k_regs[0x02+1] & 0x04) - { - if (Pico_mcd->s68k_regs[0x02+1] & 0x01) - cdc.dma_w = word_ram_0_dma_w; - else - cdc.dma_w = word_ram_1_dma_w; - } - else - { - if (Pico_mcd->s68k_regs[0x02+1] & 0x02) - cdc.dma_w = word_ram_2M_dma_w; - } - break; - } - - return 0x10960; // sizeof(old_cdc) -#undef old_load -} - static void do_dma(enum dma_type type, int words_in) { int dma_addr = (Pico_mcd->s68k_regs[0x0a] << 8) | Pico_mcd->s68k_regs[0x0b]; @@ -842,5 +728,3 @@ unsigned short cdc_host_r(void) #endif return 0xffff; } - -// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdd.c b/waterbox/picodrive/pico/cd/cdd.c index e0e1ec1c6e..c0c2c86960 100644 --- a/waterbox/picodrive/pico/cd/cdd.c +++ b/waterbox/picodrive/pico/cd/cdd.c @@ -38,413 +38,164 @@ #include "../pico_int.h" #include "genplus_macros.h" -#include "cue.h" #include "cdd.h" -#ifdef USE_LIBTREMOR -#define SUPPORTED_EXT 20 -#else -#define SUPPORTED_EXT 10 -#endif - cdd_t cdd; +void (*CDReadSector)(int lba, void *dest, int audio); + /* BCD conversion lookup tables */ static const uint8 lut_BCD_8[100] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, }; static const uint16 lut_BCD_16[100] = -{ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, - 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, - 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609, - 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, - 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, - 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, + { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, + 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609, + 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, + 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, }; /* pre-build TOC */ static const uint16 toc_snatcher[21] = -{ - 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, - 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, - 31380 -}; + { + 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, + 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, + 31380}; static const uint16 toc_lunar[52] = -{ - 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, - 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, - 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, - 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, - 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, - 685, 3167 -}; + { + 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, + 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, + 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, + 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, + 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, + 685, 3167}; static const uint32 toc_shadow[15] = -{ - 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, - 11637, 2547, 2521, 3856, 900 -}; + { + 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, + 11637, 2547, 2521, 3856, 900}; static const uint32 toc_dungeon[13] = -{ - 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, - 3325, 6825, 25275 -}; + { + 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, + 3325, 6825, 25275}; static const uint32 toc_ffight[26] = -{ - 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, - 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, - 14562, 10320, 8627, 3795, 3047 -}; + { + 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, + 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, + 14562, 10320, 8627, 3795, 3047}; static const uint32 toc_ffightj[29] = -{ - 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, - 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, - 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 -}; - -/* supported WAVE file header (16-bit stereo samples @44.1kHz) */ -static const unsigned char waveHeader[32] = -{ - 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00, - 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61 -}; - -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES -static void ogg_free(int i) -{ - /* clear OGG file descriptor to prevent file from being closed */ - cdd.toc.tracks[i].vf.datasource = NULL; - - /* close VORBIS file structure */ - ov_clear(&cdd.toc.tracks[i].vf); - - /* indicates that the track is a seekable VORBIS file */ - cdd.toc.tracks[i].vf.seekable = 1; - - /* reset file reading position */ - fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET); -} -#endif -#endif + { + 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, + 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, + 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052}; void cdd_reset(void) { - /* reset cycle counter */ - cdd.cycles = 0; - - /* reset drive access latency */ - cdd.latency = 0; - - /* reset track index */ - cdd.index = 0; - - /* reset logical block address */ - cdd.lba = 0; + /* reset cycle counter */ + cdd.cycles = 0; - /* reset status */ - cdd.status = NO_DISC; + /* reset drive access latency */ + cdd.latency = 0; - /* reset CD-DA fader (full volume) */ - cdd.volume = 0x400; + /* reset track index */ + cdd.index = 0; - /* clear CD-DA output */ - cdd.audio[0] = cdd.audio[1] = 0; + /* reset logical block address */ + cdd.lba = 0; + + /* reset status */ + cdd.status = NO_DISC; + + /* reset CD-DA fader (full volume) */ + cdd.volume = 0x400; + + /* clear CD-DA output */ + cdd.audio[0] = cdd.audio[1] = 0; } /* FIXME: use cdd_read_audio() instead */ static void cdd_change_track(int index, int lba) { - int i, base, lba_offset, lb_len; + /*int i, base, lba_offset, lb_len; - for (i = index; i > 0; i--) - if (cdd.toc.tracks[i].fd != NULL) - break; + for (i = index; i > 0; i--) + if (cdd.toc.tracks[i].fd != NULL) + break; - Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd; - base = cdd.toc.tracks[index].offset; - lba_offset = lba - cdd.toc.tracks[index].start; - lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start; + Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd; + base = cdd.toc.tracks[index].offset; + lba_offset = lba - cdd.toc.tracks[index].start; + lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start; - elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base); + elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base); - cdda_start_play(base, lba_offset, lb_len); -} - -int cdd_context_save(uint8 *state) -{ - int bufferptr = 0; - - save_param(&cdd.cycles, sizeof(cdd.cycles)); - save_param(&cdd.latency, sizeof(cdd.latency)); - save_param(&cdd.index, sizeof(cdd.index)); - save_param(&cdd.lba, sizeof(cdd.lba)); - save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - save_param(&cdd.volume, sizeof(cdd.volume)); - save_param(&cdd.status, sizeof(cdd.status)); - - return bufferptr; -} - -int cdd_context_load(uint8 *state) -{ - int lba; - int bufferptr = 0; - -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif - - load_param(&cdd.cycles, sizeof(cdd.cycles)); - load_param(&cdd.latency, sizeof(cdd.latency)); - load_param(&cdd.index, sizeof(cdd.index)); - load_param(&cdd.lba, sizeof(cdd.lba)); - load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - load_param(&cdd.volume, sizeof(cdd.volume)); - load_param(&cdd.status, sizeof(cdd.status)); - - /* adjust current LBA within track limit */ - lba = cdd.lba; - if (lba < cdd.toc.tracks[cdd.index].start) - { - lba = cdd.toc.tracks[cdd.index].start; - } - - /* seek to current track position */ - if (!cdd.index) - { - /* DATA track */ - if (cdd.toc.tracks[0].fd) - { - pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); - } - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[cdd.index].vf.seekable) - { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); -#endif - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); - } -#endif -#if 0 - else if (cdd.toc.tracks[cdd.index].fd) - { - /* PCM AUDIO track */ - fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); - } -#else - else - { - cdd_change_track(cdd.index, lba); - } -#endif - - return bufferptr; -} - -int cdd_context_load_old(uint8 *state) -{ - memcpy(&cdd.lba, state + 8, sizeof(cdd.lba)); - return 12 * 4; + cdda_start_play(base, lba_offset, lb_len);*/ } int cdd_load(const char *filename, int type) { - char header[0x210]; - int ret; + FILE *f = fopen("toc", "rb"); + fread(&cdd.toc, 1, sizeof(cdd.toc), f); + fclose(f); - /* genplus parses cue here, in PD we use our own parser */ - ret = load_cd_image(filename, &type); - if (ret != 0) - return ret; + char sector[2048]; - /* read first 16 bytes */ - pm_read(header, 0x10, cdd.toc.tracks[0].fd); + CDReadSector(0, sector, 0); - /* look for valid CD image ID string */ - if (memcmp("SEGADISCSYSTEM", header, 14)) - { - /* if not found, read next 16 bytes */ - pm_read(header, 0x10, cdd.toc.tracks[0].fd); + /* look for valid CD image ID string */ + if (memcmp("SEGADISCSYSTEM", sector, 14)) + { + /* if not found, read next 16 bytes */ - /* look again for valid CD image ID string */ - if (memcmp("SEGADISCSYSTEM", header, 14)) - { - elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?"); - /* assume bin without security code */ - } + /* look again for valid CD image ID string */ + if (memcmp("SEGADISCSYSTEM", sector + 16, 14)) + { + elprintf(EL_STATUS | EL_ANOMALY, "cd: bad cd image?"); + /* assume bin without security code */ + } + } - /* BIN format (2352 bytes data blocks) */ - cdd.sectorSize = 2352; - } - else - { - /* ISO format (2048 bytes data blocks) */ - cdd.sectorSize = 2048; - } + /* Lead-out */ + // cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - ret = (type == CT_BIN) ? 2352 : 2048; - if (ret != cdd.sectorSize) - elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch"); + /* CD loaded */ + cdd.loaded = 1; - /* read CD image header + security code */ - pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd); + /* disc not scanned yet */ + cdd.status = NO_DISC; - /* Simulate audio tracks if none found */ - if (cdd.toc.last == 1) - { - /* Some games require exact TOC infos */ - if (strstr(header + 0x180,"T-95035") != NULL) - { - /* Snatcher */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 21); - } - else if (strstr(header + 0x180,"T-127015") != NULL) - { - /* Lunar - The Silver Star */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 52); - } - else if (strstr(header + 0x180,"T-113045") != NULL) - { - /* Shadow of the Beast II */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 15); - } - else if (strstr(header + 0x180,"T-143025") != NULL) - { - /* Dungeon Explorer */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 13); - } - else if (strstr(header + 0x180,"MK-4410") != NULL) - { - /* Final Fight CD (USA, Europe) */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 26); - } - else if (strstr(header + 0x180,"G-6013") != NULL) - { - /* Final Fight CD (Japan) */ - cdd.toc.last = cdd.toc.end = 0; - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last]; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while (cdd.toc.last < 29); - } -#if 0 - else - { - /* default TOC (99 tracks & 2s per audio tracks) */ - do - { - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75; - cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75; - cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; - cdd.toc.last++; - } - while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75)); - } -#endif - } - - /* Lead-out */ - cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; - - /* CD loaded */ - cdd.loaded = 1; - - /* disc not scanned yet */ - cdd.status = NO_DISC; - - return 0; + return 0; } void cdd_read_data(uint8 *dst) { - /* only read DATA track sectors */ - if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) - { - /* BIN format ? */ - if (cdd.sectorSize == 2352) - { - /* skip 16-byte header */ - pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET); - } - - /* read sector data (Mode 1 = 2048 bytes) */ - pm_read(dst, 2048, cdd.toc.tracks[0].fd); - } + /* only read DATA track sectors */ + if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) + { + CDReadSector(cdd.lba, dst, 0); + } } #if 0 @@ -542,24 +293,24 @@ void cdd_read_audio(unsigned int samples) mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03); /* left channel */ - #ifdef LSB_FIRST +#ifdef LSB_FIRST delta = ((ptr[0] * mul) / 1024) - l; ptr++; - #else +#else delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l; ptr += 2; - #endif +#endif l += delta; blip_add_delta_fast(blip[0], i, delta); /* right channel */ - #ifdef LSB_FIRST +#ifdef LSB_FIRST delta = ((ptr[0] * mul) / 1024) - r; ptr++; - #else +#else delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r; ptr += 2; - #endif +#endif r += delta; blip_add_delta_fast(blip[1], i, delta); @@ -606,209 +357,153 @@ void cdd_read_audio(unsigned int samples) } #endif - void cdd_update(void) -{ +{ #ifdef LOG_CDD - error("LBA = %d (track n�%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency); + error("LBA = %d (track n�%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency); #endif - - /* seeking disc */ - if (cdd.status == CD_SEEK) - { - /* drive latency */ - if (cdd.latency > 0) - { - cdd.latency--; - return; - } - /* drive is ready */ - cdd.status = CD_READY; - } + /* seeking disc */ + if (cdd.status == CD_SEEK) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } - /* reading disc */ - else if (cdd.status == CD_PLAY) - { - /* drive latency */ - if (cdd.latency > 0) - { - cdd.latency--; - return; - } + /* drive is ready */ + cdd.status = CD_READY; + } - /* track type */ - if (!cdd.index) - { - /* DATA sector header (CD-ROM Mode 1) */ - uint8 header[4]; - uint32 msf = cdd.lba + 150; - header[0] = lut_BCD_8[(msf / 75) / 60]; - header[1] = lut_BCD_8[(msf / 75) % 60]; - header[2] = lut_BCD_8[(msf % 75)]; - header[3] = 0x01; + /* reading disc */ + else if (cdd.status == CD_PLAY) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } - /* data track sector read is controlled by CDC */ - cdd.lba += cdc_decoder_update(header); - } - else if (cdd.index < cdd.toc.last) - { - uint8 header[4] = { 0, }; + /* track type */ + if (!cdd.index) + { + /* DATA sector header (CD-ROM Mode 1) */ + uint8 header[4]; + uint32 msf = cdd.lba + 150; + header[0] = lut_BCD_8[(msf / 75) / 60]; + header[1] = lut_BCD_8[(msf / 75) % 60]; + header[2] = lut_BCD_8[(msf % 75)]; + header[3] = 0x01; - /* check against audio track start index */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].start) - { - /* audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x00; - } + /* data track sector read is controlled by CDC */ + cdd.lba += cdc_decoder_update(header); + } + else if (cdd.index < cdd.toc.last) + { + uint8 header[4] = { + 0, + }; - /* audio blocks are still sent to CDC as well as CD DAC/Fader */ - cdc_decoder_update(header); - - /* next audio block is automatically read */ - cdd.lba++; - } - else - { - /* end of disc */ - cdd.status = CD_END; - return; - } + /* check against audio track start index */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].start) + { + /* audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x00; + } - /* check end of current track */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].end) - { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif - /* play next track */ - cdd.index++; + /* audio blocks are still sent to CDC as well as CD DAC/Fader */ + cdc_decoder_update(header); - /* PAUSE between tracks */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* next audio block is automatically read */ + cdd.lba++; + } + else + { + /* end of disc */ + cdd.status = CD_END; + return; + } - /* seek to next audio track start */ -#ifdef USE_LIBTREMOR - if (cdd.toc.tracks[cdd.index].vf.seekable) - { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); -#endif - ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset); - } - else -#endif + /* check end of current track */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { + /* play next track */ + cdd.index++; + + /* PAUSE between tracks */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; + +/* seek to next audio track start */ #if 0 if (cdd.toc.tracks[cdd.index].fd) { fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); } #else - { - cdd_change_track(cdd.index, cdd.lba); - } + { + cdd_change_track(cdd.index, cdd.lba); + } #endif - } - } + } + } - /* scanning disc */ - else if (cdd.status == CD_SCAN) - { - /* fast-forward or fast-rewind */ - cdd.lba += cdd.scanOffset; + /* scanning disc */ + else if (cdd.status == CD_SCAN) + { + /* fast-forward or fast-rewind */ + cdd.lba += cdd.scanOffset; - /* check current track limits */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].end) - { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif - /* next track */ - cdd.index++; + /* check current track limits */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { + /* next track */ + cdd.index++; - /* skip directly to track start position */ - cdd.lba = cdd.toc.tracks[cdd.index].start; - - /* AUDIO track playing ? */ - if (cdd.status == CD_PLAY) - { - Pico_mcd->s68k_regs[0x36+0] = 0x00; - } - } - else if (cdd.lba < cdd.toc.tracks[cdd.index].start) - { -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } -#endif -#endif + /* skip directly to track start position */ + cdd.lba = cdd.toc.tracks[cdd.index].start; - /* previous track */ - cdd.index--; + /* AUDIO track playing ? */ + if (cdd.status == CD_PLAY) + { + Pico_mcd->s68k_regs[0x36 + 0] = 0x00; + } + } + else if (cdd.lba < cdd.toc.tracks[cdd.index].start) + { + /* previous track */ + cdd.index--; - /* skip directly to track end position */ - cdd.lba = cdd.toc.tracks[cdd.index].end; - } + /* skip directly to track end position */ + cdd.lba = cdd.toc.tracks[cdd.index].end; + } - /* check disc limits */ - if (cdd.index < 0) - { - cdd.index = 0; - cdd.lba = 0; - } - else if (cdd.index >= cdd.toc.last) - { - /* no AUDIO track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* check disc limits */ + if (cdd.index < 0) + { + cdd.index = 0; + cdd.lba = 0; + } + else if (cdd.index >= cdd.toc.last) + { + /* no AUDIO track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* end of disc */ - cdd.index = cdd.toc.last; - cdd.lba = cdd.toc.end; - cdd.status = CD_END; - return; - } + /* end of disc */ + cdd.index = cdd.toc.last; + cdd.lba = cdd.toc.end; + cdd.status = CD_END; + return; + } - /* seek to current block */ - if (!cdd.index) - { - /* no AUDIO track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; - - /* DATA track */ - pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET); - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[cdd.index].vf.seekable) - { -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if a new track is being played */ - if (!cdd.toc.tracks[cdd.index].vf.datasource) - { - /* VORBIS file need to be opened first */ - ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); - } -#endif - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); - } -#endif + /* seek to current block */ + if (!cdd.index) + { + /* no AUDIO track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; + } #if 0 else if (cdd.toc.tracks[cdd.index].fd) { @@ -816,234 +511,209 @@ void cdd_update(void) fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); } #else - else - { - cdd_change_track(cdd.index, cdd.lba); - } + else + { + cdd_change_track(cdd.index, cdd.lba); + } #endif - } + } } -#define set_reg16(r, v) { \ - uint16 _v = v; \ - Pico_mcd->s68k_regs[(r)] = _v >> 8; \ - Pico_mcd->s68k_regs[(r)+1] = _v; \ -} +#define set_reg16(r, v) \ + { \ + uint16 _v = v; \ + Pico_mcd->s68k_regs[(r)] = _v >> 8; \ + Pico_mcd->s68k_regs[(r) + 1] = _v; \ + } void cdd_process(void) { - /* Process CDD command */ - switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f) - { - case 0x00: /* Drive Status */ - { - /* RS1-RS8 normally unchanged */ - Pico_mcd->s68k_regs[0x38+0] = cdd.status; + /* Process CDD command */ + switch (Pico_mcd->s68k_regs[0x42 + 0] & 0x0f) + { + case 0x00: /* Drive Status */ + { + /* RS1-RS8 normally unchanged */ + Pico_mcd->s68k_regs[0x38 + 0] = cdd.status; - /* unless RS1 indicated invalid track infos */ - if (Pico_mcd->s68k_regs[0x38+1] == 0x0f) - { - /* and SEEK has ended */ - if (cdd.status != CD_SEEK) - { - /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ - Pico_mcd->s68k_regs[0x38+1] = 0x02; - set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); - } - } - break; - } + /* unless RS1 indicated invalid track infos */ + if (Pico_mcd->s68k_regs[0x38 + 1] == 0x0f) + { + /* and SEEK has ended */ + if (cdd.status != CD_SEEK) + { + /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ + Pico_mcd->s68k_regs[0x38 + 1] = 0x02; + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); + } + } + break; + } - case 0x01: /* Stop Drive */ - { - /* update status */ - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + case 0x01: /* Stop Drive */ + { + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ - set_reg16(0x38, 0x0000); - set_reg16(0x3a, 0x0000); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); - set_reg16(0x40, 0x000f); - return; - } + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + set_reg16(0x38, 0x0000); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, 0x000f); + return; + } - case 0x02: /* Read TOC */ - { - if (cdd.status == NO_DISC) - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + case 0x02: /* Read TOC */ + { + if (cdd.status == NO_DISC) + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - /* Infos automatically retrieved by CDD processor from Q-Channel */ - /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ - switch (Pico_mcd->s68k_regs[0x44+1]) - { - case 0x00: /* Current Absolute Time (MM:SS:FF) */ - { - int lba = cdd.lba + 150; - set_reg16(0x38, cdd.status << 8); - set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); - set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); - set_reg16(0x3e, lut_BCD_16[(lba%75)]); - 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) */ - break; - } + /* Infos automatically retrieved by CDD processor from Q-Channel */ + /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ + switch (Pico_mcd->s68k_regs[0x44 + 1]) + { + case 0x00: /* Current Absolute Time (MM:SS:FF) */ + { + int lba = cdd.lba + 150; + set_reg16(0x38, cdd.status << 8); + set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]); + set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]); + set_reg16(0x3e, lut_BCD_16[(lba % 75)]); + 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) */ + break; + } - case 0x01: /* Current Track Relative Time (MM:SS:FF) */ - { - int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; - set_reg16(0x38, (cdd.status << 8) | 0x01); - set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); - set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); - set_reg16(0x3e, lut_BCD_16[(lba%75)]); - 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) */ - break; - } + case 0x01: /* Current Track Relative Time (MM:SS:FF) */ + { + int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; + set_reg16(0x38, (cdd.status << 8) | 0x01); + set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]); + set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]); + set_reg16(0x3e, lut_BCD_16[(lba % 75)]); + 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) */ + break; + } - case 0x02: /* Current Track Number */ - { - set_reg16(0x38, (cdd.status << 8) | 0x02); - set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */ - Pico_mcd->s68k_regs[0x40+0] = 0x00; - break; - } + case 0x02: /* Current Track Number */ + { + set_reg16(0x38, (cdd.status << 8) | 0x02); + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */ + Pico_mcd->s68k_regs[0x40 + 0] = 0x00; + break; + } - case 0x03: /* Total length (MM:SS:FF) */ - { - int lba = cdd.toc.end + 150; - set_reg16(0x38, (cdd.status << 8) | 0x03); - set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); - set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); - set_reg16(0x3e, lut_BCD_16[(lba%75)]); - Pico_mcd->s68k_regs[0x40+0] = 0x00; - break; - } + case 0x03: /* Total length (MM:SS:FF) */ + { + int lba = cdd.toc.end + 150; + set_reg16(0x38, (cdd.status << 8) | 0x03); + set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]); + set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]); + set_reg16(0x3e, lut_BCD_16[(lba % 75)]); + Pico_mcd->s68k_regs[0x40 + 0] = 0x00; + break; + } - case 0x04: /* First & Last Track Numbers */ - { - set_reg16(0x38, (cdd.status << 8) | 0x04); - set_reg16(0x3a, 0x0001); - set_reg16(0x3c, lut_BCD_16[cdd.toc.last]); - set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */ - Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ - break; - } + case 0x04: /* First & Last Track Numbers */ + { + set_reg16(0x38, (cdd.status << 8) | 0x04); + set_reg16(0x3a, 0x0001); + set_reg16(0x3c, lut_BCD_16[cdd.toc.last]); + set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */ + Pico_mcd->s68k_regs[0x40 + 0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } - case 0x05: /* Track Start Time (MM:SS:FF) */ - { - int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1]; - int lba = cdd.toc.tracks[track-1].start + 150; - set_reg16(0x38, (cdd.status << 8) | 0x05); - set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); - set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); - set_reg16(0x3e, lut_BCD_16[(lba%75)]); - Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */ - if (track == 1) - { - /* RS6 bit 3 is set for the first (DATA) track */ - Pico_mcd->s68k_regs[0x3e + 0] |= 0x08; - } - break; - } + case 0x05: /* Track Start Time (MM:SS:FF) */ + { + int track = Pico_mcd->s68k_regs[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1]; + int lba = cdd.toc.tracks[track - 1].start + 150; + set_reg16(0x38, (cdd.status << 8) | 0x05); + set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]); + set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]); + set_reg16(0x3e, lut_BCD_16[(lba % 75)]); + Pico_mcd->s68k_regs[0x40 + 0] = track % 10; /* Track Number (low digit) */ + if (track == 1) + { + /* RS6 bit 3 is set for the first (DATA) track */ + Pico_mcd->s68k_regs[0x3e + 0] |= 0x08; + } + break; + } - default: - { + default: + { #ifdef LOG_ERROR - error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc); + error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44 + 1], s68k.pc); #endif - return; - } - } - break; - } + return; + } + } + break; + } - case 0x03: /* Play */ - { - /* reset track index */ - int index = 0; + case 0x03: /* Play */ + { + /* reset track index */ + int index = 0; - /* new LBA position */ - int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + - (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + - (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + /* new LBA position */ + int lba = ((Pico_mcd->s68k_regs[0x44 + 0] * 10 + Pico_mcd->s68k_regs[0x44 + 1]) * 60 + + (Pico_mcd->s68k_regs[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1])) * + 75 + + (Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150; - /* CD drive latency */ - if (!cdd.latency) - { - /* Fixes a few games hanging during intro because they expect data to be read with some delay */ - /* Radical Rex needs at least one interrupt delay */ - /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ - /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */ - /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */ - cdd.latency = 10; - } + /* CD drive latency */ + if (!cdd.latency) + { + /* Fixes a few games hanging during intro because they expect data to be read with some delay */ + /* Radical Rex needs at least one interrupt delay */ + /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ + /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */ + /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */ + cdd.latency = 10; + } - /* CD drive seek time */ - /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */ - /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */ - /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */ - /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */ - if (lba > cdd.lba) - { - cdd.latency += (((lba - cdd.lba) * 120) / 270000); - } - else - { - cdd.latency += (((cdd.lba - lba) * 120) / 270000); - } + /* CD drive seek time */ + /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */ + /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */ + /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */ + /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */ + if (lba > cdd.lba) + { + cdd.latency += (((lba - cdd.lba) * 120) / 270000); + } + else + { + cdd.latency += (((cdd.lba - lba) * 120) / 270000); + } - /* update current LBA */ - cdd.lba = lba; + /* update current LBA */ + cdd.lba = lba; - /* get track index */ - while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + /* get track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) + index++; -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if track index has changed */ - if (index != cdd.index) - { - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } + /* update current track index */ + cdd.index = index; - /* open current track VORBIS file */ - if (cdd.toc.tracks[index].vf.seekable) - { - ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); - } - } -#endif -#endif + /* stay within track limits when seeking files */ + if (lba < cdd.toc.tracks[index].start) + { + lba = cdd.toc.tracks[index].start; + } - /* update current track index */ - cdd.index = index; - - /* stay within track limits when seeking files */ - if (lba < cdd.toc.tracks[index].start) - { - lba = cdd.toc.tracks[index].start; - } - - /* seek to current block */ - if (!index) - { - /* DATA track */ - pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[index].vf.seekable) - { - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); - } -#endif + /* seek to current block */ + if (!index) + { + /* DATA track */ + } #if 0 else if (cdd.toc.tracks[index].fd) { @@ -1051,98 +721,72 @@ void cdd_process(void) fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET); } #else - else - { - cdd_change_track(index, lba); - } + else + { + cdd_change_track(index, lba); + } #endif - /* no audio track playing (yet) */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* no audio track playing (yet) */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* update status */ - cdd.status = CD_PLAY; + /* update status */ + cdd.status = CD_PLAY; - /* return track index in RS2-RS3 */ - set_reg16(0x38, (CD_PLAY << 8) | 0x02); - set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); - Pico_mcd->s68k_regs[0x40+0] = 0x00; - break; - } + /* return track index in RS2-RS3 */ + set_reg16(0x38, (CD_PLAY << 8) | 0x02); + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + Pico_mcd->s68k_regs[0x40 + 0] = 0x00; + break; + } - case 0x04: /* Seek */ - { - /* reset track index */ - int index = 0; + case 0x04: /* Seek */ + { + /* reset track index */ + int index = 0; - /* new LBA position */ - int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + - (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + - (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + /* new LBA position */ + int lba = ((Pico_mcd->s68k_regs[0x44 + 0] * 10 + Pico_mcd->s68k_regs[0x44 + 1]) * 60 + + (Pico_mcd->s68k_regs[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1])) * + 75 + + (Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150; - /* CD drive seek time */ - /* We are using similar linear model as above, although still not exactly accurate, */ - /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ - /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */ - if (lba > cdd.lba) - { - cdd.latency = ((lba - cdd.lba) * 120) / 270000; - } - else - { - cdd.latency = ((cdd.lba - lba) * 120) / 270000; - } + /* CD drive seek time */ + /* We are using similar linear model as above, although still not exactly accurate, */ + /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ + /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */ + if (lba > cdd.lba) + { + cdd.latency = ((lba - cdd.lba) * 120) / 270000; + } + else + { + cdd.latency = ((cdd.lba - lba) * 120) / 270000; + } - /* update current LBA */ - cdd.lba = lba; + /* update current LBA */ + cdd.lba = lba; - /* get current track index */ - while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + /* get current track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) + index++; -#ifdef USE_LIBTREMOR -#ifdef DISABLE_MANY_OGG_OPEN_FILES - /* check if track index has changed */ - if (index != cdd.index) - { - /* close previous track VORBIS file structure to save memory */ - if (cdd.toc.tracks[cdd.index].vf.datasource) - { - ogg_free(cdd.index); - } + /* update current track index */ + cdd.index = index; - /* open current track VORBIS file */ - if (cdd.toc.tracks[index].vf.seekable) - { - ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); - } - } -#endif -#endif + /* stay within track limits */ + if (lba < cdd.toc.tracks[index].start) + { + lba = cdd.toc.tracks[index].start; + } - /* update current track index */ - cdd.index = index; - - /* stay within track limits */ - if (lba < cdd.toc.tracks[index].start) - { - lba = cdd.toc.tracks[index].start; - } - - /* seek to current block */ - if (!index) - { - /* DATA track */ - pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); - } -#ifdef USE_LIBTREMOR - else if (cdd.toc.tracks[index].vf.seekable) - { - /* VORBIS AUDIO track */ - ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); - } -#endif + /* seek to current block */ + if (!index) + { + /* DATA track */ + } #if 0 else if (cdd.toc.tracks[index].fd) { @@ -1151,128 +795,126 @@ void cdd_process(void) } #endif - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* update status */ - cdd.status = CD_SEEK; + /* update status */ + cdd.status = CD_SEEK; - /* 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) */ - set_reg16(0x38, (CD_SEEK << 8) | 0x0f); - set_reg16(0x3a, 0x0000); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); - set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f); - return; - } + /* 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) */ + set_reg16(0x38, (CD_SEEK << 8) | 0x0f); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f); + return; + } - case 0x06: /* Pause */ - { - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + case 0x06: /* Pause */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* update status (RS1-RS8 unchanged) */ - cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; - break; - } + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_READY; + break; + } - case 0x07: /* Resume */ - { - /* update status (RS1-RS8 unchanged) */ - cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY; - break; - } + case 0x07: /* Resume */ + { + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_PLAY; + break; + } - case 0x08: /* Forward Scan */ - { - /* reset scanning direction / speed */ - cdd.scanOffset = CD_SCAN_SPEED; + case 0x08: /* Forward Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = CD_SCAN_SPEED; - /* update status (RS1-RS8 unchanged) */ - cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; - break; - } + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_SCAN; + break; + } - case 0x09: /* Rewind Scan */ - { - /* reset scanning direction / speed */ - cdd.scanOffset = -CD_SCAN_SPEED; + case 0x09: /* Rewind Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = -CD_SCAN_SPEED; - /* update status (RS1-RS8 unchanged) */ - cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; - break; - } + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_SCAN; + break; + } + case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ + { + /* TC3 corresponds to seek direction (00=forward, FF=reverse) */ + /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */ + /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */ + /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ - case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ - { - /* TC3 corresponds to seek direction (00=forward, FF=reverse) */ - /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */ - /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */ - /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_READY; + break; + } - /* update status (RS1-RS8 unchanged) */ - cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; - break; - } + case 0x0c: /* Close Tray */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - case 0x0c: /* Close Tray */ - { - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - /* update status */ - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + set_reg16(0x38, 0x0000); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, 0x000f); - /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ - set_reg16(0x38, 0x0000); - set_reg16(0x3a, 0x0000); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); - set_reg16(0x40, 0x000f); + if (PicoMCDcloseTray) + PicoMCDcloseTray(); - if (PicoMCDcloseTray) - PicoMCDcloseTray(); + return; + } - return; - } + case 0x0d: /* Open Tray */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36 + 0] = 0x01; - case 0x0d: /* Open Tray */ - { - /* no audio track playing */ - Pico_mcd->s68k_regs[0x36+0] = 0x01; + /* update status (RS1-RS8 ignored) */ + cdd.status = CD_OPEN; + set_reg16(0x38, CD_OPEN << 8); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, ~CD_OPEN & 0x0f); - /* update status (RS1-RS8 ignored) */ - cdd.status = CD_OPEN; - set_reg16(0x38, CD_OPEN << 8); - set_reg16(0x3a, 0x0000); - set_reg16(0x3c, 0x0000); - set_reg16(0x3e, 0x0000); - set_reg16(0x40, ~CD_OPEN & 0x0f); + if (PicoMCDopenTray) + PicoMCDopenTray(); + return; + } - if (PicoMCDopenTray) - PicoMCDopenTray(); - return; - } - - default: /* Unknown command */ + default: /* Unknown command */ #ifdef LOG_CDD - error("Unknown CDD Command !!!\n"); + error("Unknown CDD Command !!!\n"); #endif - Pico_mcd->s68k_regs[0x38+0] = cdd.status; - break; - } + Pico_mcd->s68k_regs[0x38 + 0] = cdd.status; + break; + } - /* only compute checksum when necessary */ - Pico_mcd->s68k_regs[0x40 + 1] = - ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] + - Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] + - Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] + - Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] + - Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f; + /* only compute checksum when necessary */ + Pico_mcd->s68k_regs[0x40 + 1] = + ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] + + Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] + + Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] + + Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] + + Pico_mcd->s68k_regs[0x40 + 0]) & + 0x0f; } - -// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdd.h b/waterbox/picodrive/pico/cd/cdd.h index 4789cdb49b..a660d2bf26 100644 --- a/waterbox/picodrive/pico/cd/cdd.h +++ b/waterbox/picodrive/pico/cd/cdd.h @@ -38,19 +38,17 @@ #ifndef _HW_CDD_ #define _HW_CDD_ -#ifdef USE_LIBTREMOR -#include "tremor/ivorbisfile.h" -#endif +#include /* CDD status */ -#define NO_DISC 0x00 -#define CD_PLAY 0x01 -#define CD_SEEK 0x02 -#define CD_SCAN 0x03 +#define NO_DISC 0x00 +#define CD_PLAY 0x01 +#define CD_SEEK 0x02 +#define CD_SCAN 0x03 #define CD_READY 0x04 -#define CD_OPEN 0x05 /* similar to 0x0E ? */ -#define CD_STOP 0x09 -#define CD_END 0x0C +#define CD_OPEN 0x05 /* similar to 0x0E ? */ +#define CD_STOP 0x09 +#define CD_END 0x0C /* CD blocks scanning speed */ #define CD_SCAN_SPEED 30 @@ -60,39 +58,35 @@ /* CD track */ typedef struct { - void *fd; -#ifdef USE_LIBTREMOR - OggVorbis_File vf; -#endif - int offset; - int start; - int end; -} track_t; + int start; + int end; +} track_t; /* CD TOC */ typedef struct { - int end; - int last; - track_t tracks[CD_MAX_TRACKS]; -} toc_t; + int end; + int last; + track_t tracks[CD_MAX_TRACKS]; +} toc_t; /* CDD hardware */ typedef struct { - uint32 cycles; - uint32 latency; - int loaded; - int index; - int lba; - int scanOffset; - int volume; - uint8 status; - uint16 sectorSize; - toc_t toc; - int16 audio[2]; -} cdd_t; + uint32_t cycles; + uint32_t latency; + int loaded; + int index; + int lba; + int scanOffset; + int volume; + uint8_t status; + toc_t toc; + int16_t audio[2]; +} cdd_t; extern cdd_t cdd; +extern void (*CDReadSector)(int lba, void *dest, int audio); + #endif diff --git a/waterbox/picodrive/pico/cd/cue.c b/waterbox/picodrive/pico/cd/cue.c deleted file mode 100644 index f7c15321cf..0000000000 --- a/waterbox/picodrive/pico/cd/cue.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * cuefile handling - * (C) notaz, 2008 - * - * This work is licensed under the terms of MAME license. - * See COPYING file in the top-level directory. - */ -#include -#include -#include -#include "cue.h" - -#include "../pico_int.h" -// #define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); - -#ifdef _MSC_VER -#define snprintf _snprintf -#endif -#ifdef __EPOC32__ -#define snprintf(b,s,...) sprintf(b,##__VA_ARGS__) -#endif - -#define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0) - -void cue_destroy(cue_data_t *data) -{ - int c; - - if (data == NULL) return; - - for (c = data->track_count; c > 0; c--) - if (data->tracks[c].fname != NULL) - free(data->tracks[c].fname); - free(data); -} diff --git a/waterbox/picodrive/pico/cd/cue.h b/waterbox/picodrive/pico/cd/cue.h deleted file mode 100644 index 70ade53de9..0000000000 --- a/waterbox/picodrive/pico/cd/cue.h +++ /dev/null @@ -1,29 +0,0 @@ - -typedef enum -{ - CT_UNKNOWN = 0, - CT_ISO = 1, /* 2048 B/sector */ - CT_BIN = 2, /* 2352 B/sector */ - CT_MP3 = 3, - CT_WAV = 4 -} cue_track_type; - -typedef struct -{ - char *fname; - int pregap; /* pregap for current track */ - int sector_offset; /* in current file */ - int sector_xlength; - cue_track_type type; -} cue_track; - -typedef struct -{ - int track_count; - cue_track tracks[0]; -} cue_data_t; - - -cue_data_t *cue_parse(const char *fname); -void cue_destroy(cue_data_t *data); - diff --git a/waterbox/picodrive/pico/cd/genplus_macros.h b/waterbox/picodrive/pico/cd/genplus_macros.h index 8ac5d35b08..495f5608cc 100644 --- a/waterbox/picodrive/pico/cd/genplus_macros.h +++ b/waterbox/picodrive/pico/cd/genplus_macros.h @@ -14,11 +14,3 @@ #define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1] #define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL) - -#define load_param(param, size) \ - memcpy(param, &state[bufferptr], size); \ - bufferptr += size; - -#define save_param(param, size) \ - memcpy(&state[bufferptr], param, size); \ - bufferptr += size; diff --git a/waterbox/picodrive/pico/cd/gfx.c b/waterbox/picodrive/pico/cd/gfx.c index a2c97be032..55d2d90afe 100644 --- a/waterbox/picodrive/pico/cd/gfx.c +++ b/waterbox/picodrive/pico/cd/gfx.c @@ -127,54 +127,6 @@ void gfx_init(void) } } -int gfx_context_save(uint8 *state) -{ - uint32 tmp32; - int bufferptr = 0; - - //save_param(&gfx.cycles, sizeof(gfx.cycles)); - //save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); - save_param(&gfx.dotMask, sizeof(gfx.dotMask)); - save_param(&gfx.stampShift, sizeof(gfx.stampShift)); - save_param(&gfx.mapShift, sizeof(gfx.mapShift)); - save_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset)); - save_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); - - tmp32 = (uint8 *)(gfx.tracePtr) - Pico_mcd->word_ram2M; - save_param(&tmp32, 4); - - tmp32 = (uint8 *)(gfx.mapPtr) - Pico_mcd->word_ram2M; - save_param(&tmp32, 4); - - save_param(&gfx.y_step, sizeof(gfx.y_step)); - - return bufferptr; -} - -int gfx_context_load(const uint8 *state) -{ - uint32 tmp32; - int bufferptr = 0; - - //load_param(&gfx.cycles, sizeof(gfx.cycles)); - //load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); - load_param(&gfx.dotMask, sizeof(gfx.dotMask)); - load_param(&gfx.stampShift, sizeof(gfx.stampShift)); - load_param(&gfx.mapShift, sizeof(gfx.mapShift)); - load_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset)); - load_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); - - load_param(&tmp32, 4); - gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); - - load_param(&tmp32, 4); - gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); - - load_param(&gfx.y_step, sizeof(gfx.y_step)); - - return bufferptr; -} - static void gfx_render(uint32 bufferIndex, uint32 width) { uint8 pixel_in, pixel_out; diff --git a/waterbox/picodrive/pico/media.c b/waterbox/picodrive/pico/media.c index 4f22a0c98a..ae92e68e53 100644 --- a/waterbox/picodrive/pico/media.c +++ b/waterbox/picodrive/pico/media.c @@ -8,7 +8,6 @@ #include #include "pico_int.h" -#include "cd/cue.h" unsigned char media_id_header[0x100]; diff --git a/waterbox/picodrive/pico/pico_int.h b/waterbox/picodrive/pico/pico_int.h index 30bce7bab8..2d3d04b03b 100644 --- a/waterbox/picodrive/pico/pico_int.h +++ b/waterbox/picodrive/pico/pico_int.h @@ -596,9 +596,6 @@ PICO_INTERNAL void PicoMemSetupPico(void); // cd/cdc.c void cdc_init(void); void cdc_reset(void); -int cdc_context_save(unsigned char *state); -int cdc_context_load(unsigned char *state); -int cdc_context_load_old(unsigned char *state); void cdc_dma_update(void); int cdc_decoder_update(unsigned char header[4]); void cdc_reg_w(unsigned char data); @@ -607,9 +604,6 @@ unsigned short cdc_host_r(void); // cd/cdd.c void cdd_reset(void); -int cdd_context_save(unsigned char *state); -int cdd_context_load(unsigned char *state); -int cdd_context_load_old(unsigned char *state); void cdd_read_data(unsigned char *dst); void cdd_read_audio(unsigned int samples); void cdd_update(void); @@ -622,8 +616,6 @@ int load_cd_image(const char *cd_img_name, int *type); void gfx_init(void); void gfx_start(unsigned int base); void gfx_update(unsigned int cycles); -int gfx_context_save(unsigned char *state); -int gfx_context_load(const unsigned char *state); // cd/gfx_dma.c void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc); diff --git a/waterbox/picodrive/pico/sound/sound.c b/waterbox/picodrive/pico/sound/sound.c index 69c1be0397..76c5c62df6 100644 --- a/waterbox/picodrive/pico/sound/sound.c +++ b/waterbox/picodrive/pico/sound/sound.c @@ -11,7 +11,6 @@ #include "ym2612.h" #include "sn76496.h" #include "../pico_int.h" -#include "../cd/cue.h" #include "mix.h" #define SIMPLE_WRITE_SOUND 0 @@ -191,7 +190,7 @@ PICO_INTERNAL void PsndDoDAC(int line_to) // cdda static void cdda_raw_update(int *buffer, int length) { - int ret, cdda_bytes, mult = 1; + /*int ret, cdda_bytes, mult = 1; cdda_bytes = length*4; if (PsndRate <= 22050 + 100) mult = 2; @@ -210,12 +209,12 @@ static void cdda_raw_update(int *buffer, int length) case 1: mix_16h_to_32(buffer, cdda_out_buffer, length*2); break; case 2: mix_16h_to_32_s1(buffer, cdda_out_buffer, length*2); break; case 4: mix_16h_to_32_s2(buffer, cdda_out_buffer, length*2); break; - } + }*/ } void cdda_start_play(int lba_base, int lba_offset, int lb_len) { - if (Pico_mcd->cdda_type == CT_MP3) + /*if (Pico_mcd->cdda_type == CT_MP3) { int pos1024 = 0; @@ -231,7 +230,7 @@ void cdda_start_play(int lba_base, int lba_offset, int lb_len) { // skip headers, assume it's 44kHz stereo uncompressed pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR); - } + }*/ } @@ -302,10 +301,7 @@ static int PsndRender(int offset, int length) && !(Pico_mcd->s68k_regs[0x36] & 1)) { // note: only 44, 22 and 11 kHz supported, with forced stereo - if (Pico_mcd->cdda_type == CT_MP3) - mp3_update(buf32, length, stereo); - else - cdda_raw_update(buf32, length); + cdda_raw_update(buf32, length); } if ((PicoAHW & PAHW_32X) && (PicoOpt & POPT_EN_PWM))