diff options
author | 2010-05-30 16:24:14 +0000 | |
---|---|---|
committer | 2010-05-30 16:24:14 +0000 | |
commit | 842282c0fa0e5e3ae9e36e8cab4fed65f4bead97 (patch) | |
tree | 3b55f291693f011d3d164e249105922f582f0c8a /src | |
parent | 1f47f5a0d5dc5936a46bc969e034b5a837392c25 (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.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/util/cdrom.c | 182 | ||||
-rw-r--r-- | src/lib/util/cdrom.h | 13 | ||||
-rw-r--r-- | src/lib/util/chd.h | 4 | ||||
-rw-r--r-- | src/tools/chdcd.c | 112 | ||||
-rw-r--r-- | src/tools/chdman.c | 226 |
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; } |