mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
core, groundwork for chd support
still needs some scrutiny, and build integration is missing
This commit is contained in:
parent
4da84f9454
commit
15ca715228
18 changed files with 411 additions and 100 deletions
|
@ -9,7 +9,7 @@
|
|||
#include "../pico_int.h"
|
||||
#include "genplus_macros.h"
|
||||
#include "cdd.h"
|
||||
#include "cue.h"
|
||||
#include "cd_parse.h"
|
||||
|
||||
#ifdef USE_LIBRETRO_VFS
|
||||
#include "file_stream_transforms.h"
|
||||
|
@ -90,7 +90,7 @@ int load_cd_image(const char *cd_img_name, int *type)
|
|||
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;
|
||||
cd_data_t *cue_data = NULL;
|
||||
pm_file *pmf;
|
||||
|
||||
if (PicoCDLoadProgressCB != NULL)
|
||||
|
@ -103,16 +103,21 @@ int load_cd_image(const char *cd_img_name, int *type)
|
|||
if (cue_data != NULL) {
|
||||
cd_img_name = cue_data->tracks[1].fname;
|
||||
*type = cue_data->tracks[1].type;
|
||||
} else {
|
||||
cue_data = chd_parse(cd_img_name);
|
||||
if (cue_data != NULL)
|
||||
*type = cue_data->tracks[1].type;
|
||||
}
|
||||
|
||||
pmf = pm_open(cd_img_name);
|
||||
if (pmf == NULL)
|
||||
{
|
||||
if (cue_data != NULL)
|
||||
cue_destroy(cue_data);
|
||||
cdparse_destroy(cue_data);
|
||||
return -1;
|
||||
}
|
||||
tracks[0].fd = pmf;
|
||||
tracks[0].fname = strdup(cd_img_name);
|
||||
|
||||
if (*type == CT_ISO)
|
||||
cd_img_sectors = pmf->size >>= 11; // size in sectors
|
||||
|
@ -131,7 +136,7 @@ int load_cd_image(const char *cd_img_name, int *type)
|
|||
|
||||
if (cue_data != NULL)
|
||||
{
|
||||
if (cue_data->tracks[2].fname == NULL) {
|
||||
if (cue_data->track_count > 1 && 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;
|
||||
}
|
||||
|
@ -157,6 +162,7 @@ int load_cd_image(const char *cd_img_name, int *type)
|
|||
{
|
||||
// assume raw, ignore header for wav..
|
||||
tracks[index].fd = f;
|
||||
tracks[index].fname = strdup(cue_data->tracks[n].fname);
|
||||
tracks[index].offset = cue_data->tracks[n].sector_offset;
|
||||
length = f->size / 2352;
|
||||
}
|
||||
|
@ -189,8 +195,8 @@ int load_cd_image(const char *cd_img_name, int *type)
|
|||
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);
|
||||
elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO %s", n, tmp_ext, length,
|
||||
cue_data->tracks[n].fname ? cue_data->tracks[n].fname : "");
|
||||
}
|
||||
goto finish;
|
||||
}
|
||||
|
@ -269,7 +275,7 @@ finish:
|
|||
PicoCDLoadProgressCB(cd_img_name, 100);
|
||||
|
||||
if (cue_data != NULL)
|
||||
cue_destroy(cue_data);
|
||||
cdparse_destroy(cue_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,15 +8,20 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cue.h"
|
||||
|
||||
#include "../pico_int.h"
|
||||
#include "cd_parse.h"
|
||||
// #define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__);
|
||||
|
||||
#ifdef USE_LIBRETRO_VFS
|
||||
#include "file_stream_transforms.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_LIBCHDR)
|
||||
#include "libchdr/chd.h"
|
||||
#include "libchdr/cdrom.h"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
@ -75,7 +80,8 @@ static int get_ext(const char *fname, char ext[4],
|
|||
if (len > 0)
|
||||
pos = len;
|
||||
|
||||
strcpy(ext, fname + pos + 1);
|
||||
strncpy(ext, fname + pos + 1, 4/*sizeof(ext)*/-1);
|
||||
ext[4/*sizeof(ext)*/-1] = '\0';
|
||||
|
||||
if (base != NULL) {
|
||||
if (pos + 1 < base_size)
|
||||
|
@ -111,15 +117,110 @@ static int file_openable(const char *fname)
|
|||
#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)
|
||||
cd_data_t *chd_parse(const char *fname)
|
||||
{
|
||||
cd_data_t *data = NULL;
|
||||
#if defined(USE_LIBCHDR)
|
||||
cd_data_t *tmp;
|
||||
int count = 0, count_alloc = 2;
|
||||
int sectors = 0;
|
||||
char metadata[256];
|
||||
chd_file *cf = NULL;
|
||||
|
||||
if (fname == NULL || *fname == '\0')
|
||||
return NULL;
|
||||
|
||||
if (chd_open(fname, CHD_OPEN_READ, NULL, &cf) != CHDERR_NONE)
|
||||
goto out;
|
||||
|
||||
data = calloc(1, sizeof(*data) + count_alloc * sizeof(cd_track_t));
|
||||
if (data == NULL)
|
||||
goto out;
|
||||
|
||||
// get track info
|
||||
while (count < CD_MAX_TRACKS) {
|
||||
int track = 0, frames = 0, pregap = 0, postgap = 0;
|
||||
char type[16], subtype[16], pgtype[16], pgsub[16];
|
||||
type[0] = subtype[0] = pgtype[0] = pgsub[0] = 0;
|
||||
|
||||
// get metadata for track
|
||||
if (chd_get_metadata(cf, CDROM_TRACK_METADATA2_TAG, count,
|
||||
metadata, sizeof(metadata), 0, 0, 0) == CHDERR_NONE) {
|
||||
if (sscanf(metadata, CDROM_TRACK_METADATA2_FORMAT,
|
||||
&track, &type[0], &subtype[0], &frames,
|
||||
&pregap, &pgtype[0], &pgsub[0], &postgap) != 8)
|
||||
break;
|
||||
}
|
||||
else if (chd_get_metadata(cf, CDROM_TRACK_METADATA_TAG, count,
|
||||
metadata, sizeof(metadata), 0, 0, 0) == CHDERR_NONE) {
|
||||
if (sscanf(metadata, CDROM_TRACK_METADATA_FORMAT,
|
||||
&track, &type[0], &subtype[0], &frames) != 4)
|
||||
break;
|
||||
}
|
||||
else break; // all tracks completed
|
||||
|
||||
// metadata sanity check
|
||||
if (track != count + 1 || frames < 0 || pregap < 0)
|
||||
break;
|
||||
|
||||
// allocate track structure
|
||||
count ++;
|
||||
if (count >= count_alloc) {
|
||||
count_alloc *= 2;
|
||||
tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cd_track_t));
|
||||
if (tmp == NULL) {
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
data = tmp;
|
||||
}
|
||||
memset(&data->tracks[count], 0, sizeof(data->tracks[0]));
|
||||
|
||||
if (count == 1) { // binary code
|
||||
data->tracks[count].fname = strdup(fname);
|
||||
if (!strcmp(type, "MODE1_RAW") || !strcmp(type, "MODE2_RAW")) {
|
||||
data->tracks[count].type = CT_BIN;
|
||||
} else if (!strcmp(type, "MODE1") || !strcmp(type, "MODE2_FORM1")) {
|
||||
data->tracks[count].type = CT_ISO;
|
||||
} else
|
||||
break;
|
||||
} else { // audio
|
||||
if (strcmp(type, "AUDIO"))
|
||||
break;
|
||||
data->tracks[count].type = CT_CHD;
|
||||
}
|
||||
|
||||
data->tracks[count].pregap = pregap;
|
||||
if (pgtype[0] != 'V') // VAUDIO includes pregap in file
|
||||
pregap = 0;
|
||||
data->tracks[count].sector_offset = sectors + pregap;
|
||||
data->tracks[count].sector_xlength = frames - pregap;
|
||||
sectors += (((frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING) * CD_TRACK_PADDING);
|
||||
}
|
||||
|
||||
// check if image id OK, i.e. there are tracks, and length <= 80 min
|
||||
if (count && sectors < (80*60*75)) {
|
||||
data->track_count = count;
|
||||
} else {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
if (cf)
|
||||
chd_close(cf);
|
||||
#endif
|
||||
return data;
|
||||
}
|
||||
|
||||
cd_data_t *cue_parse(const char *fname)
|
||||
{
|
||||
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;
|
||||
size_t current_filep_size, fname_len;
|
||||
cue_data_t *data = NULL;
|
||||
cd_data_t *data = NULL, *tmp;
|
||||
FILE *f = NULL;
|
||||
void *tmp;
|
||||
|
||||
if (fname == NULL || (fname_len = strlen(fname)) == 0)
|
||||
return NULL;
|
||||
|
@ -156,14 +257,13 @@ cue_data_t *cue_parse(const char *fname)
|
|||
p = strrchr(cue_base, '.');
|
||||
if (p) p[1] = '\0';
|
||||
|
||||
data = calloc(1, sizeof(*data) + count_alloc * sizeof(cue_track));
|
||||
data = calloc(1, sizeof(*data) + count_alloc * sizeof(cd_track_t));
|
||||
if (data == NULL)
|
||||
goto out;
|
||||
|
||||
while (!feof(f))
|
||||
{
|
||||
tmp = fgets(buff, sizeof(buff), f);
|
||||
if (tmp == NULL)
|
||||
if (fgets(buff, sizeof(buff), f) == NULL)
|
||||
break;
|
||||
|
||||
mystrip(buff);
|
||||
|
@ -180,7 +280,7 @@ cue_data_t *cue_parse(const char *fname)
|
|||
count++;
|
||||
if (count >= count_alloc) {
|
||||
count_alloc *= 2;
|
||||
tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cue_track));
|
||||
tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cd_track_t));
|
||||
if (tmp == NULL) {
|
||||
count--;
|
||||
break;
|
||||
|
@ -344,7 +444,7 @@ out:
|
|||
}
|
||||
|
||||
|
||||
void cue_destroy(cue_data_t *data)
|
||||
void cdparse_destroy(cd_data_t *data)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
@ -360,7 +460,7 @@ void cue_destroy(cue_data_t *data)
|
|||
#if 0
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cue_data_t *data = cue_parse(argv[1]);
|
||||
cd_data_t *data = cue_parse(argv[1]);
|
||||
int c;
|
||||
|
||||
if (data == NULL) return 1;
|
||||
|
@ -370,7 +470,7 @@ int main(int argc, char *argv[])
|
|||
data->tracks[c].sector_offset / (75*60), data->tracks[c].sector_offset / 75 % 60,
|
||||
data->tracks[c].sector_offset % 75, data->tracks[c].pregap, data->tracks[c].fname);
|
||||
|
||||
cue_destroy(data);
|
||||
cdparse_destroy(data);
|
||||
|
||||
return 0;
|
||||
}
|
5
pico/cd/cd_parse.h
Normal file
5
pico/cd/cd_parse.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
cd_data_t *chd_parse(const char *fname);
|
||||
cd_data_t *cue_parse(const char *fname);
|
||||
void cdparse_destroy(cd_data_t *data);
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "../pico_int.h"
|
||||
#include "genplus_macros.h"
|
||||
#include "cue.h"
|
||||
#include "cd_parse.h"
|
||||
#include "cdd.h"
|
||||
|
||||
#ifdef USE_LIBTREMOR
|
||||
|
@ -321,6 +321,7 @@ int cdd_load(const char *filename, int type)
|
|||
ret = (type == CT_BIN) ? 2352 : 2048;
|
||||
if (ret != cdd.sectorSize)
|
||||
elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
|
||||
pm_sectorsize(cdd.sectorSize, cdd.toc.tracks[0].fd);
|
||||
|
||||
/* read CD image header + security code */
|
||||
pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
|
||||
|
@ -448,6 +449,9 @@ int cdd_unload(void)
|
|||
{
|
||||
pm_close(cdd.toc.tracks[0].fd);
|
||||
cdd.toc.tracks[0].fd = NULL;
|
||||
if (cdd.toc.tracks[0].fname)
|
||||
free(cdd.toc.tracks[0].fd);
|
||||
cdd.toc.tracks[0].fname = NULL;
|
||||
}
|
||||
|
||||
for (i = 1; i < cdd.toc.last; i++)
|
||||
|
@ -466,7 +470,11 @@ int cdd_unload(void)
|
|||
if (Pico_mcd->cdda_type == CT_MP3)
|
||||
fclose(cdd.toc.tracks[i].fd);
|
||||
else
|
||||
pm_close(cdd.toc.tracks[0].fd);
|
||||
pm_close(cdd.toc.tracks[i].fd);
|
||||
cdd.toc.tracks[i].fd = NULL;
|
||||
if (cdd.toc.tracks[i].fname)
|
||||
free(cdd.toc.tracks[i].fd);
|
||||
cdd.toc.tracks[i].fname = NULL;
|
||||
|
||||
/* detect single file images */
|
||||
if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
/* CD track */
|
||||
typedef struct
|
||||
{
|
||||
char *fname;
|
||||
void *fd;
|
||||
#ifdef USE_LIBTREMOR
|
||||
OggVorbis_File vf;
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
typedef enum
|
||||
{
|
||||
CT_UNKNOWN = 0,
|
||||
CT_ISO = 1, /* 2048 B/sector */
|
||||
CT_BIN = 2, /* 2352 B/sector */
|
||||
CT_MP3 = 3,
|
||||
CT_WAV = 4
|
||||
} cue_track_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *fname;
|
||||
int pregap; /* pregap for current track */
|
||||
int sector_offset; /* in current file */
|
||||
int sector_xlength;
|
||||
cue_track_type type;
|
||||
} cue_track;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int track_count;
|
||||
cue_track tracks[0];
|
||||
} cue_data_t;
|
||||
|
||||
|
||||
cue_data_t *cue_parse(const char *fname);
|
||||
void cue_destroy(cue_data_t *data);
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue