Nero nrg CD image support.

This commit is contained in:
Toni Wilen 2016-03-05 12:22:30 +02:00
parent 5b8b2f5d6a
commit 243e254bfe

View File

@ -344,6 +344,15 @@ static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *
sub_to_deinterleaved (tmp, dst);
ret = 2;
}
#if 0
uae_u8 *s = dst + SUB_ENTRY_SIZE;
write_log(_T("CTRLADR:%02X TRK=%02X IDX=%02X MSF=%02X:%02X:%02X %02X:%02X:%02X\n"),
s[0], s[1], s[2],
s[3], s[4], s[5],
s[7], s[8], s[9]);
#endif
uae_sem_post (&cdu->sub_sem);
return ret;
}
@ -825,8 +834,7 @@ static int command_qcode (int unitnum, uae_u8 *buf, int sector)
return 0;
getsub_deinterleaved (subbuf, cdu, td, pos);
memcpy (p, subbuf + 12, 12);
// write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"),
// pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]);
return 1;
}
@ -1470,7 +1478,6 @@ static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
t->adr = adr;
t->ctrl = control;
t->address = lba;
t->offset = 0;
t->size = 2352;
t->offset = lba * t->size;
t->track = tracknum;
@ -1765,6 +1772,175 @@ static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
return cdu->tracks;
}
static int parsenrg(struct cdunit *cdu, struct zfile *znrg, const TCHAR *img)
{
uae_s64 size;
uae_s64 offset;
bool ner5 = false;
uae_u8 buf[256] = { 0 };
int tracknum = 0;
uae_u32 lastlba = 0;
bool gotsession = false;
size = zfile_size(znrg);
zfile_fseek(znrg, size - 12, SEEK_SET);
zfile_fread(buf, 12, 1, znrg);
if (!memcmp(buf, "NER5", 4)) {
offset = get_quad_host(buf + 4);
ner5 = true;
} else if (!memcmp(buf + 4, "NERO", 4)) {
offset = get_long_host(buf + 8);
} else {
return 0;
}
if (offset < 0 || offset >= size - 12)
return 0;
zfile_fseek(znrg, offset, SEEK_SET);
for (;;) {
memset(buf, 0, 8);
if (zfile_fread(buf, 8, 1, znrg) != 1)
return 0;
offset = zfile_ftell(znrg);
uae_s32 size = get_long_host(buf + 4);
buf[4] = 0;
offset += size;
if (!gotsession && !memcmp(buf, "ETN2", 4)) {
tracknum = 1;
int blocksize = 32;
while (size >= blocksize) {
uae_s64 toffset;
uae_u32 lba;
uae_u32 type;
cdtoc *t = &cdu->toc[tracknum - 1];
if (zfile_fread(buf, blocksize, 1, znrg) != 1)
return 0;
toffset = get_quad_host(buf);
lba = get_long_host(buf + 20);
type = get_long_host(buf + 16);
t->offset = toffset;
t->address = lba;
if (type == 7) {
t->size = 2352;
t->enctype = AUDENC_PCM;
} else if (type == 0 || type == 3) {
t->size = 2048;
t->ctrl |= 4;
}
t->track = tracknum;
t->handle = zfile_dup(znrg);
t->fname = my_strdup(zfile_getname(znrg));
lastlba = lba + get_long_host(buf + 28);
tracknum++;
size -= blocksize;
}
gotsession = true;
} else if (!memcmp(buf, "SINF", 4)) {
if (zfile_fread(buf, 4, 1, znrg) != 1)
return 0;
if (!cdu->tracks) {
cdu->tracks = get_long_host(buf);
cdtoc *t = &cdu->toc[cdu->tracks];
t->address = lastlba;
}
} else if (!memcmp(buf, "CUEX", 4) || !memcmp(buf, "CUES", 4)) {
while (size >= 8) {
if (zfile_fread(buf, 8, 1, znrg) != 1)
return 0;
uae_u8 trk = buf[1];
if (trk >= 0xa0) {
if (trk == 0xaa) {
lastlba = get_long_host(buf + 4);
}
} else {
tracknum = frombcd(trk);
int index = frombcd(buf[2]);
if (index == 0 && tracknum >= 1 && tracknum <= 99) {
struct cdtoc *t = &cdu->toc[tracknum - 1];
t->address = get_long_host(buf + 4);
t->ctrl = buf[0] >> 4;
t->adr = buf[0] & 15;
t->track = tracknum;
}
}
size -= 8;
}
} else if (!memcmp(buf, "DAOX", 4) || !memcmp(buf, "DAOI", 4)) {
bool newformat = memcmp(buf, "DAOX", 4) == 0;
int first_track, last_track;
int blocksize;
if (newformat) {
zfile_fread(buf, 22, 1, znrg);
first_track = frombcd(buf[4 + 14 + 2]);
last_track = frombcd(buf[4 + 14 + 2 + 1]);
size -= 22;
blocksize = 42;
} else {
zfile_fread(buf, 24, 1, znrg);
first_track = frombcd(buf[4 + 14 + 4]);
last_track = frombcd(buf[4 + 14 + 4 + 1]);
size -= 24;
blocksize = 32;
}
struct cdtoc *t = &cdu->toc[last_track];
t->address = lastlba;
cdu->tracks = last_track - first_track + 1;
tracknum = first_track;
while (size >= blocksize) {
if (tracknum >= 1 && tracknum <= 99) {
uae_s64 index0;
uae_s64 index1;
uae_s64 end;
int sectorsize, type;
cdtoc *t = &cdu->toc[tracknum - 1];
if (zfile_fread(buf, blocksize, 1, znrg) != 1)
return 0;
if (newformat) {
sectorsize = get_word_host(buf + 12);
type = get_word_host(buf + 14);
index0 = get_quad_host(buf + 18);
index1 = get_quad_host(buf + 26);
end = get_quad_host(buf + 34);
} else {
sectorsize = get_long_host(buf + 12);
type = get_long_host(buf + 16);
index0 = get_long_host(buf + 20);
index1 = get_long_host(buf + 24);
end = get_long_host(buf + 28);
}
if (t->address < 0) {
index0 += -t->address * sectorsize;
index1 = index0;
t->address = 0;
}
t->offset = index0;
t->index1 = (index1 - index0) / sectorsize;
t->size = sectorsize;
t->handle = zfile_dup(znrg);
t->fname = my_strdup(zfile_getname(znrg));
if (type == 0x0700 || type == 0x1000) {
t->enctype = AUDENC_PCM;
if (type == 0x1000) {
// audio with sub.
t->suboffset = t->offset;
t->size -= SUB_CHANNEL_SIZE;
t->subcode = 1;
t->subhandle = zfile_dup(t->handle);
t->skipsize = SUB_CHANNEL_SIZE;
}
}
}
tracknum++;
size -= blocksize;
}
} else if (!memcmp(buf, "END!", 4)) {
break;
}
zfile_fseek(znrg, offset, SEEK_SET);
}
return cdu->tracks;
}
static int parse_image (struct cdunit *cdu, const TCHAR *img)
{
struct zfile *zcue;
@ -1798,14 +1974,16 @@ static int parse_image (struct cdunit *cdu, const TCHAR *img)
if (p > curdir)
my_setcurrentdir (curdir, oldcurdir);
if (!_tcsicmp (ext, _T("cue"))) {
parsecue (cdu, zcue, img);
} else if (!_tcsicmp (ext, _T("ccd"))) {
parseccd (cdu, zcue, img);
} else if (!_tcsicmp (ext, _T("mds"))) {
parsemds (cdu, zcue, img);
if (!_tcsicmp(ext, _T("cue"))) {
parsecue(cdu, zcue, img);
} else if (!_tcsicmp(ext, _T("ccd"))) {
parseccd(cdu, zcue, img);
} else if (!_tcsicmp(ext, _T("mds"))) {
parsemds(cdu, zcue, img);
} else if (!_tcsicmp(ext, _T("nrg"))) {
parsenrg(cdu, zcue, img);
#ifdef WITH_CHD
} else if (!_tcsicmp (ext, _T("chd"))) {
} else if (!_tcsicmp(ext, _T("chd"))) {
if (oldcurdir[0])
my_setcurrentdir (oldcurdir, NULL);
parsechd (cdu, zcue, img);