cd: switch to CD drive emu code from genplus

same license, much cleaner code
This commit is contained in:
notaz 2013-10-06 21:08:07 +03:00
parent 3f23709ef3
commit 274fcc35aa
25 changed files with 1798 additions and 1824 deletions

View file

@ -157,7 +157,7 @@ zip_failed:
if (f == NULL) if (f == NULL)
goto cso_failed; goto cso_failed;
#ifndef __EPOC32__ #ifdef __GP2X__
/* we use our own buffering */ /* we use our own buffering */
setvbuf(f, NULL, _IONBF, 0); setvbuf(f, NULL, _IONBF, 0);
#endif #endif
@ -227,7 +227,7 @@ cso_failed:
strncpy(file->ext, ext, sizeof(file->ext) - 1); strncpy(file->ext, ext, sizeof(file->ext) - 1);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
#ifndef __EPOC32__ // makes things worse on Symbian #ifdef __GP2X__
if (file->size > 0x400000) if (file->size > 0x400000)
/* we use our own buffering */ /* we use our own buffering */
setvbuf(f, NULL, _IONBF, 0); setvbuf(f, NULL, _IONBF, 0);

View file

@ -1,43 +0,0 @@
/***********************************************************
* *
* This source was taken from the Gens project *
* Written by Stéphane Dallongeville *
* Copyright (c) 2002 by Stéphane Dallongeville *
* Modified/adapted for PicoDrive by notaz, 2007 *
* *
***********************************************************/
#ifndef _LC89510_H
#define _LC89510_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
// unsigned short Fader; // 34
// unsigned short Control; // 36
// unsigned short Cur_Comm;// unused
// "Receive status"
unsigned short Status;
unsigned short Minute;
unsigned short Seconde;
unsigned short Frame;
unsigned char Ext;
unsigned char pad[3];
} CDD;
PICO_INTERNAL void CDD_Export_Status(void);
PICO_INTERNAL void CDD_Import_Command(void);
void CDD_Reset(void);
#ifdef __cplusplus
};
#endif
#endif

View file

@ -1,152 +0,0 @@
/*
* Buffering handling
* (C) notaz, 2007,2008
*
* This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory.
*/
#include "../pico_int.h"
#include "../cd/cue.h"
int PicoCDBuffers = 0;
static unsigned char *cd_buffer = NULL;
static int prev_lba = 0x80000000;
static int hits, reads;
#undef dprintf
#define dprintf(...)
void PicoCDBufferInit(void)
{
void *tmp = NULL;
prev_lba = 0x80000000;
hits = reads = 0;
if (PicoCDBuffers <= 1) {
PicoCDBuffers = 0;
return; /* buffering off */
}
/* try alloc'ing until we succeed */
while (PicoCDBuffers > 0)
{
tmp = realloc(cd_buffer, PicoCDBuffers * 2048 + 304);
if (tmp != NULL) break;
PicoCDBuffers >>= 1;
}
if (PicoCDBuffers <= 0) return; /* buffering became off */
cd_buffer = tmp;
}
void PicoCDBufferFree(void)
{
if (cd_buffer) {
free(cd_buffer);
cd_buffer = NULL;
}
if (reads)
elprintf(EL_STATUS, "CD buffer hits: %i/%i (%i%%)\n", hits, reads, hits * 100 / reads);
}
void PicoCDBufferFlush(void)
{
prev_lba = 0x80000000;
}
/* this is was a try to fight slow SD access of GP2X */
PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
{
int is_bin, offs, read_len, moved = 0;
reads++;
is_bin = Pico_mcd->TOC.Tracks[0].ftype == CT_BIN;
if (PicoCDBuffers <= 0)
{
/* no buffering */
int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
pm_read(dest, 2048, Pico_mcd->TOC.Tracks[0].F);
return;
}
/* hit? */
offs = lba - prev_lba;
if (offs >= 0 && offs < PicoCDBuffers)
{
hits++;
if (offs == 0) dprintf("CD buffer seek to old %i -> %i\n", prev_lba, lba);
memcpy32(dest, (int *)(cd_buffer + offs*2048), 2048/4);
return;
}
if (prev_lba + PicoCDBuffers != lba)
{
int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
}
dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);
if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
{
read_len = prev_lba - lba;
dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
moved = 1;
}
else
{
read_len = PicoCDBuffers;
}
if (PicoMessage != NULL && read_len >= 512)
{
PicoMessage("Buffering data...");
}
if (is_bin)
{
int i = 0;
#ifdef _PSP_FW_VERSION
int bufs = (read_len*2048) / (2048+304);
pm_read(cd_buffer, bufs*(2048+304), Pico_mcd->TOC.Tracks[0].F);
for (i = 1; i < bufs; i++)
// should really use memmove here, but my memcpy32 implementation is also suitable here
memcpy32((int *)(cd_buffer + i*2048), (int *)(cd_buffer + i*(2048+304)), 2048/4);
#endif
for (; i < read_len - 1; i++)
{
pm_read(cd_buffer + i*2048, 2048 + 304, Pico_mcd->TOC.Tracks[0].F);
// pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR); // seeking is slower, in PSP case even more
}
// further data might be moved, do not overwrite
pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
}
else
{
pm_read(cd_buffer, read_len*2048, Pico_mcd->TOC.Tracks[0].F);
}
memcpy32(dest, (int *) cd_buffer, 2048/4);
prev_lba = lba;
if (moved)
{
/* file pointer must point to the same data in file, as would-be data after our buffer */
int where_seek;
lba += PicoCDBuffers;
where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
}
}

View file

@ -1,402 +0,0 @@
/***********************************************************
* *
* This source was taken from the Gens project *
* Written by Stéphane Dallongeville *
* Copyright (c) 2002 by Stéphane Dallongeville *
* Modified/adapted for PicoDrive by notaz, 2007 *
* *
***********************************************************/
#include "../pico_int.h"
#include "cd_file.h"
#include "cue.h"
//#define cdprintf(f,...) printf(f "\n",##__VA_ARGS__) // tmp
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;
}
}
static int audio_track_mp3(const char *fname, int index)
{
_scd_track *Tracks = Pico_mcd->TOC.Tracks;
FILE *tmp_file;
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); // used to calculate length
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
Tracks[index].KBtps = (short) mp3_get_bitrate(tmp_file, fs);
Tracks[index].KBtps >>= 3;
if (ret != 0 || Tracks[index].KBtps <= 0)
{
elprintf(EL_STATUS, "track %2i: mp3 bitrate %i", index+1, Tracks[index].KBtps);
#ifdef _PSP_FW_VERSION
free(tmp_file);
#else
fclose(tmp_file);
#endif
return -1;
}
Tracks[index].F = tmp_file;
// MP3 File
Tracks[index].ftype = CT_MP3;
fs *= 75;
fs /= Tracks[index].KBtps * 1000;
Tracks[index].Length = fs;
Tracks[index].Offset = 0;
return 0;
}
PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
{
int i, j, num_track, Cur_LBA, index, ret;
int iso_name_len, missed, cd_img_sectors;
_scd_track *Tracks = Pico_mcd->TOC.Tracks;
char tmp_name[256], tmp_ext[10], tmp_ext_u[10];
cue_data_t *cue_data = NULL;
pm_file *pmf;
static const char *exts[] = {
"%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3",
"%d.mp3", " %d.mp3", "-%d.mp3", "_%d.mp3", " - %d.mp3",
};
if (PicoCDLoadProgressCB != NULL)
PicoCDLoadProgressCB(cd_img_name, 1);
Unload_ISO();
/* is this a .cue? */
cue_data = cue_parse(cd_img_name);
if (cue_data != NULL) {
cd_img_name = cue_data->tracks[1].fname;
Tracks[0].ftype = cue_data->tracks[1].type;
}
else
Tracks[0].ftype = type == CIT_BIN ? CT_BIN : CT_ISO;
Tracks[0].F = pmf = pm_open(cd_img_name);
if (Tracks[0].F == NULL)
{
Tracks[0].ftype = 0;
Tracks[0].Length = 0;
if (cue_data != NULL)
cue_destroy(cue_data);
return -1;
}
if (Tracks[0].ftype == CT_ISO)
cd_img_sectors = pmf->size >>= 11; // size in sectors
else cd_img_sectors = pmf->size /= 2352;
Tracks[0].Offset = 0;
Tracks[0].MSF.M = 0; // minutes
Tracks[0].MSF.S = 2; // seconds
Tracks[0].MSF.F = 0; // frames
elprintf(EL_STATUS, "Track 1: %02d:%02d:%02d %9i DATA %s",
Tracks[0].MSF.M, Tracks[0].MSF.S, Tracks[0].MSF.F,
Tracks[0].Length, cd_img_name);
Cur_LBA = Tracks[0].Length = cd_img_sectors;
if (cue_data != NULL)
{
if (cue_data->tracks[2].fname == NULL) { // NULL means track2 is in same file as track1
Cur_LBA = Tracks[0].Length = cue_data->tracks[2].sector_offset;
}
i = 100 / cue_data->track_count+1;
for (num_track = 2; num_track <= cue_data->track_count; num_track++)
{
if (PicoCDLoadProgressCB != NULL)
PicoCDLoadProgressCB(cd_img_name, i * num_track);
index = num_track - 1;
Cur_LBA += cue_data->tracks[num_track].pregap;
if (cue_data->tracks[num_track].type == CT_MP3) {
ret = audio_track_mp3(cue_data->tracks[num_track].fname, index);
if (ret != 0) break;
}
else
{
Tracks[index].ftype = cue_data->tracks[num_track].type;
if (cue_data->tracks[num_track].fname != NULL)
{
pm_file *pmfn = pm_open(cue_data->tracks[num_track].fname);
if (pmfn != NULL)
{
// addume raw, ignore header for wav..
Tracks[index].F = pmfn;
Tracks[index].Length = pmfn->size / 2352;
Tracks[index].Offset = cue_data->tracks[num_track].sector_offset;
}
else
{
elprintf(EL_STATUS, "track %2i (%s): can't determine length",
num_track, cue_data->tracks[num_track].fname);
Tracks[index].Length = 2*75;
Tracks[index].Offset = 0;
}
}
else
{
if (num_track < cue_data->track_count)
Tracks[index].Length = cue_data->tracks[num_track+1].sector_offset -
cue_data->tracks[num_track].sector_offset;
else
Tracks[index].Length = cd_img_sectors - cue_data->tracks[num_track].sector_offset;
Tracks[index].Offset = cue_data->tracks[num_track].sector_offset;
}
}
if (cue_data->tracks[num_track].sector_xlength != 0)
// overriden by custom cue command
Tracks[index].Length = cue_data->tracks[num_track].sector_xlength;
LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
Cur_LBA += Tracks[index].Length;
elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO %s", num_track, Tracks[index].MSF.M,
Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length,
cue_data->tracks[num_track].fname);
}
cue_destroy(cue_data);
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 (num_track = 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 = num_track - 1;
sprintf(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 = audio_track_mp3(tmp_name, index);
if (ret != 0) {
strcpy(p, tmp_ext_u);
ret = audio_track_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 = audio_track_mp3(tmp_name, index);
if (ret != 0) {
strcpy(p, tmp_ext_u);
ret = audio_track_mp3(tmp_name, index);
}
}
if (ret == 0)
{
LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
Cur_LBA += Tracks[index].Length;
elprintf(EL_STATUS, "Track %2i: %02d:%02d:%02d %9i AUDIO - %s", num_track, Tracks[index].MSF.M,
Tracks[index].MSF.S, Tracks[index].MSF.F, Tracks[index].Length, tmp_name);
num_track++;
missed = 0;
break;
}
}
if (ret != 0 && i > 1) missed++;
}
finish:
Pico_mcd->TOC.Last_Track = num_track - 1;
index = num_track - 1;
LBA_to_MSF(Cur_LBA, &Tracks[index].MSF);
elprintf(EL_STATUS, "End CD - %02d:%02d:%02d\n", Tracks[index].MSF.M,
Tracks[index].MSF.S, Tracks[index].MSF.F);
if (PicoCDLoadProgressCB != NULL)
PicoCDLoadProgressCB(cd_img_name, 100);
return 0;
}
PICO_INTERNAL void Unload_ISO(void)
{
int i;
if (Pico_mcd == NULL) return;
if (Pico_mcd->TOC.Tracks[0].F) pm_close(Pico_mcd->TOC.Tracks[0].F);
for(i = 1; i < 100; i++)
{
if (Pico_mcd->TOC.Tracks[i].F != NULL)
{
if (Pico_mcd->TOC.Tracks[i].ftype == CT_MP3)
#ifdef _PSP_FW_VERSION
free(Pico_mcd->TOC.Tracks[i].F);
#else
fclose(Pico_mcd->TOC.Tracks[i].F);
#endif
else
pm_close(Pico_mcd->TOC.Tracks[i].F);
}
}
memset(Pico_mcd->TOC.Tracks, 0, sizeof(Pico_mcd->TOC.Tracks));
}
#if 1*0
PICO_INTERNAL int FILE_Read_One_LBA_CDC(void)
{
if (Pico_mcd->s68k_regs[0x36] & 1) // DATA
{
if (Pico_mcd->TOC.Tracks[0].F == NULL) return -1;
// moved below..
//fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
//fread(cp_buf, 1, 2048, Pico_mcd->TOC.Tracks[0].F);
cdprintf("Read file CDC 1 data sector :\n");
}
else // AUDIO
{
cdprintf("Read file CDC 1 audio sector :\n");
}
// Update CDC stuff
CDC_Update_Header();
if (Pico_mcd->s68k_regs[0x36] & 1) // DATA track
{
if (Pico_mcd->cdc.CTRL.B.B0 & 0x80) // DECEN = decoding enable
{
if (Pico_mcd->cdc.CTRL.B.B0 & 0x04) // WRRQ : this bit enable write to buffer
{
int where_read = 0;
// CAUTION : lookahead bit not implemented
if (Pico_mcd->scd.Cur_LBA < 0)
where_read = 0;
else if (Pico_mcd->scd.Cur_LBA >= Pico_mcd->TOC.Tracks[0].Length)
where_read = Pico_mcd->TOC.Tracks[0].Length - 1;
else where_read = Pico_mcd->scd.Cur_LBA;
Pico_mcd->scd.Cur_LBA++;
Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF; // add one sector to WA
Pico_mcd->cdc.PT.N = (Pico_mcd->cdc.PT.N + 2352) & 0x7FFF;
*(unsigned int *)(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N) = Pico_mcd->cdc.HEAD.N;
//memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N + 4], cp_buf, 2048);
//pm_seek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
//pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F);
PicoCDBufferRead(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, where_read);
cdprintf("Read -> WA = %d Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF);
cdprintf("Header 1 = %.2X %.2X %.2X %.2X", Pico_mcd->cdc.HEAD.B.B0,
Pico_mcd->cdc.HEAD.B.B1, Pico_mcd->cdc.HEAD.B.B2, Pico_mcd->cdc.HEAD.B.B3);
cdprintf("Header 2 = %.2X %.2X %.2X %.2X --- %.2X %.2X\n\n",
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 0) & 0x3FFF],
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 1) & 0x3FFF],
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 2) & 0x3FFF],
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 3) & 0x3FFF],
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 4) & 0x3FFF],
Pico_mcd->cdc.Buffer[(Pico_mcd->cdc.PT.N + 5) & 0x3FFF]);
}
}
}
else // music track
{
Pico_mcd->scd.Cur_LBA++;
Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF; // add one sector to WA
Pico_mcd->cdc.PT.N = (Pico_mcd->cdc.PT.N + 2352) & 0x7FFF;
if (Pico_mcd->cdc.CTRL.B.B0 & 0x80) // DECEN = decoding enable
{
if (Pico_mcd->cdc.CTRL.B.B0 & 0x04) // WRRQ : this bit enable write to buffer
{
// CAUTION : lookahead bit not implemented
// this is pretty rough, but oh well - not much depends on this anyway
memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N], cdda_out_buffer, 2352);
}
}
}
if (Pico_mcd->cdc.CTRL.B.B0 & 0x80) // DECEN = decoding enable
{
Pico_mcd->cdc.STAT.B.B0 = 0x80;
if (Pico_mcd->cdc.CTRL.B.B0 & 0x10) // determine form bit form sub header ?
{
Pico_mcd->cdc.STAT.B.B2 = Pico_mcd->cdc.CTRL.B.B1 & 0x08;
}
else
{
Pico_mcd->cdc.STAT.B.B2 = Pico_mcd->cdc.CTRL.B.B1 & 0x0C;
}
if (Pico_mcd->cdc.CTRL.B.B0 & 0x02) Pico_mcd->cdc.STAT.B.B3 = 0x20; // ECC done
else Pico_mcd->cdc.STAT.B.B3 = 0x00; // ECC not done
if (Pico_mcd->cdc.IFCTRL & 0x20)
{
if (Pico_mcd->s68k_regs[0x33] & (1<<5))
{
elprintf(EL_INTS, "cdc dec irq 5");
SekInterruptS68k(5);
}
Pico_mcd->cdc.IFSTAT &= ~0x20; // DEC interrupt happen
Pico_mcd->cdc.Decode_Reg_Read = 0; // Reset read after DEC int
}
}
return 0;
}
#endif

View file

@ -1,27 +0,0 @@
#ifndef _CD_FILE_H
#define _CD_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
CIT_NOT_CD = 0,
CIT_ISO,
CIT_BIN,
CIT_CUE
}
cd_img_type;
PICO_INTERNAL int Load_CD_Image(const char *iso_name, cd_img_type type);
PICO_INTERNAL void Unload_ISO(void);
PICO_INTERNAL int FILE_Read_One_LBA_CDC(void);
#ifdef __cplusplus
};
#endif
#endif

266
pico/cd/cd_image.c Normal file
View file

@ -0,0 +1,266 @@
/*
* 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);
}
cue_destroy(cue_data);
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);
return 0;
}
// vim:shiftwidth=2:ts=2:expandtab

View file

@ -1,933 +0,0 @@
/***********************************************************
* *
* This source file was taken from the Gens project *
* Written by Stéphane Dallongeville *
* Copyright (c) 2002 by Stéphane Dallongeville *
* Modified/adapted for PicoDrive by notaz, 2007 *
* *
***********************************************************/
#include <stdio.h>
#include "../pico_int.h"
#include "cd_sys.h"
#include "cd_file.h"
#define DEBUG_CD
#define TRAY_OPEN 0x0500 // TRAY OPEN CDD status
#define NOCD 0x0000 // CD removed CDD status
#define STOPPED 0x0900 // STOPPED CDD status (happen after stop or close tray command)
#define READY 0x0400 // READY CDD status (also used for seeking)
#define FAST_FOW 0x0300 // FAST FORWARD track CDD status
#define FAST_REV 0x10300 // FAST REVERSE track CDD status
#define PLAYING 0x0100 // PLAYING audio track CDD status
//#undef cdprintf
//#define cdprintf(x, ...) elprintf(EL_STATUS, x, ##__VA_ARGS__)
#define CDC_Update_Header()
static int CD_Present = 0;
#define CHECK_TRAY_OPEN \
if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) \
{ \
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \
\
Pico_mcd->cdd.Minute = 0; \
Pico_mcd->cdd.Seconde = 0; \
Pico_mcd->cdd.Frame = 0; \
Pico_mcd->cdd.Ext = 0; \
\
Pico_mcd->scd.CDD_Complete = 1; \
\
return 2; \
}
#define CHECK_CD_PRESENT \
if (!CD_Present) \
{ \
Pico_mcd->scd.Status_CDD = NOCD; \
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD; \
\
Pico_mcd->cdd.Minute = 0; \
Pico_mcd->cdd.Seconde = 0; \
Pico_mcd->cdd.Frame = 0; \
Pico_mcd->cdd.Ext = 0; \
\
Pico_mcd->scd.CDD_Complete = 1; \
\
return 3; \
}
static int MSF_to_LBA(_msf *MSF)
{
return (MSF->M * 60 * 75) + (MSF->S * 75) + MSF->F - 150;
}
PICO_INTERNAL void LBA_to_MSF(int lba, _msf *MSF)
{
if (lba < -150) lba = 0;
else lba += 150;
MSF->M = lba / (60 * 75);
MSF->S = (lba / 75) % 60;
MSF->F = lba % 75;
}
static unsigned int MSF_to_Track(_msf *MSF)
{
int i, Start, Cur;
Start = (MSF->M << 16) + (MSF->S << 8) + MSF->F;
for(i = 1; i <= (Pico_mcd->TOC.Last_Track + 1); i++)
{
Cur = Pico_mcd->TOC.Tracks[i - 1].MSF.M << 16;
Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.S << 8;
Cur += Pico_mcd->TOC.Tracks[i - 1].MSF.F;
if (Cur > Start) break;
}
--i;
if (i > Pico_mcd->TOC.Last_Track) return 100;
else if (i < 1) i = 1;
return (unsigned) i;
}
static unsigned int LBA_to_Track(int lba)
{
_msf MSF;
LBA_to_MSF(lba, &MSF);
return MSF_to_Track(&MSF);
}
static void Track_to_MSF(int track, _msf *MSF)
{
if (track < 1) track = 1;
else if (track > Pico_mcd->TOC.Last_Track) track = Pico_mcd->TOC.Last_Track;
MSF->M = Pico_mcd->TOC.Tracks[track - 1].MSF.M;
MSF->S = Pico_mcd->TOC.Tracks[track - 1].MSF.S;
MSF->F = Pico_mcd->TOC.Tracks[track - 1].MSF.F;
}
PICO_INTERNAL int Track_to_LBA(int track)
{
_msf MSF;
Track_to_MSF(track, &MSF);
return MSF_to_LBA(&MSF);
}
PICO_INTERNAL void Check_CD_Command(void)
{
cdprintf("CHECK CD COMMAND");
// Check CDC
if (Pico_mcd->scd.Status_CDC & 1) // CDC is reading data ...
{
cdprintf("Got a read command");
// DATA ?
if (Pico_mcd->scd.Cur_Track == 1) {
Pico_mcd->s68k_regs[0x36] |= 0x01;
if (Pico_mcd->scd.File_Add_Delay == 0)
{
unsigned char header[4];
_msf MSF;
LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);
header[0] = INT_TO_BCDB(MSF.M);
header[1] = INT_TO_BCDB(MSF.S);
header[2] = INT_TO_BCDB(MSF.F);
header[3] = 0x01;
//FILE_Read_One_LBA_CDC();
Pico_mcd->scd.Cur_LBA +=
cdc_decoder_update(header);
}
else Pico_mcd->scd.File_Add_Delay--;
}
else {
Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO
unsigned char header[4] = { 0, };
cdc_decoder_update(header);
}
}
// Check CDD
if (Pico_mcd->scd.CDD_Complete)
{
Pico_mcd->scd.CDD_Complete = 0;
CDD_Export_Status();
}
if (Pico_mcd->scd.Status_CDD == FAST_FOW)
{
Pico_mcd->scd.Cur_LBA += 10;
CDC_Update_Header();
}
else if (Pico_mcd->scd.Status_CDD == FAST_REV)
{
Pico_mcd->scd.Cur_LBA -= 10;
if (Pico_mcd->scd.Cur_LBA < -150) Pico_mcd->scd.Cur_LBA = -150;
CDC_Update_Header();
}
}
PICO_INTERNAL int Init_CD_Driver(void)
{
return 0;
}
PICO_INTERNAL void End_CD_Driver(void)
{
Unload_ISO();
}
PICO_INTERNAL void Reset_CD(void)
{
Pico_mcd->scd.Cur_Track = 0;
Pico_mcd->scd.Cur_LBA = -150;
Pico_mcd->scd.Status_CDC &= ~1;
if (Pico_mcd->scd.Status_CDD != TRAY_OPEN)
Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;
Pico_mcd->scd.CDD_Complete = 0;
Pico_mcd->scd.File_Add_Delay = 0;
}
int Insert_CD(const char *cdimg_name, int type)
{
int ret = 1;
CD_Present = 0;
if (cdimg_name != NULL && type != CIT_NOT_CD)
{
ret = Load_CD_Image(cdimg_name, type);
if (ret == 0) {
CD_Present = 1;
if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)
{
if (Pico_mcd->bios[0x122 ^ 1] == '2')
Close_Tray_CDD_cC();
// else bios will issue it
}
else
{
Pico_mcd->scd.Status_CDD = READY;
}
}
}
if (Pico_mcd->scd.Status_CDD != TRAY_OPEN && !CD_Present)
Pico_mcd->scd.Status_CDD = NOCD;
return ret;
}
int Stop_CD(void)
{
int ret = CD_Present;
Unload_ISO();
CD_Present = 0;
return ret;
}
/*
PICO_INTERNAL void Change_CD(void)
{
if (Pico_mcd->scd.Status_CDD == TRAY_OPEN) Close_Tray_CDD_cC();
else Open_Tray_CDD_cD();
}
*/
PICO_INTERNAL int Get_Status_CDD_c0(void)
{
cdprintf("Status command : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);
// Clear immediat status
if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0200)
Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);
else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0700)
Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);
else if ((Pico_mcd->cdd.Status & 0x0F00) == 0x0E00)
Pico_mcd->cdd.Status = (Pico_mcd->scd.Status_CDD & 0xFF00) | (Pico_mcd->cdd.Status & 0x00FF);
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Stop_CDD_c1(void)
{
CHECK_TRAY_OPEN
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
if (CD_Present) Pico_mcd->scd.Status_CDD = STOPPED;
else Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status = 0x0000;
Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_Pos_CDD_c20(void)
{
_msf MSF;
cdprintf("command 200 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);
CHECK_TRAY_OPEN
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);
LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);
Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);
Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);
Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_Track_Pos_CDD_c21(void)
{
int elapsed_time;
_msf MSF;
cdprintf("command 201 : Cur LBA = %d", Pico_mcd->scd.Cur_LBA);
CHECK_TRAY_OPEN
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
elapsed_time = Pico_mcd->scd.Cur_LBA - Track_to_LBA(LBA_to_Track(Pico_mcd->scd.Cur_LBA));
LBA_to_MSF(elapsed_time - 150, &MSF);
cdprintf(" elapsed = %d", elapsed_time);
Pico_mcd->cdd.Minute = INT_TO_BCDW(MSF.M);
Pico_mcd->cdd.Seconde = INT_TO_BCDW(MSF.S);
Pico_mcd->cdd.Frame = INT_TO_BCDW(MSF.F);
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_Current_Track_CDD_c22(void)
{
cdprintf("Status CDD = %.4X Status = %.4X", Pico_mcd->scd.Status_CDD, Pico_mcd->cdd.Status);
CHECK_TRAY_OPEN
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);
if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;
else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_Total_Lenght_CDD_c23(void)
{
CHECK_TRAY_OPEN
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.M);
Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.S);
Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[Pico_mcd->TOC.Last_Track].MSF.F);
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_First_Last_Track_CDD_c24(void)
{
CHECK_TRAY_OPEN
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Minute = INT_TO_BCDW(1);
Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Last_Track);
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Get_Track_Adr_CDD_c25(void)
{
int track_number;
CHECK_TRAY_OPEN
// track number in TC4 & TC5
track_number = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);
Pico_mcd->cdd.Status &= 0xFF;
if (!CD_Present)
{
Pico_mcd->scd.Status_CDD = NOCD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
}
// else if (!(CDC.CTRL.B.B0 & 0x80)) Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Status |= Pico_mcd->scd.Status_CDD;
if (track_number > Pico_mcd->TOC.Last_Track) track_number = Pico_mcd->TOC.Last_Track;
else if (track_number < 1) track_number = 1;
Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.M);
Pico_mcd->cdd.Seconde = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.S);
Pico_mcd->cdd.Frame = INT_TO_BCDW(Pico_mcd->TOC.Tracks[track_number - 1].MSF.F);
Pico_mcd->cdd.Ext = track_number % 10;
if (track_number == 1) Pico_mcd->cdd.Frame |= 0x0800; // data track
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Play_CDD_c3(void)
{
_msf MSF;
int delay, new_lba;
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
// MSF of the track to play in TC buffer
MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);
MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);
MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);
Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);
new_lba = MSF_to_LBA(&MSF);
delay = new_lba - Pico_mcd->scd.Cur_LBA;
if (delay < 0) delay = -delay;
delay >>= 12;
if (Pico_mcd->scd.Cur_LBA > 0 && delay < 13)
// based on genplus GX
delay = 13;
Pico_mcd->scd.Cur_LBA = new_lba;
CDC_Update_Header();
cdprintf("Read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);
if (Pico_mcd->scd.Status_CDD != PLAYING) delay += 20;
Pico_mcd->scd.Status_CDD = PLAYING;
Pico_mcd->cdd.Status = 0x0102;
// Pico_mcd->cdd.Status = COMM_OK;
if (Pico_mcd->scd.File_Add_Delay == 0) Pico_mcd->scd.File_Add_Delay = delay;
if (Pico_mcd->scd.Cur_Track == 1)
{
Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA
}
else
{
Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO
cdda_start_play();
}
if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;
else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Seek_CDD_c4(void)
{
_msf MSF;
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
// MSF to seek in TC buffer
MSF.M = (Pico_mcd->s68k_regs[0x38+10+2] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+3] & 0xF);
MSF.S = (Pico_mcd->s68k_regs[0x38+10+4] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+5] & 0xF);
MSF.F = (Pico_mcd->s68k_regs[0x38+10+6] & 0xF) * 10 + (Pico_mcd->s68k_regs[0x38+10+7] & 0xF);
Pico_mcd->scd.Cur_Track = MSF_to_Track(&MSF);
Pico_mcd->scd.Cur_LBA = MSF_to_LBA(&MSF);
CDC_Update_Header();
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
Pico_mcd->scd.Status_CDD = READY;
Pico_mcd->cdd.Status = 0x0200;
// DATA ?
if (Pico_mcd->scd.Cur_Track == 1)
Pico_mcd->s68k_regs[0x36] |= 0x01;
else Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Pause_CDD_c6(void)
{
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read to start a new one if raw data
Pico_mcd->scd.Status_CDD = READY;
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;
Pico_mcd->s68k_regs[0x36] |= 0x01; // Data bit set because stopped
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Resume_CDD_c7(void)
{
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
Pico_mcd->scd.Cur_Track = LBA_to_Track(Pico_mcd->scd.Cur_LBA);
#ifdef DEBUG_CD
{
_msf MSF;
LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);
cdprintf("Resume read : Cur LBA = %d, M=%d, S=%d, F=%d", Pico_mcd->scd.Cur_LBA, MSF.M, MSF.S, MSF.F);
}
#endif
Pico_mcd->scd.Status_CDD = PLAYING;
Pico_mcd->cdd.Status = 0x0102;
if (Pico_mcd->scd.Cur_Track == 1)
{
Pico_mcd->s68k_regs[0x36] |= 0x01; // DATA
}
else
{
Pico_mcd->s68k_regs[0x36] &= ~0x01; // AUDIO
cdda_start_play();
}
if (Pico_mcd->scd.Cur_Track == 100) Pico_mcd->cdd.Minute = 0x0A02;
else Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.Status_CDC |= 1; // Read data with CDC
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Fast_Foward_CDD_c8(void)
{
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
Pico_mcd->scd.Status_CDD = FAST_FOW;
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;
Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Fast_Rewind_CDD_c9(void)
{
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
Pico_mcd->scd.Status_CDD = FAST_REV;
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD | 2;
Pico_mcd->cdd.Minute = INT_TO_BCDW(Pico_mcd->scd.Cur_Track);
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Close_Tray_CDD_cC(void)
{
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
elprintf(EL_STATUS, "tray close\n");
if (PicoMCDcloseTray != NULL)
PicoMCDcloseTray();
Pico_mcd->scd.Status_CDD = CD_Present ? STOPPED : NOCD;
Pico_mcd->cdd.Status = 0x0000;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int Open_Tray_CDD_cD(void)
{
CHECK_TRAY_OPEN
Pico_mcd->scd.Status_CDC &= ~1; // Stop CDC read
elprintf(EL_STATUS, "tray open\n");
Unload_ISO();
CD_Present = 0;
if (PicoMCDopenTray != NULL)
PicoMCDopenTray();
Pico_mcd->scd.Status_CDD = TRAY_OPEN;
Pico_mcd->cdd.Status = 0x0E00;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int CDD_cA(void)
{
CHECK_TRAY_OPEN
CHECK_CD_PRESENT
Pico_mcd->scd.Status_CDC &= ~1;
Pico_mcd->scd.Status_CDD = READY;
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = INT_TO_BCDW(1);
Pico_mcd->cdd.Frame = INT_TO_BCDW(1);
Pico_mcd->cdd.Ext = 0;
Pico_mcd->scd.CDD_Complete = 1;
return 0;
}
PICO_INTERNAL int CDD_Def(void)
{
Pico_mcd->cdd.Status = Pico_mcd->scd.Status_CDD;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
return 0;
}
static int bswapwrite(int a, unsigned short d)
{
*(unsigned short *)(Pico_mcd->s68k_regs + a) = (d>>8)|(d<<8);
return d + (d >> 8);
}
PICO_INTERNAL void CDD_Export_Status(void)
{
unsigned int csum;
csum = bswapwrite( 0x38+0, Pico_mcd->cdd.Status);
csum += bswapwrite( 0x38+2, Pico_mcd->cdd.Minute);
csum += bswapwrite( 0x38+4, Pico_mcd->cdd.Seconde);
csum += bswapwrite( 0x38+6, Pico_mcd->cdd.Frame);
Pico_mcd->s68k_regs[0x38+8] = Pico_mcd->cdd.Ext;
csum += Pico_mcd->cdd.Ext;
Pico_mcd->s68k_regs[0x38+9] = ~csum & 0xf;
Pico_mcd->s68k_regs[0x37] &= 3; // CDD.Control
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4)
{
elprintf(EL_INTS, "cdd export irq 4");
SekInterruptS68k(4);
}
// cdprintf("CDD exported status\n");
cdprintf("out: Status=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",
(Pico_mcd->s68k_regs[0x38+0] << 8) | Pico_mcd->s68k_regs[0x38+1],
(Pico_mcd->s68k_regs[0x38+2] << 8) | Pico_mcd->s68k_regs[0x38+3],
(Pico_mcd->s68k_regs[0x38+4] << 8) | Pico_mcd->s68k_regs[0x38+5],
(Pico_mcd->s68k_regs[0x38+6] << 8) | Pico_mcd->s68k_regs[0x38+7],
(Pico_mcd->s68k_regs[0x38+8] << 8) | Pico_mcd->s68k_regs[0x38+9]);
}
PICO_INTERNAL void CDD_Import_Command(void)
{
// cdprintf("CDD importing command\n");
cdprintf("in: Command=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X",
(Pico_mcd->s68k_regs[0x38+10+0] << 8) | Pico_mcd->s68k_regs[0x38+10+1],
(Pico_mcd->s68k_regs[0x38+10+2] << 8) | Pico_mcd->s68k_regs[0x38+10+3],
(Pico_mcd->s68k_regs[0x38+10+4] << 8) | Pico_mcd->s68k_regs[0x38+10+5],
(Pico_mcd->s68k_regs[0x38+10+6] << 8) | Pico_mcd->s68k_regs[0x38+10+7],
(Pico_mcd->s68k_regs[0x38+10+8] << 8) | Pico_mcd->s68k_regs[0x38+10+9]);
switch (Pico_mcd->s68k_regs[0x38+10+0])
{
case 0x0: // STATUS (?)
Get_Status_CDD_c0();
break;
case 0x1: // STOP ALL (?)
Stop_CDD_c1();
break;
case 0x2: // GET TOC INFORMATIONS
switch(Pico_mcd->s68k_regs[0x38+10+3])
{
case 0x0: // get current position (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00);
Get_Pos_CDD_c20();
break;
case 0x1: // get elapsed time of current track played/scanned (relative MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 1;
Get_Track_Pos_CDD_c21();
break;
case 0x2: // get current track in RS2-RS3
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 2;
Get_Current_Track_CDD_c22();
break;
case 0x3: // get total length (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 3;
Get_Total_Lenght_CDD_c23();
break;
case 0x4: // first & last track number
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 4;
Get_First_Last_Track_CDD_c24();
break;
case 0x5: // get track addresse (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 5;
Get_Track_Adr_CDD_c25();
break;
default : // invalid, then we return status
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 0xF;
Get_Status_CDD_c0();
break;
}
break;
case 0x3: // READ
Play_CDD_c3();
break;
case 0x4: // SEEK
Seek_CDD_c4();
break;
case 0x6: // PAUSE/STOP
Pause_CDD_c6();
break;
case 0x7: // RESUME
Resume_CDD_c7();
break;
case 0x8: // FAST FOWARD
Fast_Foward_CDD_c8();
break;
case 0x9: // FAST REWIND
Fast_Rewind_CDD_c9();
break;
case 0xA: // RECOVER INITIAL STATE (?)
CDD_cA();
break;
case 0xC: // CLOSE TRAY
Close_Tray_CDD_cC();
break;
case 0xD: // OPEN TRAY
Open_Tray_CDD_cD();
break;
default: // UNKNOWN
CDD_Def();
break;
}
}
void CDD_Reset(void)
{
// Reseting CDD
memset(Pico_mcd->s68k_regs+0x34, 0, 2*2); // CDD.Fader, CDD.Control
Pico_mcd->cdd.Status = 0;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
// clear receive status and transfer command
memset(Pico_mcd->s68k_regs+0x38, 0, 20);
Pico_mcd->s68k_regs[0x38+9] = 0xF; // Default checksum
}

View file

@ -1,109 +0,0 @@
/***********************************************************
* *
* This source was taken from the Gens project *
* Written by Stéphane Dallongeville *
* Copyright (c) 2002 by Stéphane Dallongeville *
* Modified/adapted for PicoDrive by notaz, 2007 *
* *
***********************************************************/
#ifndef _CD_SYS_H
#define _CD_SYS_H
#include "cd_file.h"
#ifdef __cplusplus
extern "C" {
#endif
#define INT_TO_BCDB(c) \
((c) > 99)?(0x99):((((c) / 10) << 4) + ((c) % 10));
#define INT_TO_BCDW(c) \
((c) > 99)?(0x0909):((((c) / 10) << 8) + ((c) % 10));
#define BCDB_TO_INT(c) \
(((c) >> 4) * 10) + ((c) & 0xF);
#define BCDW_TO_INT(c) \
(((c) >> 8) * 10) + ((c) & 0xF);
typedef struct
{
unsigned char M;
unsigned char S;
unsigned char F;
} _msf;
typedef struct
{
_msf MSF;
//
char ftype; // cue_track_type
void *F;
int Length;
int Offset; // sector offset, when single file is used for multiple virtual tracks
short KBtps; // kbytes per sec for mp3s (bitrate / 1000 / 8)
short pad;
} _scd_track;
typedef struct
{
// unsigned char First_Track; // always 1
_scd_track Tracks[100];
unsigned int Last_Track;
} _scd_toc;
typedef struct {
unsigned int Status_CDD;
unsigned int Status_CDC;
int Cur_LBA;
unsigned int Cur_Track;
int File_Add_Delay;
char CDD_Complete;
int pad[6];
} _scd;
PICO_INTERNAL void LBA_to_MSF(int lba, _msf *MSF);
PICO_INTERNAL int Track_to_LBA(int track);
// moved to pico.h
// int Insert_CD(char *iso_name, int is_bin);
// void Stop_CD(void);
PICO_INTERNAL void Check_CD_Command(void);
PICO_INTERNAL int Init_CD_Driver(void);
PICO_INTERNAL void End_CD_Driver(void);
PICO_INTERNAL void Reset_CD(void);
PICO_INTERNAL int Get_Status_CDD_c0(void);
PICO_INTERNAL int Stop_CDD_c1(void);
PICO_INTERNAL int Get_Pos_CDD_c20(void);
PICO_INTERNAL int Get_Track_Pos_CDD_c21(void);
PICO_INTERNAL int Get_Current_Track_CDD_c22(void);
PICO_INTERNAL int Get_Total_Lenght_CDD_c23(void);
PICO_INTERNAL int Get_First_Last_Track_CDD_c24(void);
PICO_INTERNAL int Get_Track_Adr_CDD_c25(void);
PICO_INTERNAL int Play_CDD_c3(void);
PICO_INTERNAL int Seek_CDD_c4(void);
PICO_INTERNAL int Pause_CDD_c6(void);
PICO_INTERNAL int Resume_CDD_c7(void);
PICO_INTERNAL int Fast_Foward_CDD_c8(void);
PICO_INTERNAL int Fast_Rewind_CDD_c9(void);
PICO_INTERNAL int CDD_cA(void);
PICO_INTERNAL int Close_Tray_CDD_cC(void);
PICO_INTERNAL int Open_Tray_CDD_cD(void);
PICO_INTERNAL int CDD_Def(void);
#ifdef __cplusplus
};
#endif
#endif

View file

@ -341,19 +341,6 @@ update_dma:
Pico_mcd->s68k_regs[0x0b] = dma_addr; Pico_mcd->s68k_regs[0x0b] = dma_addr;
} }
// tmp
static void cdd_read_data(uint8 *dst)
{
int lba = Pico_mcd->scd.Cur_LBA;
/* only read DATA track sectors */
if (0 <= lba && lba < Pico_mcd->TOC.Tracks[0].Length)
{
/* read sector data (Mode 1 = 2048 bytes) */
PicoCDBufferRead(dst, lba);
}
}
void cdc_dma_update(void) void cdc_dma_update(void)
{ {
/* end of DMA transfer ? */ /* end of DMA transfer ? */

1328
pico/cd/cdd.c Normal file

File diff suppressed because it is too large Load diff

98
pico/cd/cdd.h Normal file
View file

@ -0,0 +1,98 @@
/***************************************************************************************
* Genesis Plus
* CD drive processor & CD-DA fader
*
* Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
*
* - Redistributions may not be sold, nor may they be used in a commercial
* product or activity.
*
* - Redistributions that are modified from the original source must include the
* complete source code, including the source code for all components used by a
* binary built from the modified sources. However, as a special exception, the
* source code distributed need not include anything that is normally distributed
* (in either source or binary form) with the major components (compiler, kernel,
* and so on) of the operating system on which the executable runs, unless that
* component itself accompanies the executable.
*
* - Redistributions must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************************/
#ifndef _HW_CDD_
#define _HW_CDD_
#ifdef USE_LIBTREMOR
#include "tremor/ivorbisfile.h"
#endif
/* CDD status */
#define NO_DISC 0x00
#define CD_PLAY 0x01
#define CD_SEEK 0x02
#define CD_SCAN 0x03
#define CD_READY 0x04
#define CD_OPEN 0x05 /* similar to 0x0E ? */
#define CD_STOP 0x09
#define CD_END 0x0C
/* CD blocks scanning speed */
#define CD_SCAN_SPEED 30
#define CD_MAX_TRACKS 100
/* CD track */
typedef struct
{
void *fd;
#ifdef USE_LIBTREMOR
OggVorbis_File vf;
#endif
int offset;
int start;
int end;
} track_t;
/* CD TOC */
typedef struct
{
int end;
int last;
track_t tracks[CD_MAX_TRACKS];
} toc_t;
/* CDD hardware */
typedef struct
{
uint32 cycles;
uint32 latency;
int loaded;
int index;
int lba;
int scanOffset;
int volume;
uint8 status;
uint16 sectorSize;
toc_t toc;
int16 audio[2];
} cdd_t;
extern cdd_t cdd;
#endif

View file

@ -242,6 +242,8 @@ file_ok:
data->tracks[count].type = CT_MP3; data->tracks[count].type = CT_MP3;
else if (strcasecmp(ext, "wav") == 0) else if (strcasecmp(ext, "wav") == 0)
data->tracks[count].type = CT_WAV; data->tracks[count].type = CT_WAV;
else if (strcasecmp(ext, "bin") == 0)
data->tracks[count].type = CT_BIN;
else { else {
elprintf(EL_STATUS, "unhandled audio format: \"%s\"", elprintf(EL_STATUS, "unhandled audio format: \"%s\"",
data->tracks[count].fname); data->tracks[count].fname);

View file

@ -22,13 +22,10 @@ void (*PicoMCDcloseTray)(void) = NULL;
PICO_INTERNAL void PicoInitMCD(void) PICO_INTERNAL void PicoInitMCD(void)
{ {
SekInitS68k(); SekInitS68k();
Init_CD_Driver();
gfx_init();
} }
PICO_INTERNAL void PicoExitMCD(void) PICO_INTERNAL void PicoExitMCD(void)
{ {
End_CD_Driver();
} }
PICO_INTERNAL void PicoPowerMCD(void) PICO_INTERNAL void PicoPowerMCD(void)
@ -45,9 +42,11 @@ PICO_INTERNAL void PicoPowerMCD(void)
memset(Pico_mcd->s68k_regs, 0, sizeof(Pico_mcd->s68k_regs)); memset(Pico_mcd->s68k_regs, 0, sizeof(Pico_mcd->s68k_regs));
memset(&Pico_mcd->pcm, 0, sizeof(Pico_mcd->pcm)); memset(&Pico_mcd->pcm, 0, sizeof(Pico_mcd->pcm));
memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m));
Pico_mcd->s68k_regs[0x38+9] = 0x0f; // default checksum
cdc_init(); cdc_init();
Reset_CD(); cdd_reset();
gfx_init();
// cold reset state (tested) // cold reset state (tested)
Pico_mcd->m.state_flags = PCD_ST_S68K_RST; Pico_mcd->m.state_flags = PCD_ST_S68K_RST;
@ -62,7 +61,7 @@ void pcd_soft_reset(void)
Pico_mcd->m.s68k_pend_ints = 0; Pico_mcd->m.s68k_pend_ints = 0;
cdc_reset(); cdc_reset();
CDD_Reset(); cdd_reset();
#ifdef _ASM_CD_MEMORY_C #ifdef _ASM_CD_MEMORY_C
//PicoMemResetCDdecode(1); // don't have to call this in 2M mode //PicoMemResetCDdecode(1); // don't have to call this in 2M mode
#endif #endif
@ -135,7 +134,20 @@ unsigned int pcd_cycles_m68k_to_s68k(unsigned int c)
static void pcd_cdc_event(unsigned int now) static void pcd_cdc_event(unsigned int now)
{ {
// 75Hz CDC update // 75Hz CDC update
Check_CD_Command(); cdd_update();
/* check if a new CDD command has been processed */
if (!(Pico_mcd->s68k_regs[0x4b] & 0xf0))
{
/* reset CDD command wait flag */
Pico_mcd->s68k_regs[0x4b] = 0xf0;
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) {
elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4");
SekInterruptS68k(4);
}
}
pcd_event_schedule(now, PCD_EVENT_CDC, 12500000/75); pcd_event_schedule(now, PCD_EVENT_CDC, 12500000/75);
} }

View file

@ -407,8 +407,11 @@ void s68k_reg_write8(u32 a, u32 d)
elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d); elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d);
d &= 0x7e; d &= 0x7e;
if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) { if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) {
if (Pico_mcd->s68k_regs[0x37] & 4) // XXX: emulate pending irq instead?
CDD_Export_Status(); if (Pico_mcd->s68k_regs[0x37] & 4) {
elprintf(EL_INTS, "cdd export irq 4 (unmask)");
SekInterruptS68k(4);
}
} }
break; break;
case 0x34: // fader case 0x34: // fader
@ -418,15 +421,21 @@ void s68k_reg_write8(u32 a, u32 d)
return; // d/m bit is unsetable return; // d/m bit is unsetable
case 0x37: { case 0x37: {
u32 d_old = Pico_mcd->s68k_regs[0x37]; u32 d_old = Pico_mcd->s68k_regs[0x37];
Pico_mcd->s68k_regs[0x37] = d&7; Pico_mcd->s68k_regs[0x37] = d & 7;
if ((d&4) && !(d_old&4)) { if ((d&4) && !(d_old&4)) {
CDD_Export_Status(); // ??
pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75);
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) {
elprintf(EL_INTS, "cdd export irq 4");
SekInterruptS68k(4);
}
} }
return; return;
} }
case 0x4b: case 0x4b:
Pico_mcd->s68k_regs[a] = (u8) d; Pico_mcd->s68k_regs[a] = (u8) d;
CDD_Import_Command(); cdd_process();
return; return;
case 0x58: case 0x58:
return; return;

View file

@ -198,7 +198,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
{ {
const char *rom_fname = filename; const char *rom_fname = filename;
enum media_type_e media_type; enum media_type_e media_type;
cd_img_type cd_img_type = CIT_NOT_CD; enum cd_img_type cd_img_type = CIT_NOT_CD;
unsigned char *rom_data = NULL; unsigned char *rom_data = NULL;
unsigned int rom_size = 0; unsigned int rom_size = 0;
pm_file *rom = NULL; pm_file *rom = NULL;
@ -210,7 +210,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
goto out; goto out;
if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL) if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL)
Stop_CD(); cdd_unload();
PicoCartUnload(); PicoCartUnload();
PicoAHW = 0; PicoAHW = 0;
PicoQuirks = 0; PicoQuirks = 0;
@ -291,7 +291,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
// insert CD if it was detected // insert CD if it was detected
if (cd_img_type != CIT_NOT_CD) { if (cd_img_type != CIT_NOT_CD) {
ret = Insert_CD(filename, cd_img_type); ret = cdd_load(filename, cd_img_type);
if (ret != 0) { if (ret != 0) {
PicoCartUnload(); PicoCartUnload();
media_type = PM_BAD_CD; media_type = PM_BAD_CD;

View file

@ -102,7 +102,6 @@ void PicoGetInternal(pint_t which, pint_ret_t *ret);
// cd/mcd.c // cd/mcd.c
extern void (*PicoMCDopenTray)(void); extern void (*PicoMCDopenTray)(void);
extern void (*PicoMCDcloseTray)(void); extern void (*PicoMCDcloseTray)(void);
extern int PicoCDBuffers;
// pico.c // pico.c
#define XPCM_BUFFER_SIZE (320+160) #define XPCM_BUFFER_SIZE (320+160)
@ -128,14 +127,9 @@ void *PicoTmpStateSave(void);
void PicoTmpStateRestore(void *data); void PicoTmpStateRestore(void *data);
extern void (*PicoStateProgressCB)(const char *str); extern void (*PicoStateProgressCB)(const char *str);
// cd/buffering.c // cd/cdd.c
void PicoCDBufferInit(void); int cdd_load(const char *filename, int type);
void PicoCDBufferFree(void); int cdd_unload(void);
void PicoCDBufferFlush(void);
// cd/cd_sys.c
int Insert_CD(const char *cdimg_name, int type);
int Stop_CD(void); // unloads CD, returns 1 if there was cd loaded
// Cart.c // Cart.c
typedef enum typedef enum
@ -244,6 +238,15 @@ enum media_type_e {
PM_MARK3, PM_MARK3,
PM_CD, PM_CD,
}; };
enum cd_img_type
{
CIT_NOT_CD = 0,
CIT_ISO,
CIT_BIN,
CIT_CUE
};
enum media_type_e PicoLoadMedia(const char *filename, enum media_type_e PicoLoadMedia(const char *filename,
const char *carthw_cfg_fname, const char *carthw_cfg_fname,
const char *(*get_bios_filename)(int *region, const char *cd_fname), const char *(*get_bios_filename)(int *region, const char *cd_fname),

View file

@ -374,9 +374,6 @@ struct PicoSRAM
}; };
// MCD // MCD
#include "cd/cd_sys.h"
#include "cd/LC89510.h"
#define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1) #define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1)
struct mcd_pcm struct mcd_pcm
@ -448,9 +445,8 @@ typedef struct
unsigned char bram[0x2000]; // 110200: 8K unsigned char bram[0x2000]; // 110200: 8K
struct mcd_misc m; // 112200: misc struct mcd_misc m; // 112200: misc
struct mcd_pcm pcm; // 112240: struct mcd_pcm pcm; // 112240:
_scd_toc TOC; // not to be saved void *cdda_stream;
CDD cdd; int cdda_type;
_scd scd;
int pcm_mixbuf[PCM_MIXBUF_LEN * 2]; int pcm_mixbuf[PCM_MIXBUF_LEN * 2];
int pcm_mixpos; int pcm_mixpos;
char pcm_mixbuf_dirty; char pcm_mixbuf_dirty;
@ -628,6 +624,19 @@ void cdc_reg_w(unsigned char data);
unsigned char cdc_reg_r(void); unsigned char cdc_reg_r(void);
unsigned short cdc_host_r(void); unsigned short cdc_host_r(void);
// cd/cdd.c
void cdd_reset(void);
int cdd_context_save(unsigned char *state);
int cdd_context_load(unsigned char *state);
int cdd_context_load_old(unsigned char *state);
void cdd_read_data(unsigned char *dst);
void cdd_read_audio(unsigned int samples);
void cdd_update(void);
void cdd_process(void);
// cd/cd_image.c
int load_cd_image(const char *cd_img_name, int *type);
// cd/gfx.c // cd/gfx.c
void gfx_init(void); void gfx_init(void);
void gfx_start(unsigned int base); void gfx_start(unsigned int base);
@ -727,13 +736,14 @@ PICO_INTERNAL int SekInterruptS68k(int irq);
void SekInterruptClearS68k(int irq); void SekInterruptClearS68k(int irq);
// sound/sound.c // sound/sound.c
PICO_INTERNAL void cdda_start_play();
extern short cdda_out_buffer[2*1152]; extern short cdda_out_buffer[2*1152];
extern int PsndLen_exc_cnt; extern int PsndLen_exc_cnt;
extern int PsndLen_exc_add; extern int PsndLen_exc_add;
extern int timer_a_next_oflow, timer_a_step; // in z80 cycles extern int timer_a_next_oflow, timer_a_step; // in z80 cycles
extern int timer_b_next_oflow, timer_b_step; extern int timer_b_next_oflow, timer_b_step;
void cdda_start_play(int lba_base, int lba_offset, int lb_len);
void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new); void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new);
void ym2612_pack_state(void); void ym2612_pack_state(void);
void ym2612_unpack_state(void); void ym2612_unpack_state(void);
@ -786,9 +796,6 @@ PICO_INTERNAL void z80_exit(void);
PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m); PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m);
PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m); PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m);
// cd/buffering.c
PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba);
// sound/sound.c // sound/sound.c
PICO_INTERNAL void PsndReset(void); PICO_INTERNAL void PsndReset(void);
PICO_INTERNAL void PsndDoDAC(int line_to); PICO_INTERNAL void PsndDoDAC(int line_to);

View file

@ -132,8 +132,6 @@ void PsndRerate(int preserve_state)
// feed it back it's own registers, just like after loading state // feed it back it's own registers, just like after loading state
memcpy(YM2612GetRegs(), state, 0x204); memcpy(YM2612GetRegs(), state, 0x204);
ym2612_unpack_state(); ym2612_unpack_state();
if ((PicoAHW & PAHW_MCD) && !(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
cdda_start_play();
} }
if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state
@ -191,23 +189,19 @@ PICO_INTERNAL void PsndDoDAC(int line_to)
} }
// cdda // cdda
static pm_file *cdda_stream = NULL;
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;
if (cdda_stream == NULL)
return;
cdda_bytes = length*4; cdda_bytes = length*4;
if (PsndRate <= 22050 + 100) mult = 2; if (PsndRate <= 22050 + 100) mult = 2;
if (PsndRate < 22050 - 100) mult = 4; if (PsndRate < 22050 - 100) mult = 4;
cdda_bytes *= mult; cdda_bytes *= mult;
ret = pm_read(cdda_out_buffer, cdda_bytes, cdda_stream); ret = pm_read(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream);
if (ret < cdda_bytes) { if (ret < cdda_bytes) {
memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret); memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret);
cdda_stream = NULL; Pico_mcd->cdda_stream = NULL;
return; return;
} }
@ -219,51 +213,24 @@ static void cdda_raw_update(int *buffer, int length)
} }
} }
PICO_INTERNAL void cdda_start_play(void) void cdda_start_play(int lba_base, int lba_offset, int lb_len)
{ {
int lba_offset, index, lba_length, i; if (Pico_mcd->cdda_type == CT_MP3)
elprintf(EL_STATUS, "cdda play track #%i", Pico_mcd->scd.Cur_Track);
index = Pico_mcd->scd.Cur_Track - 1;
lba_offset = Pico_mcd->scd.Cur_LBA - Track_to_LBA(index + 1);
if (lba_offset < 0) lba_offset = 0;
lba_offset += Pico_mcd->TOC.Tracks[index].Offset;
// find the actual file for this track
for (i = index; i > 0; i--)
if (Pico_mcd->TOC.Tracks[i].F != NULL) break;
if (Pico_mcd->TOC.Tracks[i].F == NULL) {
elprintf(EL_STATUS|EL_ANOMALY, "no track?!");
return;
}
if (Pico_mcd->TOC.Tracks[i].ftype == CT_MP3)
{ {
int pos1024 = 0; int pos1024 = 0;
lba_length = Pico_mcd->TOC.Tracks[i].Length;
for (i++; i < Pico_mcd->TOC.Last_Track; i++) {
if (Pico_mcd->TOC.Tracks[i].F != NULL) break;
lba_length += Pico_mcd->TOC.Tracks[i].Length;
}
if (lba_offset) if (lba_offset)
pos1024 = lba_offset * 1024 / lba_length; pos1024 = lba_offset * 1024 / lb_len;
mp3_start_play(Pico_mcd->TOC.Tracks[index].F, pos1024); mp3_start_play(Pico_mcd->cdda_stream, pos1024);
return; return;
} }
cdda_stream = Pico_mcd->TOC.Tracks[i].F; pm_seek(Pico_mcd->cdda_stream, (lba_base + lba_offset) * 2352, SEEK_SET);
PicoCDBufferFlush(); // buffering relies on fp not being touched if (Pico_mcd->cdda_type == CT_WAV)
pm_seek(cdda_stream, lba_offset * 2352, SEEK_SET);
if (Pico_mcd->TOC.Tracks[i].ftype == CT_WAV)
{ {
// skip headers, assume it's 44kHz stereo uncompressed // skip headers, assume it's 44kHz stereo uncompressed
pm_seek(cdda_stream, 44, SEEK_CUR); pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR);
} }
} }
@ -330,13 +297,12 @@ static int PsndRender(int offset, int length)
// CD: CDDA audio // CD: CDDA audio
// CD mode, cdda enabled, not data track, CDC is reading // CD mode, cdda enabled, not data track, CDC is reading
if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA) && if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA)
!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1)) && Pico_mcd->cdda_stream != NULL
&& !(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
int index = Pico_mcd->scd.Cur_Track - 1; if (Pico_mcd->cdda_type == CT_MP3)
if (Pico_mcd->TOC.Tracks[index].ftype == CT_MP3)
mp3_update(buf32, length, stereo); mp3_update(buf32, length, stereo);
else else
cdda_raw_update(buf32, length); cdda_raw_update(buf32, length);

View file

@ -149,8 +149,8 @@ typedef enum {
CHUNK_GA_REGS, CHUNK_GA_REGS,
CHUNK_PCM, CHUNK_PCM,
CHUNK_CDC, // old CHUNK_CDC, // old
CHUNK_CDD, // 20 CHUNK_CDD, // 20 old
CHUNK_SCD, CHUNK_SCD, // old
CHUNK_RC, // old CHUNK_RC, // old
CHUNK_MISC_CD, CHUNK_MISC_CD,
// //
@ -177,6 +177,7 @@ typedef enum {
CHUNK_CD_EVT = 50, CHUNK_CD_EVT = 50,
CHUNK_CD_GFX, CHUNK_CD_GFX,
CHUNK_CD_CDC, CHUNK_CD_CDC,
CHUNK_CD_CDD,
// //
CHUNK_DEFAULT_COUNT, CHUNK_DEFAULT_COUNT,
CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt) CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt)
@ -317,8 +318,6 @@ static int state_save(void *file)
CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram); CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm); CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);
CHECKED_WRITE_BUFF(CHUNK_CDD, Pico_mcd->cdd);
CHECKED_WRITE_BUFF(CHUNK_SCD, Pico_mcd->scd);
CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m); CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
memset(buff, 0, 0x40); memset(buff, 0, 0x40);
memcpy(buff, pcd_event_times, sizeof(pcd_event_times)); memcpy(buff, pcd_event_times, sizeof(pcd_event_times));
@ -328,6 +327,8 @@ static int state_save(void *file)
CHECKED_WRITE(CHUNK_CD_GFX, len, buf2); CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);
len = cdc_context_save(buf2); len = cdc_context_save(buf2);
CHECKED_WRITE(CHUNK_CD_CDC, len, buf2); CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);
len = cdd_context_save(buf2);
CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);
if (Pico_mcd->s68k_regs[3] & 4) // convert back if (Pico_mcd->s68k_regs[3] & 4) // convert back
wram_2M_to_1M(Pico_mcd->word_ram2M); wram_2M_to_1M(Pico_mcd->word_ram2M);
@ -498,8 +499,6 @@ static int state_load(void *file)
case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break; case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break; case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break; case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;
case CHUNK_CDD: CHECKED_READ_BUFF(Pico_mcd->cdd); break;
case CHUNK_SCD: CHECKED_READ_BUFF(Pico_mcd->scd); break;
case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break; case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
case CHUNK_CD_EVT: case CHUNK_CD_EVT:
@ -517,12 +516,22 @@ static int state_load(void *file)
len_check = cdc_context_load(buf); len_check = cdc_context_load(buf);
break; break;
case CHUNK_CD_CDD:
CHECKED_READ_LIM(buf);
len_check = cdd_context_load(buf);
break;
// old, to be removed: // old, to be removed:
case CHUNK_CDC: case CHUNK_CDC:
CHECKED_READ_LIM(buf); CHECKED_READ_LIM(buf);
cdc_context_load_old(buf); cdc_context_load_old(buf);
break; break;
case CHUNK_SCD:
CHECKED_READ_LIM(buf);
cdd_context_load_old(buf);
break;
// 32x stuff // 32x stuff
#ifndef NO_32X #ifndef NO_32X
case CHUNK_MSH2: case CHUNK_MSH2:
@ -596,9 +605,6 @@ readend:
{ {
SekCycleAimS68k = SekCycleCntS68k; SekCycleAimS68k = SekCycleCntS68k;
pcd_state_loaded(); pcd_state_loaded();
if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
cdda_start_play();
} }
retval = 0; retval = 0;

View file

@ -520,9 +520,6 @@ Homepage: http://www.mame.net/
Eke Eke
CD graphics processor and CD controller implementation (from Genesis Plus GX) CD graphics processor and CD controller implementation (from Genesis Plus GX)
Stephane Dallongeville
Gens, MD/Mega CD/32X emulator. Some Sega CD code is based on this emu.
#ifdef PSP #ifdef PSP
people @ ps2dev.org forums / PSPSDK crew people @ ps2dev.org forums / PSPSDK crew
@ -537,6 +534,7 @@ Additional thanks
* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful * Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful
info about genesis hardware. info about genesis hardware.
* Steve Snake for all that he has done for Genesis emulation scene. * Steve Snake for all that he has done for Genesis emulation scene.
* Stephane Dallongeville for writing Gens and making it open source.
* Tasco Deluxe for his reverse engineering work on SVP and some mappers. * Tasco Deluxe for his reverse engineering work on SVP and some mappers.
* Bart Trzynadlowski for his SSFII and 68000 docs. * Bart Trzynadlowski for his SSFII and 68000 docs.
* Haze for his research (http://haze.mameworld.info). * Haze for his research (http://haze.mameworld.info).

View file

@ -93,9 +93,9 @@ DEFINES += NO_SMS
endif endif
# CD # CD
SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \ SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \
$(R)pico/cd/cdc.c $(R)pico/cd/cd_sys.c $(R)pico/cd/cd_file.c \ $(R)pico/cd/cdc.c $(R)pico/cd/cdd.c $(R)pico/cd/cd_image.c \
$(R)pico/cd/cue.c $(R)pico/cd/gfx.c $(R)pico/cd/gfx_dma.c \ $(R)pico/cd/cue.c $(R)pico/cd/gfx.c $(R)pico/cd/gfx_dma.c \
$(R)pico/cd/misc.c $(R)pico/cd/pcm.c $(R)pico/cd/buffering.c $(R)pico/cd/misc.c $(R)pico/cd/pcm.c
# 32X # 32X
ifneq "$(no_32x)" "1" ifneq "$(no_32x)" "1"
SRCS_COMMON += $(R)pico/32x/32x.c $(R)pico/32x/memory.c $(R)pico/32x/draw.c \ SRCS_COMMON += $(R)pico/32x/32x.c $(R)pico/32x/memory.c $(R)pico/32x/draw.c \

View file

@ -308,11 +308,6 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
return 0; return 0;
return 1; return 1;
case MA_CDOPT_READAHEAD:
if (strcasecmp(var, "ReadAhead buffer") != 0) return 0;
PicoCDBuffers = atoi(val) / 2;
return 1;
case MA_32XOPT_MSH2_CYCLES: case MA_32XOPT_MSH2_CYCLES:
currentConfig.msh2_khz = atoi(val); currentConfig.msh2_khz = atoi(val);
Pico32xSetClocks(currentConfig.msh2_khz * 1000, 0); Pico32xSetClocks(currentConfig.msh2_khz * 1000, 0);

View file

@ -530,19 +530,20 @@ out:
int emu_swap_cd(const char *fname) int emu_swap_cd(const char *fname)
{ {
cd_img_type cd_type; enum cd_img_type cd_type;
int ret = -1; int ret = -1;
cd_type = PicoCdCheck(fname, NULL); cd_type = PicoCdCheck(fname, NULL);
if (cd_type != CIT_NOT_CD) if (cd_type != CIT_NOT_CD)
ret = Insert_CD(fname, cd_type); ret = cdd_load(fname, cd_type);
if (ret != 0) { if (ret != 0) {
menu_update_msg("Load failed, invalid CD image?"); menu_update_msg("Load failed, invalid CD image?");
return 0; return 0;
} }
strncpy(rom_fname_loaded, fname, sizeof(rom_fname_loaded)-1); strncpy(rom_fname_loaded, fname, sizeof(rom_fname_loaded)-1);
rom_fname_loaded[sizeof(rom_fname_loaded)-1] = 0; rom_fname_loaded[sizeof(rom_fname_loaded) - 1] = 0;
return 1; return 1;
} }
@ -606,7 +607,6 @@ void emu_set_defconfig(void)
PsndRate = currentConfig.s_PsndRate; PsndRate = currentConfig.s_PsndRate;
PicoRegionOverride = currentConfig.s_PicoRegion; PicoRegionOverride = currentConfig.s_PicoRegion;
PicoAutoRgnOrder = currentConfig.s_PicoAutoRgnOrder; PicoAutoRgnOrder = currentConfig.s_PicoAutoRgnOrder;
PicoCDBuffers = currentConfig.s_PicoCDBuffers;
} }
int emu_read_config(const char *rom_fname, int no_defaults) int emu_read_config(const char *rom_fname, int no_defaults)
@ -1336,10 +1336,6 @@ void emu_loop(void)
PicoLoopPrepare(); PicoLoopPrepare();
// prepare CD buffer
if (PicoAHW & PAHW_MCD)
PicoCDBufferInit();
plat_video_loop_prepare(); plat_video_loop_prepare();
emu_loop_prep(); emu_loop_prep();
pemu_sound_start(); pemu_sound_start();
@ -1501,10 +1497,4 @@ void emu_loop(void)
pemu_loop_end(); pemu_loop_end();
emu_sound_stop(); emu_sound_stop();
// pemu_loop_end() might want to do 1 frame for bg image,
// so free CD buffer here
if (PicoAHW & PAHW_MCD)
PicoCDBufferFree();
} }

View file

@ -395,31 +395,6 @@ static int menu_loop_keyconfig(int id, int keys)
// ------------ SCD options menu ------------ // ------------ SCD options menu ------------
static const char *mgn_cdopt_ra(int id, int *offs)
{
*offs = -5;
if (PicoCDBuffers <= 0)
return " OFF";
sprintf(static_buff, "%5iK", PicoCDBuffers * 2);
return static_buff;
}
static int mh_cdopt_ra(int id, int keys)
{
if (keys & PBTN_LEFT) {
PicoCDBuffers >>= 1;
if (PicoCDBuffers < 2)
PicoCDBuffers = 0;
} else {
if (PicoCDBuffers <= 0)
PicoCDBuffers = 1;
PicoCDBuffers <<= 1;
if (PicoCDBuffers > 8*1024)
PicoCDBuffers = 8*1024; // 16M
}
return 0;
}
static const char h_cdleds[] = "Show power/CD LEDs of emulated console"; static const char h_cdleds[] = "Show power/CD LEDs of emulated console";
static const char h_cdda[] = "Play audio tracks from mp3s/wavs/bins"; static const char h_cdda[] = "Play audio tracks from mp3s/wavs/bins";
static const char h_cdpcm[] = "Emulate PCM audio chip for effects/voices/music"; static const char h_cdpcm[] = "Emulate PCM audio chip for effects/voices/music";
@ -435,7 +410,6 @@ static menu_entry e_menu_cd_options[] =
mee_onoff_h("CD LEDs", MA_CDOPT_LEDS, currentConfig.EmuOpt, EOPT_EN_CD_LEDS, h_cdleds), mee_onoff_h("CD LEDs", MA_CDOPT_LEDS, currentConfig.EmuOpt, EOPT_EN_CD_LEDS, h_cdleds),
mee_onoff_h("CDDA audio", MA_CDOPT_CDDA, PicoOpt, POPT_EN_MCD_CDDA, h_cdda), mee_onoff_h("CDDA audio", MA_CDOPT_CDDA, PicoOpt, POPT_EN_MCD_CDDA, h_cdda),
mee_onoff_h("PCM audio", MA_CDOPT_PCM, PicoOpt, POPT_EN_MCD_PCM, h_cdpcm), mee_onoff_h("PCM audio", MA_CDOPT_PCM, PicoOpt, POPT_EN_MCD_PCM, h_cdpcm),
mee_cust ("ReadAhead buffer", MA_CDOPT_READAHEAD, mh_cdopt_ra, mgn_cdopt_ra),
mee_onoff_h("SaveRAM cart", MA_CDOPT_SAVERAM, PicoOpt, POPT_EN_MCD_RAMCART, h_srcart), mee_onoff_h("SaveRAM cart", MA_CDOPT_SAVERAM, PicoOpt, POPT_EN_MCD_RAMCART, h_srcart),
mee_onoff_h("Scale/Rot. fx (slow)", MA_CDOPT_SCALEROT_CHIP, PicoOpt, POPT_EN_MCD_GFX, h_scfx), mee_onoff_h("Scale/Rot. fx (slow)", MA_CDOPT_SCALEROT_CHIP, PicoOpt, POPT_EN_MCD_GFX, h_scfx),
mee_end, mee_end,
@ -1045,7 +1019,7 @@ static int main_menu_handler(int id, int keys)
break; break;
case MA_MAIN_CHANGE_CD: case MA_MAIN_CHANGE_CD:
if (PicoAHW & PAHW_MCD) { if (PicoAHW & PAHW_MCD) {
if (!Stop_CD()) if (!cdd_unload())
menu_loop_tray(); menu_loop_tray();
return 1; return 1;
} }

View file

@ -500,7 +500,7 @@ static unsigned int disk_get_image_index(void)
static bool disk_set_image_index(unsigned int index) static bool disk_set_image_index(unsigned int index)
{ {
cd_img_type cd_type; enum cd_img_type cd_type;
int ret; int ret;
if (index >= sizeof(disks) / sizeof(disks[0])) if (index >= sizeof(disks) / sizeof(disks[0]))
@ -521,7 +521,7 @@ static bool disk_set_image_index(unsigned int index)
ret = -1; ret = -1;
cd_type = PicoCdCheck(disks[index].fname, NULL); cd_type = PicoCdCheck(disks[index].fname, NULL);
if (cd_type != CIT_NOT_CD) if (cd_type != CIT_NOT_CD)
ret = Insert_CD(disks[index].fname, cd_type); ret = cdd_load(disks[index].fname, cd_type);
if (ret != 0) { if (ret != 0) {
lprintf("Load failed, invalid CD image?\n"); lprintf("Load failed, invalid CD image?\n");
return 0; return 0;
@ -882,7 +882,6 @@ void retro_init(void)
#endif #endif
PsndRate = 44100; PsndRate = 44100;
PicoAutoRgnOrder = 0x184; // US, EU, JP PicoAutoRgnOrder = 0x184; // US, EU, JP
PicoCDBuffers = 0;
vout_width = 320; vout_width = 320;
vout_height = 240; vout_height = 240;