mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-04 23:07:46 -04:00
improve cue handling a bit
This commit is contained in:
parent
c7fd7bb8b7
commit
e71fae1f13
7 changed files with 156 additions and 62 deletions
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include "../pico_int.h"
|
||||
#include "../cd/cue.h"
|
||||
|
||||
int PicoCDBuffers = 0;
|
||||
static unsigned char *cd_buffer = NULL;
|
||||
|
@ -66,7 +67,7 @@ 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 == TYPE_BIN;
|
||||
is_bin = Pico_mcd->TOC.Tracks[0].ftype == CT_BIN;
|
||||
|
||||
if (PicoCDBuffers <= 0)
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ static int audio_track_mp3(const char *fname, int index)
|
|||
Tracks[index].F = tmp_file;
|
||||
|
||||
// MP3 File
|
||||
Tracks[index].ftype = TYPE_MP3;
|
||||
Tracks[index].ftype = CT_MP3;
|
||||
fs *= 75;
|
||||
fs /= Tracks[index].KBtps * 1000;
|
||||
Tracks[index].Length = fs;
|
||||
|
@ -70,9 +70,10 @@ static int audio_track_mp3(const char *fname, int index)
|
|||
|
||||
PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
|
||||
{
|
||||
int i, j, num_track, Cur_LBA, index, ret, iso_name_len, missed, cd_img_sectors;
|
||||
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[1024], tmp_ext[10], tmp_ext_u[10];
|
||||
char tmp_name[256], tmp_ext[10], tmp_ext_u[10];
|
||||
cue_data_t *cue_data = NULL;
|
||||
pm_file *pmf;
|
||||
static const char *exts[] = {
|
||||
|
@ -85,14 +86,14 @@ PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
|
|||
|
||||
Unload_ISO();
|
||||
|
||||
/* is this .cue? */
|
||||
ret = strlen(cd_img_name);
|
||||
if (ret >= 3 && strcasecmp(cd_img_name + ret - 3, "cue") == 0)
|
||||
cue_data = cue_parse(cd_img_name);
|
||||
if (cue_data != NULL)
|
||||
/* 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 = type == CIT_BIN ? TYPE_BIN : TYPE_ISO;
|
||||
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)
|
||||
|
@ -104,7 +105,7 @@ PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (Tracks[0].ftype == TYPE_ISO)
|
||||
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;
|
||||
|
@ -113,8 +114,9 @@ PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
|
|||
Tracks[0].MSF.S = 2; // seconds
|
||||
Tracks[0].MSF.F = 0; // frames
|
||||
|
||||
elprintf(EL_STATUS, "Track 1: %02d:%02d:%02d %9i DATA",
|
||||
Tracks[0].MSF.M, Tracks[0].MSF.S, Tracks[0].MSF.F, Tracks[0].Length);
|
||||
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;
|
||||
|
||||
|
@ -173,7 +175,7 @@ PICO_INTERNAL int Load_CD_Image(const char *cd_img_name, cd_img_type type)
|
|||
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,
|
||||
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);
|
||||
}
|
||||
|
@ -267,7 +269,7 @@ PICO_INTERNAL void Unload_ISO(void)
|
|||
{
|
||||
if (Pico_mcd->TOC.Tracks[i].F != NULL)
|
||||
{
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == TYPE_MP3)
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == CT_MP3)
|
||||
#ifdef _PSP_FW_VERSION
|
||||
free(Pico_mcd->TOC.Tracks[i].F);
|
||||
#else
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TYPE_ISO 1
|
||||
#define TYPE_BIN 2
|
||||
#define TYPE_MP3 3
|
||||
#define TYPE_WAV 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CIT_NOT_CD = 0,
|
||||
|
|
|
@ -39,11 +39,9 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
// unsigned char Type; // always 1 (data) for 1st track, 0 (audio) for others
|
||||
// unsigned char Num; // unused
|
||||
_msf MSF;
|
||||
//
|
||||
char ftype; // TYPE_ISO, TYPE_BIN, TYPE_MP3
|
||||
char ftype; // cue_track_type
|
||||
void *F;
|
||||
int Length;
|
||||
int Offset; // sector offset, when single file is used for multiple virtual tracks
|
||||
|
|
150
pico/cd/cue.c
150
pico/cd/cue.c
|
@ -62,49 +62,113 @@ static int get_token(const char *buff, char *dest, int len)
|
|||
return d + skip;
|
||||
}
|
||||
|
||||
static char *get_ext(char *fname)
|
||||
static int get_ext(const char *fname, char ext[4],
|
||||
char *base, size_t base_size)
|
||||
{
|
||||
int len = strlen(fname);
|
||||
return (len >= 3) ? (fname + len - 3) : fname;
|
||||
int len, pos = 0;
|
||||
|
||||
len = strlen(fname);
|
||||
if (len >= 3)
|
||||
pos = len - 3;
|
||||
|
||||
strcpy(ext, fname + pos);
|
||||
|
||||
if (base != NULL) {
|
||||
len = pos;
|
||||
if (len + 1 < base_size)
|
||||
len = base_size - 1;
|
||||
memcpy(base, fname, len);
|
||||
base[len] = 0;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void change_case(char *p, int to_upper)
|
||||
{
|
||||
for (; *p != 0; p++) {
|
||||
if (to_upper && 'a' <= *p && *p <= 'z')
|
||||
*p += 'A' - 'a';
|
||||
else if (!to_upper && 'A' <= *p && *p <= 'Z')
|
||||
*p += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
|
||||
static int file_openable(const char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "rb");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0)
|
||||
|
||||
/* note: tracks[0] is not used */
|
||||
cue_data_t *cue_parse(const char *fname)
|
||||
{
|
||||
char buff[256], current_file[256], buff2[32], *current_filep;
|
||||
FILE *f, *tmpf;
|
||||
char current_file[256], *current_filep, cue_base[256];
|
||||
char buff[256], buff2[32], ext[4], *p;
|
||||
int ret, count = 0, count_alloc = 2, pending_pregap = 0;
|
||||
cue_data_t *data;
|
||||
size_t current_filep_size, fname_len;
|
||||
cue_data_t *data = NULL;
|
||||
FILE *f = NULL;
|
||||
void *tmp;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if (f == NULL) return NULL;
|
||||
if (fname == NULL || (fname_len = strlen(fname)) == 0)
|
||||
return NULL;
|
||||
|
||||
ret = get_ext(fname, ext, cue_base, sizeof(cue_base));
|
||||
if (strcasecmp(ext, "cue") == 0) {
|
||||
f = fopen(fname, "r");
|
||||
}
|
||||
else {
|
||||
// not a .cue, try one with the same base name
|
||||
if (ret + 3 < sizeof(cue_base)) {
|
||||
strcpy(cue_base + ret, "cue");
|
||||
f = fopen(cue_base, "r");
|
||||
if (f == NULL) {
|
||||
strcpy(cue_base + ret, "CUE");
|
||||
f = fopen(cue_base, "r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
snprintf(current_file, sizeof(current_file), "%s", fname);
|
||||
for (current_filep = current_file + strlen(current_file); current_filep > current_file; current_filep--)
|
||||
if (current_filep[-1] == '/' || current_filep[-1] == '\\') break;
|
||||
current_filep = current_file + strlen(current_file);
|
||||
for (; current_filep > current_file; current_filep--)
|
||||
if (current_filep[-1] == '/' || current_filep[-1] == '\\')
|
||||
break;
|
||||
|
||||
current_filep_size = sizeof(current_file) - (current_filep - current_file);
|
||||
|
||||
// the basename of cuefile, no path
|
||||
snprintf(cue_base, sizeof(cue_base), "%s", current_filep);
|
||||
p = cue_base + strlen(cue_base);
|
||||
if (p - 3 >= cue_base)
|
||||
p[-3] = 0;
|
||||
|
||||
data = calloc(1, sizeof(*data) + count_alloc * sizeof(cue_track));
|
||||
if (data == NULL) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
if (data == NULL)
|
||||
goto out;
|
||||
|
||||
while (!feof(f))
|
||||
{
|
||||
tmp = fgets(buff, sizeof(buff), f);
|
||||
if (tmp == NULL) break;
|
||||
if (tmp == NULL)
|
||||
break;
|
||||
|
||||
mystrip(buff);
|
||||
if (buff[0] == 0) continue;
|
||||
if (buff[0] == 0)
|
||||
continue;
|
||||
if (BEGINS(buff, "TITLE ") || BEGINS(buff, "PERFORMER ") || BEGINS(buff, "SONGWRITER "))
|
||||
continue; /* who would put those here? Ignore! */
|
||||
else if (BEGINS(buff, "FILE "))
|
||||
{
|
||||
get_token(buff+5, current_filep, sizeof(current_file) - (current_filep - current_file));
|
||||
get_token(buff + 5, current_filep, current_filep_size);
|
||||
}
|
||||
else if (BEGINS(buff, "TRACK "))
|
||||
{
|
||||
|
@ -112,21 +176,48 @@ cue_data_t *cue_parse(const char *fname)
|
|||
if (count >= count_alloc) {
|
||||
count_alloc *= 2;
|
||||
tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cue_track));
|
||||
if (tmp == NULL) { count--; break; }
|
||||
if (tmp == NULL) {
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
data = tmp;
|
||||
}
|
||||
memset(&data->tracks[count], 0, sizeof(data->tracks[0]));
|
||||
|
||||
if (count == 1 || strcmp(data->tracks[1].fname, current_file) != 0)
|
||||
{
|
||||
data->tracks[count].fname = strdup(current_file);
|
||||
if (data->tracks[count].fname == NULL) break;
|
||||
if (file_openable(current_file))
|
||||
goto file_ok;
|
||||
|
||||
tmpf = fopen(current_file, "rb");
|
||||
if (tmpf == NULL) {
|
||||
elprintf(EL_STATUS, "cue: bad/missing file: \"%s\"", current_file);
|
||||
count--; break;
|
||||
elprintf(EL_STATUS, "cue: bad/missing file: \"%s\"", current_file);
|
||||
if (count == 1) {
|
||||
int cue_ucase;
|
||||
char v;
|
||||
|
||||
get_ext(current_file, ext, NULL, 0);
|
||||
snprintf(current_filep, current_filep_size,
|
||||
"%s%s", cue_base, ext);
|
||||
if (file_openable(current_file))
|
||||
goto file_ok;
|
||||
|
||||
// try with the same case (for unix)
|
||||
v = fname[fname_len - 1];
|
||||
cue_ucase = ('A' <= v && v <= 'Z');
|
||||
change_case(ext, cue_ucase);
|
||||
|
||||
snprintf(current_filep, current_filep_size,
|
||||
"%s%s", cue_base, ext);
|
||||
if (file_openable(current_file))
|
||||
goto file_ok;
|
||||
}
|
||||
fclose(tmpf);
|
||||
|
||||
count--;
|
||||
break;
|
||||
|
||||
file_ok:
|
||||
data->tracks[count].fname = strdup(current_file);
|
||||
if (data->tracks[count].fname == NULL)
|
||||
break;
|
||||
}
|
||||
data->tracks[count].pregap = pending_pregap;
|
||||
pending_pregap = 0;
|
||||
|
@ -146,7 +237,7 @@ cue_data_t *cue_parse(const char *fname)
|
|||
if (data->tracks[count].fname != NULL)
|
||||
{
|
||||
// rely on extension, not type in cue..
|
||||
char *ext = get_ext(data->tracks[count].fname);
|
||||
get_ext(data->tracks[count].fname, ext, NULL, 0);
|
||||
if (strcasecmp(ext, "mp3") == 0)
|
||||
data->tracks[count].type = CT_MP3;
|
||||
else if (strcasecmp(ext, "wav") == 0)
|
||||
|
@ -233,10 +324,15 @@ cue_data_t *cue_parse(const char *fname)
|
|||
if (data->tracks[count].fname != NULL)
|
||||
free(data->tracks[count].fname);
|
||||
free(data);
|
||||
return NULL;
|
||||
data = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->track_count = count;
|
||||
|
||||
out:
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
17
pico/media.c
17
pico/media.c
|
@ -132,14 +132,15 @@ int PicoCdCheck(const char *fname_in, int *pregion)
|
|||
cue_track_type type = CT_UNKNOWN;
|
||||
cue_data_t *cue_data = NULL;
|
||||
|
||||
get_ext(fname_in, ext);
|
||||
if (strcasecmp(ext, ".cue") == 0) {
|
||||
cue_data = cue_parse(fname_in);
|
||||
if (cue_data != NULL) {
|
||||
fname = cue_data->tracks[1].fname;
|
||||
type = cue_data->tracks[1].type;
|
||||
}
|
||||
else
|
||||
// opens a cue, or searches for one
|
||||
cue_data = cue_parse(fname_in);
|
||||
if (cue_data != NULL) {
|
||||
fname = cue_data->tracks[1].fname;
|
||||
type = cue_data->tracks[1].type;
|
||||
}
|
||||
else {
|
||||
get_ext(fname_in, ext);
|
||||
if (strcasecmp(ext, ".cue") == 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "sn76496.h"
|
||||
#include "../pico_int.h"
|
||||
#include "../cd/pcm.h"
|
||||
#include "../cd/cue.h"
|
||||
#include "mix.h"
|
||||
|
||||
#define SIMPLE_WRITE_SOUND 0
|
||||
|
@ -260,7 +261,7 @@ PICO_INTERNAL void cdda_start_play(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == TYPE_MP3)
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == CT_MP3)
|
||||
{
|
||||
int pos1024 = 0;
|
||||
|
||||
|
@ -280,7 +281,7 @@ PICO_INTERNAL void cdda_start_play(void)
|
|||
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 == TYPE_WAV)
|
||||
if (Pico_mcd->TOC.Tracks[i].ftype == CT_WAV)
|
||||
{
|
||||
// skip headers, assume it's 44kHz stereo uncompressed
|
||||
pm_seek(cdda_stream, 44, SEEK_CUR);
|
||||
|
@ -358,7 +359,7 @@ static int PsndRender(int offset, int length)
|
|||
// 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 == TYPE_MP3)
|
||||
if (Pico_mcd->TOC.Tracks[index].ftype == CT_MP3)
|
||||
mp3_update(buf32, length, stereo);
|
||||
else
|
||||
cdda_raw_update(buf32, length);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue