From: Toni Wilen Date: Sat, 5 Mar 2016 10:22:30 +0000 (+0200) Subject: Nero nrg CD image support. X-Git-Tag: 3300~66 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=243e254bfe95672177d195d2cd0937bc099b2ba5;p=francis%2Fwinuae.git Nero nrg CD image support. --- diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index c5849f7c..a73b9e33 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -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);