mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
cd: switch to CD drive emu code from genplus
same license, much cleaner code
This commit is contained in:
parent
3f23709ef3
commit
274fcc35aa
25 changed files with 1798 additions and 1824 deletions
|
@ -157,7 +157,7 @@ zip_failed:
|
|||
if (f == NULL)
|
||||
goto cso_failed;
|
||||
|
||||
#ifndef __EPOC32__
|
||||
#ifdef __GP2X__
|
||||
/* we use our own buffering */
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
#endif
|
||||
|
@ -227,7 +227,7 @@ cso_failed:
|
|||
strncpy(file->ext, ext, sizeof(file->ext) - 1);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
#ifndef __EPOC32__ // makes things worse on Symbian
|
||||
#ifdef __GP2X__
|
||||
if (file->size > 0x400000)
|
||||
/* we use our own buffering */
|
||||
setvbuf(f, NULL, _IONBF, 0);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
266
pico/cd/cd_image.c
Normal 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
|
933
pico/cd/cd_sys.c
933
pico/cd/cd_sys.c
|
@ -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
|
||||
}
|
||||
|
||||
|
109
pico/cd/cd_sys.h
109
pico/cd/cd_sys.h
|
@ -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
|
||||
|
|
@ -341,19 +341,6 @@ update_dma:
|
|||
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)
|
||||
{
|
||||
/* end of DMA transfer ? */
|
||||
|
|
1328
pico/cd/cdd.c
Normal file
1328
pico/cd/cdd.c
Normal file
File diff suppressed because it is too large
Load diff
98
pico/cd/cdd.h
Normal file
98
pico/cd/cdd.h
Normal 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
|
|
@ -242,6 +242,8 @@ file_ok:
|
|||
data->tracks[count].type = CT_MP3;
|
||||
else if (strcasecmp(ext, "wav") == 0)
|
||||
data->tracks[count].type = CT_WAV;
|
||||
else if (strcasecmp(ext, "bin") == 0)
|
||||
data->tracks[count].type = CT_BIN;
|
||||
else {
|
||||
elprintf(EL_STATUS, "unhandled audio format: \"%s\"",
|
||||
data->tracks[count].fname);
|
||||
|
|
|
@ -22,13 +22,10 @@ void (*PicoMCDcloseTray)(void) = NULL;
|
|||
PICO_INTERNAL void PicoInitMCD(void)
|
||||
{
|
||||
SekInitS68k();
|
||||
Init_CD_Driver();
|
||||
gfx_init();
|
||||
}
|
||||
|
||||
PICO_INTERNAL void PicoExitMCD(void)
|
||||
{
|
||||
End_CD_Driver();
|
||||
}
|
||||
|
||||
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->pcm, 0, sizeof(Pico_mcd->pcm));
|
||||
memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m));
|
||||
Pico_mcd->s68k_regs[0x38+9] = 0x0f; // default checksum
|
||||
|
||||
cdc_init();
|
||||
Reset_CD();
|
||||
cdd_reset();
|
||||
gfx_init();
|
||||
|
||||
// cold reset state (tested)
|
||||
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;
|
||||
cdc_reset();
|
||||
CDD_Reset();
|
||||
cdd_reset();
|
||||
#ifdef _ASM_CD_MEMORY_C
|
||||
//PicoMemResetCDdecode(1); // don't have to call this in 2M mode
|
||||
#endif
|
||||
|
@ -135,7 +134,20 @@ unsigned int pcd_cycles_m68k_to_s68k(unsigned int c)
|
|||
static void pcd_cdc_event(unsigned int now)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -407,8 +407,11 @@ void s68k_reg_write8(u32 a, u32 d)
|
|||
elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d);
|
||||
d &= 0x7e;
|
||||
if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) {
|
||||
if (Pico_mcd->s68k_regs[0x37] & 4)
|
||||
CDD_Export_Status();
|
||||
// XXX: emulate pending irq instead?
|
||||
if (Pico_mcd->s68k_regs[0x37] & 4) {
|
||||
elprintf(EL_INTS, "cdd export irq 4 (unmask)");
|
||||
SekInterruptS68k(4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x34: // fader
|
||||
|
@ -418,15 +421,21 @@ void s68k_reg_write8(u32 a, u32 d)
|
|||
return; // d/m bit is unsetable
|
||||
case 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)) {
|
||||
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;
|
||||
}
|
||||
case 0x4b:
|
||||
Pico_mcd->s68k_regs[a] = (u8) d;
|
||||
CDD_Import_Command();
|
||||
cdd_process();
|
||||
return;
|
||||
case 0x58:
|
||||
return;
|
||||
|
|
|
@ -198,7 +198,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
{
|
||||
const char *rom_fname = filename;
|
||||
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 int rom_size = 0;
|
||||
pm_file *rom = NULL;
|
||||
|
@ -210,7 +210,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
goto out;
|
||||
|
||||
if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL)
|
||||
Stop_CD();
|
||||
cdd_unload();
|
||||
PicoCartUnload();
|
||||
PicoAHW = 0;
|
||||
PicoQuirks = 0;
|
||||
|
@ -291,7 +291,7 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
|
||||
// insert CD if it was detected
|
||||
if (cd_img_type != CIT_NOT_CD) {
|
||||
ret = Insert_CD(filename, cd_img_type);
|
||||
ret = cdd_load(filename, cd_img_type);
|
||||
if (ret != 0) {
|
||||
PicoCartUnload();
|
||||
media_type = PM_BAD_CD;
|
||||
|
|
21
pico/pico.h
21
pico/pico.h
|
@ -102,7 +102,6 @@ void PicoGetInternal(pint_t which, pint_ret_t *ret);
|
|||
// cd/mcd.c
|
||||
extern void (*PicoMCDopenTray)(void);
|
||||
extern void (*PicoMCDcloseTray)(void);
|
||||
extern int PicoCDBuffers;
|
||||
|
||||
// pico.c
|
||||
#define XPCM_BUFFER_SIZE (320+160)
|
||||
|
@ -128,14 +127,9 @@ void *PicoTmpStateSave(void);
|
|||
void PicoTmpStateRestore(void *data);
|
||||
extern void (*PicoStateProgressCB)(const char *str);
|
||||
|
||||
// cd/buffering.c
|
||||
void PicoCDBufferInit(void);
|
||||
void PicoCDBufferFree(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
|
||||
// cd/cdd.c
|
||||
int cdd_load(const char *filename, int type);
|
||||
int cdd_unload(void);
|
||||
|
||||
// Cart.c
|
||||
typedef enum
|
||||
|
@ -244,6 +238,15 @@ enum media_type_e {
|
|||
PM_MARK3,
|
||||
PM_CD,
|
||||
};
|
||||
|
||||
enum cd_img_type
|
||||
{
|
||||
CIT_NOT_CD = 0,
|
||||
CIT_ISO,
|
||||
CIT_BIN,
|
||||
CIT_CUE
|
||||
};
|
||||
|
||||
enum media_type_e PicoLoadMedia(const char *filename,
|
||||
const char *carthw_cfg_fname,
|
||||
const char *(*get_bios_filename)(int *region, const char *cd_fname),
|
||||
|
|
|
@ -374,9 +374,6 @@ struct PicoSRAM
|
|||
};
|
||||
|
||||
// MCD
|
||||
#include "cd/cd_sys.h"
|
||||
#include "cd/LC89510.h"
|
||||
|
||||
#define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1)
|
||||
|
||||
struct mcd_pcm
|
||||
|
@ -448,9 +445,8 @@ typedef struct
|
|||
unsigned char bram[0x2000]; // 110200: 8K
|
||||
struct mcd_misc m; // 112200: misc
|
||||
struct mcd_pcm pcm; // 112240:
|
||||
_scd_toc TOC; // not to be saved
|
||||
CDD cdd;
|
||||
_scd scd;
|
||||
void *cdda_stream;
|
||||
int cdda_type;
|
||||
int pcm_mixbuf[PCM_MIXBUF_LEN * 2];
|
||||
int pcm_mixpos;
|
||||
char pcm_mixbuf_dirty;
|
||||
|
@ -628,6 +624,19 @@ void cdc_reg_w(unsigned char data);
|
|||
unsigned char cdc_reg_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
|
||||
void gfx_init(void);
|
||||
void gfx_start(unsigned int base);
|
||||
|
@ -727,13 +736,14 @@ PICO_INTERNAL int SekInterruptS68k(int irq);
|
|||
void SekInterruptClearS68k(int irq);
|
||||
|
||||
// sound/sound.c
|
||||
PICO_INTERNAL void cdda_start_play();
|
||||
extern short cdda_out_buffer[2*1152];
|
||||
extern int PsndLen_exc_cnt;
|
||||
extern int PsndLen_exc_add;
|
||||
extern int timer_a_next_oflow, timer_a_step; // in z80 cycles
|
||||
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_pack_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_1M_to_2M(unsigned char *m);
|
||||
|
||||
// cd/buffering.c
|
||||
PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba);
|
||||
|
||||
// sound/sound.c
|
||||
PICO_INTERNAL void PsndReset(void);
|
||||
PICO_INTERNAL void PsndDoDAC(int line_to);
|
||||
|
|
|
@ -132,8 +132,6 @@ void PsndRerate(int preserve_state)
|
|||
// feed it back it's own registers, just like after loading state
|
||||
memcpy(YM2612GetRegs(), state, 0x204);
|
||||
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
|
||||
|
@ -191,23 +189,19 @@ PICO_INTERNAL void PsndDoDAC(int line_to)
|
|||
}
|
||||
|
||||
// cdda
|
||||
static pm_file *cdda_stream = NULL;
|
||||
|
||||
static void cdda_raw_update(int *buffer, int length)
|
||||
{
|
||||
int ret, cdda_bytes, mult = 1;
|
||||
if (cdda_stream == NULL)
|
||||
return;
|
||||
|
||||
cdda_bytes = length*4;
|
||||
if (PsndRate <= 22050 + 100) mult = 2;
|
||||
if (PsndRate < 22050 - 100) mult = 4;
|
||||
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) {
|
||||
memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret);
|
||||
cdda_stream = NULL;
|
||||
Pico_mcd->cdda_stream = NULL;
|
||||
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;
|
||||
|
||||
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)
|
||||
if (Pico_mcd->cdda_type == CT_MP3)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
cdda_stream = Pico_mcd->TOC.Tracks[i].F;
|
||||
PicoCDBufferFlush(); // buffering relies on fp not being touched
|
||||
pm_seek(cdda_stream, lba_offset * 2352, SEEK_SET);
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == CT_WAV)
|
||||
pm_seek(Pico_mcd->cdda_stream, (lba_base + lba_offset) * 2352, SEEK_SET);
|
||||
if (Pico_mcd->cdda_type == CT_WAV)
|
||||
{
|
||||
// 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 mode, cdda enabled, not data track, CDC is reading
|
||||
if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA) &&
|
||||
!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
|
||||
if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA)
|
||||
&& Pico_mcd->cdda_stream != NULL
|
||||
&& !(Pico_mcd->s68k_regs[0x36] & 1))
|
||||
{
|
||||
// note: only 44, 22 and 11 kHz supported, with forced stereo
|
||||
int index = Pico_mcd->scd.Cur_Track - 1;
|
||||
|
||||
if (Pico_mcd->TOC.Tracks[index].ftype == CT_MP3)
|
||||
if (Pico_mcd->cdda_type == CT_MP3)
|
||||
mp3_update(buf32, length, stereo);
|
||||
else
|
||||
cdda_raw_update(buf32, length);
|
||||
|
|
24
pico/state.c
24
pico/state.c
|
@ -149,8 +149,8 @@ typedef enum {
|
|||
CHUNK_GA_REGS,
|
||||
CHUNK_PCM,
|
||||
CHUNK_CDC, // old
|
||||
CHUNK_CDD, // 20
|
||||
CHUNK_SCD,
|
||||
CHUNK_CDD, // 20 old
|
||||
CHUNK_SCD, // old
|
||||
CHUNK_RC, // old
|
||||
CHUNK_MISC_CD,
|
||||
//
|
||||
|
@ -177,6 +177,7 @@ typedef enum {
|
|||
CHUNK_CD_EVT = 50,
|
||||
CHUNK_CD_GFX,
|
||||
CHUNK_CD_CDC,
|
||||
CHUNK_CD_CDD,
|
||||
//
|
||||
CHUNK_DEFAULT_COUNT,
|
||||
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_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
|
||||
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);
|
||||
memset(buff, 0, 0x40);
|
||||
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);
|
||||
len = cdc_context_save(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
|
||||
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_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); 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_CD_EVT:
|
||||
|
@ -517,12 +516,22 @@ static int state_load(void *file)
|
|||
len_check = cdc_context_load(buf);
|
||||
break;
|
||||
|
||||
case CHUNK_CD_CDD:
|
||||
CHECKED_READ_LIM(buf);
|
||||
len_check = cdd_context_load(buf);
|
||||
break;
|
||||
|
||||
// old, to be removed:
|
||||
case CHUNK_CDC:
|
||||
CHECKED_READ_LIM(buf);
|
||||
cdc_context_load_old(buf);
|
||||
break;
|
||||
|
||||
case CHUNK_SCD:
|
||||
CHECKED_READ_LIM(buf);
|
||||
cdd_context_load_old(buf);
|
||||
break;
|
||||
|
||||
// 32x stuff
|
||||
#ifndef NO_32X
|
||||
case CHUNK_MSH2:
|
||||
|
@ -596,9 +605,6 @@ readend:
|
|||
{
|
||||
SekCycleAimS68k = SekCycleCntS68k;
|
||||
pcd_state_loaded();
|
||||
|
||||
if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
|
||||
cdda_start_play();
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue