From c8f480317b0571b63797f03d7bda5d15b6d9fe5b Mon Sep 17 00:00:00 2001 From: pixel Date: Tue, 19 Oct 2004 01:27:27 +0000 Subject: Blah... too much diffs to follow --- lib/isobuilder.cpp | 1744 ++++++++++++++++++++++++++-------------------------- 1 file changed, 872 insertions(+), 872 deletions(-) (limited to 'lib') diff --git a/lib/isobuilder.cpp b/lib/isobuilder.cpp index 3f31c73..1414e96 100644 --- a/lib/isobuilder.cpp +++ b/lib/isobuilder.cpp @@ -1,872 +1,872 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: isobuilder.cpp,v 1.12 2004-05-03 12:55:04 pixel Exp $ */ - -#include "isobuilder.h" - -void isobuilder::Date::dump(Byte * datas) { - char pbuf[256]; - - sprintf(pbuf, "%04i", year); - memcpy(datas + 0, pbuf, 4); - sprintf(pbuf, "%02i", month); - memcpy(datas + 4, pbuf, 2); - sprintf(pbuf, "%02i", day); - memcpy(datas + 6, pbuf, 2); - sprintf(pbuf, "%02i", hour); - memcpy(datas + 8, pbuf, 2); - sprintf(pbuf, "%02i", minute); - memcpy(datas + 10, pbuf, 2); - sprintf(pbuf, "%02i", second); - memcpy(datas + 12, pbuf, 2); - sprintf(pbuf, "%02i", hundredths); - memcpy(datas + 14, pbuf, 2); - - *((char *) (datas + 16)) = offset; -} - -isobuilder::Date::Date(int) { - year = month = day = hour = minute = second = hundredths = offset = 0; -} - -isobuilder::Date::Date(Byte * datas) { - char pbuf[256]; - char * cdatas = (char *) datas; - - memcpy(pbuf, cdatas + 0, 4); - pbuf[4] = 0; - sscanf(pbuf, "%d", &year); - - memcpy(pbuf, cdatas + 4, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &month); - - memcpy(pbuf, cdatas + 6, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &day); - - memcpy(pbuf, cdatas + 8, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &hour); - - memcpy(pbuf, cdatas + 10, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &minute); - - memcpy(pbuf, cdatas + 12, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &second); - - memcpy(pbuf, cdatas + 14, 2); - pbuf[2] = 0; - sscanf(pbuf, "%d", &hundredths); - - offset = *(cdatas + 16); -} - -isobuilder::DirTree::DirTree(isobuilder::DirTree * _father, bool _dir) : mode(-1), father(_father), dir(_dir) { - DirTree * p; - - child = brother = 0; - - if (!father) - return; - - creation = father->creation; - - if (father->child) { - for (p = father->child; p->brother; p = p->brother); - p->brother = this; - } else { - father->child = this; - } -} - -isobuilder::DirTree::~DirTree() { - while (child) { - delete child; - } - - if (!father) - return; - - if (father->child == this) { - father->child = brother; - } else { - // Dirty, should not happen. - DirTree * p; - for (p = father->child; p->brother != this; p = p->brother); - p->brother = brother; - } -} - -void isobuilder::DirTree::dumpdirs(isobuilder * builder) throw (GeneralException) { - Byte * dir, * odir; - int cursiz, cursectsize, R; - String oldname; - DirTree * p; - - odir = dir = (Byte *) malloc(cursiz = size); - cursectsize = 2048; - - oldname = name; - name = "."; - R = buildentry(dir, cursectsize); - name = oldname; - cursectsize -= R; - dir += R; - - if (father) { - oldname = father->name; - father->name = ".."; - R = father->buildentry(dir, cursectsize); - father->name = oldname; - } else { - name = ".."; - R = buildentry(dir, cursectsize); - name = "."; - } - - cursectsize -= R; - dir += R; - - for (p = child; p; p = p->brother) { - if (p->dir) { - p->dumpdirs(builder); - } - if (p->hardhide) - continue; - while (!(R = p->buildentry(dir, cursectsize))) { - cursiz -= 2048; - dir += cursectsize; - cursectsize = 2048; - if (!cursiz) - throw GeneralException("Directory is too small! Entries don't fit."); - } - cursectsize -= R; - dir += R; - } - - builder->putdatas(odir, size, mode, sector); - - free(odir); -} - -int isobuilder::DirTree::buildpath(Byte * datas, int size, bool bigendian) throw (GeneralException) { - int N, r, tr; - Uint16 pn; - char pbuf[256], pad; - - if (!dir) { - if (brother) { - return brother->buildpath(datas, size, bigendian); - } else { - return 0; - } - } - - if (!father) { - numerate(1); - N = 1; - pbuf[0] = 0; - pn = 1; - } else { - N = name.strlen(); - strcpy(pbuf, name.to_charp()); - pn = father->node; - } - - pad = N & 1; - size -= (r = N + pad + 8); - - if (size < 0) - throw GeneralException("Path table too small."); - - datas[0] = N; - datas[1] = 0; - *((Uint32 *) (datas + 2)) = bigendian ? cdutils::swap_dword(sector) : sector; - *((Uint16 *) (datas + 6)) = bigendian ? cdutils::swap_word(pn) : pn; - memcpy(datas + 8, pbuf, N); - if (pad) - datas[8 + N] = 0; - - datas += r; - - if (brother) { - tr = brother->buildpath(datas, size, bigendian); - r += tr; - size -= tr; - datas += tr; - } - - if (child) { - tr = child->buildpath(datas, size, bigendian); - r += tr; - size -= tr; - datas += tr; - } - - return r; -} - -int isobuilder::DirTree::buildentry(Byte * buffer, int spaceleft, bool put_xa) { - int N, R; - char pbuf[256], pad; - Byte * p; - cdutils::DirEntry * d = (cdutils::DirEntry *) buffer; - - put_xa = put_xa && have_xa; - - memset(pbuf, 0, 256); - - if (name == ".") { - N = 1; - pbuf[0] = 0; - } else if (name == "..") { - N = 1; - pbuf[0] = 1; - } else { - strcpy(pbuf, name.to_charp()); - N = name.strlen(); - if (!dir) { - N += 2; - strcat(pbuf, ";1"); - } - } - - R = N + 33; - - if (R & 1) { - R++; - pad = 1; - } else { - pad = 0; - } - - if (put_xa) { - R += 14; - p = (Byte *) pbuf + N + pad; - p[4] = 0x05; - p[5] = 0x55; - p[6] = 'X'; - p[7] = 'A'; - - p[4] |= xa_dir ? 0x80 : 0; - p[4] |= xa_audio ? 0x40 : 0; - p[4] |= xa_str ? 0x20 : 0; - p[4] |= xa_xa ? 0x10 : 0; - p[4] |= xa_form1 ? 0x08 : 0; - } - - if (R > spaceleft) { - return 0; - } - - memset(d, 0, R); - - d->R = R; - d->N = N; - memcpy(d->id, pbuf, N + pad + (put_xa ? 14 : 0)); - - d->Sector = sector; - d->BESector = cdutils::swap_dword(sector); - d->Size = size; - d->BESize = cdutils::swap_dword(size); - d->Year = creation.year - 1900; - d->Month = creation.month; - d->Day = creation.day; - d->Hour = creation.hour; - d->Minute = creation.minute; - d->Second = creation.second; - d->Offset = creation.offset; - d->Flags |= hidden ? 1 : 0; - d->Flags |= dir ? 2 : 0; - - return R; -} - -void isobuilder::DirTree::fromdir(cdutils::DirEntry * d) { - Date t; - char pbuf[200], pad; - int s; - if ((!d) || (!d->R)) { - return; - } - - if ((d->N == 1) && (d->id[0] == 0)) { - name = "."; - } else if ((d->N == 1) && (d->id[0] == 1)) { - name = ".."; - } else { - memcpy(pbuf, d->id, s = (d->N - ((d->Flags & 2) ? 0 : 2))); - pbuf[s] = 0; - name = pbuf; - } - hidden = d->Flags & 1; - if (d->Year < 70) - d->Year += 100; - t.year = d->Year; - t.month = d->Month; - t.day = d->Day; - t.hour = d->Hour; - t.second = d->Second; - t.hundredths = 0; - t.offset = d->Offset; - creation = t; - - s = 33 + d->N; - if (s & 1) { - s++; - pad = 1; - } else { - pad = 0; - } - if (s != d->R) { - if ((s + 14) == d->R) { - Byte * p; - p = (Byte *) d->id + d->N + pad; - if ((p[6] == 'X') && (p[7] == 'A')) { - have_xa = true; - xa_dir = p[4] & 0x80; - xa_audio = p[4] & 0x40; - xa_str = p[4] & 0x20; - xa_xa = p[4] & 0x10; - xa_form1 = p[4] & 0x08; - } - } - } -} - -bool isobuilder::DirTree::isdir() { - return dir; -} - -void isobuilder::DirTree::setbasicsxa() { - have_xa = true; - if (dir) - xa_dir = true; - xa_form1 = true; -} - -int isobuilder::DirTree::numerate(int n) { - if (!dir) { - if (brother) { - return brother->numerate(n); - } else { - return n; - } - } - - node = n++; - - if (brother) - n = brother->numerate(n); - - if (child) - n = child->numerate(n); - - return n; -} - -isobuilder::DirTree * isobuilder::DirTree::Father() { - return father; -} - -isobuilder::DirTree * isobuilder::DirTree::Brother() { - return brother; -} - -isobuilder::DirTree * isobuilder::DirTree::Child() { - return child; -} - -isobuilder::DirTree * isobuilder::DirTree::Find(const String & _name) { - DirTree * p = 0; - - if (name == _name) - return this; - - if (brother) - p = brother->Find(_name); - - if (!p && child) - return child->Find(_name); - - return p; -} - -isobuilder::isobuilder(Handle * _w, int _mode) : w(_w), sector(0), nsectors(0), basics(false), dmode(_mode) { - Byte sect[2352]; - memset(sect, 0, 2352); - - for (int i = 0; i < 16; i++) { - createsector(sect, MODE2, i); - } -} - -isobuilder::~isobuilder() { - if (!closed) - close(); - if (root) - delete root; -} - -void isobuilder::foreword(cdutils * cd) { - Byte sect[2352]; - for (int i = 0; i < 16; i++) { - cd->read_sector(sect, MODE_RAW, i); - createsector(sect, MODE_RAW, i); - } -} - -void isobuilder::foreword(Handle * forewords, int mode) { - Byte sect[2352]; - for (int i = 0; i < 16; i++) { - forewords->read(sect, sec_sizes[mode]); - createsector(sect, mode, i); - } -} - -void isobuilder::foreword(Byte * forewords, int mode) { - for (int i = 0; i < 16; i++) { - createsector(forewords + i * sec_sizes[mode], mode, i); - } -} - -int isobuilder::getdispsect() { - return lastdispsect; -} - -int isobuilder::putfile(Handle * file, int mode, int n) { - Byte datas[2352]; - ssize_t filesize; - int fsect; - - if (mode < 0) - mode = dmode; - - if (n >= 0) { - sector = n; - } else { - sector = lastdispsect; - } - - fsect = sector; - - filesize = file->GetSize(); - - while (filesize > 0) { - memset(datas, 0, 2352); - filesize -= file->read(datas, sec_sizes[mode]); - if ((mode == MODE2_FORM1) || (mode == MODE2_FORM2)) { - if (filesize) { - clearEOF(); - } else { - setEOF(); - } - } - createsector(datas, mode); - } - - return fsect; -} - -int isobuilder::putdatas(Byte * _datas, size_t size, int smode, int n) { - Byte datas[2352]; - size_t eating; - int dsect; - if (n >= 0) { - sector = n; - } else { - sector = lastdispsect; - } - - dsect = sector; - - if (smode < 0) - smode = dmode; - - while (size > 0) { - memset(datas, 0, 2352); - eating = MIN(size, (size_t) sec_sizes[smode]); - memcpy(datas, _datas, eating); - size -= eating; - _datas += eating; - if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) { - if (size) { - clearEOF(); - } else { - setEOF(); - } - } - createsector(datas, smode); - } - - return dsect; -} - -int isobuilder::createsector(Byte * datas, int smode, int n) { - Byte dsector[2352]; - int rsector; - if (n >= 0) - sector = n; - - if (smode < 0) - smode = dmode; - - rsector = sector; - - w->seek(2352 * sector, SEEK_SET); - - memcpy(dsector + sec_offsts[smode], datas, sec_sizes[smode]); - - if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) { - // Mode 2 Form 2 would be odd, but well.... - dsector[16] = dsector[20] = 0; // File Number - dsector[17] = dsector[21] = 0; // Channel Number - dsector[18] = dsector[22] = sub_EOR | sub_EOF | 8 | - (smode == MODE2_FORM2 ? 32 : 0); - dsector[19] = dsector[23] = 0; // Coding Info - } - - if (smode != MODE_RAW) { - sector += 150; - yazedc_o.minute = cdutils::to_BCD(sector / 60 / 75); - yazedc_o.second = cdutils::to_BCD((sector / 75) % 60); - yazedc_o.frame = cdutils::to_BCD(sector % 75); - sector -= 150; - yazedc_o.do_encode_L2(dsector, smode, 0); - } - - w->write(dsector, 2352); - - sector++; - - nsectors = MAX(nsectors, sector); - lastdispsect = MAX(lastdispsect, sector); - - return rsector; -} - -void isobuilder::setEOF() { - sub_EOF = 128; - sub_EOR = 1; -} - -void isobuilder::clearEOF() { - sub_EOF = sub_EOR = 0; -} - -isobuilder::DirTree * isobuilder::setbasics(PVD _pvd, int _rootsize, int _ptsize, int _nvd, int _rootsect) throw (GeneralException) { - if (basics) { - throw GeneralException("Basic ISO structures already set"); - } - basics = true; - - pvd = _pvd; - rootsize = _rootsize; - ptsize = _ptsize; - nvd = _nvd; - - ptsect = 17 + nvd; - rootsect = ptsect + ptsize * 4; - if (_rootsect >= 0) - rootsect = _rootsect; - lastdispsect = rootsect + rootsize; - - root = new DirTree(0); - root->name = "."; - root->creation = pvd.volcreat; - root->sector = rootsect; - root->size = rootsize * 2048; - return root; -} - -isobuilder::DirTree * isobuilder::createdir(DirTree * p, const String & _name, int size, cdutils::DirEntry * d, int mode) throw (GeneralException) { - DirTree * r; - - if (!p) - throw GeneralException("Empty father"); - - if (closed) - throw GeneralException("ISO is closed"); - - if (!basics) - throw GeneralException("ISO basis not created (no root!)"); - - r = new DirTree(p); - - r->creation = p->creation; - if (d) - r->fromdir(d); - if (_name != "") - r->name = _name; - r->size = size * 2048; - if (!r->size) - r->size = d->Size; - r->sector = lastdispsect; - if (mode >= 0) - r->mode = mode; - else - r->mode = dmode; - - lastdispsect += size; - - return r; -} - -isobuilder::DirTree * isobuilder::createfile(DirTree * p, Handle * file, const String & _name, cdutils::DirEntry * d, int mode) throw (GeneralException) { - DirTree * r; - - if (!p) - throw GeneralException("Empty father"); - - if (closed) - throw GeneralException("ISO is closed"); - - if (!basics) - throw GeneralException("ISO basis not created (no root!)"); - - r = new DirTree(p, false); - - r->name = _name; - r->creation = p->creation; - r->fromdir(d); - if (_name != "") - r->name = _name; - r->size = file->GetSize(); - r->sector = putfile(file, mode); - if (mode >= 0) - r->mode = mode; - else - r->mode = dmode; - - return r; -} - -void isobuilder::copydir(isobuilder::DirTree * r, cdutils * cd, cdutils::DirEntry * d, int mode) { - Byte datas[2048]; - cdutils::DirEntry * p; - int nsectors = d->Size / 2048, ssize, c = 0; - int fsize, osize; - - if (mode < 0) - mode = dmode; - - while (nsectors) { - cd->read_sector(datas, mode, d->Sector + c++); - nsectors--; - p = (cdutils::DirEntry *) datas; - ssize = 2048; - while ((ssize) && (p->R)) { - ssize -= p->R; - char pbuf[256]; - memcpy(pbuf, p->id, p->N); - pbuf[p->N] = 0; - if (p->Flags & 2) { - if (!((p->N == 1) && ((p->id[0] == 0) || (p->id[0] == 1)))) - copydir(createdir(r, "", p->Size / 2048, p, mode), cd, p, mode); - } else { - printm(M_INFO, "Dupping %s\n", pbuf); - int fmode; - osize = fsize = p->Size; - if (mode == MODE1) { - fmode = mode; - } else { - fmode = MODE2_FORM1; - int s, pad; - s = 33 + p->N; - if (s & 1) { - s++; - pad = 1; - } else { - pad = 0; - } - if ((s != p->R) && ((s + 14) == p->R)) { - if (!(p->id[p->N + pad + 4] & 8)) { - fmode = MODE2; - fsize = (p->Size / 2048) * 2336; - } - } - } - p->Size = fsize; - cdfile * tmp = new cdfile(cd, p, fmode); - createfile(r, tmp, "", p, fmode)->size = osize; - delete tmp; - p->Size = osize; - } - p = (cdutils::DirEntry *) (((Byte *) p) + p->R); - } - } -} - -isobuilder::PVD isobuilder::createpvd(Handle * f) { - Byte datas[2048]; - f->read(datas, 2048); - return createpvd(datas); -} - -isobuilder::PVD isobuilder::createpvd(cdutils * cd) { - Byte datas[2048]; - cd->read_sector(datas, GUESS, 16); - return createpvd(datas); -} - -isobuilder::PVD isobuilder::createpvd(Byte * buffer) { - PVD r; - char pbuff[256]; - - memcpy(pbuff, buffer + 8, 32); - pbuff[32] = 0; - r.sysid = pbuff; - r.sysid.rtrim(); - memcpy(pbuff, buffer + 40, 32); - pbuff[32] = 0; - r.volid = pbuff; - r.volid.rtrim(); - memcpy(pbuff, buffer + 190, 128); - pbuff[128] = 0; - r.volsetid = pbuff; - r.volsetid.rtrim(); - memcpy(pbuff, buffer + 318, 128); - pbuff[128] = 0; - r.pubid = pbuff; - r.pubid.rtrim(); - memcpy(pbuff, buffer + 446, 128); - pbuff[128] = 0; - r.prepid = pbuff; - r.prepid.rtrim(); - memcpy(pbuff, buffer + 574, 128); - pbuff[128] = 0; - r.appid = pbuff; - r.appid.rtrim(); - memcpy(pbuff, buffer + 702, 37); - pbuff[37] = 0; - r.copyright = pbuff; - r.copyright.rtrim(); - memcpy(pbuff, buffer + 739, 37); - pbuff[37] = 0; - r.abstract = pbuff; - r.abstract.rtrim(); - memcpy(pbuff, buffer + 776, 37); - pbuff[37] = 0; - r.biblio = pbuff; - r.biblio.rtrim(); - - r.volcreat = Date(buffer + 813); - r.modif = Date(buffer + 830); - r.volexp = Date(buffer + 847); - r.voleff = Date(buffer + 864); - - memcpy(r.appdata, buffer + 883, 512); - - return r; -} - -void isobuilder::close(Handle * cue, int mode, int nsects) throw (GeneralException) { - Byte datas[2048]; - Byte * pdatas; - char * cdatas = (char *) datas; - int psize; - - if (nsects < 0) - nsects = nsectors; - - memset(datas, 0, 2048); - - pdatas = (Byte *) malloc(ptsize * 2048); - psize = root->buildpath(pdatas, ptsize * 2048); - putdatas(pdatas, ptsize * 2048, mode, ptsect); - putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize); - root->buildpath(pdatas, ptsize * 2048, true); - putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 2); - putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 3); - free(pdatas); - - datas[0] = 1; - datas[1] = 67; - datas[2] = 68; - datas[3] = 48; - datas[4] = 48; - datas[5] = 49; - datas[6] = 1; - datas[7] = 0; - - sprintf(cdatas + 8, "%-32s", pvd.sysid.to_charp()); - sprintf(cdatas + 40, "%-32s", pvd.volid.to_charp()); - *((Uint32 *) (datas + 80)) = nsects; - *((Uint32 *) (datas + 84)) = cdutils::swap_dword(nsects); - - datas[120] = 1; - datas[121] = 0; - datas[122] = 0; - datas[123] = 1; - datas[124] = 1; - datas[125] = 0; - datas[126] = 0; - datas[127] = 1; - datas[128] = 0; - datas[129] = 8; - datas[130] = 8; - datas[131] = 0; - *((Uint32 *) (datas + 132)) = psize; - *((Uint32 *) (datas + 136)) = cdutils::swap_dword(psize); - *((Uint32 *) (datas + 140)) = ptsect; - *((Uint32 *) (datas + 144)) = ptsect + ptsize; - *((Uint32 *) (datas + 148)) = cdutils::swap_dword(ptsect + ptsize * 2); - *((Uint32 *) (datas + 152)) = cdutils::swap_dword(ptsect + ptsize * 2); - - root->buildentry(datas + 156, 34, false); - - sprintf(cdatas + 190, "%-128s", pvd.volsetid.to_charp()); - sprintf(cdatas + 318, "%-128s", pvd.pubid.to_charp()); - sprintf(cdatas + 446, "%-128s", pvd.prepid.to_charp()); - sprintf(cdatas + 574, "%-128s", pvd.appid.to_charp()); - sprintf(cdatas + 702, "%-37s", pvd.copyright.to_charp()); - sprintf(cdatas + 739, "%-37s", pvd.appid.to_charp()); - sprintf(cdatas + 776, "%-37s", pvd.biblio.to_charp()); - - pvd.volcreat.dump(datas + 813); - pvd.modif.dump(datas + 830); - pvd.volexp.dump(datas + 847); - pvd.voleff.dump(datas + 864); - - memcpy(datas + 883, pvd.appdata, 512); - - clearEOF(); - sub_EOR = 1; - createsector(datas, mode, 16); - - memset(datas, 0, 2048); - datas[0] =255; - datas[1] = 67; - datas[2] = 68; - datas[3] = 48; - datas[4] = 48; - datas[5] = 49; - datas[6] = 1; - - setEOF(); - createsector(datas, mode); - - root->dumpdirs(this); - - closed = true; -} +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2003 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: isobuilder.cpp,v 1.13 2004-10-19 01:27:29 pixel Exp $ */ + +#include "isobuilder.h" + +void isobuilder::Date::dump(Byte * datas) { + char pbuf[256]; + + sprintf(pbuf, "%04i", year); + memcpy(datas + 0, pbuf, 4); + sprintf(pbuf, "%02i", month); + memcpy(datas + 4, pbuf, 2); + sprintf(pbuf, "%02i", day); + memcpy(datas + 6, pbuf, 2); + sprintf(pbuf, "%02i", hour); + memcpy(datas + 8, pbuf, 2); + sprintf(pbuf, "%02i", minute); + memcpy(datas + 10, pbuf, 2); + sprintf(pbuf, "%02i", second); + memcpy(datas + 12, pbuf, 2); + sprintf(pbuf, "%02i", hundredths); + memcpy(datas + 14, pbuf, 2); + + *((char *) (datas + 16)) = offset; +} + +isobuilder::Date::Date(int) { + year = month = day = hour = minute = second = hundredths = offset = 0; +} + +isobuilder::Date::Date(Byte * datas) { + char pbuf[256]; + char * cdatas = (char *) datas; + + memcpy(pbuf, cdatas + 0, 4); + pbuf[4] = 0; + sscanf(pbuf, "%d", &year); + + memcpy(pbuf, cdatas + 4, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &month); + + memcpy(pbuf, cdatas + 6, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &day); + + memcpy(pbuf, cdatas + 8, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &hour); + + memcpy(pbuf, cdatas + 10, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &minute); + + memcpy(pbuf, cdatas + 12, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &second); + + memcpy(pbuf, cdatas + 14, 2); + pbuf[2] = 0; + sscanf(pbuf, "%d", &hundredths); + + offset = *(cdatas + 16); +} + +isobuilder::DirTree::DirTree(isobuilder::DirTree * _father, bool _dir) : mode(-1), father(_father), dir(_dir) { + DirTree * p; + + child = brother = 0; + + if (!father) + return; + + creation = father->creation; + + if (father->child) { + for (p = father->child; p->brother; p = p->brother); + p->brother = this; + } else { + father->child = this; + } +} + +isobuilder::DirTree::~DirTree() { + while (child) { + delete child; + } + + if (!father) + return; + + if (father->child == this) { + father->child = brother; + } else { + // Dirty, should not happen. + DirTree * p; + for (p = father->child; p->brother != this; p = p->brother); + p->brother = brother; + } +} + +void isobuilder::DirTree::dumpdirs(isobuilder * builder) throw (GeneralException) { + Byte * dir, * odir; + int cursiz, cursectsize, R; + String oldname; + DirTree * p; + + odir = dir = (Byte *) malloc(cursiz = size); + cursectsize = 2048; + + oldname = name; + name = "."; + R = buildentry(dir, cursectsize); + name = oldname; + cursectsize -= R; + dir += R; + + if (father) { + oldname = father->name; + father->name = ".."; + R = father->buildentry(dir, cursectsize); + father->name = oldname; + } else { + name = ".."; + R = buildentry(dir, cursectsize); + name = "."; + } + + cursectsize -= R; + dir += R; + + for (p = child; p; p = p->brother) { + if (p->dir) { + p->dumpdirs(builder); + } + if (p->hardhide) + continue; + while (!(R = p->buildentry(dir, cursectsize))) { + cursiz -= 2048; + dir += cursectsize; + cursectsize = 2048; + if (!cursiz) + throw GeneralException("Directory is too small! Entries don't fit."); + } + cursectsize -= R; + dir += R; + } + + builder->putdatas(odir, size, mode, sector); + + free(odir); +} + +int isobuilder::DirTree::buildpath(Byte * datas, int size, bool bigendian) throw (GeneralException) { + int N, r, tr; + Uint16 pn; + char pbuf[256], pad; + + if (!dir) { + if (brother) { + return brother->buildpath(datas, size, bigendian); + } else { + return 0; + } + } + + if (!father) { + numerate(1); + N = 1; + pbuf[0] = 0; + pn = 1; + } else { + N = name.strlen(); + strcpy(pbuf, name.to_charp()); + pn = father->node; + } + + pad = N & 1; + size -= (r = N + pad + 8); + + if (size < 0) + throw GeneralException("Path table too small."); + + datas[0] = N; + datas[1] = 0; + *((Uint32 *) (datas + 2)) = bigendian ? cdutils::swap_dword(sector) : sector; + *((Uint16 *) (datas + 6)) = bigendian ? cdutils::swap_word(pn) : pn; + memcpy(datas + 8, pbuf, N); + if (pad) + datas[8 + N] = 0; + + datas += r; + + if (brother) { + tr = brother->buildpath(datas, size, bigendian); + r += tr; + size -= tr; + datas += tr; + } + + if (child) { + tr = child->buildpath(datas, size, bigendian); + r += tr; + size -= tr; + datas += tr; + } + + return r; +} + +int isobuilder::DirTree::buildentry(Byte * buffer, int spaceleft, bool put_xa) { + int N, R; + char pbuf[256], pad; + Byte * p; + cdutils::DirEntry * d = (cdutils::DirEntry *) buffer; + + put_xa = put_xa && have_xa; + + memset(pbuf, 0, 256); + + if (name == ".") { + N = 1; + pbuf[0] = 0; + } else if (name == "..") { + N = 1; + pbuf[0] = 1; + } else { + strcpy(pbuf, name.to_charp()); + N = name.strlen(); + if (!dir) { + N += 2; + strcat(pbuf, ";1"); + } + } + + R = N + 33; + + if (R & 1) { + R++; + pad = 1; + } else { + pad = 0; + } + + if (put_xa) { + R += 14; + p = (Byte *) pbuf + N + pad; + p[4] = 0x05; + p[5] = 0x55; + p[6] = 'X'; + p[7] = 'A'; + + p[4] |= xa_dir ? 0x80 : 0; + p[4] |= xa_audio ? 0x40 : 0; + p[4] |= xa_str ? 0x20 : 0; + p[4] |= xa_xa ? 0x10 : 0; + p[4] |= xa_form1 ? 0x08 : 0; + } + + if (R > spaceleft) { + return 0; + } + + memset(d, 0, R); + + d->R = R; + d->N = N; + memcpy(d->id, pbuf, N + pad + (put_xa ? 14 : 0)); + + d->Sector = sector; + d->BESector = cdutils::swap_dword(sector); + d->Size = size; + d->BESize = cdutils::swap_dword(size); + d->Year = creation.year - 1900; + d->Month = creation.month; + d->Day = creation.day; + d->Hour = creation.hour; + d->Minute = creation.minute; + d->Second = creation.second; + d->Offset = creation.offset; + d->Flags |= hidden ? 1 : 0; + d->Flags |= dir ? 2 : 0; + + return R; +} + +void isobuilder::DirTree::fromdir(cdutils::DirEntry * d) { + Date t; + char pbuf[200], pad; + int s; + if ((!d) || (!d->R)) { + return; + } + + if ((d->N == 1) && (d->id[0] == 0)) { + name = "."; + } else if ((d->N == 1) && (d->id[0] == 1)) { + name = ".."; + } else { + memcpy(pbuf, d->id, s = (d->N - ((d->Flags & 2) ? 0 : 2))); + pbuf[s] = 0; + name = pbuf; + } + hidden = d->Flags & 1; + if (d->Year < 70) + d->Year += 100; + t.year = d->Year; + t.month = d->Month; + t.day = d->Day; + t.hour = d->Hour; + t.second = d->Second; + t.hundredths = 0; + t.offset = d->Offset; + creation = t; + + s = 33 + d->N; + if (s & 1) { + s++; + pad = 1; + } else { + pad = 0; + } + if (s != d->R) { + if ((s + 14) == d->R) { + Byte * p; + p = (Byte *) d->id + d->N + pad; + if ((p[6] == 'X') && (p[7] == 'A')) { + have_xa = true; + xa_dir = p[4] & 0x80; + xa_audio = p[4] & 0x40; + xa_str = p[4] & 0x20; + xa_xa = p[4] & 0x10; + xa_form1 = p[4] & 0x08; + } + } + } +} + +bool isobuilder::DirTree::isdir() { + return dir; +} + +void isobuilder::DirTree::setbasicsxa() { + have_xa = true; + if (dir) + xa_dir = true; + xa_form1 = true; +} + +int isobuilder::DirTree::numerate(int n) { + if (!dir) { + if (brother) { + return brother->numerate(n); + } else { + return n; + } + } + + node = n++; + + if (brother) + n = brother->numerate(n); + + if (child) + n = child->numerate(n); + + return n; +} + +isobuilder::DirTree * isobuilder::DirTree::Father() { + return father; +} + +isobuilder::DirTree * isobuilder::DirTree::Brother() { + return brother; +} + +isobuilder::DirTree * isobuilder::DirTree::Child() { + return child; +} + +isobuilder::DirTree * isobuilder::DirTree::Find(const String & _name) { + DirTree * p = 0; + + if (name == _name) + return this; + + if (brother) + p = brother->Find(_name); + + if (!p && child) + return child->Find(_name); + + return p; +} + +isobuilder::isobuilder(Handle * _w, int _mode) : w(_w), sector(0), nsectors(0), basics(false), dmode(_mode) { + Byte sect[2352]; + memset(sect, 0, 2352); + + for (int i = 0; i < 16; i++) { + createsector(sect, MODE2, i); + } +} + +isobuilder::~isobuilder() { + if (!closed) + close(); + if (root) + delete root; +} + +void isobuilder::foreword(cdutils * cd) { + Byte sect[2352]; + for (int i = 0; i < 16; i++) { + cd->read_sector(sect, MODE_RAW, i); + createsector(sect, MODE_RAW, i); + } +} + +void isobuilder::foreword(Handle * forewords, int mode) { + Byte sect[2352]; + for (int i = 0; i < 16; i++) { + forewords->read(sect, sec_sizes[mode]); + createsector(sect, mode, i); + } +} + +void isobuilder::foreword(Byte * forewords, int mode) { + for (int i = 0; i < 16; i++) { + createsector(forewords + i * sec_sizes[mode], mode, i); + } +} + +int isobuilder::getdispsect() { + return lastdispsect; +} + +int isobuilder::putfile(Handle * file, int mode, int n) { + Byte datas[2352]; + ssize_t filesize; + int fsect; + + if (mode < 0) + mode = dmode; + + if (n >= 0) { + sector = n; + } else { + sector = lastdispsect; + } + + fsect = sector; + + filesize = file->GetSize(); + + while (filesize > 0) { + memset(datas, 0, 2352); + filesize -= file->read(datas, sec_sizes[mode]); + if ((mode == MODE2_FORM1) || (mode == MODE2_FORM2)) { + if (filesize) { + clearEOF(); + } else { + setEOF(); + } + } + createsector(datas, mode); + } + + return fsect; +} + +int isobuilder::putdatas(Byte * _datas, size_t size, int smode, int n) { + Byte datas[2352]; + size_t eating; + int dsect; + if (n >= 0) { + sector = n; + } else { + sector = lastdispsect; + } + + dsect = sector; + + if (smode < 0) + smode = dmode; + + while (size > 0) { + memset(datas, 0, 2352); + eating = MIN(size, (size_t) sec_sizes[smode]); + memcpy(datas, _datas, eating); + size -= eating; + _datas += eating; + if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) { + if (size) { + clearEOF(); + } else { + setEOF(); + } + } + createsector(datas, smode); + } + + return dsect; +} + +int isobuilder::createsector(Byte * datas, int smode, int n) { + Byte dsector[2352]; + int rsector; + if (n >= 0) + sector = n; + + if (smode < 0) + smode = dmode; + + rsector = sector; + + w->seek(2352 * sector, SEEK_SET); + + memcpy(dsector + sec_offsts[smode], datas, sec_sizes[smode]); + + if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) { + // Mode 2 Form 2 would be odd, but well.... + dsector[16] = dsector[20] = 0; // File Number + dsector[17] = dsector[21] = 0; // Channel Number + dsector[18] = dsector[22] = sub_EOR | sub_EOF | 8 | + (smode == MODE2_FORM2 ? 32 : 0); + dsector[19] = dsector[23] = 0; // Coding Info + } + + if (smode != MODE_RAW) { + sector += 150; + yazedc_o.minute = cdutils::to_BCD(sector / 60 / 75); + yazedc_o.second = cdutils::to_BCD((sector / 75) % 60); + yazedc_o.frame = cdutils::to_BCD(sector % 75); + sector -= 150; + yazedc_o.do_encode_L2(dsector, smode, 0); + } + + w->write(dsector, 2352); + + sector++; + + nsectors = MAX(nsectors, sector); + lastdispsect = MAX(lastdispsect, sector); + + return rsector; +} + +void isobuilder::setEOF() { + sub_EOF = 128; + sub_EOR = 1; +} + +void isobuilder::clearEOF() { + sub_EOF = sub_EOR = 0; +} + +isobuilder::DirTree * isobuilder::setbasics(PVD _pvd, int _rootsize, int _ptsize, int _nvd, int _rootsect) throw (GeneralException) { + if (basics) { + throw GeneralException("Basic ISO structures already set"); + } + basics = true; + + pvd = _pvd; + rootsize = _rootsize; + ptsize = _ptsize; + nvd = _nvd; + + ptsect = 17 + nvd; + rootsect = ptsect + ptsize * 4; + if (_rootsect >= 0) + rootsect = _rootsect; + lastdispsect = rootsect + rootsize; + + root = new DirTree(0); + root->name = "."; + root->creation = pvd.volcreat; + root->sector = rootsect; + root->size = rootsize * 2048; + return root; +} + +isobuilder::DirTree * isobuilder::createdir(DirTree * p, const String & _name, int size, cdutils::DirEntry * d, int mode) throw (GeneralException) { + DirTree * r; + + if (!p) + throw GeneralException("Empty father"); + + if (closed) + throw GeneralException("ISO is closed"); + + if (!basics) + throw GeneralException("ISO basis not created (no root!)"); + + r = new DirTree(p); + + r->creation = p->creation; + if (d) + r->fromdir(d); + if (_name != "") + r->name = _name; + r->size = size * 2048; + if (!r->size) + r->size = d->Size; + r->sector = lastdispsect; + if (mode >= 0) + r->mode = mode; + else + r->mode = dmode; + + lastdispsect += size; + + return r; +} + +isobuilder::DirTree * isobuilder::createfile(DirTree * p, Handle * file, const String & _name, cdutils::DirEntry * d, int mode) throw (GeneralException) { + DirTree * r; + + if (!p) + throw GeneralException("Empty father"); + + if (closed) + throw GeneralException("ISO is closed"); + + if (!basics) + throw GeneralException("ISO basis not created (no root!)"); + + r = new DirTree(p, false); + + r->name = _name; + r->creation = p->creation; + r->fromdir(d); + if (_name != "") + r->name = _name; + r->size = file->GetSize(); + r->sector = putfile(file, mode); + if (mode >= 0) + r->mode = mode; + else + r->mode = dmode; + + return r; +} + +void isobuilder::copydir(isobuilder::DirTree * r, cdutils * cd, cdutils::DirEntry * d, int mode) { + Byte datas[2048]; + cdutils::DirEntry * p; + int nsectors = d->Size / 2048, ssize, c = 0; + int fsize, osize; + + if (mode < 0) + mode = dmode; + + while (nsectors) { + cd->read_sector(datas, mode, d->Sector + c++); + nsectors--; + p = (cdutils::DirEntry *) datas; + ssize = 2048; + while ((ssize) && (p->R)) { + ssize -= p->R; + char pbuf[256]; + memcpy(pbuf, p->id, p->N); + pbuf[p->N] = 0; + if (p->Flags & 2) { + if (!((p->N == 1) && ((p->id[0] == 0) || (p->id[0] == 1)))) + copydir(createdir(r, "", p->Size / 2048, p, mode), cd, p, mode); + } else { + printm(M_INFO, "Dupping %s\n", pbuf); + int fmode; + osize = fsize = p->Size; + if (mode == MODE1) { + fmode = mode; + } else { + fmode = MODE2_FORM1; + int s, pad; + s = 33 + p->N; + if (s & 1) { + s++; + pad = 1; + } else { + pad = 0; + } + if ((s != p->R) && ((s + 14) == p->R)) { + if (!(p->id[p->N + pad + 4] & 8)) { + fmode = MODE2; + fsize = (p->Size / 2048) * 2336; + } + } + } + p->Size = fsize; + cdfile * tmp = new cdfile(cd, p, fmode); + createfile(r, tmp, "", p, fmode)->size = osize; + delete tmp; + p->Size = osize; + } + p = (cdutils::DirEntry *) (((Byte *) p) + p->R); + } + } +} + +isobuilder::PVD isobuilder::createpvd(Handle * f) { + Byte datas[2048]; + f->read(datas, 2048); + return createpvd(datas); +} + +isobuilder::PVD isobuilder::createpvd(cdutils * cd) { + Byte datas[2048]; + cd->read_sector(datas, GUESS, 16); + return createpvd(datas); +} + +isobuilder::PVD isobuilder::createpvd(Byte * buffer) { + PVD r; + char pbuff[256]; + + memcpy(pbuff, buffer + 8, 32); + pbuff[32] = 0; + r.sysid = pbuff; + r.sysid.rtrim(); + memcpy(pbuff, buffer + 40, 32); + pbuff[32] = 0; + r.volid = pbuff; + r.volid.rtrim(); + memcpy(pbuff, buffer + 190, 128); + pbuff[128] = 0; + r.volsetid = pbuff; + r.volsetid.rtrim(); + memcpy(pbuff, buffer + 318, 128); + pbuff[128] = 0; + r.pubid = pbuff; + r.pubid.rtrim(); + memcpy(pbuff, buffer + 446, 128); + pbuff[128] = 0; + r.prepid = pbuff; + r.prepid.rtrim(); + memcpy(pbuff, buffer + 574, 128); + pbuff[128] = 0; + r.appid = pbuff; + r.appid.rtrim(); + memcpy(pbuff, buffer + 702, 37); + pbuff[37] = 0; + r.copyright = pbuff; + r.copyright.rtrim(); + memcpy(pbuff, buffer + 739, 37); + pbuff[37] = 0; + r.abstract = pbuff; + r.abstract.rtrim(); + memcpy(pbuff, buffer + 776, 37); + pbuff[37] = 0; + r.biblio = pbuff; + r.biblio.rtrim(); + + r.volcreat = Date(buffer + 813); + r.modif = Date(buffer + 830); + r.volexp = Date(buffer + 847); + r.voleff = Date(buffer + 864); + + memcpy(r.appdata, buffer + 883, 512); + + return r; +} + +void isobuilder::close(Handle * cue, int mode, int nsects) throw (GeneralException) { + Byte datas[2048]; + Byte * pdatas; + char * cdatas = (char *) datas; + int psize; + + if (nsects < 0) + nsects = nsectors; + + memset(datas, 0, 2048); + + pdatas = (Byte *) malloc(ptsize * 2048); + psize = root->buildpath(pdatas, ptsize * 2048); + putdatas(pdatas, ptsize * 2048, mode, ptsect); + putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize); + root->buildpath(pdatas, ptsize * 2048, true); + putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 2); + putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 3); + free(pdatas); + + datas[0] = 1; + datas[1] = 67; + datas[2] = 68; + datas[3] = 48; + datas[4] = 48; + datas[5] = 49; + datas[6] = 1; + datas[7] = 0; + + sprintf(cdatas + 8, "%-32s", pvd.sysid.to_charp()); + sprintf(cdatas + 40, "%-32s", pvd.volid.to_charp()); + *((Uint32 *) (datas + 80)) = nsects; + *((Uint32 *) (datas + 84)) = cdutils::swap_dword(nsects); + + datas[120] = 1; + datas[121] = 0; + datas[122] = 0; + datas[123] = 1; + datas[124] = 1; + datas[125] = 0; + datas[126] = 0; + datas[127] = 1; + datas[128] = 0; + datas[129] = 8; + datas[130] = 8; + datas[131] = 0; + *((Uint32 *) (datas + 132)) = psize; + *((Uint32 *) (datas + 136)) = cdutils::swap_dword(psize); + *((Uint32 *) (datas + 140)) = ptsect; + *((Uint32 *) (datas + 144)) = ptsect + ptsize; + *((Uint32 *) (datas + 148)) = cdutils::swap_dword(ptsect + ptsize * 2); + *((Uint32 *) (datas + 152)) = cdutils::swap_dword(ptsect + ptsize * 3); + + root->buildentry(datas + 156, 34, false); + + sprintf(cdatas + 190, "%-128s", pvd.volsetid.to_charp()); + sprintf(cdatas + 318, "%-128s", pvd.pubid.to_charp()); + sprintf(cdatas + 446, "%-128s", pvd.prepid.to_charp()); + sprintf(cdatas + 574, "%-128s", pvd.appid.to_charp()); + sprintf(cdatas + 702, "%-37s", pvd.copyright.to_charp()); + sprintf(cdatas + 739, "%-37s", pvd.appid.to_charp()); + sprintf(cdatas + 776, "%-37s", pvd.biblio.to_charp()); + + pvd.volcreat.dump(datas + 813); + pvd.modif.dump(datas + 830); + pvd.volexp.dump(datas + 847); + pvd.voleff.dump(datas + 864); + + memcpy(datas + 883, pvd.appdata, 512); + + clearEOF(); + sub_EOR = 1; + createsector(datas, mode, 16); + + memset(datas, 0, 2048); + datas[0] =255; + datas[1] = 67; + datas[2] = 68; + datas[3] = 48; + datas[4] = 48; + datas[5] = 49; + datas[6] = 1; + + setEOF(); + createsector(datas, mode); + + root->dumpdirs(this); + + closed = true; +} -- cgit v1.2.3