summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2010-05-30 16:24:14 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2010-05-30 16:24:14 +0000
commit842282c0fa0e5e3ae9e36e8cab4fed65f4bead97 (patch)
tree3b55f291693f011d3d164e249105922f582f0c8a
parent1f47f5a0d5dc5936a46bc969e034b5a837392c25 (diff)
chdman/cdrom updates: [R. Belmont]
- CDRWIN .bin/.cue images now supported for both input and output - Pregap and postgap information is now preserved in the format - Output of CDRDAO images is significantly improved Existing CHD-CDs will continue to work fine and for data-only discs no action needs to be taken. For mixed data/audio discs (e.g. analog 573/Bemani games) they should be re-converted for better preservation.
-rw-r--r--src/lib/util/cdrom.c182
-rw-r--r--src/lib/util/cdrom.h13
-rw-r--r--src/lib/util/chd.h4
-rw-r--r--src/tools/chdcd.c112
-rw-r--r--src/tools/chdman.c226
5 files changed, 422 insertions, 115 deletions
diff --git a/src/lib/util/cdrom.c b/src/lib/util/cdrom.c
index 0ad16a88286..c48eedc5996 100644
--- a/src/lib/util/cdrom.c
+++ b/src/lib/util/cdrom.c
@@ -414,55 +414,111 @@ const cdrom_toc *cdrom_get_toc(cdrom_file *file)
***************************************************************************/
/*-------------------------------------------------
- cdrom_convert_type_string_to_track_info -
+ cdrom_get_info_from_type_string
take a string and convert it into track type
and track data size
-------------------------------------------------*/
-void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info)
+void cdrom_get_info_from_type_string(const char *typestring, UINT32 *trktype, UINT32 *datasize)
{
if (!strcmp(typestring, "MODE1"))
{
- info->trktype = CD_TRACK_MODE1;
- info->datasize = 2048;
+ *trktype = CD_TRACK_MODE1;
+ *datasize = 2048;
+ }
+ else if (!strcmp(typestring, "MODE1/2048"))
+ {
+ *trktype = CD_TRACK_MODE1;
+ *datasize = 2048;
}
else if (!strcmp(typestring, "MODE1_RAW"))
{
- info->trktype = CD_TRACK_MODE1_RAW;
- info->datasize = 2352;
+ *trktype = CD_TRACK_MODE1_RAW;
+ *datasize = 2352;
+ }
+ else if (!strcmp(typestring, "MODE1/2352"))
+ {
+ *trktype = CD_TRACK_MODE1_RAW;
+ *datasize = 2352;
}
else if (!strcmp(typestring, "MODE2"))
{
- info->trktype = CD_TRACK_MODE2;
- info->datasize = 2336;
+ *trktype = CD_TRACK_MODE2;
+ *datasize = 2336;
+ }
+ else if (!strcmp(typestring, "MODE2/2336"))
+ {
+ *trktype = CD_TRACK_MODE2;
+ *datasize = 2336;
}
else if (!strcmp(typestring, "MODE2_FORM1"))
{
- info->trktype = CD_TRACK_MODE2_FORM1;
- info->datasize = 2048;
+ *trktype = CD_TRACK_MODE2_FORM1;
+ *datasize = 2048;
+ }
+ else if (!strcmp(typestring, "MODE2/2048"))
+ {
+ *trktype = CD_TRACK_MODE2_FORM1;
+ *datasize = 2048;
}
else if (!strcmp(typestring, "MODE2_FORM2"))
{
- info->trktype = CD_TRACK_MODE2_FORM2;
- info->datasize = 2324;
+ *trktype = CD_TRACK_MODE2_FORM2;
+ *datasize = 2324;
+ }
+ else if (!strcmp(typestring, "MODE2/2324"))
+ {
+ *trktype = CD_TRACK_MODE2_FORM2;
+ *datasize = 2324;
}
else if (!strcmp(typestring, "MODE2_FORM_MIX"))
{
- info->trktype = CD_TRACK_MODE2_FORM_MIX;
- info->datasize = 2336;
+ *trktype = CD_TRACK_MODE2_FORM_MIX;
+ *datasize = 2336;
+ }
+ else if (!strcmp(typestring, "MODE2/2336"))
+ {
+ *trktype = CD_TRACK_MODE2_FORM_MIX;
+ *datasize = 2336;
}
else if (!strcmp(typestring, "MODE2_RAW"))
{
- info->trktype = CD_TRACK_MODE2_RAW;
- info->datasize = 2352;
+ *trktype = CD_TRACK_MODE2_RAW;
+ *datasize = 2352;
+ }
+ else if (!strcmp(typestring, "MODE2/2352"))
+ {
+ *trktype = CD_TRACK_MODE2_RAW;
+ *datasize = 2352;
}
else if (!strcmp(typestring, "AUDIO"))
{
- info->trktype = CD_TRACK_AUDIO;
- info->datasize = 2352;
+ *trktype = CD_TRACK_AUDIO;
+ *datasize = 2352;
}
}
+/*-------------------------------------------------
+ cdrom_convert_type_string_to_track_info -
+ take a string and convert it into track type
+ and track data size
+-------------------------------------------------*/
+
+void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info)
+{
+ cdrom_get_info_from_type_string(typestring, &info->trktype, &info->datasize);
+}
+
+/*-------------------------------------------------
+ cdrom_convert_type_string_to_pregap_info -
+ take a string and convert it into pregap type
+ and pregap data size
+-------------------------------------------------*/
+
+void cdrom_convert_type_string_to_pregap_info(const char *typestring, cdrom_track_info *info)
+{
+ cdrom_get_info_from_type_string(typestring, &info->pgtype, &info->pgdatasize);
+}
/*-------------------------------------------------
cdrom_convert_subtype_string_to_track_info -
@@ -484,17 +540,36 @@ void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_tr
}
}
+/*-------------------------------------------------
+ cdrom_convert_subtype_string_to_pregap_info -
+ take a string and convert it into track subtype
+ and track subcode data size
+-------------------------------------------------*/
+
+void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info)
+{
+ if (!strcmp(typestring, "RW"))
+ {
+ info->pgsub = CD_SUB_NORMAL;
+ info->pgsubsize = 96;
+ }
+ else if (!strcmp(typestring, "RW_RAW"))
+ {
+ info->pgsub = CD_SUB_RAW;
+ info->pgsubsize = 96;
+ }
+}
/*-------------------------------------------------
cdrom_get_type_string - get the string
associated with the given type
-------------------------------------------------*/
-const char *cdrom_get_type_string(const cdrom_track_info *info)
+const char *cdrom_get_type_string(UINT32 trktype)
{
- switch (info->trktype)
+ switch (trktype)
{
- case CD_TRACK_MODE1: return "MODE1";
+ case CD_TRACK_MODE1: return "MODE1";
case CD_TRACK_MODE1_RAW: return "MODE1_RAW";
case CD_TRACK_MODE2: return "MODE2";
case CD_TRACK_MODE2_FORM1: return "MODE2_FORM1";
@@ -512,9 +587,9 @@ const char *cdrom_get_type_string(const cdrom_track_info *info)
associated with the given subcode type
-------------------------------------------------*/
-const char *cdrom_get_subtype_string(const cdrom_track_info *info)
+const char *cdrom_get_subtype_string(UINT32 subtype)
{
- switch (info->subtype)
+ switch (subtype)
{
case CD_SUB_NORMAL: return "RW";
case CD_SUB_RAW: return "RW_RAW";
@@ -566,29 +641,45 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
static UINT32 oldmetadata[CD_METADATA_WORDS], *mrp;
const chd_header *header = chd_get_header(chd);
UINT32 hunksectors = header->hunkbytes / CD_FRAME_SIZE;
- char metadata[256];
+ char metadata[512];
chd_error err;
int i;
/* start with no tracks */
for (toc->numtrks = 0; toc->numtrks < CD_MAX_TRACKS; toc->numtrks++)
{
- int tracknum = -1, frames = 0, hunks;
- char type[16], subtype[16];
+ int tracknum = -1, frames = 0, hunks, pregap, postgap;
+ char type[16], subtype[16], pgtype[16], pgsub[16];
cdrom_track_info *track;
+ pregap = postgap = 0;
+
/* fetch the metadata for this track */
err = chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata, sizeof(metadata), NULL, NULL, NULL);
- if (err != CHDERR_NONE)
- break;
-
- /* parse the metadata */
- type[0] = subtype[0] = 0;
- if (sscanf(metadata, CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4)
- return CHDERR_INVALID_DATA;
- if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
- return CHDERR_INVALID_DATA;
- track = &toc->tracks[tracknum - 1];
+ if (err == CHDERR_NONE)
+ {
+ /* parse the metadata */
+ type[0] = subtype[0] = 0;
+ if (sscanf(metadata, CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4)
+ return CHDERR_INVALID_DATA;
+ if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
+ return CHDERR_INVALID_DATA;
+ track = &toc->tracks[tracknum - 1];
+ }
+ else
+ {
+ err = chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata, sizeof(metadata), NULL, NULL, NULL);
+ if (err != CHDERR_NONE)
+ break;
+ /* parse the metadata */
+ type[0] = subtype[0] = 0;
+ pregap = postgap = 0;
+ if (sscanf(metadata, CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8)
+ return CHDERR_INVALID_DATA;
+ if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
+ return CHDERR_INVALID_DATA;
+ track = &toc->tracks[tracknum - 1];
+ }
/* extract the track type and determine the data size */
track->trktype = CD_TRACK_MODE1;
@@ -606,6 +697,15 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
track->frames = frames;
hunks = (frames + hunksectors - 1) / hunksectors;
track->extraframes = hunks * hunksectors - frames;
+
+ /* set the pregap info */
+ track->pregap = pregap;
+ track->pgtype = CD_TRACK_MODE1;
+ track->pgsub = CD_SUB_NONE;
+ track->pgdatasize = 0;
+ track->pgsubsize = 0;
+ cdrom_convert_type_string_to_pregap_info(pgtype, track);
+ cdrom_convert_subtype_string_to_pregap_info(pgsub, track);
}
/* if we got any tracks this way, we're done */
@@ -662,11 +762,13 @@ chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
/* write the metadata */
for (i = 0; i < toc->numtrks; i++)
{
- char metadata[256];
- sprintf(metadata, CDROM_TRACK_METADATA_FORMAT, i + 1, cdrom_get_type_string(&toc->tracks[i]),
- cdrom_get_subtype_string(&toc->tracks[i]), toc->tracks[i].frames);
+ char metadata[512];
+ sprintf(metadata, CDROM_TRACK_METADATA2_FORMAT, i + 1, cdrom_get_type_string(toc->tracks[i].trktype),
+ cdrom_get_subtype_string(toc->tracks[i].subtype), toc->tracks[i].frames, toc->tracks[i].pregap,
+ cdrom_get_type_string(toc->tracks[i].pgtype), cdrom_get_subtype_string(toc->tracks[i].pgsub),
+ toc->tracks[i].postgap);
- err = chd_set_metadata(chd, CDROM_TRACK_METADATA_TAG, i, metadata, strlen(metadata) + 1, CHD_MDFLAGS_CHECKSUM);
+ err = chd_set_metadata(chd, CDROM_TRACK_METADATA2_TAG, i, metadata, strlen(metadata) + 1, CHD_MDFLAGS_CHECKSUM);
if (err != CHDERR_NONE)
return err;
}
diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h
index d8a37c0b7a6..226f190f17a 100644
--- a/src/lib/util/cdrom.h
+++ b/src/lib/util/cdrom.h
@@ -59,6 +59,7 @@
#define CD_FRAMES_PER_HUNK (4)
#define CD_METADATA_WORDS (1+(CD_MAX_TRACKS * 6))
+
enum
{
CD_TRACK_MODE1 = 0, /* mode 1 2048 bytes/sector */
@@ -99,6 +100,12 @@ struct _cdrom_track_info
UINT32 subsize; /* size of subchannel data in each sector of this track */
UINT32 frames; /* number of frames in this track */
UINT32 extraframes; /* number of "spillage" frames in this track */
+ UINT32 pregap; /* number of pregap frames */
+ UINT32 postgap; /* number of postgap frames */
+ UINT32 pgtype; /* type of sectors in pregap */
+ UINT32 pgsub; /* type of subchannel data in pregap */
+ UINT32 pgdatasize; /* size of data in each sector of the pregap */
+ UINT32 pgsubsize; /* size of subchannel data in each sector of the pregap */
/* fields used in MAME only */
UINT32 physframeofs; /* frame number on the real CD this track starts at */
@@ -139,9 +146,11 @@ const cdrom_toc *cdrom_get_toc(cdrom_file *file);
/* extra utilities */
void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info);
+void cdrom_convert_type_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_track_info *info);
-const char *cdrom_get_type_string(const cdrom_track_info *info);
-const char *cdrom_get_subtype_string(const cdrom_track_info *info);
+void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
+const char *cdrom_get_type_string(UINT32 trktype);
+const char *cdrom_get_subtype_string(UINT32 subtype);
chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc);
chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc);
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index c090c04ac81..fa3291baa79 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -182,7 +182,9 @@
#define CDROM_OLD_METADATA_TAG 0x43484344 /* 'CHCD' */
#define CDROM_TRACK_METADATA_TAG 0x43485452 /* 'CHTR' */
#define CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
-
+#define CDROM_TRACK_METADATA2_TAG 0x43485432 /* 'CHT2' */
+#define CDROM_TRACK_METADATA2_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
+
/* standard A/V metadata */
#define AV_METADATA_TAG 0x41564156 /* 'AVAV' */
#define AV_METADATA_FORMAT "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d"
diff --git a/src/tools/chdcd.c b/src/tools/chdcd.c
index cbb19b10070..8895003784a 100644
--- a/src/tools/chdcd.c
+++ b/src/tools/chdcd.c
@@ -1,6 +1,7 @@
/***************************************************************************
- CDRDAO TOC parser for CHD compression frontend
+ TOC parser for CHD compression frontend
+ Handles CDRDAO .toc, CDRWIN .cue, and Sega GDROM .gdi
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
@@ -231,13 +232,33 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc *outtoc, chdcd_
}
/*-------------------------------------------------
+ chdcd_tracksize_helper - fixes up track sizes
+ for bin/cue images
+-------------------------------------------------*/
+
+static void chdcd_tracksize_helper(int trknum, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
+{
+ if (outtoc->tracks[trknum].frames == 0)
+ {
+ UINT64 tlen;
+
+ tlen = get_file_size(outinfo->fname[trknum]) - outinfo->offset[trknum];
+ tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
+
+ outtoc->tracks[trknum].frames = tlen;
+ }
+
+// printf("track %d: %d frames\n", trknum, outtoc->tracks[trknum].frames);
+}
+
+/*-------------------------------------------------
chdcd_parse_toc - parse a CDRDAO format TOC file
-------------------------------------------------*/
chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
{
FILE *infile;
- int i, trknum;
+ int i, trknum, cuemode = 0;
static char token[128];
if (strstr(tocfname,".gdi"))
@@ -245,6 +266,11 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i
return chdcd_parse_gdi(tocfname, outtoc, outinfo);
}
+ if (strstr(tocfname,".cue"))
+ {
+ cuemode = 1;
+ }
+
infile = fopen(tocfname, "rt");
if (infile == (FILE *)NULL)
@@ -274,6 +300,17 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i
{
int f;
+ /* for bin/cue, this is where you increment the track # */
+ if (cuemode)
+ {
+ /* make sure we have a size for the current track before moving on */
+ if (trknum > -1)
+ {
+ chdcd_tracksize_helper(trknum, outtoc, outinfo);
+ }
+ trknum++;
+ }
+
/* found the data file for a track */
TOKENIZE
@@ -341,27 +378,29 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i
}
else
{
- /* guesstimate the track length */
- UINT64 tlen;
- printf("Warning: Estimating length of track %d. If this is not the final or only track\n on the disc, the estimate may be wrong.\n", trknum+1);
-
- tlen = get_file_size(outinfo->fname[trknum]) - outinfo->offset[trknum];
-
- tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
-
- f = tlen;
+ /* guesstimate the track length? */
+ f = 0;
}
outtoc->tracks[trknum].frames = f;
}
else if (!strcmp(token, "TRACK"))
{
- /* found a new track */
- trknum++;
+ /* found a new track if CDRDAO .toc, not if .cue */
+ if (!cuemode)
+ {
+ trknum++;
+ }
/* next token on the line is the track type */
TOKENIZE
+ /* for bin/cue skip the track number */
+ if (cuemode)
+ {
+ TOKENIZE
+ }
+
outtoc->tracks[trknum].trktype = CD_TRACK_MODE1;
outtoc->tracks[trknum].datasize = 0;
outtoc->tracks[trknum].subtype = CD_SUB_NONE;
@@ -376,8 +415,8 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i
outtoc->tracks[trknum].trktype != CD_TRACK_MODE2_RAW &&
outtoc->tracks[trknum].trktype != CD_TRACK_AUDIO)
{
- printf("Note: MAME now prefers and can accept RAW format images.\n");
- printf("At least one track of this CDRDAO rip is not either RAW or AUDIO.\n");
+ printf("Note: MAME prefers and can accept RAW format images.\n");
+ printf("At least one track of this rip is not either RAW or AUDIO.\n");
}
/* next (optional) token on the line is the subcode type */
@@ -385,9 +424,52 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_i
cdrom_convert_subtype_string_to_track_info(token, &outtoc->tracks[trknum]);
}
+ else if (!strcmp(token, "INDEX")) /* only in bin/cue files */
+ {
+ int idx, frames;
+
+ /* get index number */
+ TOKENIZE
+ idx = strtoul(token, NULL, 10);
+
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames( token );
+
+ if (idx == 1)
+ {
+ outtoc->tracks[trknum].pregap = frames;
+ }
+ }
+ else if ((!strcmp(token, "START")) || (!strcmp(token, "PREGAP"))) /* START for CDRDAO, PREGAP for CDRWIN */
+ {
+ int frames;
+
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames( token );
+
+ outtoc->tracks[trknum].pregap = frames;
+ }
+ else if (!strcmp(token, "POSTGAP")) /* only in CDRWIN files */
+ {
+ int frames;
+
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames( token );
+
+ outtoc->tracks[trknum].postgap = frames;
+ }
}
}
+ if (cuemode)
+ {
+ /* make sure we have a size for the last track before moving on */
+ chdcd_tracksize_helper(trknum, outtoc, outinfo);
+ }
+
/* close the input TOC */
fclose(infile);
diff --git a/src/tools/chdman.c b/src/tools/chdman.c
index 9868ec91dcc..608205cce52 100644
--- a/src/tools/chdman.c
+++ b/src/tools/chdman.c
@@ -183,11 +183,11 @@ static int usage(void)
printf(" or: chdman -createhd inputhd.raw output.chd [ident.bin] [inputoffs [cylinders heads sectors [sectorsize [hunksize]]]]\n");
printf(" or: chdman -createuncomphd inputhd.raw output.chd [ident.bin] [inputoffs [cylinders heads sectors [sectorsize [hunksize]]]]\n");
printf(" or: chdman -createblankhd output.chd cylinders heads sectors [sectorsize [hunksize]]\n");
- printf(" or: chdman -createcd input.toc output.chd\n");
+ printf(" or: chdman -createcd input.(toc/cue/gdi) output.chd\n");
printf(" or: chdman -createav input.avi output.chd [firstframe [numframes]]\n");
printf(" or: chdman -copydata input.chd output.chd\n");
printf(" or: chdman -extract input.chd output.raw\n");
- printf(" or: chdman -extractcd input.chd output.toc output.bin\n");
+ printf(" or: chdman -extractcd input.chd output.(toc/cue) output.bin (if toc, no extension if cue)\n");
printf(" or: chdman -extractav input.chd output.avi [firstframe [numframes]]\n");
printf(" or: chdman -verify input.chd\n");
printf(" or: chdman -verifyfix input.chd\n");
@@ -689,6 +689,9 @@ static int do_createcd(int argc, char *argv[], int param)
inputfile = argv[2];
outputfile = argv[3];
+ /* clear the TOC */
+ memset(&toc, 0, sizeof(toc));
+
/* allocate a cache */
cache = (UINT8 *)malloc(hunksize);
if (cache == NULL)
@@ -773,7 +776,7 @@ static int do_createcd(int argc, char *argv[], int param)
goto cleanup;
}
- printf("Track %d/%d (%s:%d,%d frames,%d hunks,swap %d)\n", i+1, toc.numtrks, track_info.fname[i], track_info.offset[i], toc.tracks[i].frames, trackhunks, track_info.swap[i]);
+ printf("Track %d/%d (%s:%d,%d frames,%d hunks,swap %d,pregap %d,postgap %d)\n", i+1, toc.numtrks, track_info.fname[i], track_info.offset[i], toc.tracks[i].frames, trackhunks, track_info.swap[i], toc.tracks[i].pregap, toc.tracks[i].postgap);
/* loop over hunks */
for (curhunk = 0; curhunk < trackhunks; curhunk++, totalhunks++)
@@ -1514,7 +1517,7 @@ cleanup:
/*-------------------------------------------------
do_extractcd - extract a CDRDAO .toc/.bin
- file from a CHD-CD image
+ or CDRWIN .cue/.bin file from a CHD-CD image
-------------------------------------------------*/
static int do_extractcd(int argc, char *argv[], int param)
@@ -1528,7 +1531,7 @@ static int do_extractcd(int argc, char *argv[], int param)
UINT64 out2offs;
file_error filerr;
chd_error err;
- int track;
+ int track, cuemode;
/* require 5 args total */
if (argc != 5)
@@ -1541,7 +1544,7 @@ static int do_extractcd(int argc, char *argv[], int param)
/* print some info */
printf("Input file: %s\n", inputfile);
- printf("Output files: %s (toc) and %s (bin)\n", outputfile, outputfile2);
+ printf("Output files: %s and %s\n", outputfile, outputfile2);
/* get the header */
err = chd_open(inputfile, CHD_OPEN_READ, NULL, &inputchd);
@@ -1560,6 +1563,13 @@ static int do_extractcd(int argc, char *argv[], int param)
goto cleanup;
}
+ /* check for CDRWIN format */
+ cuemode = 0;
+ if (strstr(outputfile, ".cue"))
+ {
+ cuemode = 1;
+ }
+
/* get the TOC data */
toc = cdrom_get_toc(cdrom);
@@ -1571,14 +1581,18 @@ static int do_extractcd(int argc, char *argv[], int param)
err = CHDERR_CANT_CREATE_FILE;
goto cleanup;
}
- fprintf(outfile, "CD_ROM\n\n\n");
- filerr = core_fopen(outputfile2, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &outfile2);
- if (filerr != FILERR_NONE)
+ if (!cuemode)
{
- fprintf(stderr, "Error opening output file '%s'\n", outputfile2);
- err = CHDERR_CANT_CREATE_FILE;
- goto cleanup;
+ fprintf(outfile, "CD_ROM\n\n\n");
+
+ filerr = core_fopen(outputfile2, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &outfile2);
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Error opening output file '%s'\n", outputfile2);
+ err = CHDERR_CANT_CREATE_FILE;
+ goto cleanup;
+ }
}
/* process away */
@@ -1586,52 +1600,141 @@ static int do_extractcd(int argc, char *argv[], int param)
for (track = 0; track < toc->numtrks; track++)
{
UINT32 m, s, f, frame, trackframes;
+ char trackoutname[512];
- progress(TRUE, "Extracting track %d... \r", track+1);
+ if (cuemode)
+ {
+ sprintf(trackoutname, "%s (track %02d).bin", outputfile2, track+1);
- fprintf(outfile, "// Track %d\n", track+1);
+ filerr = core_fopen(trackoutname, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &outfile2);
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Error opening output file '%s'\n", outputfile2);
+ err = CHDERR_CANT_CREATE_FILE;
+ goto cleanup;
+ }
- /* write out the track type */
- if (toc->tracks[track].subtype != CD_SUB_NONE)
- fprintf(outfile, "TRACK %s %s\n", cdrom_get_type_string(&toc->tracks[track]), cdrom_get_subtype_string(&toc->tracks[track]));
- else
- fprintf(outfile, "TRACK %s\n", cdrom_get_type_string(&toc->tracks[track]));
+ out2offs = 0;
+ }
- /* write out the attributes */
- fprintf(outfile, "NO COPY\n");
- if (toc->tracks[track].trktype == CD_TRACK_AUDIO)
+ progress(TRUE, "Extracting track %d... \r", track+1);
+
+ trackframes = toc->tracks[track].frames;
+
+ if (cuemode)
{
- fprintf(outfile, "NO PRE_EMPHASIS\n");
- fprintf(outfile, "TWO_CHANNEL_AUDIO\n");
+ char modestr[16];
- /* the first audio track on a mixed-track disc always has a 2 second pad */
- if (track == 1)
+ fprintf(outfile, "FILE \"%s\" BINARY\n", trackoutname);
+
+ switch (toc->tracks[track].trktype)
{
- if (toc->tracks[track].subtype != CD_SUB_NONE)
- fprintf(outfile, "ZERO AUDIO %s 00:02:00\n", cdrom_get_subtype_string(&toc->tracks[track]));
- else
- fprintf(outfile, "ZERO AUDIO 00:02:00\n");
+ case CD_TRACK_MODE1:
+ case CD_TRACK_MODE1_RAW:
+ sprintf(modestr, "MODE1/%04d", toc->tracks[track].datasize);
+ break;
+
+ case CD_TRACK_MODE2:
+ case CD_TRACK_MODE2_FORM1:
+ case CD_TRACK_MODE2_FORM2:
+ case CD_TRACK_MODE2_FORM_MIX:
+ case CD_TRACK_MODE2_RAW:
+ sprintf(modestr, "MODE2/%04d", toc->tracks[track].datasize);
+ break;
+
+ case CD_TRACK_AUDIO:
+ strcpy(modestr, "AUDIO");
+ break;
}
- }
- /* convert to minutes/seconds/frames */
- trackframes = toc->tracks[track].frames;
- f = trackframes;
- s = f / 75;
- f %= 75;
- m = s / 60;
- s %= 60;
-
- /* all tracks but the first one have a file offset */
- if (track > 0)
- fprintf(outfile, "DATAFILE \"%s\" #%d %02d:%02d:%02d // length in bytes: %d\n", outputfile2, (UINT32)out2offs, m, s, f, trackframes*(toc->tracks[track].datasize+toc->tracks[track].subsize));
+ fprintf(outfile, " TRACK %02d %s\n", track+1, modestr);
+
+ fprintf(outfile, " INDEX 00 00:00:00\n");
+
+ if (toc->tracks[track].pregap > 0)
+ {
+ f = toc->tracks[track].pregap;
+ s = f / 75;
+ f %= 75;
+ m = s / 60;
+ s %= 60;
+ fprintf(outfile, " INDEX 01 %02d:%02d:%02d\n", m, s, f);
+ }
+
+ if (toc->tracks[track].postgap > 0)
+ {
+ f = toc->tracks[track].postgap;
+ s = f / 75;
+ f %= 75;
+ m = s / 60;
+ s %= 60;
+ fprintf(outfile, " POSTGAP %02d:%02d:%02d\n", m, s, f);
+ }
+ }
else
- fprintf(outfile, "DATAFILE \"%s\" %02d:%02d:%02d // length in bytes: %d\n", outputfile2, m, s, f, trackframes*(toc->tracks[track].datasize+toc->tracks[track].subsize));
+ {
+ char modesubmode[64];
- if ((toc->tracks[track].trktype == CD_TRACK_AUDIO) && (track == 1))
- fprintf(outfile, "START 00:02:00\n");
+ fprintf(outfile, "// Track %d\n", track+1);
- fprintf(outfile, "\n\n");
+ /* write out the track type */
+ if (toc->tracks[track].subtype != CD_SUB_NONE)
+ {
+ sprintf(modesubmode, "%s %s", cdrom_get_type_string(toc->tracks[track].trktype), cdrom_get_subtype_string(toc->tracks[track].subtype));
+ }
+ else
+ {
+ sprintf(modesubmode, "%s", cdrom_get_type_string(toc->tracks[track].trktype));
+ }
+
+ fprintf(outfile, "TRACK %s\n", modesubmode);
+
+ /* write out the attributes */
+ fprintf(outfile, "NO COPY\n");
+ if (toc->tracks[track].trktype == CD_TRACK_AUDIO)
+ {
+ fprintf(outfile, "NO PRE_EMPHASIS\n");
+ fprintf(outfile, "TWO_CHANNEL_AUDIO\n");
+ }
+
+ if (toc->tracks[track].pregap > 0)
+ {
+ f = toc->tracks[track].pregap;
+ s = f / 75;
+ f %= 75;
+ m = s / 60;
+ s %= 60;
+
+ fprintf(outfile, "ZERO %s %02d:%02d:%02d\n", modesubmode, m, s, f);
+ }
+
+ /* convert to minutes/seconds/frames */
+ f = trackframes;
+ s = f / 75;
+ f %= 75;
+ m = s / 60;
+ s %= 60;
+
+ /* all tracks but the first one have a file offset */
+ if (track > 0)
+ fprintf(outfile, "DATAFILE \"%s\" #%d %02d:%02d:%02d // length in bytes: %d\n", outputfile2, (UINT32)out2offs, m, s, f, trackframes*(toc->tracks[track].datasize+toc->tracks[track].subsize));
+ else
+ fprintf(outfile, "DATAFILE \"%s\" %02d:%02d:%02d // length in bytes: %d\n", outputfile2, m, s, f, trackframes*(toc->tracks[track].datasize+toc->tracks[track].subsize));
+
+ /* tracks with pregaps get a START marker too */
+ if (toc->tracks[track].pregap > 0)
+ {
+ f = toc->tracks[track].pregap;
+ s = f / 75;
+ f %= 75;
+ m = s / 60;
+ s %= 60;
+
+ fprintf(outfile, "START %02d:%02d:%02d\n", m, s, f);
+ }
+
+ fprintf(outfile, "\n\n");
+ }
/* now write the actual data */
for (frame = 0; frame < trackframes; frame++)
@@ -1656,20 +1759,29 @@ static int do_extractcd(int argc, char *argv[], int param)
out2offs += toc->tracks[track].datasize;
/* read the subcode data */
- cdrom_read_subcode(cdrom, cdrom_get_track_start(cdrom, track) + frame, sector);
-
- /* write it out */
- core_fseek(outfile2, out2offs, SEEK_SET);
- byteswritten = core_fwrite(outfile2, sector, toc->tracks[track].subsize);
- if (byteswritten != toc->tracks[track].subsize)
+ if (toc->tracks[track].subtype != CD_SUB_NONE)
{
- fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, chd_error_string(CHDERR_WRITE_ERROR));
- err = CHDERR_WRITE_ERROR;
- goto cleanup;
+ cdrom_read_subcode(cdrom, cdrom_get_track_start(cdrom, track) + frame, sector);
+
+ /* write it out */
+ core_fseek(outfile2, out2offs, SEEK_SET);
+ byteswritten = core_fwrite(outfile2, sector, toc->tracks[track].subsize);
+ if (byteswritten != toc->tracks[track].subsize)
+ {
+ fprintf(stderr, "Error writing frame %d to output file: %s\n", frame, chd_error_string(CHDERR_WRITE_ERROR));
+ err = CHDERR_WRITE_ERROR;
+ goto cleanup;
+ }
+ out2offs += toc->tracks[track].subsize;
}
- out2offs += toc->tracks[track].subsize;
}
progress(TRUE, "Extracting track %d... complete \n", track+1);
+
+ if (cuemode)
+ {
+ core_fclose(outfile2);
+ outfile2 = NULL;
+ }
}
progress(TRUE, "Completed!\n");
@@ -3248,7 +3360,7 @@ static chd_error chdman_clone_metadata(chd_file *source, chd_file *dest)
{
if (metatag == HARD_DISK_METADATA_TAG || metatag == CDROM_OLD_METADATA_TAG ||
metatag == CDROM_TRACK_METADATA_TAG || metatag == AV_METADATA_TAG ||
- metatag == AV_LD_METADATA_TAG)
+ metatag == CDROM_TRACK_METADATA2_TAG || metatag == AV_LD_METADATA_TAG)
{
metaflags |= CHD_MDFLAGS_CHECKSUM;
}