瀏覽代碼

cue support wip

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@432 be3aeb3a-fb24-0410-a615-afba39da0efa
notaz 16 年之前
父節點
當前提交
b923ecbe75
共有 10 個文件被更改,包括 285 次插入24 次删除
  1. 2 1
      Pico/Pico.h
  2. 2 2
      Pico/cd/cd_file.c
  3. 9 1
      Pico/cd/cd_file.h
  4. 4 4
      Pico/cd/cd_sys.c
  5. 218 0
      Pico/cd/cue.c
  6. 28 0
      Pico/cd/cue.h
  7. 6 3
      platform/common/emu.c
  8. 4 3
      platform/gizmondo/menu.c
  9. 6 5
      platform/gp2x/menu.c
  10. 6 5
      platform/psp/menu.c

+ 2 - 1
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)

+ 2 - 2
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)

+ 9 - 1
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);

+ 4 - 4
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;

+ 218 - 0
Pico/cd/cue.c

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

+ 28 - 0
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);
+

+ 6 - 3
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);

+ 4 - 3
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);

+ 6 - 5
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);

+ 6 - 5
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);