mirror of
https://github.com/holub/mame
synced 2025-05-14 18:08:13 +03:00
chdman: Correct processing of GDI files, add ability to extractcd to .gdi, verified perfect checksum round-tripping on .GDI files. [R. Belmont]
This commit is contained in:
parent
b89d7c94c7
commit
bb993d1174
@ -702,11 +702,11 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
/* start with no tracks */
|
/* start with no tracks */
|
||||||
for (toc->numtrks = 0; toc->numtrks < CD_MAX_TRACKS; toc->numtrks++)
|
for (toc->numtrks = 0; toc->numtrks < CD_MAX_TRACKS; toc->numtrks++)
|
||||||
{
|
{
|
||||||
int tracknum = -1, frames = 0, pregap, postgap;
|
int tracknum = -1, frames = 0, pregap, postgap, padframes;
|
||||||
char type[16], subtype[16], pgtype[16], pgsub[16];
|
char type[16], subtype[16], pgtype[16], pgsub[16];
|
||||||
cdrom_track_info *track;
|
cdrom_track_info *track;
|
||||||
|
|
||||||
pregap = postgap = 0;
|
pregap = postgap = padframes = 0;
|
||||||
|
|
||||||
/* fetch the metadata for this track */
|
/* fetch the metadata for this track */
|
||||||
err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
|
err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
|
||||||
@ -723,8 +723,8 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata);
|
err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata);
|
||||||
if (err != CHDERR_NONE)
|
if (err == CHDERR_NONE)
|
||||||
break;
|
{
|
||||||
/* parse the metadata */
|
/* parse the metadata */
|
||||||
type[0] = subtype[0] = 0;
|
type[0] = subtype[0] = 0;
|
||||||
pregap = postgap = 0;
|
pregap = postgap = 0;
|
||||||
@ -734,6 +734,27 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
return CHDERR_INVALID_DATA;
|
return CHDERR_INVALID_DATA;
|
||||||
track = &toc->tracks[tracknum - 1];
|
track = &toc->tracks[tracknum - 1];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
|
||||||
|
|
||||||
|
if (err == CHDERR_NONE)
|
||||||
|
{
|
||||||
|
/* parse the metadata */
|
||||||
|
type[0] = subtype[0] = 0;
|
||||||
|
pregap = postgap = 0;
|
||||||
|
if (sscanf(metadata, GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9)
|
||||||
|
return CHDERR_INVALID_DATA;
|
||||||
|
if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
|
||||||
|
return CHDERR_INVALID_DATA;
|
||||||
|
track = &toc->tracks[tracknum - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* extract the track type and determine the data size */
|
/* extract the track type and determine the data size */
|
||||||
track->trktype = CD_TRACK_MODE1;
|
track->trktype = CD_TRACK_MODE1;
|
||||||
@ -749,6 +770,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
|
|
||||||
/* set the frames and extra frames data */
|
/* set the frames and extra frames data */
|
||||||
track->frames = frames;
|
track->frames = frames;
|
||||||
|
track->padframes = padframes;
|
||||||
int padded = (frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
|
int padded = (frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
|
||||||
track->extraframes = padded * CD_TRACK_PADDING - frames;
|
track->extraframes = padded * CD_TRACK_PADDING - frames;
|
||||||
|
|
||||||
@ -769,6 +791,8 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
if (toc->numtrks > 0)
|
if (toc->numtrks > 0)
|
||||||
return CHDERR_NONE;
|
return CHDERR_NONE;
|
||||||
|
|
||||||
|
printf("toc->numtrks = %d?!\n", toc->numtrks);
|
||||||
|
|
||||||
/* look for old-style metadata */
|
/* look for old-style metadata */
|
||||||
dynamic_buffer oldmetadata;
|
dynamic_buffer oldmetadata;
|
||||||
err = chd->read_metadata(CDROM_OLD_METADATA_TAG, 0, oldmetadata);
|
err = chd->read_metadata(CDROM_OLD_METADATA_TAG, 0, oldmetadata);
|
||||||
@ -806,6 +830,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
|
|||||||
toc->tracks[i].datasize = FLIPENDIAN_INT32(toc->tracks[i].datasize);
|
toc->tracks[i].datasize = FLIPENDIAN_INT32(toc->tracks[i].datasize);
|
||||||
toc->tracks[i].subsize = FLIPENDIAN_INT32(toc->tracks[i].subsize);
|
toc->tracks[i].subsize = FLIPENDIAN_INT32(toc->tracks[i].subsize);
|
||||||
toc->tracks[i].frames = FLIPENDIAN_INT32(toc->tracks[i].frames);
|
toc->tracks[i].frames = FLIPENDIAN_INT32(toc->tracks[i].frames);
|
||||||
|
toc->tracks[i].padframes = FLIPENDIAN_INT32(toc->tracks[i].padframes);
|
||||||
toc->tracks[i].extraframes = FLIPENDIAN_INT32(toc->tracks[i].extraframes);
|
toc->tracks[i].extraframes = FLIPENDIAN_INT32(toc->tracks[i].extraframes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -827,12 +852,24 @@ chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
|
|||||||
for (i = 0; i < toc->numtrks; i++)
|
for (i = 0; i < toc->numtrks; i++)
|
||||||
{
|
{
|
||||||
astring metadata;
|
astring metadata;
|
||||||
|
if (!(toc->flags & CD_FLAG_GDROM))
|
||||||
|
{
|
||||||
metadata.format(CDROM_TRACK_METADATA2_FORMAT, i + 1, cdrom_get_type_string(toc->tracks[i].trktype),
|
metadata.format(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_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),
|
cdrom_get_type_string(toc->tracks[i].pgtype), cdrom_get_subtype_string(toc->tracks[i].pgsub),
|
||||||
toc->tracks[i].postgap);
|
toc->tracks[i].postgap);
|
||||||
|
|
||||||
err = chd->write_metadata(CDROM_TRACK_METADATA2_TAG, i, metadata);
|
err = chd->write_metadata(CDROM_TRACK_METADATA2_TAG, i, metadata);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadata.format(GDROM_TRACK_METADATA_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].padframes,
|
||||||
|
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->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata);
|
||||||
|
}
|
||||||
if (err != CHDERR_NONE)
|
if (err != CHDERR_NONE)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ enum
|
|||||||
CD_SUB_NONE /* no subcode data stored */
|
CD_SUB_NONE /* no subcode data stored */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CD_FLAG_GDROM 0x00000001 // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
TYPE DEFINITIONS
|
TYPE DEFINITIONS
|
||||||
@ -109,6 +109,9 @@ struct cdrom_track_info
|
|||||||
UINT32 pgdatasize; /* size of data in each sector of the pregap */
|
UINT32 pgdatasize; /* size of data in each sector of the pregap */
|
||||||
UINT32 pgsubsize; /* size of subchannel data in each sector of the pregap */
|
UINT32 pgsubsize; /* size of subchannel data in each sector of the pregap */
|
||||||
|
|
||||||
|
/* fields used in CHDMAN only */
|
||||||
|
UINT32 padframes; /* number of frames of padding to add to the end of the track; needed for GDI */
|
||||||
|
|
||||||
/* fields used in MAME only */
|
/* fields used in MAME only */
|
||||||
UINT32 physframeofs; /* frame number on the real CD this track starts at */
|
UINT32 physframeofs; /* frame number on the real CD this track starts at */
|
||||||
UINT32 chdframeofs; /* frame number this track starts at on the CHD */
|
UINT32 chdframeofs; /* frame number this track starts at on the CHD */
|
||||||
@ -118,6 +121,7 @@ struct cdrom_track_info
|
|||||||
struct cdrom_toc
|
struct cdrom_toc
|
||||||
{
|
{
|
||||||
UINT32 numtrks; /* number of tracks */
|
UINT32 numtrks; /* number of tracks */
|
||||||
|
UINT32 flags; /* see FLAG_ above */
|
||||||
cdrom_track_info tracks[CD_MAX_TRACKS];
|
cdrom_track_info tracks[CD_MAX_TRACKS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
const char *HARD_DISK_METADATA_FORMAT = "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d";
|
const char *HARD_DISK_METADATA_FORMAT = "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d";
|
||||||
const char *CDROM_TRACK_METADATA_FORMAT = "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d";
|
const char *CDROM_TRACK_METADATA_FORMAT = "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d";
|
||||||
const char *CDROM_TRACK_METADATA2_FORMAT = "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d";
|
const char *CDROM_TRACK_METADATA2_FORMAT = "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d";
|
||||||
|
const char *GDROM_TRACK_METADATA_FORMAT = "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d";
|
||||||
const char *AV_METADATA_FORMAT = "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d";
|
const char *AV_METADATA_FORMAT = "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d";
|
||||||
|
|
||||||
static const UINT32 METADATA_HEADER_SIZE = 16; // metadata header size
|
static const UINT32 METADATA_HEADER_SIZE = 16; // metadata header size
|
||||||
@ -1440,7 +1441,8 @@ UINT32 chd_file::guess_unitbytes()
|
|||||||
// look for CD-ROM metadata; if found, then the unit size == CD frame size
|
// look for CD-ROM metadata; if found, then the unit size == CD frame size
|
||||||
if (read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
|
if (read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
|
||||||
read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
|
read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
|
||||||
read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE)
|
read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE ||
|
||||||
|
read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE)
|
||||||
return CD_FRAME_SIZE;
|
return CD_FRAME_SIZE;
|
||||||
|
|
||||||
// otherwise, just map 1:1 with the hunk size
|
// otherwise, just map 1:1 with the hunk size
|
||||||
|
@ -254,6 +254,8 @@ const chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R');
|
|||||||
extern const char *CDROM_TRACK_METADATA_FORMAT;
|
extern const char *CDROM_TRACK_METADATA_FORMAT;
|
||||||
const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
|
const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
|
||||||
extern const char *CDROM_TRACK_METADATA2_FORMAT;
|
extern const char *CDROM_TRACK_METADATA2_FORMAT;
|
||||||
|
const chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
|
||||||
|
extern const char *GDROM_TRACK_METADATA_FORMAT;
|
||||||
|
|
||||||
// standard A/V metadata
|
// standard A/V metadata
|
||||||
const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
|
const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
TOC parser for CHD compression frontend
|
TOC parser for CHD compression frontend
|
||||||
Handles CDRDAO .toc, CDRWIN .cue, and Sega GDROM .gdi
|
Handles CDRDAO .toc, CDRWIN .cue, Nero .nrg, and Sega GDROM .gdi
|
||||||
|
|
||||||
Copyright Nicola Salmoria and the MAME Team.
|
Copyright Nicola Salmoria and the MAME Team.
|
||||||
Visit http://mamedev.org for licensing and usage restrictions.
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
@ -301,7 +301,7 @@ UINT64 read_uint64(FILE *infile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
chdcd_parse_nero - parse a Nero format image file
|
chdcd_parse_nero - parse a Nero .NRG file
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
|
chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
|
||||||
@ -427,6 +427,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
|
|||||||
outtoc.tracks[track-1].pgsub = CD_SUB_NONE;
|
outtoc.tracks[track-1].pgsub = CD_SUB_NONE;
|
||||||
outtoc.tracks[track-1].pgdatasize = 0;
|
outtoc.tracks[track-1].pgdatasize = 0;
|
||||||
outtoc.tracks[track-1].pgsubsize = 0;
|
outtoc.tracks[track-1].pgsubsize = 0;
|
||||||
|
outtoc.tracks[track-1].padframes = 0;
|
||||||
|
|
||||||
offset += (UINT32)index2-index1;
|
offset += (UINT32)index2-index1;
|
||||||
}
|
}
|
||||||
@ -455,7 +456,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
{
|
{
|
||||||
FILE *infile;
|
FILE *infile;
|
||||||
int i, numtracks;
|
int i, numtracks;
|
||||||
//int chdpos=0;
|
|
||||||
|
|
||||||
astring path = astring(tocfname);
|
astring path = astring(tocfname);
|
||||||
|
|
||||||
@ -471,6 +471,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
memset(&outtoc, 0, sizeof(outtoc));
|
memset(&outtoc, 0, sizeof(outtoc));
|
||||||
outinfo.reset();
|
outinfo.reset();
|
||||||
|
|
||||||
|
outtoc.flags = CD_FLAG_GDROM;
|
||||||
|
|
||||||
fgets(linebuffer,511,infile);
|
fgets(linebuffer,511,infile);
|
||||||
numtracks=atoi(linebuffer);
|
numtracks=atoi(linebuffer);
|
||||||
@ -481,8 +482,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
int trknum;
|
int trknum;
|
||||||
int trksize,trktype;
|
int trksize,trktype;
|
||||||
int sz;
|
int sz;
|
||||||
int hunks;
|
|
||||||
|
|
||||||
|
|
||||||
fgets(linebuffer,511,infile);
|
fgets(linebuffer,511,infile);
|
||||||
|
|
||||||
@ -493,7 +492,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
outinfo.track[trknum].swap=false;
|
outinfo.track[trknum].swap=false;
|
||||||
outinfo.track[trknum].offset=0;
|
outinfo.track[trknum].offset=0;
|
||||||
|
|
||||||
//outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
|
|
||||||
outtoc.tracks[trknum].datasize = 0;
|
outtoc.tracks[trknum].datasize = 0;
|
||||||
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
||||||
outtoc.tracks[trknum].subsize = 0;
|
outtoc.tracks[trknum].subsize = 0;
|
||||||
@ -519,7 +517,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
}
|
}
|
||||||
if(trktype==0)
|
if(trktype==0)
|
||||||
{
|
{
|
||||||
//assert(trksize==2352);
|
|
||||||
outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO;
|
outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO;
|
||||||
outtoc.tracks[trknum].datasize=2352;
|
outtoc.tracks[trknum].datasize=2352;
|
||||||
}
|
}
|
||||||
@ -543,32 +540,23 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
sz = get_file_size(outinfo.track[trknum].fname);
|
sz = get_file_size(outinfo.track[trknum].fname);
|
||||||
|
|
||||||
outtoc.tracks[trknum].frames = sz/trksize;
|
outtoc.tracks[trknum].frames = sz/trksize;
|
||||||
outtoc.tracks[trknum].extraframes=0;
|
outtoc.tracks[trknum].padframes = 0;
|
||||||
|
|
||||||
if (trknum != 0)
|
if (trknum != 0)
|
||||||
{
|
{
|
||||||
int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
|
int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
|
||||||
outtoc.tracks[trknum-1].frames += dif;
|
outtoc.tracks[trknum-1].frames += dif;
|
||||||
|
outtoc.tracks[trknum-1].padframes = dif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#if 0
|
||||||
if(trknum!=0)
|
for(i=0; i < numtracks; i++)
|
||||||
{
|
{
|
||||||
outtoc.tracks[trknum-1].extraframes=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
|
printf("%s %d %d %d (true %d)\n", outinfo.track[i].fname.cstr(), outtoc.tracks[i].frames, outtoc.tracks[i].padframes, outtoc.tracks[i].physframeofs, outtoc.tracks[i].frames - outtoc.tracks[i].padframes);
|
||||||
}
|
}
|
||||||
*/
|
#endif
|
||||||
hunks = (outtoc.tracks[trknum].frames+CD_FRAMES_PER_HUNK - 1) / CD_FRAMES_PER_HUNK;
|
|
||||||
outtoc.tracks[trknum].extraframes = hunks * CD_FRAMES_PER_HUNK - outtoc.tracks[trknum].frames;
|
|
||||||
|
|
||||||
//chdpos+=outtoc.tracks[trknum].frames+outtoc.tracks[trknum].extraframes;
|
|
||||||
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
for(i=0;i<numtracks;++i)
|
|
||||||
{
|
|
||||||
printf("%s %d %d %d\n",outinfo.track[i].fname,outtoc.tracks[i].frames,outtoc.tracks[i].extraframes,outtoc.tracks[i].physframeofs);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/* close the input TOC */
|
/* close the input TOC */
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
|
|
||||||
@ -579,7 +567,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
chdcd_parse_cue - parse a CDRWin format CUE file
|
chdcd_parse_toc - parse a CDRWin format CUE file
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
|
chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
|
||||||
@ -683,6 +671,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
|
|||||||
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
||||||
outtoc.tracks[trknum].subsize = 0;
|
outtoc.tracks[trknum].subsize = 0;
|
||||||
outtoc.tracks[trknum].pregap = 0;
|
outtoc.tracks[trknum].pregap = 0;
|
||||||
|
outtoc.tracks[trknum].padframes = 0;
|
||||||
outinfo.track[trknum].idx0offs = -1;
|
outinfo.track[trknum].idx0offs = -1;
|
||||||
outinfo.track[trknum].idx1offs = 0;
|
outinfo.track[trknum].idx1offs = 0;
|
||||||
|
|
||||||
@ -988,6 +977,7 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
|
|||||||
outtoc.tracks[trknum].datasize = 0;
|
outtoc.tracks[trknum].datasize = 0;
|
||||||
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
|
||||||
outtoc.tracks[trknum].subsize = 0;
|
outtoc.tracks[trknum].subsize = 0;
|
||||||
|
outtoc.tracks[trknum].padframes = 0;
|
||||||
|
|
||||||
cdrom_convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
|
cdrom_convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
|
||||||
if (outtoc.tracks[trknum].datasize == 0)
|
if (outtoc.tracks[trknum].datasize == 0)
|
||||||
|
@ -64,6 +64,11 @@ const UINT32 IDE_SECTOR_SIZE = 512;
|
|||||||
// temporary input buffer size
|
// temporary input buffer size
|
||||||
const UINT32 TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
|
const UINT32 TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
|
||||||
|
|
||||||
|
// modes
|
||||||
|
const int MODE_NORMAL = 0;
|
||||||
|
const int MODE_CUEBIN = 1;
|
||||||
|
const int MODE_GDI = 2;
|
||||||
|
|
||||||
// command modifier
|
// command modifier
|
||||||
#define REQUIRED "~"
|
#define REQUIRED "~"
|
||||||
|
|
||||||
@ -113,7 +118,6 @@ const UINT32 TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
|
|||||||
#define OPTION_NUMPROCESSORS "numprocessors"
|
#define OPTION_NUMPROCESSORS "numprocessors"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// FUNCTION PROTOTYPES
|
// FUNCTION PROTOTYPES
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -318,17 +322,25 @@ public:
|
|||||||
UINT32 bytesperframe = trackinfo.datasize + trackinfo.subsize;
|
UINT32 bytesperframe = trackinfo.datasize + trackinfo.subsize;
|
||||||
UINT64 src_track_start = m_info.track[tracknum].offset;
|
UINT64 src_track_start = m_info.track[tracknum].offset;
|
||||||
UINT64 src_track_end = src_track_start + bytesperframe * trackinfo.frames;
|
UINT64 src_track_end = src_track_start + bytesperframe * trackinfo.frames;
|
||||||
|
UINT64 pad_track_start = src_track_end - (m_toc.tracks[tracknum].padframes * bytesperframe);
|
||||||
while (length_remaining != 0 && offset < endoffs)
|
while (length_remaining != 0 && offset < endoffs)
|
||||||
{
|
{
|
||||||
// determine start of current frame
|
// determine start of current frame
|
||||||
UINT64 src_frame_start = src_track_start + ((offset - startoffs) / CD_FRAME_SIZE) * bytesperframe;
|
UINT64 src_frame_start = src_track_start + ((offset - startoffs) / CD_FRAME_SIZE) * bytesperframe;
|
||||||
if (src_frame_start < src_track_end)
|
if (src_frame_start < src_track_end)
|
||||||
{
|
{
|
||||||
// read it in
|
// read it in, or pad if we're into the padframes
|
||||||
|
if (src_frame_start >= pad_track_start)
|
||||||
|
{
|
||||||
|
memset(dest, 0, bytesperframe);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
core_fseek(m_file, src_frame_start, SEEK_SET);
|
core_fseek(m_file, src_frame_start, SEEK_SET);
|
||||||
UINT32 count = core_fread(m_file, dest, bytesperframe);
|
UINT32 count = core_fread(m_file, dest, bytesperframe);
|
||||||
if (count != bytesperframe)
|
if (count != bytesperframe)
|
||||||
report_error(1, "Error reading input file (%s)'", m_lastfile.cstr());
|
report_error(1, "Error reading input file (%s)'", m_lastfile.cstr());
|
||||||
|
}
|
||||||
|
|
||||||
// swap if appropriate
|
// swap if appropriate
|
||||||
if (m_info.track[tracknum].swap)
|
if (m_info.track[tracknum].swap)
|
||||||
@ -1156,10 +1168,57 @@ static void compress_common(chd_file_compressor &chd)
|
|||||||
// to a CUE file
|
// to a CUE file
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void output_track_metadata(bool cuemode, core_file *file, int tracknum, const cdrom_track_info &info, const char *filename, UINT32 frameoffs, UINT64 discoffs)
|
void output_track_metadata(int mode, core_file *file, int tracknum, const cdrom_track_info &info, const char *filename, UINT32 frameoffs, UINT64 discoffs)
|
||||||
{
|
{
|
||||||
// CUE mode?
|
if (mode == MODE_GDI)
|
||||||
if (cuemode)
|
{
|
||||||
|
int mode = 0, size = 2048;
|
||||||
|
|
||||||
|
switch (info.trktype)
|
||||||
|
{
|
||||||
|
case CD_TRACK_MODE1:
|
||||||
|
mode = 0;
|
||||||
|
size = 2048;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE1_RAW:
|
||||||
|
mode = 4;
|
||||||
|
size = 2352;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE2:
|
||||||
|
mode = 4;
|
||||||
|
size = 2336;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE2_FORM1:
|
||||||
|
mode = 4;
|
||||||
|
size = 2048;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE2_FORM2:
|
||||||
|
mode = 4;
|
||||||
|
size = 2324;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE2_FORM_MIX:
|
||||||
|
mode = 4;
|
||||||
|
size = 2336;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_MODE2_RAW:
|
||||||
|
mode = 4;
|
||||||
|
size = 2352;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CD_TRACK_AUDIO:
|
||||||
|
mode = 0;
|
||||||
|
size = 2352;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
core_fprintf(file, "%d %d %d %d %s %lld\n", tracknum+1, frameoffs, mode, size, filename, discoffs);
|
||||||
|
}
|
||||||
|
else if (mode == MODE_CUEBIN)
|
||||||
{
|
{
|
||||||
// first track specifies the file
|
// first track specifies the file
|
||||||
if (tracknum == 0)
|
if (tracknum == 0)
|
||||||
@ -1201,9 +1260,8 @@ void output_track_metadata(bool cuemode, core_file *file, int tracknum, const cd
|
|||||||
if (info.postgap > 0)
|
if (info.postgap > 0)
|
||||||
core_fprintf(file, " POSTGAP %s\n", msf_string_from_frames(tempstr, info.postgap));
|
core_fprintf(file, " POSTGAP %s\n", msf_string_from_frames(tempstr, info.postgap));
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-CUE mode
|
// non-CUE mode
|
||||||
else
|
else if (mode == MODE_NORMAL)
|
||||||
{
|
{
|
||||||
// header on the first track
|
// header on the first track
|
||||||
if (tracknum == 0)
|
if (tracknum == 0)
|
||||||
@ -2194,6 +2252,8 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
int chop = default_name.rchr(0, '.');
|
int chop = default_name.rchr(0, '.');
|
||||||
if (chop != -1)
|
if (chop != -1)
|
||||||
default_name.substr(0, chop);
|
default_name.substr(0, chop);
|
||||||
|
char basename[128];
|
||||||
|
strncpy(basename, default_name.cstr(), 127);
|
||||||
default_name.cat(".bin");
|
default_name.cat(".bin");
|
||||||
if (output_bin_file_str == NULL)
|
if (output_bin_file_str == NULL)
|
||||||
output_bin_file_str = &default_name;
|
output_bin_file_str = &default_name;
|
||||||
@ -2210,38 +2270,86 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
core_file *output_toc_file = NULL;
|
core_file *output_toc_file = NULL;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
int mode = MODE_NORMAL;
|
||||||
|
|
||||||
|
if (output_file_str->find(".cue") != -1)
|
||||||
|
{
|
||||||
|
mode = MODE_CUEBIN;
|
||||||
|
}
|
||||||
|
else if (output_file_str->find(".gdi") != -1)
|
||||||
|
{
|
||||||
|
mode = MODE_GDI;
|
||||||
|
}
|
||||||
|
|
||||||
// process output file
|
// process output file
|
||||||
file_error filerr = core_fopen(*output_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, &output_toc_file);
|
file_error filerr = core_fopen(*output_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, &output_toc_file);
|
||||||
if (filerr != FILERR_NONE)
|
if (filerr != FILERR_NONE)
|
||||||
report_error(1, "Unable to open file (%s)", output_file_str->cstr());
|
report_error(1, "Unable to open file (%s)", output_file_str->cstr());
|
||||||
bool cuemode = (output_file_str->find(".cue") != -1);
|
|
||||||
|
|
||||||
// process output BIN file
|
// process output BIN file
|
||||||
|
if (mode != MODE_GDI)
|
||||||
|
{
|
||||||
filerr = core_fopen(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &output_bin_file);
|
filerr = core_fopen(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &output_bin_file);
|
||||||
if (filerr != FILERR_NONE)
|
if (filerr != FILERR_NONE)
|
||||||
report_error(1, "Unable to open file (%s)", output_bin_file_str->cstr());
|
report_error(1, "Unable to open file (%s)", output_bin_file_str->cstr());
|
||||||
|
}
|
||||||
|
|
||||||
// determine total frames
|
// determine total frames
|
||||||
UINT64 total_bytes = 0;
|
UINT64 total_bytes = 0;
|
||||||
for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
|
for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
|
||||||
total_bytes += toc->tracks[tracknum].frames * (toc->tracks[tracknum].datasize + toc->tracks[tracknum].subsize);
|
total_bytes += toc->tracks[tracknum].frames * (toc->tracks[tracknum].datasize + toc->tracks[tracknum].subsize);
|
||||||
|
|
||||||
|
// GDI must start with the # of tracks
|
||||||
|
if (mode == MODE_GDI)
|
||||||
|
{
|
||||||
|
core_fprintf(output_toc_file, "%d\n", toc->numtrks);
|
||||||
|
}
|
||||||
|
|
||||||
// iterate over tracks and copy all data
|
// iterate over tracks and copy all data
|
||||||
UINT64 outputoffs = 0;
|
UINT64 outputoffs = 0;
|
||||||
UINT32 discoffs = 0;
|
UINT32 discoffs = 0;
|
||||||
dynamic_buffer buffer;
|
dynamic_buffer buffer;
|
||||||
for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
|
for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
|
||||||
{
|
{
|
||||||
|
astring trackbin_name(basename);
|
||||||
|
|
||||||
|
if (mode == MODE_GDI)
|
||||||
|
{
|
||||||
|
char temp[8];
|
||||||
|
sprintf(temp, "%02d", tracknum+1);
|
||||||
|
trackbin_name.cat(temp);
|
||||||
|
trackbin_name.cat(".bin");
|
||||||
|
|
||||||
|
if (output_bin_file)
|
||||||
|
{
|
||||||
|
core_fclose(output_bin_file);
|
||||||
|
output_bin_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filerr = core_fopen(trackbin_name, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &output_bin_file);
|
||||||
|
if (filerr != FILERR_NONE)
|
||||||
|
report_error(1, "Unable to open file (%s)", trackbin_name.cstr());
|
||||||
|
|
||||||
|
outputoffs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// output the metadata about the track to the TOC file
|
// output the metadata about the track to the TOC file
|
||||||
const cdrom_track_info &trackinfo = toc->tracks[tracknum];
|
const cdrom_track_info &trackinfo = toc->tracks[tracknum];
|
||||||
output_track_metadata(cuemode, output_toc_file, tracknum, trackinfo, *output_bin_file_str, discoffs, outputoffs);
|
if (mode == MODE_GDI)
|
||||||
|
{
|
||||||
|
output_track_metadata(mode, output_toc_file, tracknum, trackinfo, trackbin_name, discoffs, outputoffs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_track_metadata(mode, output_toc_file, tracknum, trackinfo, *output_bin_file_str, discoffs, outputoffs);
|
||||||
|
}
|
||||||
|
|
||||||
// If this is bin/cue output and the CHD contains subdata, warn the user and don't include
|
// If this is bin/cue output and the CHD contains subdata, warn the user and don't include
|
||||||
// the subdata size in the buffer calculation.
|
// the subdata size in the buffer calculation.
|
||||||
UINT32 output_frame_size = trackinfo.datasize + ((trackinfo.subtype != CD_SUB_NONE) ? trackinfo.subsize : 0);
|
UINT32 output_frame_size = trackinfo.datasize + ((trackinfo.subtype != CD_SUB_NONE) ? trackinfo.subsize : 0);
|
||||||
if (trackinfo.subtype != CD_SUB_NONE && cuemode)
|
if (trackinfo.subtype != CD_SUB_NONE && ((mode == MODE_CUEBIN) || (mode == MODE_GDI)))
|
||||||
{
|
{
|
||||||
printf("Warning: Track %d has subcode data. bin/cue format cannot contain subcode data and it will be omitted.\n", tracknum+1);
|
printf("Warning: Track %d has subcode data. bin/cue and gdi formats cannot contain subcode data and it will be omitted.\n", tracknum+1);
|
||||||
printf(" : This may affect usage of the output image. Use bin/toc output to keep all data.\n");
|
printf(" : This may affect usage of the output image. Use bin/toc output to keep all data.\n");
|
||||||
output_frame_size = trackinfo.datasize;
|
output_frame_size = trackinfo.datasize;
|
||||||
}
|
}
|
||||||
@ -2251,7 +2359,8 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
|
|
||||||
// now read and output the actual data
|
// now read and output the actual data
|
||||||
UINT32 bufferoffs = 0;
|
UINT32 bufferoffs = 0;
|
||||||
for (int frame = 0; frame < trackinfo.frames; frame++)
|
UINT32 actualframes = trackinfo.frames - trackinfo.padframes;
|
||||||
|
for (UINT32 frame = 0; frame < actualframes; frame++)
|
||||||
{
|
{
|
||||||
progress(false, "Extracting, %.1f%% complete... \r", 100.0 * double(outputoffs) / double(total_bytes));
|
progress(false, "Extracting, %.1f%% complete... \r", 100.0 * double(outputoffs) / double(total_bytes));
|
||||||
|
|
||||||
@ -2259,7 +2368,7 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
cdrom_read_data(cdrom, cdrom_get_track_start(cdrom, tracknum) + frame, &buffer[bufferoffs], trackinfo.trktype);
|
cdrom_read_data(cdrom, cdrom_get_track_start(cdrom, tracknum) + frame, &buffer[bufferoffs], trackinfo.trktype);
|
||||||
|
|
||||||
// for CDRWin, audio tracks must be reversed
|
// for CDRWin, audio tracks must be reversed
|
||||||
if (cuemode && (trackinfo.trktype == CD_TRACK_AUDIO))
|
if ((mode == MODE_CUEBIN) && (trackinfo.trktype == CD_TRACK_AUDIO))
|
||||||
for (int swapindex = 0; swapindex < trackinfo.datasize; swapindex += 2)
|
for (int swapindex = 0; swapindex < trackinfo.datasize; swapindex += 2)
|
||||||
{
|
{
|
||||||
UINT8 swaptemp = buffer[bufferoffs + swapindex];
|
UINT8 swaptemp = buffer[bufferoffs + swapindex];
|
||||||
@ -2270,14 +2379,14 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
discoffs++;
|
discoffs++;
|
||||||
|
|
||||||
// read the subcode data
|
// read the subcode data
|
||||||
if (trackinfo.subtype != CD_SUB_NONE && !cuemode)
|
if (trackinfo.subtype != CD_SUB_NONE && (mode == MODE_NORMAL))
|
||||||
{
|
{
|
||||||
cdrom_read_subcode(cdrom, cdrom_get_track_start(cdrom, tracknum) + frame, &buffer[bufferoffs]);
|
cdrom_read_subcode(cdrom, cdrom_get_track_start(cdrom, tracknum) + frame, &buffer[bufferoffs]);
|
||||||
bufferoffs += trackinfo.subsize;
|
bufferoffs += trackinfo.subsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write it out if we need to
|
// write it out if we need to
|
||||||
if (bufferoffs == buffer.count() || frame == trackinfo.frames - 1)
|
if (bufferoffs == buffer.count() || frame == actualframes - 1)
|
||||||
{
|
{
|
||||||
core_fseek(output_bin_file, outputoffs, SEEK_SET);
|
core_fseek(output_bin_file, outputoffs, SEEK_SET);
|
||||||
UINT32 byteswritten = core_fwrite(output_bin_file, buffer, bufferoffs);
|
UINT32 byteswritten = core_fwrite(output_bin_file, buffer, bufferoffs);
|
||||||
@ -2287,6 +2396,8 @@ static void do_extract_cd(parameters_t ¶ms)
|
|||||||
bufferoffs = 0;
|
bufferoffs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
discoffs += trackinfo.padframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
|
Loading…
Reference in New Issue
Block a user