cue support wip
authornotaz <notasas@gmail.com>
Sun, 27 Apr 2008 19:16:32 +0000 (19:16 +0000)
committernotaz <notasas@gmail.com>
Sun, 27 Apr 2008 19:16:32 +0000 (19:16 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@432 be3aeb3a-fb24-0410-a615-afba39da0efa

Pico/Pico.h
Pico/cd/cd_file.c
Pico/cd/cd_file.h
Pico/cd/cd_sys.c
Pico/cd/cue.c [new file with mode: 0644]
Pico/cd/cue.h [new file with mode: 0644]
platform/common/emu.c
platform/gizmondo/menu.c
platform/gp2x/menu.c
platform/psp/menu.c

index 59ccb77..cfcd7e4 100644 (file)
@@ -94,6 +94,7 @@ void PicoCDBufferFree(void);
 \r
 // cd/cd_sys.c\r
 int Insert_CD(char *iso_name, int is_bin);\r
+int Insert_CD(char *cdimg_name, int type);\r
 void Stop_CD(void); // releases all resources taken when CD game was started.\r
 \r
 // Cart.c\r
@@ -137,7 +138,7 @@ void vidConvCpyRGB565(void *to, void *from, int pixels);
 #define PDRAW_SPRITES_MOVED (1<<0)\r
 #define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority\r
 #define PDRAW_ACC_SPRITES   (1<<2) // accurate sprites (copied from PicoOpt)\r
-#define PDRAW_INTERLACE     (1<<3) // \r
+#define PDRAW_INTERLACE     (1<<3) //\r
 #define PDRAW_DIRTY_SPRITES (1<<4)\r
 #define PDRAW_SONIC_MODE    (1<<5) // mid-frame palette changes for 8bit renderer\r
 #define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3)\r
index 838d8d7..895a75f 100644 (file)
@@ -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)
index 6b5f213..181800f 100644 (file)
@@ -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);
index 581583b..ee6dda5 100644 (file)
@@ -196,16 +196,16 @@ PICO_INTERNAL void Reset_CD(void)
 }\r
 \r
 \r
-int Insert_CD(char *iso_name, int is_bin)\r
+int Insert_CD(char *cdimg_name, int type)\r
 {\r
-       int ret = 0;\r
+       int ret = 1;\r
 \r
        CD_Present = 0;\r
        Pico_mcd->scd.Status_CDD = NOCD;\r
 \r
-       if (iso_name != NULL)\r
+       if (cdimg_name != NULL && type != CIT_NOT_CD)\r
        {\r
-               ret = Load_ISO(iso_name, is_bin);\r
+               ret = Load_CD_Image(cdimg_name, type);\r
                if (ret == 0) {\r
                        CD_Present = 1;\r
                        Pico_mcd->scd.Status_CDD = READY;\r
diff --git a/Pico/cd/cue.c b/Pico/cd/cue.c
new file mode 100644 (file)
index 0000000..2ef320b
--- /dev/null
@@ -0,0 +1,218 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..0c4b183
--- /dev/null
@@ -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);
+
index feb3167..1bbdf35 100644 (file)
@@ -164,6 +164,9 @@ int emu_cdCheck(int *pregion)
        unsigned char buf[32];\r
        pm_file *cd_f;\r
        int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe\r
+       char ext[5];\r
+\r
+       get_ext(romFileName, ext);\r
 \r
        cd_f = pm_open(romFileName);\r
        if (!cd_f) return 0; // let the upper level handle this\r
@@ -330,7 +333,7 @@ int emu_ReloadRom(void)
 \r
        // check for MegaCD image\r
        cd_state = emu_cdCheck(&cd_region);\r
-       if (cd_state > 0)\r
+       if (cd_state != CIT_NOT_CD)\r
        {\r
                PicoAHW |= PAHW_MCD;\r
                // valid CD image, check for BIOS..\r
@@ -405,8 +408,8 @@ int emu_ReloadRom(void)
        Pico.m.frame_count = 0;\r
 \r
        // insert CD if it was detected\r
-       if (cd_state > 0) {\r
-               ret = Insert_CD(romFileName, cd_state == 2);\r
+       if (cd_state != CIT_NOT_CD) {\r
+               ret = Insert_CD(romFileName, cd_state);\r
                if (ret != 0) {\r
                        sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?");\r
                        lprintf("%s\n", menuErrorMsg);\r
index 4f156b4..64222e5 100644 (file)
@@ -1618,10 +1618,11 @@ int menu_loop_tray(void)
                                case 0: // select image\r
                                        selfname = romsel_loop(curr_path);\r
                                        if (selfname) {\r
-                                               int ret = -1, cd_type;\r
+                                               int ret = -1;\r
+                                               cd_img_type cd_type;\r
                                                cd_type = emu_cdCheck(NULL);\r
-                                               if (cd_type > 0)\r
-                                                       ret = Insert_CD(romFileName, cd_type == 2);\r
+                                               if (cd_type != CIT_NOT_CD)\r
+                                                       ret = Insert_CD(romFileName, cd_type);\r
                                                if (ret != 0) {\r
                                                        sprintf(menuErrorMsg, "Load failed, invalid CD image?");\r
                                                        lprintf("%s\n", menuErrorMsg);\r
index 919fdb9..af7397e 100644 (file)
@@ -200,7 +200,7 @@ void menu_romload_end(void)
 static unsigned short file2color(const char *fname)\r
 {\r
        const char *ext = fname + strlen(fname) - 3;\r
-       static const char *rom_exts[]   = { "zip", "bin", "smd", "gen", "iso", "cso" };\r
+       static const char *rom_exts[]   = { "zip", "bin", "smd", "gen", "iso", "cso", "cue" };\r
        static const char *other_exts[] = { "gmv", "pat" };\r
        int i;\r
 \r
@@ -256,7 +256,7 @@ static int scandir_cmp(const void *p1, const void *p2)
 \r
 static char *filter_exts[] = {\r
        ".mp3", ".MP3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html",\r
-       ".jpg", ".gpe", ".cue"\r
+       ".jpg", ".gpe"\r
 };\r
 \r
 static int scandir_filter(const struct dirent *ent)\r
@@ -1724,10 +1724,11 @@ int menu_loop_tray(void)
                                case 0: // select image\r
                                        selfname = romsel_loop(curr_path);\r
                                        if (selfname) {\r
-                                               int ret = -1, cd_type;\r
+                                               int ret = -1;\r
+                                               cd_img_type cd_type;\r
                                                cd_type = emu_cdCheck(NULL);\r
-                                               if (cd_type > 0)\r
-                                                       ret = Insert_CD(romFileName, cd_type == 2);\r
+                                               if (cd_type != CIT_NOT_CD)\r
+                                                       ret = Insert_CD(romFileName, cd_type);\r
                                                if (ret != 0) {\r
                                                        sprintf(menuErrorMsg, "Load failed, invalid CD image?");\r
                                                        printf("%s\n", menuErrorMsg);\r
index 1613cfb..48de81e 100644 (file)
@@ -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);