PicoDrive: Mega CD. No CD audio yet.
This commit is contained in:
parent
a80f16c032
commit
24cd317a1c
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -111,7 +140,7 @@ static const uint8_t* TryLoadBios(const char* name)
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
||||||
|
|
|
@ -38,17 +38,12 @@
|
||||||
|
|
||||||
#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] =
|
||||||
{
|
{
|
||||||
|
@ -83,8 +78,7 @@ 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] =
|
||||||
{
|
{
|
||||||
|
@ -93,60 +87,29 @@ static const uint16 toc_lunar[52] =
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,7 +403,9 @@ 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)
|
||||||
|
@ -678,15 +430,6 @@ 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++;
|
||||||
|
|
||||||
|
@ -694,17 +437,6 @@ void cdd_update(void)
|
||||||
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++;
|
||||||
|
|
||||||
|
@ -750,16 +473,6 @@ void cdd_update(void)
|
||||||
}
|
}
|
||||||
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--;
|
||||||
|
|
||||||
|
@ -790,25 +503,7 @@ void cdd_update(void)
|
||||||
{
|
{
|
||||||
/* 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,7 +519,8 @@ 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; \
|
||||||
|
@ -968,7 +664,8 @@ void cdd_process(void)
|
||||||
|
|
||||||
/* 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])) *
|
||||||
|
75 +
|
||||||
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
|
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
|
||||||
|
|
||||||
/* CD drive latency */
|
/* CD drive 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)
|
||||||
{
|
{
|
||||||
|
@ -1079,7 +749,8 @@ void cdd_process(void)
|
||||||
|
|
||||||
/* 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])) *
|
||||||
|
75 +
|
||||||
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
|
(Pico_mcd->s68k_regs[0x48 + 0] * 10 + Pico_mcd->s68k_regs[0x48 + 1]) - 150;
|
||||||
|
|
||||||
/* CD drive seek time */
|
/* CD drive seek time */
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -1203,7 +847,6 @@ void cdd_process(void)
|
||||||
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) */
|
||||||
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue