summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2012-03-04 02:17:35 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2012-03-04 02:17:35 +0000
commitbb993d1174a63b09b040251dec236a0a2c60aeb2 (patch)
tree76497c6e90eb4f2d0fb92d69f1a6c15e81a84e1f /src
parentb89d7c94c7a2000cb896eb7fd0efa5cc012c672f (diff)
chdman: Correct processing of GDI files, add ability to extractcd to .gdi, verified perfect checksum round-tripping on .GDI files. [R. Belmont]
Diffstat (limited to 'src')
-rw-r--r--src/lib/util/cdrom.c75
-rw-r--r--src/lib/util/cdrom.h6
-rw-r--r--src/lib/util/chd.c4
-rw-r--r--src/lib/util/chd.h2
-rw-r--r--src/lib/util/chdcd.c50
-rw-r--r--src/tools/chdman.c329
6 files changed, 306 insertions, 160 deletions
diff --git a/src/lib/util/cdrom.c b/src/lib/util/cdrom.c
index d0977a1f534..9178fb5e5b3 100644
--- a/src/lib/util/cdrom.c
+++ b/src/lib/util/cdrom.c
@@ -702,11 +702,11 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
/* start with no tracks */
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];
cdrom_track_info *track;
- pregap = postgap = 0;
+ pregap = postgap = padframes = 0;
/* fetch the metadata for this track */
err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
@@ -723,16 +723,37 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
else
{
err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata);
- 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];
+ if (err == CHDERR_NONE)
+ {
+ /* 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];
+ }
+ 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 */
@@ -749,6 +770,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
/* set the frames and extra frames data */
track->frames = frames;
+ track->padframes = padframes;
int padded = (frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
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)
return CHDERR_NONE;
+ printf("toc->numtrks = %d?!\n", toc->numtrks);
+
/* look for old-style metadata */
dynamic_buffer 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].subsize = FLIPENDIAN_INT32(toc->tracks[i].subsize);
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);
}
}
@@ -826,13 +851,25 @@ chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
/* write the metadata */
for (i = 0; i < toc->numtrks; i++)
{
- astring metadata;
- 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_type_string(toc->tracks[i].pgtype), cdrom_get_subtype_string(toc->tracks[i].pgsub),
- toc->tracks[i].postgap);
-
- err = chd->write_metadata(CDROM_TRACK_METADATA2_TAG, i, 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),
+ 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->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)
return err;
}
diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h
index 7ac5bead1b7..6a2832e21f8 100644
--- a/src/lib/util/cdrom.h
+++ b/src/lib/util/cdrom.h
@@ -84,7 +84,7 @@ enum
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
@@ -109,6 +109,9 @@ struct cdrom_track_info
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 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 */
UINT32 physframeofs; /* frame number on the real CD this track starts at */
UINT32 chdframeofs; /* frame number this track starts at on the CHD */
@@ -118,6 +121,7 @@ struct cdrom_track_info
struct cdrom_toc
{
UINT32 numtrks; /* number of tracks */
+ UINT32 flags; /* see FLAG_ above */
cdrom_track_info tracks[CD_MAX_TRACKS];
};
diff --git a/src/lib/util/chd.c b/src/lib/util/chd.c
index eda906740f5..697d1ea7889 100644
--- a/src/lib/util/chd.c
+++ b/src/lib/util/chd.c
@@ -58,6 +58,7 @@
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_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";
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
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_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;
// otherwise, just map 1:1 with the hunk size
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index 4eb54371e09..4ae65830dba 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -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;
const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
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
const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
diff --git a/src/lib/util/chdcd.c b/src/lib/util/chdcd.c
index 49eed70fce6..360258c9ea4 100644
--- a/src/lib/util/chdcd.c
+++ b/src/lib/util/chdcd.c
@@ -1,7 +1,7 @@
/***************************************************************************
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.
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)
@@ -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].pgdatasize = 0;
outtoc.tracks[track-1].pgsubsize = 0;
+ outtoc.tracks[track-1].padframes = 0;
offset += (UINT32)index2-index1;
}
@@ -455,7 +456,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
{
FILE *infile;
int i, numtracks;
- //int chdpos=0;
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));
outinfo.reset();
+ outtoc.flags = CD_FLAG_GDROM;
fgets(linebuffer,511,infile);
numtracks=atoi(linebuffer);
@@ -481,8 +482,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
int trknum;
int trksize,trktype;
int sz;
- int hunks;
-
fgets(linebuffer,511,infile);
@@ -493,8 +492,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
outinfo.track[trknum].swap=false;
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].subsize = 0;
@@ -519,7 +517,6 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
}
if(trktype==0)
{
- //assert(trksize==2352);
outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO;
outtoc.tracks[trknum].datasize=2352;
}
@@ -540,35 +537,26 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
}
outinfo.track[trknum].fname.cpy(path).cat(name);
- 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].extraframes=0;
+ outtoc.tracks[trknum].frames = sz/trksize;
+ 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);
- outtoc.tracks[trknum-1].frames+=dif;
+ outtoc.tracks[trknum-1].frames += dif;
+ outtoc.tracks[trknum-1].padframes = dif;
}
-
-/*
- if(trknum!=0)
- {
- outtoc.tracks[trknum-1].extraframes=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
- }
-*/
- 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)
+
+ #if 0
+ 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);
+ 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
+
/* close the input TOC */
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)
@@ -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].subsize = 0;
outtoc.tracks[trknum].pregap = 0;
+ outtoc.tracks[trknum].padframes = 0;
outinfo.track[trknum].idx0offs = -1;
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].subtype = CD_SUB_NONE;
outtoc.tracks[trknum].subsize = 0;
+ outtoc.tracks[trknum].padframes = 0;
cdrom_convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
if (outtoc.tracks[trknum].datasize == 0)
diff --git a/src/tools/chdman.c b/src/tools/chdman.c
index b9ceb1b4d40..b37f9eaceb7 100644
--- a/src/tools/chdman.c
+++ b/src/tools/chdman.c
@@ -64,6 +64,11 @@ const UINT32 IDE_SECTOR_SIZE = 512;
// temporary input buffer size
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
#define REQUIRED "~"
@@ -113,7 +118,6 @@ const UINT32 TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
#define OPTION_NUMPROCESSORS "numprocessors"
-
//**************************************************************************
// FUNCTION PROTOTYPES
//**************************************************************************
@@ -318,17 +322,25 @@ public:
UINT32 bytesperframe = trackinfo.datasize + trackinfo.subsize;
UINT64 src_track_start = m_info.track[tracknum].offset;
UINT64 src_track_end = src_track_start + bytesperframe * trackinfo.frames;
- while (length_remaining != 0 && offset < endoffs)
+ UINT64 pad_track_start = src_track_end - (m_toc.tracks[tracknum].padframes * bytesperframe);
+ while (length_remaining != 0 && offset < endoffs)
{
// determine start of current frame
UINT64 src_frame_start = src_track_start + ((offset - startoffs) / CD_FRAME_SIZE) * bytesperframe;
if (src_frame_start < src_track_end)
{
- // read it in
- core_fseek(m_file, src_frame_start, SEEK_SET);
- UINT32 count = core_fread(m_file, dest, bytesperframe);
- if (count != bytesperframe)
- report_error(1, "Error reading input file (%s)'", m_lastfile.cstr());
+ // 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);
+ UINT32 count = core_fread(m_file, dest, bytesperframe);
+ if (count != bytesperframe)
+ report_error(1, "Error reading input file (%s)'", m_lastfile.cstr());
+ }
// swap if appropriate
if (m_info.track[tracknum].swap)
@@ -1156,93 +1168,139 @@ static void compress_common(chd_file_compressor &chd)
// 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 (cuemode)
- {
- // first track specifies the file
- if (tracknum == 0)
- core_fprintf(file, "FILE \"%s\" BINARY\n", filename);
-
- // determine submode
- astring tempstr;
- switch (info.trktype)
- {
- case CD_TRACK_MODE1:
- case CD_TRACK_MODE1_RAW:
- tempstr.format("MODE1/%04d", info.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:
- tempstr.format("MODE2/%04d", info.datasize);
- break;
-
- case CD_TRACK_AUDIO:
- tempstr.cpy("AUDIO");
- break;
- }
-
- // output TRACK entry
- core_fprintf(file, " TRACK %02d %s\n", tracknum + 1, tempstr.cstr());
-
- // output PREGAP
- if (info.pregap > 0)
- core_fprintf(file, " PREGAP %s\n", msf_string_from_frames(tempstr, info.pregap));
-
- // output track data
- core_fprintf(file, " INDEX 01 %s\n", msf_string_from_frames(tempstr, frameoffs));
-
- // output POSTGAP
- if (info.postgap > 0)
- core_fprintf(file, " POSTGAP %s\n", msf_string_from_frames(tempstr, info.postgap));
- }
-
- // non-CUE mode
- else
- {
- // header on the first track
- if (tracknum == 0)
- core_fprintf(file, "CD_ROM\n\n\n");
- core_fprintf(file, "// Track %d\n", tracknum + 1);
-
- // write out the track type
- astring modesubmode;
- if (info.subtype != CD_SUB_NONE)
- modesubmode.format("%s %s", cdrom_get_type_string(info.trktype), cdrom_get_subtype_string(info.subtype));
- else
- modesubmode.format("%s", cdrom_get_type_string(info.trktype));
- core_fprintf(file, "TRACK %s\n", modesubmode.cstr());
-
- // write out the attributes
- core_fprintf(file, "NO COPY\n");
- if (info.trktype == CD_TRACK_AUDIO)
- {
- core_fprintf(file, "NO PRE_EMPHASIS\n");
- core_fprintf(file, "TWO_CHANNEL_AUDIO\n");
- }
-
- // output pregap
- astring tempstr;
- if (info.pregap > 0)
- core_fprintf(file, "ZERO %s %s\n", modesubmode.cstr(), msf_string_from_frames(tempstr, info.pregap));
-
- // all tracks but the first one have a file offset
- if (tracknum > 0)
- core_fprintf(file, "DATAFILE \"%s\" #%d %s // length in bytes: %d\n", filename, UINT32(discoffs), msf_string_from_frames(tempstr, info.frames), info.frames * (info.datasize + info.subsize));
- else
- core_fprintf(file, "DATAFILE \"%s\" %s // length in bytes: %d\n", filename, msf_string_from_frames(tempstr, info.frames), info.frames * (info.datasize + info.subsize));
-
- // tracks with pregaps get a START marker too
- if (info.pregap > 0)
- core_fprintf(file, "START %s\n", msf_string_from_frames(tempstr, info.pregap));
-
- core_fprintf(file, "\n\n");
- }
+ if (mode == MODE_GDI)
+ {
+ 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
+ if (tracknum == 0)
+ core_fprintf(file, "FILE \"%s\" BINARY\n", filename);
+
+ // determine submode
+ astring tempstr;
+ switch (info.trktype)
+ {
+ case CD_TRACK_MODE1:
+ case CD_TRACK_MODE1_RAW:
+ tempstr.format("MODE1/%04d", info.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:
+ tempstr.format("MODE2/%04d", info.datasize);
+ break;
+
+ case CD_TRACK_AUDIO:
+ tempstr.cpy("AUDIO");
+ break;
+ }
+
+ // output TRACK entry
+ core_fprintf(file, " TRACK %02d %s\n", tracknum + 1, tempstr.cstr());
+
+ // output PREGAP
+ if (info.pregap > 0)
+ core_fprintf(file, " PREGAP %s\n", msf_string_from_frames(tempstr, info.pregap));
+
+ // output track data
+ core_fprintf(file, " INDEX 01 %s\n", msf_string_from_frames(tempstr, frameoffs));
+
+ // output POSTGAP
+ if (info.postgap > 0)
+ core_fprintf(file, " POSTGAP %s\n", msf_string_from_frames(tempstr, info.postgap));
+ }
+ // non-CUE mode
+ else if (mode == MODE_NORMAL)
+ {
+ // header on the first track
+ if (tracknum == 0)
+ core_fprintf(file, "CD_ROM\n\n\n");
+ core_fprintf(file, "// Track %d\n", tracknum + 1);
+
+ // write out the track type
+ astring modesubmode;
+ if (info.subtype != CD_SUB_NONE)
+ modesubmode.format("%s %s", cdrom_get_type_string(info.trktype), cdrom_get_subtype_string(info.subtype));
+ else
+ modesubmode.format("%s", cdrom_get_type_string(info.trktype));
+ core_fprintf(file, "TRACK %s\n", modesubmode.cstr());
+
+ // write out the attributes
+ core_fprintf(file, "NO COPY\n");
+ if (info.trktype == CD_TRACK_AUDIO)
+ {
+ core_fprintf(file, "NO PRE_EMPHASIS\n");
+ core_fprintf(file, "TWO_CHANNEL_AUDIO\n");
+ }
+
+ // output pregap
+ astring tempstr;
+ if (info.pregap > 0)
+ core_fprintf(file, "ZERO %s %s\n", modesubmode.cstr(), msf_string_from_frames(tempstr, info.pregap));
+
+ // all tracks but the first one have a file offset
+ if (tracknum > 0)
+ core_fprintf(file, "DATAFILE \"%s\" #%d %s // length in bytes: %d\n", filename, UINT32(discoffs), msf_string_from_frames(tempstr, info.frames), info.frames * (info.datasize + info.subsize));
+ else
+ core_fprintf(file, "DATAFILE \"%s\" %s // length in bytes: %d\n", filename, msf_string_from_frames(tempstr, info.frames), info.frames * (info.datasize + info.subsize));
+
+ // tracks with pregaps get a START marker too
+ if (info.pregap > 0)
+ core_fprintf(file, "START %s\n", msf_string_from_frames(tempstr, info.pregap));
+
+ core_fprintf(file, "\n\n");
+ }
}
@@ -2194,6 +2252,8 @@ static void do_extract_cd(parameters_t &params)
int chop = default_name.rchr(0, '.');
if (chop != -1)
default_name.substr(0, chop);
+ char basename[128];
+ strncpy(basename, default_name.cstr(), 127);
default_name.cat(".bin");
if (output_bin_file_str == NULL)
output_bin_file_str = &default_name;
@@ -2210,38 +2270,86 @@ static void do_extract_cd(parameters_t &params)
core_file *output_toc_file = NULL;
try
{
- // process output 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)
- report_error(1, "Unable to open file (%s)", output_file_str->cstr());
- bool cuemode = (output_file_str->find(".cue") != -1);
+ 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
+ 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)
+ report_error(1, "Unable to open file (%s)", output_file_str->cstr());
// process output BIN file
- filerr = core_fopen(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &output_bin_file);
- if (filerr != FILERR_NONE)
- report_error(1, "Unable to open file (%s)", output_bin_file_str->cstr());
+ if (mode != MODE_GDI)
+ {
+ filerr = core_fopen(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &output_bin_file);
+ if (filerr != FILERR_NONE)
+ report_error(1, "Unable to open file (%s)", output_bin_file_str->cstr());
+ }
// determine total frames
UINT64 total_bytes = 0;
for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
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
UINT64 outputoffs = 0;
UINT32 discoffs = 0;
dynamic_buffer buffer;
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
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
// the subdata size in the buffer calculation.
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");
output_frame_size = trackinfo.datasize;
}
@@ -2251,7 +2359,8 @@ static void do_extract_cd(parameters_t &params)
// now read and output the actual data
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));
@@ -2259,7 +2368,7 @@ static void do_extract_cd(parameters_t &params)
cdrom_read_data(cdrom, cdrom_get_track_start(cdrom, tracknum) + frame, &buffer[bufferoffs], trackinfo.trktype);
// 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)
{
UINT8 swaptemp = buffer[bufferoffs + swapindex];
@@ -2270,14 +2379,14 @@ static void do_extract_cd(parameters_t &params)
discoffs++;
// 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]);
bufferoffs += trackinfo.subsize;
}
// 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);
UINT32 byteswritten = core_fwrite(output_bin_file, buffer, bufferoffs);
@@ -2287,10 +2396,12 @@ static void do_extract_cd(parameters_t &params)
bufferoffs = 0;
}
}
+
+ discoffs += trackinfo.padframes;
}
// finish up
- core_fclose(output_bin_file);
+ core_fclose(output_bin_file);
core_fclose(output_toc_file);
printf("Extraction complete \n");
}