PicoDrive: Mega CD. No CD audio yet.

This commit is contained in:
nattthebear 2017-07-02 20:46:01 -04:00
parent a80f16c032
commit 24cd317a1c
16 changed files with 729 additions and 1496 deletions

View File

@ -17,7 +17,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
public int Buttons; public int Buttons;
} }
[UnmanagedFunctionPointer(CC)]
public delegate void CDReadCallback(int lba, IntPtr dest, bool audio);
[BizImport(CC)] [BizImport(CC)]
public abstract bool Init(); public abstract bool Init(bool cd);
[BizImport(CC)]
public abstract void SetCDReadCallback(CDReadCallback callback);
} }
} }

View File

@ -1,21 +1,35 @@
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Emulation.DiscSystem;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO;
namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
{ {
[CoreAttributes("PicoDrive", "notaz", true, false, [CoreAttributes("PicoDrive", "notaz", true, false,
"0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)] "0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)]
public class PicoDrive : WaterboxCore public class PicoDrive : WaterboxCore, IDriveLight
{ {
private LibPicoDrive _core; private LibPicoDrive _core;
private LibPicoDrive.CDReadCallback _cdcallback;
private Disc _cd;
private DiscSectorReader _cdReader;
[CoreConstructor("GEN")] [CoreConstructor("GEN")]
public PicoDrive(CoreComm comm, byte[] rom, bool deterministic) 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 : base(comm, new Configuration
{ {
MaxSamples = 2048, MaxSamples = 2048,
@ -51,12 +65,38 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
_exe.AddReadonlyFile(bioss, "32x.s"); _exe.AddReadonlyFile(bioss, "32x.s");
Console.WriteLine("Using supplied 32x BIOS files"); Console.WriteLine("Using supplied 32x BIOS files");
} }
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"); _exe.AddReadonlyFile(rom, "romfile.md");
}
if (!_core.Init()) if (!_core.Init(cd != null))
throw new InvalidOperationException("Core rejected the rom!"); throw new InvalidOperationException("Core rejected the file!");
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"); _exe.RemoveReadonlyFile("romfile.md");
}
if (has32xBios) if (has32xBios)
{ {
_exe.RemoveReadonlyFile("32x.g"); _exe.RemoveReadonlyFile("32x.g");
@ -67,6 +107,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
PostInit(); PostInit();
ControllerDefinition = PicoDriveController; ControllerDefinition = PicoDriveController;
DeterministicEmulation = deterministic; DeterministicEmulation = deterministic;
_core.SetCDReadCallback(_cdcallback);
} }
public static readonly ControllerDefinition PicoDriveController = new ControllerDefinition public static readonly ControllerDefinition PicoDriveController = new ControllerDefinition
@ -97,7 +138,40 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
b |= v; b |= v;
v <<= 1; v <<= 1;
} }
DriveLightOn = false;
return new LibPicoDrive.FrameInfo { Buttons = b }; 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
} }
} }

View File

@ -6,6 +6,7 @@ using BizHawk.Common.BizInvoke;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.DiscSystem;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 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); Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename);
return 0; return 0;
} }
srcdata = GetCDData(); srcdata = GetCDData(CD);
if (srcdata.Length != maxsize) if (srcdata.Length != maxsize)
{ {
Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename); 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; LibGPGX.cd_read_cb cd_callback_handle;
unsafe byte[] GetCDData() public static unsafe byte[] GetCDData(Disc cd)
{ {
LibGPGX.CDData ret = new LibGPGX.CDData(); LibGPGX.CDData ret = new LibGPGX.CDData();
int size = Marshal.SizeOf(ret); int size = Marshal.SizeOf(ret);
var ses = CD.Session1; var ses = cd.Session1;
int ntrack = ses.InformationTrackCount; int ntrack = ses.InformationTrackCount;
// bet you a dollar this is all wrong // bet you a dollar this is all wrong

View File

@ -6,7 +6,7 @@
#include "../emulibc/emulibc.h" #include "../emulibc/emulibc.h"
#include "../emulibc/waterboxcore.h" #include "../emulibc/waterboxcore.h"
#include "pico/pico.h" #include "pico/pico.h"
#include "pico/cd/cue.h" #include "pico/cd/cdd.h"
void lprintf(const char *fmt, ...) void lprintf(const char *fmt, ...)
{ {
@ -24,12 +24,41 @@ int PicoCartResize(int newsize)
int PicoCdCheck(const char *fname_in, int *pregion) 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) 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_start_play(void *f, int pos) {}
void mp3_update(int *buffer, int length, int stereo) {} 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"); FILE *f = fopen(name, "rb");
if (!f) if (!f)
return NULL; return NULL;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int size = ftell(f); int size = ftell(f);
uint8_t* ret = alloc_sealed(size); uint8_t *ret = alloc_sealed(size);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
fread(ret, 1, size, f); fread(ret, 1, size, f);
fclose(f); fclose(f);
return ret; return ret;
} }
ECL_EXPORT int Init(void) ECL_EXPORT int Init(int cd)
{ {
p32x_bios_g = TryLoadBios("32x.g"); p32x_bios_g = TryLoadBios("32x.g");
p32x_bios_m = TryLoadBios("32x.m"); 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; 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(); PicoInit();
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) if (PicoLoadMedia("romfile.md", NULL, NULL, NULL, PM_MD_CART) != PM_MD_CART)
return 0; return 0;
}
PicoLoopPrepare(); PicoLoopPrepare();
video_buffer = alloc_invisible(512 * 512 * sizeof(uint16_t)); video_buffer = alloc_invisible(512 * 512 * sizeof(uint16_t));
@ -189,6 +226,10 @@ ECL_EXPORT void SetInputCallback(void (*callback)(void))
{ {
PicoInputCallback = callback; PicoInputCallback = callback;
} }
ECL_EXPORT void SetCDReadCallback(void (*callback)(int lba, void *dest, int audio))
{
CDReadSector = callback;
}
int main(void) int main(void)
{ {

View File

@ -107,14 +107,6 @@ void PicoSVPInit(void)
#endif #endif
} }
static void PicoSVPExit(void)
{
#ifdef _SVP_DRC
ssp1601_dyn_exit();
#endif
}
void PicoSVPStartup(void) void PicoSVPStartup(void)
{ {
int ret; int ret;

View File

@ -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

View File

@ -130,120 +130,6 @@ void cdc_reset(void)
cdc.dma_w = 0; 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) 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]; 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 #endif
return 0xffff; return 0xffff;
} }
// vim:shiftwidth=2:ts=2:expandtab

View File

@ -38,20 +38,15 @@
#include "../pico_int.h" #include "../pico_int.h"
#include "genplus_macros.h" #include "genplus_macros.h"
#include "cue.h"
#include "cdd.h" #include "cdd.h"
#ifdef USE_LIBTREMOR
#define SUPPORTED_EXT 20
#else
#define SUPPORTED_EXT 10
#endif
cdd_t cdd; cdd_t cdd;
void (*CDReadSector)(int lba, void *dest, int audio);
/* BCD conversion lookup tables */ /* BCD conversion lookup tables */
static const uint8 lut_BCD_8[100] = static const uint8 lut_BCD_8[100] =
{ {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
@ -65,7 +60,7 @@ static const uint8 lut_BCD_8[100] =
}; };
static const uint16 lut_BCD_16[100] = static const uint16 lut_BCD_16[100] =
{ {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
@ -80,73 +75,41 @@ static const uint16 lut_BCD_16[100] =
/* pre-build TOC */ /* pre-build TOC */
static const uint16 toc_snatcher[21] = static const uint16 toc_snatcher[21] =
{ {
56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681,
8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485,
31380 31380};
};
static const uint16 toc_lunar[52] = static const uint16 toc_lunar[52] =
{ {
5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870,
6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263,
6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205,
1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549,
1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132,
685, 3167 685, 3167};
};
static const uint32 toc_shadow[15] = static const uint32 toc_shadow[15] =
{ {
10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792,
11637, 2547, 2521, 3856, 900 11637, 2547, 2521, 3856, 900};
};
static const uint32 toc_dungeon[13] = static const uint32 toc_dungeon[13] =
{ {
2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
3325, 6825, 25275 3325, 6825, 25275};
};
static const uint32 toc_ffight[26] = static const uint32 toc_ffight[26] =
{ {
11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764,
9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024,
14562, 10320, 8627, 3795, 3047 14562, 10320, 8627, 3795, 3047};
};
static const uint32 toc_ffightj[29] = static const uint32 toc_ffightj[29] =
{ {
11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763,
9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026,
14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 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
void cdd_reset(void) void cdd_reset(void)
{ {
@ -175,7 +138,7 @@ void cdd_reset(void)
/* FIXME: use cdd_read_audio() instead */ /* FIXME: use cdd_read_audio() instead */
static void cdd_change_track(int index, int lba) 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--) for (i = index; i > 0; i--)
if (cdd.toc.tracks[i].fd != NULL) if (cdd.toc.tracks[i].fd != NULL)
@ -188,238 +151,34 @@ static void cdd_change_track(int index, int lba)
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); 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;
} }
int cdd_load(const char *filename, int type) int cdd_load(const char *filename, int type)
{ {
char header[0x210]; FILE *f = fopen("toc", "rb");
int ret; fread(&cdd.toc, 1, sizeof(cdd.toc), f);
fclose(f);
/* genplus parses cue here, in PD we use our own parser */ char sector[2048];
ret = load_cd_image(filename, &type);
if (ret != 0)
return ret;
/* read first 16 bytes */ CDReadSector(0, sector, 0);
pm_read(header, 0x10, cdd.toc.tracks[0].fd);
/* look for valid CD image ID string */ /* look for valid CD image ID string */
if (memcmp("SEGADISCSYSTEM", header, 14)) if (memcmp("SEGADISCSYSTEM", sector, 14))
{ {
/* if not found, read next 16 bytes */ /* if not found, read next 16 bytes */
pm_read(header, 0x10, cdd.toc.tracks[0].fd);
/* look again for valid CD image ID string */ /* look again for valid CD image ID string */
if (memcmp("SEGADISCSYSTEM", header, 14)) if (memcmp("SEGADISCSYSTEM", sector + 16, 14))
{ {
elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?"); elprintf(EL_STATUS | EL_ANOMALY, "cd: bad cd image?");
/* assume bin without security code */ /* assume bin without security code */
} }
/* BIN format (2352 bytes data blocks) */
cdd.sectorSize = 2352;
}
else
{
/* ISO format (2048 bytes data blocks) */
cdd.sectorSize = 2048;
}
ret = (type == CT_BIN) ? 2352 : 2048;
if (ret != cdd.sectorSize)
elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
/* read CD image header + security code */
pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
/* 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 */ /* Lead-out */
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; // cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
/* CD loaded */ /* CD loaded */
cdd.loaded = 1; cdd.loaded = 1;
@ -435,15 +194,7 @@ void cdd_read_data(uint8 *dst)
/* only read DATA track sectors */ /* only read DATA track sectors */
if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
{ {
/* BIN format ? */ CDReadSector(cdd.lba, dst, 0);
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);
} }
} }
@ -542,24 +293,24 @@ void cdd_read_audio(unsigned int samples)
mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03); mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
/* left channel */ /* left channel */
#ifdef LSB_FIRST #ifdef LSB_FIRST
delta = ((ptr[0] * mul) / 1024) - l; delta = ((ptr[0] * mul) / 1024) - l;
ptr++; ptr++;
#else #else
delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l; delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
ptr += 2; ptr += 2;
#endif #endif
l += delta; l += delta;
blip_add_delta_fast(blip[0], i, delta); blip_add_delta_fast(blip[0], i, delta);
/* right channel */ /* right channel */
#ifdef LSB_FIRST #ifdef LSB_FIRST
delta = ((ptr[0] * mul) / 1024) - r; delta = ((ptr[0] * mul) / 1024) - r;
ptr++; ptr++;
#else #else
delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r; delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
ptr += 2; ptr += 2;
#endif #endif
r += delta; r += delta;
blip_add_delta_fast(blip[1], i, delta); blip_add_delta_fast(blip[1], i, delta);
@ -606,7 +357,6 @@ void cdd_read_audio(unsigned int samples)
} }
#endif #endif
void cdd_update(void) void cdd_update(void)
{ {
#ifdef LOG_CDD #ifdef LOG_CDD
@ -653,13 +403,15 @@ void cdd_update(void)
} }
else if (cdd.index < cdd.toc.last) else if (cdd.index < cdd.toc.last)
{ {
uint8 header[4] = { 0, }; uint8 header[4] = {
0,
};
/* check against audio track start index */ /* check against audio track start index */
if (cdd.lba >= cdd.toc.tracks[cdd.index].start) if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
{ {
/* audio track playing */ /* audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x00; Pico_mcd->s68k_regs[0x36 + 0] = 0x00;
} }
/* audio blocks are still sent to CDC as well as CD DAC/Fader */ /* audio blocks are still sent to CDC as well as CD DAC/Fader */
@ -678,33 +430,13 @@ void cdd_update(void)
/* check end of current track */ /* check end of current track */
if (cdd.lba >= cdd.toc.tracks[cdd.index].end) 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 */ /* play next track */
cdd.index++; cdd.index++;
/* PAUSE between tracks */ /* PAUSE between tracks */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* seek to next audio track start */ /* 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
#if 0 #if 0
if (cdd.toc.tracks[cdd.index].fd) if (cdd.toc.tracks[cdd.index].fd)
{ {
@ -727,15 +459,6 @@ void cdd_update(void)
/* check current track limits */ /* check current track limits */
if (cdd.lba >= cdd.toc.tracks[cdd.index].end) 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 */ /* next track */
cdd.index++; cdd.index++;
@ -745,21 +468,11 @@ void cdd_update(void)
/* AUDIO track playing ? */ /* AUDIO track playing ? */
if (cdd.status == CD_PLAY) if (cdd.status == CD_PLAY)
{ {
Pico_mcd->s68k_regs[0x36+0] = 0x00; Pico_mcd->s68k_regs[0x36 + 0] = 0x00;
} }
} }
else if (cdd.lba < cdd.toc.tracks[cdd.index].start) 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
/* previous track */ /* previous track */
cdd.index--; cdd.index--;
@ -776,7 +489,7 @@ void cdd_update(void)
else if (cdd.index >= cdd.toc.last) else if (cdd.index >= cdd.toc.last)
{ {
/* no AUDIO track playing */ /* no AUDIO track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* end of disc */ /* end of disc */
cdd.index = cdd.toc.last; cdd.index = cdd.toc.last;
@ -789,26 +502,8 @@ void cdd_update(void)
if (!cdd.index) if (!cdd.index)
{ {
/* no AUDIO track playing */ /* no AUDIO track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; 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
#if 0 #if 0
else if (cdd.toc.tracks[cdd.index].fd) else if (cdd.toc.tracks[cdd.index].fd)
{ {
@ -824,30 +519,31 @@ void cdd_update(void)
} }
} }
#define set_reg16(r, v) { \ #define set_reg16(r, v) \
{ \
uint16 _v = v; \ uint16 _v = v; \
Pico_mcd->s68k_regs[(r)] = _v >> 8; \ Pico_mcd->s68k_regs[(r)] = _v >> 8; \
Pico_mcd->s68k_regs[(r)+1] = _v; \ Pico_mcd->s68k_regs[(r) + 1] = _v; \
} }
void cdd_process(void) void cdd_process(void)
{ {
/* Process CDD command */ /* Process CDD command */
switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f) switch (Pico_mcd->s68k_regs[0x42 + 0] & 0x0f)
{ {
case 0x00: /* Drive Status */ case 0x00: /* Drive Status */
{ {
/* RS1-RS8 normally unchanged */ /* RS1-RS8 normally unchanged */
Pico_mcd->s68k_regs[0x38+0] = cdd.status; Pico_mcd->s68k_regs[0x38 + 0] = cdd.status;
/* unless RS1 indicated invalid track infos */ /* unless RS1 indicated invalid track infos */
if (Pico_mcd->s68k_regs[0x38+1] == 0x0f) if (Pico_mcd->s68k_regs[0x38 + 1] == 0x0f)
{ {
/* and SEEK has ended */ /* and SEEK has ended */
if (cdd.status != CD_SEEK) if (cdd.status != CD_SEEK)
{ {
/* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ /* 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; Pico_mcd->s68k_regs[0x38 + 1] = 0x02;
set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
} }
} }
@ -860,7 +556,7 @@ void cdd_process(void)
cdd.status = cdd.loaded ? CD_STOP : NO_DISC; cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
set_reg16(0x38, 0x0000); set_reg16(0x38, 0x0000);
@ -878,16 +574,16 @@ void cdd_process(void)
/* Infos automatically retrieved by CDD processor from Q-Channel */ /* Infos automatically retrieved by CDD processor from Q-Channel */
/* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
switch (Pico_mcd->s68k_regs[0x44+1]) switch (Pico_mcd->s68k_regs[0x44 + 1])
{ {
case 0x00: /* Current Absolute Time (MM:SS:FF) */ case 0x00: /* Current Absolute Time (MM:SS:FF) */
{ {
int lba = cdd.lba + 150; int lba = cdd.lba + 150;
set_reg16(0x38, cdd.status << 8); set_reg16(0x38, cdd.status << 8);
set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]);
set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]);
set_reg16(0x3e, lut_BCD_16[(lba%75)]); 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) */ 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; break;
} }
@ -895,10 +591,10 @@ void cdd_process(void)
{ {
int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
set_reg16(0x38, (cdd.status << 8) | 0x01); set_reg16(0x38, (cdd.status << 8) | 0x01);
set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]);
set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]);
set_reg16(0x3e, lut_BCD_16[(lba%75)]); 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) */ 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; break;
} }
@ -908,7 +604,7 @@ void cdd_process(void)
set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
set_reg16(0x3c, 0x0000); set_reg16(0x3c, 0x0000);
set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */ set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
Pico_mcd->s68k_regs[0x40+0] = 0x00; Pico_mcd->s68k_regs[0x40 + 0] = 0x00;
break; break;
} }
@ -916,10 +612,10 @@ void cdd_process(void)
{ {
int lba = cdd.toc.end + 150; int lba = cdd.toc.end + 150;
set_reg16(0x38, (cdd.status << 8) | 0x03); set_reg16(0x38, (cdd.status << 8) | 0x03);
set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]);
set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]);
set_reg16(0x3e, lut_BCD_16[(lba%75)]); set_reg16(0x3e, lut_BCD_16[(lba % 75)]);
Pico_mcd->s68k_regs[0x40+0] = 0x00; Pico_mcd->s68k_regs[0x40 + 0] = 0x00;
break; break;
} }
@ -929,19 +625,19 @@ void cdd_process(void)
set_reg16(0x3a, 0x0001); set_reg16(0x3a, 0x0001);
set_reg16(0x3c, lut_BCD_16[cdd.toc.last]); set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */ 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) */ Pico_mcd->s68k_regs[0x40 + 0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
break; break;
} }
case 0x05: /* Track Start Time (MM:SS:FF) */ case 0x05: /* Track Start Time (MM:SS:FF) */
{ {
int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1]; int track = Pico_mcd->s68k_regs[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1];
int lba = cdd.toc.tracks[track-1].start + 150; int lba = cdd.toc.tracks[track - 1].start + 150;
set_reg16(0x38, (cdd.status << 8) | 0x05); set_reg16(0x38, (cdd.status << 8) | 0x05);
set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); set_reg16(0x3a, lut_BCD_16[(lba / 75) / 60]);
set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); set_reg16(0x3c, lut_BCD_16[(lba / 75) % 60]);
set_reg16(0x3e, lut_BCD_16[(lba%75)]); set_reg16(0x3e, lut_BCD_16[(lba % 75)]);
Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */ Pico_mcd->s68k_regs[0x40 + 0] = track % 10; /* Track Number (low digit) */
if (track == 1) if (track == 1)
{ {
/* RS6 bit 3 is set for the first (DATA) track */ /* RS6 bit 3 is set for the first (DATA) track */
@ -953,7 +649,7 @@ void cdd_process(void)
default: default:
{ {
#ifdef LOG_ERROR #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 #endif
return; return;
} }
@ -967,9 +663,10 @@ void cdd_process(void)
int index = 0; int index = 0;
/* new LBA position */ /* new LBA position */
int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + 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[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1])) *
(Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; 75 +
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
/* CD drive latency */ /* CD drive latency */
if (!cdd.latency) if (!cdd.latency)
@ -1000,27 +697,8 @@ void cdd_process(void)
cdd.lba = lba; cdd.lba = lba;
/* get track index */ /* get track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) 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);
}
/* 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
/* update current track index */ /* update current track index */
cdd.index = index; cdd.index = index;
@ -1035,15 +713,7 @@ void cdd_process(void)
if (!index) if (!index)
{ {
/* DATA track */ /* 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
#if 0 #if 0
else if (cdd.toc.tracks[index].fd) else if (cdd.toc.tracks[index].fd)
{ {
@ -1058,7 +728,7 @@ void cdd_process(void)
#endif #endif
/* no audio track playing (yet) */ /* no audio track playing (yet) */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status */ /* update status */
cdd.status = CD_PLAY; cdd.status = CD_PLAY;
@ -1068,7 +738,7 @@ void cdd_process(void)
set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A); set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A);
set_reg16(0x3c, 0x0000); set_reg16(0x3c, 0x0000);
set_reg16(0x3e, 0x0000); set_reg16(0x3e, 0x0000);
Pico_mcd->s68k_regs[0x40+0] = 0x00; Pico_mcd->s68k_regs[0x40 + 0] = 0x00;
break; break;
} }
@ -1078,9 +748,10 @@ void cdd_process(void)
int index = 0; int index = 0;
/* new LBA position */ /* new LBA position */
int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + 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[0x46 + 0] * 10 + Pico_mcd->s68k_regs[0x46 + 1])) *
(Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; 75 +
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
/* CD drive seek time */ /* CD drive seek time */
/* We are using similar linear model as above, although still not exactly accurate, */ /* We are using similar linear model as above, although still not exactly accurate, */
@ -1099,27 +770,8 @@ void cdd_process(void)
cdd.lba = lba; cdd.lba = lba;
/* get current track index */ /* get current track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) 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);
}
/* 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
/* update current track index */ /* update current track index */
cdd.index = index; cdd.index = index;
@ -1134,15 +786,7 @@ void cdd_process(void)
if (!index) if (!index)
{ {
/* DATA track */ /* 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
#if 0 #if 0
else if (cdd.toc.tracks[index].fd) else if (cdd.toc.tracks[index].fd)
{ {
@ -1152,7 +796,7 @@ void cdd_process(void)
#endif #endif
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status */ /* update status */
cdd.status = CD_SEEK; cdd.status = CD_SEEK;
@ -1169,17 +813,17 @@ void cdd_process(void)
case 0x06: /* Pause */ case 0x06: /* Pause */
{ {
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status (RS1-RS8 unchanged) */ /* update status (RS1-RS8 unchanged) */
cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_READY;
break; break;
} }
case 0x07: /* Resume */ case 0x07: /* Resume */
{ {
/* update status (RS1-RS8 unchanged) */ /* update status (RS1-RS8 unchanged) */
cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY; cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_PLAY;
break; break;
} }
@ -1189,7 +833,7 @@ void cdd_process(void)
cdd.scanOffset = CD_SCAN_SPEED; cdd.scanOffset = CD_SCAN_SPEED;
/* update status (RS1-RS8 unchanged) */ /* update status (RS1-RS8 unchanged) */
cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_SCAN;
break; break;
} }
@ -1199,11 +843,10 @@ void cdd_process(void)
cdd.scanOffset = -CD_SCAN_SPEED; cdd.scanOffset = -CD_SCAN_SPEED;
/* update status (RS1-RS8 unchanged) */ /* update status (RS1-RS8 unchanged) */
cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_SCAN;
break; break;
} }
case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
{ {
/* TC3 corresponds to seek direction (00=forward, FF=reverse) */ /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
@ -1212,17 +855,17 @@ void cdd_process(void)
/* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status (RS1-RS8 unchanged) */ /* update status (RS1-RS8 unchanged) */
cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; cdd.status = Pico_mcd->s68k_regs[0x38 + 0] = CD_READY;
break; break;
} }
case 0x0c: /* Close Tray */ case 0x0c: /* Close Tray */
{ {
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status */ /* update status */
cdd.status = cdd.loaded ? CD_STOP : NO_DISC; cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
@ -1243,7 +886,7 @@ void cdd_process(void)
case 0x0d: /* Open Tray */ case 0x0d: /* Open Tray */
{ {
/* no audio track playing */ /* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01; Pico_mcd->s68k_regs[0x36 + 0] = 0x01;
/* update status (RS1-RS8 ignored) */ /* update status (RS1-RS8 ignored) */
cdd.status = CD_OPEN; cdd.status = CD_OPEN;
@ -1262,7 +905,7 @@ void cdd_process(void)
#ifdef LOG_CDD #ifdef LOG_CDD
error("Unknown CDD Command !!!\n"); error("Unknown CDD Command !!!\n");
#endif #endif
Pico_mcd->s68k_regs[0x38+0] = cdd.status; Pico_mcd->s68k_regs[0x38 + 0] = cdd.status;
break; break;
} }
@ -1272,7 +915,6 @@ void cdd_process(void)
Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 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[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] +
Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] + Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] +
Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f; Pico_mcd->s68k_regs[0x40 + 0]) &
0x0f;
} }
// vim:shiftwidth=2:ts=2:expandtab

View File

@ -38,9 +38,7 @@
#ifndef _HW_CDD_ #ifndef _HW_CDD_
#define _HW_CDD_ #define _HW_CDD_
#ifdef USE_LIBTREMOR #include <stdint.h>
#include "tremor/ivorbisfile.h"
#endif
/* CDD status */ /* CDD status */
#define NO_DISC 0x00 #define NO_DISC 0x00
@ -60,11 +58,6 @@
/* CD track */ /* CD track */
typedef struct typedef struct
{ {
void *fd;
#ifdef USE_LIBTREMOR
OggVorbis_File vf;
#endif
int offset;
int start; int start;
int end; int end;
} track_t; } track_t;
@ -80,19 +73,20 @@ typedef struct
/* CDD hardware */ /* CDD hardware */
typedef struct typedef struct
{ {
uint32 cycles; uint32_t cycles;
uint32 latency; uint32_t latency;
int loaded; int loaded;
int index; int index;
int lba; int lba;
int scanOffset; int scanOffset;
int volume; int volume;
uint8 status; uint8_t status;
uint16 sectorSize;
toc_t toc; toc_t toc;
int16 audio[2]; int16_t audio[2];
} cdd_t; } cdd_t;
extern cdd_t cdd; extern cdd_t cdd;
extern void (*CDReadSector)(int lba, void *dest, int audio);
#endif #endif

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -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);

View File

@ -14,11 +14,3 @@
#define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1] #define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1]
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL) #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;

View File

@ -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) static void gfx_render(uint32 bufferIndex, uint32 width)
{ {
uint8 pixel_in, pixel_out; uint8 pixel_in, pixel_out;

View File

@ -8,7 +8,6 @@
#include <string.h> #include <string.h>
#include "pico_int.h" #include "pico_int.h"
#include "cd/cue.h"
unsigned char media_id_header[0x100]; unsigned char media_id_header[0x100];

View File

@ -596,9 +596,6 @@ PICO_INTERNAL void PicoMemSetupPico(void);
// cd/cdc.c // cd/cdc.c
void cdc_init(void); void cdc_init(void);
void cdc_reset(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); void cdc_dma_update(void);
int cdc_decoder_update(unsigned char header[4]); int cdc_decoder_update(unsigned char header[4]);
void cdc_reg_w(unsigned char data); void cdc_reg_w(unsigned char data);
@ -607,9 +604,6 @@ unsigned short cdc_host_r(void);
// cd/cdd.c // cd/cdd.c
void cdd_reset(void); 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_data(unsigned char *dst);
void cdd_read_audio(unsigned int samples); void cdd_read_audio(unsigned int samples);
void cdd_update(void); 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_init(void);
void gfx_start(unsigned int base); void gfx_start(unsigned int base);
void gfx_update(unsigned int cycles); 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 // cd/gfx_dma.c
void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc); void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc);

View File

@ -11,7 +11,6 @@
#include "ym2612.h" #include "ym2612.h"
#include "sn76496.h" #include "sn76496.h"
#include "../pico_int.h" #include "../pico_int.h"
#include "../cd/cue.h"
#include "mix.h" #include "mix.h"
#define SIMPLE_WRITE_SOUND 0 #define SIMPLE_WRITE_SOUND 0
@ -191,7 +190,7 @@ PICO_INTERNAL void PsndDoDAC(int line_to)
// cdda // cdda
static void cdda_raw_update(int *buffer, int length) 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; cdda_bytes = length*4;
if (PsndRate <= 22050 + 100) mult = 2; 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 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 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; 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) 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; 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 // skip headers, assume it's 44kHz stereo uncompressed
pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR); pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR);
} }*/
} }
@ -302,9 +301,6 @@ static int PsndRender(int offset, int length)
&& !(Pico_mcd->s68k_regs[0x36] & 1)) && !(Pico_mcd->s68k_regs[0x36] & 1))
{ {
// note: only 44, 22 and 11 kHz supported, with forced stereo // 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);
} }