2013-12-19 17:10:14 +00:00
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#include "deps/chdr/chd.h"
|
|
|
|
|
2018-09-22 13:27:08 +00:00
|
|
|
/* tracks are padded to a multiple of this many frames */
|
|
|
|
const uint32_t CD_TRACK_PADDING = 4;
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
struct CHDDisc : Disc
|
|
|
|
{
|
|
|
|
chd_file* chd;
|
|
|
|
u8* hunk_mem;
|
|
|
|
u32 old_hunk;
|
|
|
|
|
|
|
|
u32 hunkbytes;
|
|
|
|
u32 sph;
|
2018-09-22 13:19:57 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
CHDDisc()
|
|
|
|
{
|
|
|
|
chd=0;
|
|
|
|
hunk_mem=0;
|
|
|
|
}
|
|
|
|
|
2014-06-13 15:41:48 +00:00
|
|
|
bool TryOpen(const wchar* file);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-09-22 13:19:57 +00:00
|
|
|
~CHDDisc()
|
|
|
|
{
|
2019-09-07 12:37:39 +00:00
|
|
|
delete[] hunk_mem;
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
if (chd)
|
|
|
|
chd_close(chd);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CHDTrack : TrackFile
|
|
|
|
{
|
|
|
|
CHDDisc* disc;
|
|
|
|
u32 StartFAD;
|
2018-11-02 09:14:25 +00:00
|
|
|
s32 Offset;
|
2013-12-19 17:10:14 +00:00
|
|
|
u32 fmt;
|
2018-11-03 18:29:55 +00:00
|
|
|
bool swap_bytes;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-11-02 09:14:25 +00:00
|
|
|
CHDTrack(CHDDisc* disc, u32 StartFAD, s32 Offset, u32 fmt, bool swap_bytes)
|
2018-09-22 13:19:57 +00:00
|
|
|
{
|
|
|
|
this->disc=disc;
|
2013-12-19 17:10:14 +00:00
|
|
|
this->StartFAD=StartFAD;
|
2018-11-02 09:14:25 +00:00
|
|
|
this->Offset = Offset;
|
2013-12-19 17:10:14 +00:00
|
|
|
this->fmt=fmt;
|
2018-11-03 18:29:55 +00:00
|
|
|
this->swap_bytes = swap_bytes;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-11-03 18:24:53 +00:00
|
|
|
virtual void Read(u32 FAD, u8* dst, SectorFormat* sector_type, u8* subcode, SubcodeFormat* subcode_type)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2018-11-02 09:14:25 +00:00
|
|
|
u32 fad_offs = FAD + Offset;
|
|
|
|
u32 hunk=(fad_offs)/disc->sph;
|
2013-12-19 17:10:14 +00:00
|
|
|
if (disc->old_hunk!=hunk)
|
|
|
|
{
|
|
|
|
chd_read(disc->chd,hunk,disc->hunk_mem); //CHDERR_NONE
|
2018-10-09 20:13:35 +00:00
|
|
|
disc->old_hunk = hunk;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-11-03 18:24:53 +00:00
|
|
|
u32 hunk_ofs = fad_offs%disc->sph;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-11-03 18:24:53 +00:00
|
|
|
memcpy(dst, disc->hunk_mem + hunk_ofs * (2352+96), fmt);
|
2018-09-22 13:19:57 +00:00
|
|
|
|
2018-11-03 18:29:55 +00:00
|
|
|
if (swap_bytes)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < fmt; i += 2)
|
|
|
|
{
|
|
|
|
u8 b = dst[i];
|
|
|
|
dst[i] = dst[i + 1];
|
|
|
|
dst[i + 1] = b;
|
|
|
|
}
|
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
*sector_type=fmt==2352?SECFMT_2352:SECFMT_2048_MODE1;
|
2018-09-22 13:19:57 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
//While space is reserved for it, the images contain no actual subcodes
|
|
|
|
//memcpy(subcode,disc->hunk_mem+hunk_ofs*(2352+96)+2352,96);
|
|
|
|
*subcode_type=SUBFMT_NONE;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-06-13 15:41:48 +00:00
|
|
|
bool CHDDisc::TryOpen(const wchar* file)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
chd_error err=chd_open(file,CHD_OPEN_READ,0,&chd);
|
|
|
|
|
|
|
|
if (err!=CHDERR_NONE)
|
2018-10-22 15:39:02 +00:00
|
|
|
{
|
2019-07-01 14:10:28 +00:00
|
|
|
INFO_LOG(GDROM, "chd: chd_open failed for file %s: %d", file, err);
|
2013-12-19 17:10:14 +00:00
|
|
|
return false;
|
2018-10-22 15:39:02 +00:00
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2019-07-01 14:10:28 +00:00
|
|
|
INFO_LOG(GDROM, "chd: parsing file %s", file);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
const chd_header* head = chd_get_header(chd);
|
|
|
|
|
|
|
|
hunkbytes = head->hunkbytes;
|
|
|
|
hunk_mem = new u8[hunkbytes];
|
|
|
|
old_hunk=0xFFFFFFF;
|
|
|
|
|
|
|
|
sph = hunkbytes/(2352+96);
|
|
|
|
|
2018-09-22 13:19:57 +00:00
|
|
|
if (hunkbytes%(2352+96)!=0)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2019-07-01 14:10:28 +00:00
|
|
|
INFO_LOG(GDROM, "chd: hunkbytes is invalid, %d\n",hunkbytes);
|
2013-12-19 17:10:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
2018-09-22 13:19:57 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
u32 tag;
|
|
|
|
u8 flags;
|
|
|
|
char temp[512];
|
|
|
|
u32 temp_len;
|
2018-09-22 13:27:08 +00:00
|
|
|
u32 total_frames = 150;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-11-03 18:24:53 +00:00
|
|
|
u32 Offset = 0;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
2018-09-22 13:19:57 +00:00
|
|
|
char type[16], subtype[16], pgtype[16], pgsub[16];
|
|
|
|
int tkid=-1, frames=0, pregap=0, postgap=0, padframes=0;
|
|
|
|
|
|
|
|
err = chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, tracks.size(), temp, sizeof(temp), &temp_len, &tag, &flags);
|
|
|
|
if (err == CHDERR_NONE)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
//"TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
|
2018-09-22 13:19:57 +00:00
|
|
|
sscanf(temp, CDROM_TRACK_METADATA2_FORMAT, &tkid, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2018-09-22 13:19:57 +00:00
|
|
|
else if (CHDERR_NONE== (err = chd_get_metadata(chd, CDROM_TRACK_METADATA_TAG, tracks.size(), temp, sizeof(temp), &temp_len, &tag, &flags)) )
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
//CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
|
2018-09-22 13:19:57 +00:00
|
|
|
sscanf(temp, CDROM_TRACK_METADATA_FORMAT, &tkid, type, subtype, &frames);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-22 13:19:57 +00:00
|
|
|
err = chd_get_metadata(chd, GDROM_OLD_METADATA_TAG, tracks.size(), temp, sizeof(temp), &temp_len, &tag, &flags);
|
|
|
|
if (err != CHDERR_NONE)
|
|
|
|
{
|
|
|
|
err = chd_get_metadata(chd, GDROM_TRACK_METADATA_TAG, tracks.size(), temp, sizeof(temp), &temp_len, &tag, &flags);
|
|
|
|
}
|
|
|
|
if (err == CHDERR_NONE)
|
|
|
|
{
|
|
|
|
//GDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
|
|
|
|
sscanf(temp, GDROM_TRACK_METADATA_FORMAT, &tkid, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tkid!=(tracks.size()+1) || (strcmp(type,"MODE1_RAW")!=0 && strcmp(type,"AUDIO")!=0 && strcmp(type,"MODE1")!=0) || strcmp(subtype,"NONE")!=0 || pregap!=0 || postgap!=0)
|
|
|
|
{
|
2019-07-01 14:10:28 +00:00
|
|
|
INFO_LOG(GDROM, "chd: track type %s is not supported", type);
|
2013-12-19 17:10:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-01 14:10:28 +00:00
|
|
|
DEBUG_LOG(GDROM, "%s", temp);
|
2013-12-19 17:10:14 +00:00
|
|
|
Track t;
|
2018-10-09 20:12:47 +00:00
|
|
|
t.StartFAD = total_frames;
|
2018-09-22 13:27:08 +00:00
|
|
|
total_frames += frames;
|
2018-10-09 20:12:47 +00:00
|
|
|
t.EndFAD = total_frames - 1;
|
2018-09-22 13:27:08 +00:00
|
|
|
t.ADDR = 0;
|
|
|
|
t.CTRL = strcmp(type,"AUDIO") == 0 ? 0 : 4;
|
2018-11-03 18:29:55 +00:00
|
|
|
|
|
|
|
t.file = new CHDTrack(this, t.StartFAD, Offset - t.StartFAD, strcmp(type, "MODE1") ? 2352 : 2048,
|
|
|
|
// audio tracks are byteswapped in CHDv5+
|
|
|
|
t.CTRL == 0 && head->version >= 5);
|
2018-09-22 13:27:08 +00:00
|
|
|
|
2018-11-03 18:24:53 +00:00
|
|
|
// CHD files are padded, so we have to respect the offset
|
|
|
|
int padded = (frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
|
|
|
|
Offset += padded * CD_TRACK_PADDING;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
tracks.push_back(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (total_frames!=549300 || tracks.size()<3)
|
|
|
|
{
|
2019-07-01 14:10:28 +00:00
|
|
|
WARN_LOG(GDROM, "WARNING: chd: Total frames is wrong: %u frames in %zu tracks", total_frames, tracks.size());
|
2014-05-26 12:32:07 +00:00
|
|
|
#ifndef NOT_REICAST
|
2013-12-19 17:10:14 +00:00
|
|
|
msgboxf("This is an improper dump!",MBX_ICONEXCLAMATION);
|
2014-05-26 12:32:07 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
FillGDSession();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-13 15:41:48 +00:00
|
|
|
Disc* chd_parse(const wchar* file)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
CHDDisc* rv = new CHDDisc();
|
2018-09-22 13:19:57 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
if (rv->TryOpen(file))
|
|
|
|
return rv;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete rv;
|
|
|
|
return 0;
|
|
|
|
}
|
2018-09-22 13:19:57 +00:00
|
|
|
}
|