]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Nero nrg CD image support.
authorToni Wilen <twilen@winuae.net>
Sat, 5 Mar 2016 10:22:30 +0000 (12:22 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 5 Mar 2016 10:22:30 +0000 (12:22 +0200)
blkdev_cdimage.cpp

index c5849f7cada39a82df01a72c7863d4e9d9026765..a73b9e33a17148c1d1dfe9bb5ffcd0fdddef7c38 100644 (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);