From b923ecbe75225bc7a1b6fbf419fd962a59066d59 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 27 Apr 2008 19:16:32 +0000 Subject: [PATCH] cue support wip git-svn-id: file:///home/notaz/opt/svn/PicoDrive@432 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Pico.h | 3 +- Pico/cd/cd_file.c | 4 +- Pico/cd/cd_file.h | 10 +- Pico/cd/cd_sys.c | 8 +- Pico/cd/cue.c | 218 +++++++++++++++++++++++++++++++++++++++ Pico/cd/cue.h | 28 +++++ platform/common/emu.c | 9 +- platform/gizmondo/menu.c | 7 +- platform/gp2x/menu.c | 11 +- platform/psp/menu.c | 11 +- 10 files changed, 285 insertions(+), 24 deletions(-) create mode 100644 Pico/cd/cue.c create mode 100644 Pico/cd/cue.h diff --git a/Pico/Pico.h b/Pico/Pico.h index 59ccb779..cfcd7e47 100644 --- a/Pico/Pico.h +++ b/Pico/Pico.h @@ -94,6 +94,7 @@ void PicoCDBufferFree(void); // cd/cd_sys.c int Insert_CD(char *iso_name, int is_bin); +int Insert_CD(char *cdimg_name, int type); void Stop_CD(void); // releases all resources taken when CD game was started. // Cart.c @@ -137,7 +138,7 @@ void vidConvCpyRGB565(void *to, void *from, int pixels); #define PDRAW_SPRITES_MOVED (1<<0) #define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority #define PDRAW_ACC_SPRITES (1<<2) // accurate sprites (copied from PicoOpt) -#define PDRAW_INTERLACE (1<<3) // +#define PDRAW_INTERLACE (1<<3) // #define PDRAW_DIRTY_SPRITES (1<<4) #define PDRAW_SONIC_MODE (1<<5) // mid-frame palette changes for 8bit renderer #define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3) diff --git a/Pico/cd/cd_file.c b/Pico/cd/cd_file.c index 838d8d75..895a75f5 100644 --- a/Pico/cd/cd_file.c +++ b/Pico/cd/cd_file.c @@ -13,7 +13,7 @@ //#define cdprintf(f,...) printf(f "\n",##__VA_ARGS__) // tmp #define DEBUG_CD -PICO_INTERNAL int Load_ISO(const char *iso_name, int is_bin) +PICO_INTERNAL int Load_CD_Image(const char *iso_name, cd_img_type type) { int i, j, num_track, Cur_LBA, index, ret, iso_name_len; _scd_track *Tracks = Pico_mcd->TOC.Tracks; @@ -31,7 +31,7 @@ PICO_INTERNAL int Load_ISO(const char *iso_name, int is_bin) Unload_ISO(); - Tracks[0].ftype = is_bin ? TYPE_BIN : TYPE_ISO; + Tracks[0].ftype = type == CIT_BIN ? TYPE_BIN : TYPE_ISO; Tracks[0].F = pmf = pm_open(iso_name); if (Tracks[0].F == NULL) diff --git a/Pico/cd/cd_file.h b/Pico/cd/cd_file.h index 6b5f2131..181800fe 100644 --- a/Pico/cd/cd_file.h +++ b/Pico/cd/cd_file.h @@ -10,9 +10,17 @@ extern "C" { #define TYPE_MP3 3 //#define TYPE_WAV 4 +typedef enum +{ + CIT_NOT_CD = 0, + CIT_ISO, + CIT_BIN, + CIT_CUE +} +cd_img_type; -PICO_INTERNAL int Load_ISO(const char *iso_name, int is_bin); +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); PICO_INTERNAL int FILE_Play_CD_LBA(void); diff --git a/Pico/cd/cd_sys.c b/Pico/cd/cd_sys.c index 581583b8..ee6dda5a 100644 --- a/Pico/cd/cd_sys.c +++ b/Pico/cd/cd_sys.c @@ -196,16 +196,16 @@ PICO_INTERNAL void Reset_CD(void) } -int Insert_CD(char *iso_name, int is_bin) +int Insert_CD(char *cdimg_name, int type) { - int ret = 0; + int ret = 1; CD_Present = 0; Pico_mcd->scd.Status_CDD = NOCD; - if (iso_name != NULL) + if (cdimg_name != NULL && type != CIT_NOT_CD) { - ret = Load_ISO(iso_name, is_bin); + ret = Load_CD_Image(cdimg_name, type); if (ret == 0) { CD_Present = 1; Pico_mcd->scd.Status_CDD = READY; diff --git a/Pico/cd/cue.c b/Pico/cd/cue.c new file mode 100644 index 00000000..2ef320b1 --- /dev/null +++ b/Pico/cd/cue.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include "cue.h" + +//#include "../PicoInt.h" +#define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); + +static char *mystrip(char *str) +{ + int i, len; + + len = strlen(str); + for (i = 0; i < len; i++) + if (str[i] != ' ') break; + if (i > 0) memmove(str, str + i, len - i + 1); + + len = strlen(str); + for (i = len - 1; i >= 0; i--) + if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n') break; + str[i+1] = 0; + + return str; +} + +static int get_token(const char *buff, char *dest, int len) +{ + const char *p = buff; + char sep = ' '; + int d = 0, skip = 0; + + while (*p && *p == ' ') { + skip++; + p++; + } + + if (*p == '\"') { + sep = '\"'; + p++; + } + while (*p && *p != sep && d < len-1) + dest[d++] = *p++; + dest[d] = 0; + + if (*p != sep) + elprintf(EL_STATUS, "cue: bad token: \"%s\"", buff); + + return d + skip; +} + +static char *get_ext(char *fname) +{ + int len = strlen(fname); + return (len >= 3) ? (fname - 3) : (fname - len); +} + + +#define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0) + +/* note: tracks[0] is not used */ +cue_data *cue_parse(const char *fname) +{ + char buff[256], current_file[256], buff2[32]; + FILE *f, *tmpf; + int ret, count = 0, count_alloc = 2; + cue_data *data; + void *tmp; + + f = fopen(fname, "r"); + if (f == NULL) return NULL; + + current_file[0] = 0; + data = calloc(1, sizeof(*data) + count_alloc * sizeof(cue_track)); + + while (!feof(f)) + { + tmp = fgets(buff, sizeof(buff), f); + if (tmp == NULL) break; + + mystrip(buff); + if (buff[0] == 0) continue; + if (BEGINS(buff, "TITLE ") || BEGINS(buff, "PERFORMER ")) + continue; /* who would put those here? Ignore! */ + else if (BEGINS(buff, "FILE ")) + { + get_token(buff+5, current_file, sizeof(current_file)); + } + else if (BEGINS(buff, "TRACK ")) + { + count++; + if (count >= count_alloc) { + count_alloc *= 2; + tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cue_track)); + if (tmp == NULL) { count--; break; } + } + 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; + + tmpf = fopen(current_file, "rb"); + if (tmpf == NULL) { + elprintf(EL_STATUS, "cue: bad/missing file: \"%s\"", current_file); + count--; break; + } + fclose(tmpf); + } + // track number + ret = get_token(buff+6, buff2, sizeof(buff2)); + if (count != atoi(buff2)) + elprintf(EL_STATUS, "cue: track index mismatch: track %i is track %i in cue", + count, atoi(buff2)); + // check type + get_token(buff+6+ret, buff2, sizeof(buff2)); + if (strcmp(buff2, "MODE1/2352")) + data->tracks[count].type = CT_BIN; + else if (strcmp(buff2, "MODE1/2048")) + data->tracks[count].type = CT_ISO; + else if (strcmp(buff2, "AUDIO")) + { + if (data->tracks[count].fname != NULL) + { + // rely on extension, not type in cue.. + char *ext = get_ext(data->tracks[count].fname); + if (strcasecmp(ext, "mp3") == 0) + data->tracks[count].type = CT_MP3; + else if (strcasecmp(ext, "wav") == 0) + data->tracks[count].type = CT_WAV; + else { + elprintf(EL_STATUS, "unhandled audio format: \"%s\"", + data->tracks[count].fname); + } + } + } + else { + elprintf(EL_STATUS, "unhandled track type: \"%s\"", buff2); + } + } + else if (BEGINS(buff, "INDEX ")) + { + int m, s, f; + // type + ret = get_token(buff+6, buff2, sizeof(buff2)); + if (atoi(buff2) == 0) continue; + if (atoi(buff2) != 1) { + elprintf(EL_STATUS, "cue: don't know how to handle: \"%s\"", buff); + count--; break; + } + // offset in file + get_token(buff+6+ret, buff2, sizeof(buff2)); + ret = sscanf(buff2, "%i:%i:%i", &m, &s, &f); + if (ret != 3) { + elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); + count--; break; + } + data->tracks[count].sector_offset = m*60*75 + s*75 + f; + } + else if (BEGINS(buff, "PREGAP ")) + { + int m, s, f; + get_token(buff+7, buff2, sizeof(buff2)); + ret = sscanf(buff2, "%i:%i:%i", &m, &s, &f); + if (ret != 3) { + elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); + continue; + } + data->tracks[count].pregap = m*60*75 + s*75 + f; + } + else + { + elprintf(EL_STATUS, "cue: failed to parse: \"%s\"", buff); + } + } + + if (count < 1 || data->tracks[1].fname == NULL) { + // failed.. + for (; count > 0; count--) + if (data->tracks[count].fname != NULL) + free(data->tracks[count].fname); + free(data); + return NULL; + } + + data->track_count = count; + return data; +} + + +void cue_destroy(cue_data *data) +{ + int c; + + if (data == NULL) return; + + for (c = data->track_count; c > 0; c--) + if (data->tracks[c].fname != NULL) + free(data->tracks[c].fname); + free(data); +} + + +int main(int argc, char *argv[]) +{ + cue_data *data = cue_parse(argv[1]); + int c; + + if (data == NULL) return 1; + + for (c = 1; c <= data->track_count; c++) + printf("%2i: %i %9i %9i %s\n", c, data->tracks[c].type, data->tracks[c].sector_offset, + data->tracks[c].pregap, data->tracks[c].fname); + + cue_destroy(data); + + return 0; +} + diff --git a/Pico/cd/cue.h b/Pico/cd/cue.h new file mode 100644 index 00000000..0c4b1835 --- /dev/null +++ b/Pico/cd/cue.h @@ -0,0 +1,28 @@ + +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 */ + cue_track_type type; +} cue_track; + +typedef struct +{ + int track_count; + cue_track tracks[0]; +} cue_data; + + +cue_data *cue_parse(const char *fname); +void cue_destroy(cue_data *data); + diff --git a/platform/common/emu.c b/platform/common/emu.c index feb31676..1bbdf35f 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -164,6 +164,9 @@ int emu_cdCheck(int *pregion) unsigned char buf[32]; pm_file *cd_f; int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe + char ext[5]; + + get_ext(romFileName, ext); cd_f = pm_open(romFileName); if (!cd_f) return 0; // let the upper level handle this @@ -330,7 +333,7 @@ int emu_ReloadRom(void) // check for MegaCD image cd_state = emu_cdCheck(&cd_region); - if (cd_state > 0) + if (cd_state != CIT_NOT_CD) { PicoAHW |= PAHW_MCD; // valid CD image, check for BIOS.. @@ -405,8 +408,8 @@ int emu_ReloadRom(void) Pico.m.frame_count = 0; // insert CD if it was detected - if (cd_state > 0) { - ret = Insert_CD(romFileName, cd_state == 2); + if (cd_state != CIT_NOT_CD) { + ret = Insert_CD(romFileName, cd_state); if (ret != 0) { sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?"); lprintf("%s\n", menuErrorMsg); diff --git a/platform/gizmondo/menu.c b/platform/gizmondo/menu.c index 4f156b4d..64222e58 100644 --- a/platform/gizmondo/menu.c +++ b/platform/gizmondo/menu.c @@ -1618,10 +1618,11 @@ int menu_loop_tray(void) case 0: // select image selfname = romsel_loop(curr_path); if (selfname) { - int ret = -1, cd_type; + int ret = -1; + cd_img_type cd_type; cd_type = emu_cdCheck(NULL); - if (cd_type > 0) - ret = Insert_CD(romFileName, cd_type == 2); + if (cd_type != CIT_NOT_CD) + ret = Insert_CD(romFileName, cd_type); if (ret != 0) { sprintf(menuErrorMsg, "Load failed, invalid CD image?"); lprintf("%s\n", menuErrorMsg); diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index 919fdb9b..af7397eb 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -200,7 +200,7 @@ void menu_romload_end(void) static unsigned short file2color(const char *fname) { const char *ext = fname + strlen(fname) - 3; - static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "iso", "cso" }; + static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "iso", "cso", "cue" }; static const char *other_exts[] = { "gmv", "pat" }; int i; @@ -256,7 +256,7 @@ static int scandir_cmp(const void *p1, const void *p2) static char *filter_exts[] = { ".mp3", ".MP3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html", - ".jpg", ".gpe", ".cue" + ".jpg", ".gpe" }; static int scandir_filter(const struct dirent *ent) @@ -1724,10 +1724,11 @@ int menu_loop_tray(void) case 0: // select image selfname = romsel_loop(curr_path); if (selfname) { - int ret = -1, cd_type; + int ret = -1; + cd_img_type cd_type; cd_type = emu_cdCheck(NULL); - if (cd_type > 0) - ret = Insert_CD(romFileName, cd_type == 2); + if (cd_type != CIT_NOT_CD) + ret = Insert_CD(romFileName, cd_type); if (ret != 0) { sprintf(menuErrorMsg, "Load failed, invalid CD image?"); printf("%s\n", menuErrorMsg); diff --git a/platform/psp/menu.c b/platform/psp/menu.c index 1613cfb7..48de81ed 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -185,7 +185,7 @@ struct my_dirent static unsigned short file2color(const char *fname) { const char *ext = fname + strlen(fname) - 3; - static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "iso", "cso" }; + static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "iso", "cso", "cue" }; static const char *other_exts[] = { "gmv", "pat" }; int i; @@ -241,7 +241,7 @@ static int scandir_cmp(const void *p1, const void *p2) static char *filter_exts[] = { ".mp3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html", - ".jpg", ".cue", ".pbp" + ".jpg", ".pbp" }; static int scandir_filter(const struct my_dirent *ent) @@ -1810,10 +1810,11 @@ int menu_loop_tray(void) case 0: // select image selfname = romsel_loop(curr_path); if (selfname) { - int ret = -1, cd_type; + int ret = -1; + cd_img_type cd_type; cd_type = emu_cdCheck(NULL); - if (cd_type > 0) - ret = Insert_CD(romFileName, cd_type == 2); + if (cd_type != CIT_NOT_CD) + ret = Insert_CD(romFileName, cd_type); if (ret != 0) { sprintf(menuErrorMsg, "Load failed, invalid CD image?"); lprintf("%s\n", menuErrorMsg); -- 2.39.5