improve cue handling a bit

This commit is contained in:
notaz 2013-09-08 00:35:09 +03:00
parent c7fd7bb8b7
commit e71fae1f13
7 changed files with 156 additions and 62 deletions

View file

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

View file

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

View file

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

View file

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

View file

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