summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/lib/util/cdrom.c45
-rw-r--r--src/lib/util/cdrom.h1
-rw-r--r--src/lib/util/chd.c1
-rw-r--r--src/lib/util/chd.h3
-rw-r--r--src/lib/util/chdcd.c2
-rw-r--r--src/tools/chdman.c60
6 files changed, 93 insertions, 19 deletions
diff --git a/src/lib/util/cdrom.c b/src/lib/util/cdrom.c
index e2419ea1a0b..2d2dbddb006 100644
--- a/src/lib/util/cdrom.c
+++ b/src/lib/util/cdrom.c
@@ -142,6 +142,7 @@ cdrom_file *cdrom_open(const char *inputfile)
file = new cdrom_file();
if (file == NULL)
return NULL;
+ memset(file, 0, sizeof(cdrom_file));
/* setup the CDROM module and get the disc info */
chd_error err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info);
@@ -239,6 +240,7 @@ cdrom_file *cdrom_open(chd_file *chd)
file = new cdrom_file();
if (file == NULL)
return NULL;
+ memset(file, 0, sizeof(cdrom_file));
/* fill in the data */
file->chd = chd;
@@ -330,32 +332,44 @@ void cdrom_close(cdrom_file *file)
chd_error read_partial_sector(cdrom_file *file, void *dest, UINT32 lbasector, UINT32 chdsector, UINT32 tracknum, UINT32 startoffs, UINT32 length)
{
+ chd_error result = CHDERR_NONE;
+ bool needswap = false;
+
// if this is pregap info that isn't actually in the file, just return blank data
if ((file->cdtoc.tracks[tracknum].pgdatasize == 0) && (lbasector < (file->cdtoc.tracks[tracknum].logframeofs + file->cdtoc.tracks[tracknum].pregap)))
{
// printf("PG missing sector: LBA %d, trklog %d\n", lbasector, file->cdtoc.tracks[tracknum].logframeofs);
memset(dest, 0, length);
- return CHDERR_NONE;
+ return result;
}
// if a CHD, just read
if (file->chd != NULL)
- return file->chd->read_bytes(UINT64(chdsector) * UINT64(CD_FRAME_SIZE) + startoffs, dest, length);
+ {
+ result = file->chd->read_bytes(UINT64(chdsector) * UINT64(CD_FRAME_SIZE) + startoffs, dest, length);
+ /* swap CDDA in the case of LE GDROMs */
+ if ((file->cdtoc.flags & CD_FLAG_GDROMLE) && (file->cdtoc.tracks[tracknum].trktype == CD_TRACK_AUDIO))
+ needswap = true;
+ }
+ else
+ {
+ // else read from the appropriate file
+ core_file *srcfile = file->fhandle[tracknum];
- // else read from the appropriate file
- core_file *srcfile = file->fhandle[tracknum];
+ UINT64 sourcefileoffset = file->track_info.track[tracknum].offset;
+ int bytespersector = file->cdtoc.tracks[tracknum].datasize + file->cdtoc.tracks[tracknum].subsize;
- UINT64 sourcefileoffset = file->track_info.track[tracknum].offset;
- int bytespersector = file->cdtoc.tracks[tracknum].datasize + file->cdtoc.tracks[tracknum].subsize;
+ sourcefileoffset += chdsector * bytespersector + startoffs;
- sourcefileoffset += chdsector * bytespersector + startoffs;
+ // printf("Reading sector %d from track %d at offset %lld\n", chdsector, tracknum, sourcefileoffset);
-// printf("Reading sector %d from track %d at offset %lld\n", chdsector, tracknum, sourcefileoffset);
+ core_fseek(srcfile, sourcefileoffset, SEEK_SET);
+ core_fread(srcfile, dest, length);
- core_fseek(srcfile, sourcefileoffset, SEEK_SET);
- core_fread(srcfile, dest, length);
+ needswap = file->track_info.track[tracknum].swap;
+ }
- if (file->track_info.track[tracknum].swap)
+ if (needswap)
{
UINT8 *buffer = (UINT8 *)dest - startoffs;
for (int swapindex = startoffs; swapindex < 2352; swapindex += 2 )
@@ -365,7 +379,7 @@ chd_error read_partial_sector(cdrom_file *file, void *dest, UINT32 lbasector, UI
buffer[ swapindex + 1 ] = swaptemp;
}
}
- return CHDERR_NONE;
+ return result;
}
@@ -839,7 +853,12 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
}
else
{
- err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
+ err = chd->read_metadata(GDROM_OLD_METADATA_TAG, toc->numtrks, metadata);
+ if (err == CHDERR_NONE)
+ /* legacy GDROM track was detected */
+ toc->flags |= CD_FLAG_GDROMLE;
+ else
+ err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
if (err == CHDERR_NONE)
{
diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h
index 68538f6a298..426bcf36a36 100644
--- a/src/lib/util/cdrom.h
+++ b/src/lib/util/cdrom.h
@@ -56,6 +56,7 @@ enum
};
#define CD_FLAG_GDROM 0x00000001 // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
+#define CD_FLAG_GDROMLE 0x00000002 // legacy GD-ROM, with little-endian CDDA data
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/lib/util/chd.c b/src/lib/util/chd.c
index 68332479312..7a32f2262d5 100644
--- a/src/lib/util/chd.c
+++ b/src/lib/util/chd.c
@@ -1412,6 +1412,7 @@ UINT32 chd_file::guess_unitbytes()
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(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE)
return CD_FRAME_SIZE;
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index cc0f493cc0b..9beb674cc47 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -225,7 +225,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');
+const chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
+const chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D');
extern const char *GDROM_TRACK_METADATA_FORMAT;
// standard A/V metadata
diff --git a/src/lib/util/chdcd.c b/src/lib/util/chdcd.c
index 9059d65aacb..8690cc65ffa 100644
--- a/src/lib/util/chdcd.c
+++ b/src/lib/util/chdcd.c
@@ -634,6 +634,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
outtoc.tracks[trknum].datasize = 0;
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
outtoc.tracks[trknum].subsize = 0;
+ outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
tok=strtok(NULL," ");
outtoc.tracks[trknum].physframeofs=atoi(tok);
@@ -658,6 +659,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
{
outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO;
outtoc.tracks[trknum].datasize=2352;
+ outinfo.track[trknum].swap = true;
}
astring name;
diff --git a/src/tools/chdman.c b/src/tools/chdman.c
index 5c1068c8099..1fe97a68f3c 100644
--- a/src/tools/chdman.c
+++ b/src/tools/chdman.c
@@ -215,7 +215,8 @@ class chd_chdfile_compressor : public chd_file_compressor
public:
// construction/destruction
chd_chdfile_compressor(chd_file &file, UINT64 offset = 0, UINT64 maxoffset = ~0)
- : m_file(file),
+ : m_toc(NULL),
+ m_file(file),
m_offset(offset),
m_maxoffset(MIN(maxoffset, file.logical_bytes())) { }
@@ -230,9 +231,46 @@ public:
chd_error err = m_file.read_bytes(offset, dest, length);
if (err != CHDERR_NONE)
throw err;
+
+ // if we have TOC - detect audio sectors and swap data
+ if (m_toc)
+ {
+ assert(offset % CD_FRAME_SIZE == 0);
+ assert(length % CD_FRAME_SIZE == 0);
+
+ int startlba = offset / CD_FRAME_SIZE;
+ int lenlba = length / CD_FRAME_SIZE;
+ UINT8 *_dest = reinterpret_cast<UINT8 *>(dest);
+
+ for (int chdlba = 0; chdlba < lenlba; chdlba++)
+ {
+ // find current frame's track number
+ int tracknum = m_toc->numtrks;
+ for (int track = 0; track < m_toc->numtrks; track++)
+ if ((chdlba + startlba) < m_toc->tracks[track + 1].chdframeofs)
+ {
+ tracknum = track;
+ break;
+ }
+ // is it audio ?
+ if (m_toc->tracks[tracknum].trktype != CD_TRACK_AUDIO)
+ continue;
+ // byteswap if yes
+ int dataoffset = chdlba * CD_FRAME_SIZE;
+ for (UINT32 swapindex = dataoffset; swapindex < (dataoffset + CD_MAX_SECTOR_DATA); swapindex += 2)
+ {
+ UINT8 temp = _dest[swapindex];
+ _dest[swapindex] = _dest[swapindex + 1];
+ _dest[swapindex + 1] = temp;
+ }
+ }
+ }
+
return length;
}
+const cdrom_toc * m_toc;
+
private:
// internal state
chd_file & m_file;
@@ -2042,8 +2080,10 @@ static void do_copy(parameters_t &params)
memcpy(compression, s_default_ld_compression, sizeof(compression));
else if (input_chd.read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
input_chd.read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- input_chd.read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE)
- memcpy(compression, s_default_cd_compression, sizeof(compression));
+ input_chd.read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE ||
+ input_chd.read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
+ input_chd.read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE)
+ memcpy(compression, s_default_cd_compression, sizeof(compression));
else
memcpy(compression, s_default_raw_compression, sizeof(compression));
}
@@ -2087,6 +2127,7 @@ static void do_copy(parameters_t &params)
UINT8 metaflags;
UINT32 index = 0;
bool redo_cd = false;
+ bool cdda_swap = false;
for (err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags); err == CHDERR_NONE; err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags))
{
// if this is an old CD-CHD tag, note that we want to re-do it
@@ -2095,6 +2136,12 @@ static void do_copy(parameters_t &params)
redo_cd = true;
continue;
}
+ // if this is old GD tag we want re-do it and swap CDDA
+ if (metatag == GDROM_OLD_METADATA_TAG)
+ {
+ cdda_swap = redo_cd = true;
+ continue;
+ }
// otherwise, clone it
err = chd->write_metadata(metatag, CHDMETAINDEX_APPEND, metadata, metaflags);
@@ -2112,6 +2159,8 @@ static void do_copy(parameters_t &params)
err = cdrom_write_metadata(chd, toc);
if (err != CHDERR_NONE)
report_error(1, "Error writing upgraded CD metadata: %s", chd_file::error_string(err));
+ if (cdda_swap)
+ chd->m_toc = toc;
}
// compress it generically
@@ -2354,8 +2403,9 @@ static void do_extract_cd(parameters_t &params)
// read the data
cdrom_read_data(cdrom, cdrom_get_track_start_phys(cdrom, tracknum) + frame, &buffer[bufferoffs], trackinfo.trktype, true);
- // for CDRWin, audio tracks must be reversed
- if ((mode == MODE_CUEBIN) && (trackinfo.trktype == CD_TRACK_AUDIO))
+ // for CDRWin and GDI audio tracks must be reversed
+ // in the case of GDI and CHD version < 5 we assuming source CHD image is GDROM so audio tracks is already reversed
+ if (((mode == MODE_GDI && input_chd.version() > 4) || (mode == MODE_CUEBIN)) && (trackinfo.trktype == CD_TRACK_AUDIO))
for (int swapindex = 0; swapindex < trackinfo.datasize; swapindex += 2)
{
UINT8 swaptemp = buffer[bufferoffs + swapindex];