diff options
-rw-r--r-- | FAQ-psx.txt | 7 | ||||
-rw-r--r-- | MSVC/PSX-Bundle - library/PSX-Bundle - library.vcproj | 12 | ||||
-rw-r--r-- | cd-tool.cpp | 54 | ||||
-rw-r--r-- | includes/cdabstract.h | 2 | ||||
-rw-r--r-- | includes/cdreader.h | 18 | ||||
-rw-r--r-- | includes/cdutils.h | 41 | ||||
-rw-r--r-- | includes/isobuilder.h | 77 | ||||
-rw-r--r-- | includes/yazedc.h | 1 | ||||
-rw-r--r-- | lib/cdabstract.cpp | 8 | ||||
-rw-r--r-- | lib/cdreader.cpp | 140 | ||||
-rw-r--r-- | lib/cdutils.cpp | 234 | ||||
-rw-r--r-- | lib/isobuilder.cpp | 781 |
12 files changed, 1325 insertions, 50 deletions
diff --git a/FAQ-psx.txt b/FAQ-psx.txt index 0bcd24f..84fbc03 100644 --- a/FAQ-psx.txt +++ b/FAQ-psx.txt @@ -150,3 +150,10 @@ A: Don't panic and press the buttons L2 and Select simoultaneously, and answer Q: Help! When I flashed my PAR with the Caetla bios, it is now black and white! A: Don't panic and press the buttons L1 and Select simoultaneously ;-) + + + + o _ _ _
+ _o /\_ _ \\o (_)\__/o (_)
+ _< \_ _>(_) (_)/<_ \_| \ _|/' \/
+ (_)>(_) (_) (_) (_) (_)' _\o_
diff --git a/MSVC/PSX-Bundle - library/PSX-Bundle - library.vcproj b/MSVC/PSX-Bundle - library/PSX-Bundle - library.vcproj index f3537ed..8e23fb4 100644 --- a/MSVC/PSX-Bundle - library/PSX-Bundle - library.vcproj +++ b/MSVC/PSX-Bundle - library/PSX-Bundle - library.vcproj @@ -118,6 +118,18 @@ RelativePath="..\..\includes\cdutils.h">
</File>
<File
+ RelativePath="..\..\lib\isobuilder.cpp">
+ </File>
+ <File
+ RelativePath="..\..\includes\isobuilder.h">
+ </File>
+ <File
+ RelativePath="..\..\lib\luacd.cpp">
+ </File>
+ <File
+ RelativePath="..\..\includes\luacd.h">
+ </File>
+ <File
RelativePath="..\..\lib\yazedc.cpp">
</File>
<File
diff --git a/cd-tool.cpp b/cd-tool.cpp index e828233..8016aa9 100644 --- a/cd-tool.cpp +++ b/cd-tool.cpp @@ -26,18 +26,22 @@ #include <string.h> #include "Input.h" #include "Output.h" +#include "Buffer.h" #include "cdreader.h" #include "cdutils.h" #include "generic.h" #include "Main.h" #include "cdabstract.h" +#include "isobuilder.h" + int lga = 0; struct option long_options[] = { {"help", 0, NULL, 'h'}, {"ppf", 1, NULL, 'p'}, {"mode", 1, NULL, 'm'}, - {"force", 1, NULL, 'f'}, + {"force", 0, NULL, 'f'}, + {"verbose", 0, NULL, 'v'}, {0, 0, NULL, 0 } }; @@ -71,6 +75,7 @@ void showhelp(void) { " extract <file> <addr> <size> - extract some sectors to <file>\n" " insert-file <file> <path> - insert the file to <path>\n" " insert <file> <addr> - insert some sectors at <addr>\n" +" copy <isofile> - copy to another iso\n" "\n", argv[0]); } @@ -96,7 +101,7 @@ virtual int startup() throw (GeneralException) { verbosity = M_WARNING; - while ((c = getopt_long(argc, argv, "Hhm:p:f", long_options, NULL)) != EOF) { + while ((c = getopt_long(argc, argv, "Hhm:p:fv", long_options, NULL)) != EOF) { switch (c) { case 'h': case 'H': @@ -112,6 +117,9 @@ virtual int startup() throw (GeneralException) { case 'f': force = 1; break; + case 'v': + verbosity = M_INFO; + break; } } @@ -140,7 +148,6 @@ virtual int startup() throw (GeneralException) { if (!cdutil->get_iso_infos()) exit(-1); - if (!strcmp(argv[optind], "infos")) { cdutil->show_iso_infos(); } else if (!strcmp(argv[optind], "path")) { @@ -167,7 +174,8 @@ virtual int startup() throw (GeneralException) { cdutil->show_head_entry(); cdutil->show_dir(&dir); } else if (!strcmp(argv[optind], "extract-file")) { - cdutils::DirEntry dir; + cdutils::DirEntry * dir; + Byte * buffer; optind++; if ((argc - 2) != optind) { @@ -178,14 +186,21 @@ virtual int startup() throw (GeneralException) { arg1 = argv[optind++]; arg2 = argv[optind++]; file = new Output(arg1); - dir = cdutil->find_path(f = strdup(arg2)); - free(f); - if (!dir.R) { + dir = cdutil->find_path(&buffer, arg2); + if (!dir) { printm(M_ERROR, "Path %s was not found on iso.\n", arg2); throw Exit(-1); } printm(M_STATUS, "Reading path %s to file %s.\n", arg2, arg1); - cdutil->read_file(file, type, dir.Sector, dir.Size); +#if 0 + cdutil->read_file(file, type, dir->Sector, dir->Size); +#else + cdfile * f = new cdfile(cdutil, dir, type); + printm(M_STATUS, f->GetName()); + copy(f, file); + delete f; +#endif + free(buffer); } else if (!strcmp(argv[optind], "extract")) { optind++; if ((argc - 3) != optind) { @@ -279,6 +294,29 @@ virtual int startup() throw (GeneralException) { file = new Input(arg1); printm(M_STATUS, "Writing file %s at sector %i.\n", arg1, sector); cdutil->write_file(file, type, sector); + } else if (!strcmp(argv[optind], "copy")) { + optind++; + if ((argc - 1) != optind) { + showhelp(); + printm(M_ERROR, "copy needs one argument.\n"); + throw Exit(-1); + } + arg1 = argv[optind]; + Output * o = new Output(arg1); + isobuilder * b = new isobuilder(o); + isobuilder::DirTree * root = b->setbasics(isobuilder::createpvd(cdutil)); + iso_r->seek(0); + b->foreword(iso_r); + b->copydir(root, ".", cdutil, cdutil->rootDir); + + Buffer * buf = new Buffer(true); + (*buf) << "Touched!\n"; + b->createfile(root, buf, "TOUCHED.TXT")->setbasicsxa(); + b->close(); + + delete o; o = 0; + delete b; b = 0; + delete buf; buf = 0; } else { showhelp(); printm(M_ERROR, "Command %s unknow.\n", argv[optind]); diff --git a/includes/cdabstract.h b/includes/cdabstract.h index 60061d4..7897bf9 100644 --- a/includes/cdabstract.h +++ b/includes/cdabstract.h @@ -31,7 +31,7 @@ class cdabstract : public Base { static Handle * open_cd(const String &); static bool canprobe(); static std::vector<String> probe() throw (GeneralException); -#if defined (_MSC_VER) || defined (__MINGW32__) +#ifdef _WIN32 protected: static HANDLE OpenIOCTLFile(char cLetter); static void GetIOCTLAdapter(HANDLE hF, int * iDA, int * iDT, int * iDL); diff --git a/includes/cdreader.h b/includes/cdreader.h index 6e952bb..4be3344 100644 --- a/includes/cdreader.h +++ b/includes/cdreader.h @@ -11,7 +11,7 @@ class cdreader : public Handle { public: cdreader(const String &) throw (GeneralException); cdreader(const cdreader &); - virtual ~cdreader() {} + virtual ~cdreader(); virtual bool CanWrite() const; virtual bool CanRead() const; virtual bool CanSeek() const; @@ -22,12 +22,24 @@ class cdreader : public Handle { virtual off_t seek(off_t, int = SEEK_SET) throw (GeneralException); virtual String GetName() const; virtual ssize_t GetSize() const; - virtual void getsector(void *, int = -1) throw (GeneralException); - virtual void sectorseek(int); + void fetchsector(void *, int = -1); + void getsector(void *, int = -1, int = 1) throw (GeneralException); + void sectorseek(int); private: + struct cachedsector { + Byte sector[2352]; + cachedsector * next, * prev; + int n; + }; String n; int sector; + cachedsector * head, * tail, * sectors[400000]; + int nsectors; + + void removetail(); + void actualize(cachedsector * s); + void introduce(Byte * datas, int n); }; #endif diff --git a/includes/cdutils.h b/includes/cdutils.h index 12746dd..cf1af4a 100644 --- a/includes/cdutils.h +++ b/includes/cdutils.h @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: cdutils.h,v 1.11 2003-11-25 01:55:45 pixel Exp $ */ +/* $Id: cdutils.h,v 1.12 2003-12-04 00:57:35 pixel Exp $ */ #ifndef __CDUTILS_H__ #define __CDUTILS_H__ @@ -71,14 +71,13 @@ class cdutils : public Base { char id[1]; } PACKED; - - struct DirEntry rootDir; + struct DirEntry * rootDir; Handle * open_ppf(String ppf, String comment) throw(GeneralException); void close_ppf() throw(GeneralException); void set_iso_w(Handle *); - unsigned short int swap_word(unsigned short int i); - unsigned long int swap_dword(unsigned long int i); + static unsigned short int swap_word(unsigned short int i); + static unsigned long int swap_dword(unsigned long int i); int guess_type(int number = -1); void sector_seek(long sector); long read_sector(Byte * buffer, int type, int number = -1); @@ -93,16 +92,18 @@ class cdutils : public Base { int show_pt_infos(); struct DirEntry find_path(String path); struct DirEntry find_parent(String path); + struct DirEntry * find_path(Byte ** buffer, String path); + struct DirEntry * find_parent(Byte ** buffer, String path); void show_head_entry(void); int show_entry(struct DirEntry * dir); int show_dir(struct DirEntry * dir); struct DirEntry find_dir_entry(struct DirEntry * dir, String name); struct DirEntry * find_dir_entry(Byte ** buffer, struct DirEntry * dir, String name); - unsigned char from_BCD(unsigned char x); - unsigned char to_BCD(unsigned char x); - bool is_valid_BCD(unsigned char x); - unsigned long from_MSF(unsigned long msf, unsigned long start = 150); - unsigned long from_MSF(unsigned char m, unsigned char s, unsigned char f, unsigned long start = 150); + static unsigned char from_BCD(unsigned char x); + static unsigned char to_BCD(unsigned char x); + static bool is_valid_BCD(unsigned char x); + static unsigned long from_MSF(unsigned long msf, unsigned long start = 150); + static unsigned long from_MSF(unsigned char m, unsigned char s, unsigned char f, unsigned long start = 150); private: void write_ppf(Byte * old_sec, Byte * new_sec, int sec_num); String format_date(String input); @@ -112,4 +113,24 @@ class cdutils : public Base { int pt1, pt2, snum, ptl, root; }; +class cdfile : public Handle { + public: + cdfile(cdutils *, const cdutils::DirEntry *, int = GUESS); + cdfile(cdutils *, int sector, ssize_t = -1, int = GUESS); + virtual ~cdfile(); + virtual ssize_t read(void *buf, size_t count) throw (GeneralException); + virtual bool CanRead() const; + virtual String GetName() const; + virtual bool CanWatch() const; + virtual ssize_t GetSize() const; + virtual bool CanSeek() const; + virtual off_t seek(off_t, int = SEEK_SET) throw (GeneralException); + private: + cdutils * cd; + int sector, mode; + size_t size; + String name; + cdutils::DirEntry * dir; +}; + #endif diff --git a/includes/isobuilder.h b/includes/isobuilder.h new file mode 100644 index 0000000..bbbe6bf --- /dev/null +++ b/includes/isobuilder.h @@ -0,0 +1,77 @@ +#ifndef __ISOBUILDER_H__
+#define __ISOBUILDER_H__
+
+#include <Handle.h>
+#include "cdutils.h"
+#include "yazedc.h" + +class isobuilder : public Base {
+ public:
+ struct Date {
+ int year, month, day, hour, minute, second, hundredths, offset;
+ void dump(Byte * datas);
+ Date(int = 0);
+ Date(Byte * datas);
+ };
+ struct PVD { + String sysid, volid; + String volsetid, pubid, prepid, appid; + String copyright, abstract, biblio; + Date volcreat, modif, volexp, voleff; + Byte appdata[512]; + };
+ class DirTree : public Base {
+ public:
+ DirTree(DirTree * father, bool dir = true);
+ virtual ~DirTree();
+ void fromdir(cdutils::DirEntry *);
+ void dumpdirs(isobuilder *) throw (GeneralException);
+ int buildpath(Byte * datas, int size, bool bigendian = false) throw (GeneralException);
+ void setbasicsxa();
+ int sector;
+ int size;
+ bool hidden;
+ String name;
+ Date creation;
+ bool have_xa, xa_dir, xa_audio, xa_str, xa_xa, xa_form1;
+ int buildentry(Byte * buffer, int spaceleft, bool put_xa = true);
+ int mode;
+ private:
+ DirTree * father, * child, * brother;
+ bool dir;
+ int node;
+ int numerate(int);
+ };
+ isobuilder(Handle * w, int mode = MODE2_FORM1);
+ ~isobuilder();
+ void foreword(Handle * forewords, int mode = MODE_RAW);
+ void foreword(Byte * forewords, int mode = MODE_RAW);
+ int getdispsect();
+ int putfile(Handle * file, int mode = -1, int n = -1);
+ void putdatas(Byte * datas, size_t size, int mode = -1, int n = -1);
+ void createsector(Byte * datas, int type = -1, int n = -1);
+ void setEOF();
+ void clearEOF();
+ DirTree * setbasics(PVD pvd, int rootsize = 1, int ptsize = 1, int nvd = 1) throw (GeneralException);
+ DirTree * createdir(DirTree *, const String & _name, int size = 1, cdutils::DirEntry * = 0, int mode = MODE2_FORM1) throw (GeneralException);
+ DirTree * createfile(DirTree *, Handle * file, const String & _name, cdutils::DirEntry * = 0, int mode = MODE2_FORM1) throw (GeneralException);
+ void copydir(DirTree *, const String & _name, cdutils *, cdutils::DirEntry *, int mode = MODE2_FORM1);
+ static PVD createpvd(Handle *);
+ static PVD createpvd(cdutils *);
+ static PVD createpvd(Byte *);
+ void close(Handle * cue = 0, int mode = -1) throw (GeneralException);
+ private:
+ Handle * w;
+ int sector, nsectors;
+ int sub_EOF, sub_EOR;
+ bool basics;
+ PVD pvd;
+ int rootsize, ptsize, nvd, ptsect, rootsect;
+ int lastdispsect;
+ DirTree * root;
+ yazedc yazedc_o;
+ bool closed;
+ int dmode;
+};
+
+#endif
diff --git a/includes/yazedc.h b/includes/yazedc.h index 298c0eb..87f026c 100644 --- a/includes/yazedc.h +++ b/includes/yazedc.h @@ -21,6 +21,7 @@ */ #ifndef __YAZEDC_H__ +#define __YAZEDC_H__ #include "Exceptions.h" diff --git a/lib/cdabstract.cpp b/lib/cdabstract.cpp index ce22fad..d7cf18e 100644 --- a/lib/cdabstract.cpp +++ b/lib/cdabstract.cpp @@ -25,7 +25,7 @@ bool cdabstract::canprobe() { #ifdef __linux__ return true; #endif -#if defined (_MSC_VER) || defined (_MINGW32) +#ifdef _WIN32 OSVERSIONINFO ov;
memset(&ov, 0, sizeof(OSVERSIONINFO));
ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -61,7 +61,7 @@ std::vector<String> cdabstract::probe() throw (GeneralException) { } #endif -#if defined (_MSC_VER) || defined (__MINGW32__) +#ifdef _WIN32 for (i = 'A'; i <= 'Z'; i++) { probed.set("%c:\\", i); if (subprobe(probed)) @@ -72,7 +72,7 @@ std::vector<String> cdabstract::probe() throw (GeneralException) { return r; } -#if defined (_MSC_VER) || defined (__MINGW32__) +#ifdef _WIN32 HANDLE cdabstract::OpenIOCTLFile(char cLetter) {
HANDLE hF;
char szFName[16];
@@ -151,7 +151,7 @@ bool cdabstract::subprobe(String & probed) { } #endif -#if defined (_MSC_VER) || defined (__MINGW32__) +#ifdef _WIN32 int iDA, iDT, iDL; char letter[4]; HANDLE h; diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp index d3d315f..5507588 100644 --- a/lib/cdreader.cpp +++ b/lib/cdreader.cpp @@ -14,6 +14,9 @@ #endif #include "cdabstract.h" +#define nsectorsarow 1 +#define cachesize 2048 + bool cdreader::CanWrite() const { return 0; } @@ -57,7 +60,7 @@ ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) { while (count > 0) { size_t n = MIN(2352 - remain, count); - getsector(sector); + fetchsector(sector); bcopy(sector + remain, buf, n); buf = ((char *) buf) + n; itell += n; @@ -72,6 +75,94 @@ void cdreader::sectorseek(int sec) { sector = sec; } +void cdreader::fetchsector(void * buf, int sec) { + if (sec >= 0) + sector = sec; + + if (sectors[sector]) { + actualize(sectors[sector]); + memcpy(buf, sectors[sector]->sector, 2352); + return; + } + + Byte buffers[2352 * nsectorsarow]; + + getsector(buffers, sec = sector, nsectorsarow); + + for (int i = nsectorsarow - 1; i >= 0; i--) { + introduce(buffers + i * 2352, sec + i); + } + + memcpy(buf, buffers, 2352); + + while (nsectors > cachesize) { + removetail(); + } +} + +cdreader::~cdreader() { + while (nsectors) { + removetail(); + } +} + +void cdreader::removetail() { + void * t = (void *) tail; + if (!tail) + return; + + sectors[tail->n] = 0; + + if (head == tail) { + free(t); + head = tail = 0; + nsectors = 0; + } else { + cachedsector * p; + (p = tail->prev)->next = 0; + free(t); + tail = p; + nsectors--; + } +} + +void cdreader::actualize(cachedsector * s) { + if (s == head) + return; + + if (s != tail) { + s->next->prev = s->prev; + } else { + tail = s->prev; + } + s->prev->next = s->next; + + head->prev = s; + s->prev = 0; + s->next = head; + head = s; +} + +void cdreader::introduce(Byte * datas, int n) { + cachedsector * s; + + s = (cachedsector *) malloc(sizeof(cachedsector)); + memcpy(s->sector, datas, 2352); + s->n = n; + + if (head) { + s->next = head; + head->prev = s; + head = s; + } else { + head = tail = s; + s->prev = s->next = 0; + } + sectors[n] = s; + + nsectors++; +} + #ifdef __linux__ #include <unistd.h> #include <sys/ioctl.h> @@ -94,24 +185,35 @@ cdreader::cdreader(const String & no) throw (GeneralException) : if (!S_ISBLK(s.st_mode)) { throw GeneralException(no + " is not a block device."); } + + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { + for (i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } -void cdreader::getsector(void *buf, int sec) throw (GeneralException) { +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { struct cdrom_msf * msf = (struct cdrom_msf *) buf; if (sec >= 0) sector = sec; sector += 150; - msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; - msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; - msf->cdmsf_frame0= sector %CD_FRAMES; - msf->cdmsf_min1 = (sector+1)/CD_SECS /CD_FRAMES; - msf->cdmsf_sec1 = ((sector+1)/CD_FRAMES)%CD_SECS; - msf->cdmsf_frame1= (sector+1)%CD_FRAMES; + msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; + msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; + msf->cdmsf_frame0= sector %CD_FRAMES; + msf->cdmsf_min1 = (sector + nb)/CD_SECS /CD_FRAMES; + msf->cdmsf_sec1 = ((sector + nb)/CD_FRAMES)%CD_SECS; + msf->cdmsf_frame1= (sector + nb)%CD_FRAMES; sector -= 150; @@ -119,7 +221,7 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno)); } - sector++; + sector += nb; } #endif @@ -128,10 +230,20 @@ cdreader::cdreader(const String & no) throw (GeneralException) : Handle(-1), n(no), sector(0) { if (!(hFile = cdabstract::OpenIOCTLFile(no[0]))) throw GeneralException("Error opening device " + no); + for (int i = 0; i < 400000; i++) { + sectors[i] = 0; + } + head = tail = 0; + nsectors = 0; } cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { - hFile = i.hFile; + hFile = i.hFile; + for (int x = 0; x < 400000; x++) { + sectors[x] = 0; + } + head = tail = 0; + nsectors = 0; } void cdreader::close() throw (GeneralException) { @@ -150,7 +262,7 @@ typedef struct _RAW_READ_INFO { TRACK_MODE_TYPE TrackMode;
} RAW_READ_INFO, *PRAW_READ_INFO; -void cdreader::getsector(void *buf, int sec) throw (GeneralException) { +void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) { RAW_READ_INFO rawIOCTL;
DWORD dwRet;
BOOL bStat;
@@ -159,14 +271,14 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { sector = sec; rawIOCTL.DiskOffset.QuadPart = sector * 2048;
- rawIOCTL.SectorCount = 1;
+ rawIOCTL.SectorCount = nb;
rawIOCTL.TrackMode = YellowMode2;
while (!done) {
SetLastError(0);
bStat = DeviceIoControl(hFile, IOCTL_CDROM_RAW_READ,
&rawIOCTL, sizeof(RAW_READ_INFO),
- buf, 2352, &dwRet, NULL);
+ buf, 2352 * nb, &dwRet, NULL);
if (!bStat) {
DWORD dwErrCode = GetLastError();
if (dwErrCode == ERROR_INVALID_FUNCTION) {
@@ -192,6 +304,8 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { done = true;
}
}
+
+ sector += nb;
} #endif diff --git a/lib/cdutils.cpp b/lib/cdutils.cpp index 413f95d..b3468e7 100644 --- a/lib/cdutils.cpp +++ b/lib/cdutils.cpp @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: cdutils.cpp,v 1.15 2003-11-25 01:55:45 pixel Exp $ */ +/* $Id: cdutils.cpp,v 1.16 2003-12-04 00:57:35 pixel Exp $ */ #include <stdio.h> #include <string.h> @@ -31,11 +31,14 @@ const long sec_sizes[7] = {0, 2048, 2336, 2048, 2324, 2352, 2352}; const long sec_offsts[7] = {0, 16, 16, 24, 24, 0, 0}; const String sec_modes[7] = {"MODE 0 (empty)", "MODE 1", "MODE 2", "MODE 2 FORM 1", "MODE 2 FORM 2", "Raw", "Autodetect"}; -cdutils::cdutils(Handle * r, Handle * w) : f_iso_r(r), f_iso_w(w), ppf_file(0), pt1(-1), pt2(-1), snum(0), ptl(0), root(0) {} +cdutils::cdutils(Handle * r, Handle * w) : rootDir(0), f_iso_r(r), f_iso_w(w), ppf_file(0), pt1(-1), pt2(-1), snum(0), ptl(0), root(0) {} cdutils::~cdutils() { if (ppf_file) delete ppf_file; + void * t = rootDir; + free(t); + rootDir = 0; } unsigned char cdutils::from_BCD(unsigned char x) { @@ -328,12 +331,13 @@ void cdutils::write_file(Handle * file, int type, int number) { } void cdutils::show_head_entry(void) { - printm(M_BARE, "Sector - Size - Date - Time - Flags - Name\n"); + printm(M_BARE, "Sector Size Date Time Flags Name XA flags\n"); } int cdutils::show_entry(struct DirEntry * dir) { - char pbuf[200]; - if (!dir->R) { + char pbuf[200], pad; + int s; + if ((!dir) || (!dir->R)) { return 1; } @@ -346,10 +350,32 @@ int cdutils::show_entry(struct DirEntry * dir) { strcpy(pbuf, ".."); } + s = 33 + dir->N; + if (s & 1) { + s++; + pad = 1; + } else { + pad = 0; + } + if (s != dir->R) { + if ((s + 14) == dir->R) { + Byte * p; + p = (Byte *) dir->id + dir->N + pad; + if ((p[6] == 'X') && (p[7] == 'A')) { + sprintf(pbuf, "%-14s %c%c%c%c%c", pbuf, + p[4] & 0x80 ? 'd' : '-', + p[4] & 0x40 ? 'a' : '-', + p[4] & 0x20 ? 's' : '-', + p[4] & 0x10 ? 'x' : '-', + p[4] & 0x08 ? 'f' : '-'); + } + } + } + if (dir->Year < 70) dir->Year += 100; - printm(M_BARE, "%6i - %8i - %2i/%02i/%04i - %2i:%02i:%02i%+03.1f - %c%c%c%c%c%c%c%c - %s\n", + printm(M_BARE, "%6i %9i %2i/%02i/%04i %2i:%02i:%02i%+03.1f %c%c%c%c%c%c%c%c %s\n", dir->Sector, dir->Size, dir->Day, dir->Month, dir->Year + 1900, dir->Hour, dir->Minute, dir->Second, ((float) dir->Offset) / 4, dir->Flags & 1 ? 'H' : '-', dir->Flags & 2 ? 'D' : '-', dir->Flags & 4 ? 'A' : '-', dir->Flags & 8 ? 'R' : '-', dir->Flags & 16 ? 'P' : '-', dir->Flags & 32 ? '1' : '-', dir->Flags & 64 ? '1' : '-', dir->Flags & 128 ? 'C' : '-', pbuf); @@ -432,9 +458,11 @@ struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutil } if (rdir->R) { + free(*bufout); *bufout = buffer; } else { free(buffer); + rdir = 0; } return rdir; } @@ -512,9 +540,10 @@ int cdutils::show_iso_infos() { } int cdutils::get_iso_infos() { - unsigned char buffer[2048]; + Byte buffer[2048]; char pbuff[130]; short int s, nogood = 0; + int rootsec; read_sector(buffer, GUESS, 16); @@ -535,7 +564,10 @@ int cdutils::get_iso_infos() { pt2 = *((short int *) &(buffer[144])); snum = *((int *) &(buffer[80])); ptl = *((long int *) &(buffer[132])); - rootDir = *((struct DirEntry *) &(buffer[156])); + rootsec = ((struct DirEntry *) (&buffer[156]))->Sector; + read_sector(buffer, GUESS, rootsec); + rootDir = (struct DirEntry *) malloc(buffer[0]); + memcpy(rootDir, buffer, buffer[0]); return 1; } @@ -615,7 +647,7 @@ struct cdutils::DirEntry cdutils::find_path(String path) { if (!**pts) pts++; - for (dir = rootDir; *pts; pts++) { + for (dir = *rootDir; *pts; pts++) { if (!strlen(*pts)) continue; dir = find_dir_entry(&dir, *pts); @@ -639,7 +671,7 @@ struct cdutils::DirEntry cdutils::find_parent(String path) { } if (!*newpath) { free(newpath); - return rootDir; + return *rootDir; } pts = split(newpath, '/'); @@ -658,7 +690,7 @@ struct cdutils::DirEntry cdutils::find_parent(String path) { if (!**pts) pts++; - for (dir = rootDir; *pts; pts++) { + for (dir = *rootDir; *pts; pts++) { if (!strlen(*pts)) continue; dir = find_dir_entry(&dir, *pts); @@ -671,3 +703,183 @@ struct cdutils::DirEntry cdutils::find_parent(String path) { free(newpath); return dir; } + +struct cdutils::DirEntry * cdutils::find_path(Byte ** bufout, String path) { + char * newpath = path.strdup(); + char ** pts = split(newpath, '/'); + struct DirEntry * dir; + + *bufout = 0; + + if ((pt1 <= 0) && (pt2 <= 0)) + if (!get_iso_infos()) { + free(newpath); + return 0; + } + + if ((!pt1) & (!pt2)) { + printm(M_ERROR, "No path table defined.\n"); + free(newpath); + return 0; + } + + if (!**pts) + pts++; + + for (dir = rootDir; *pts; pts++) { + if (!strlen(*pts)) + continue; + dir = find_dir_entry(bufout, dir, *pts); + if (!dir) { + free(newpath); + free(*bufout); + return 0; + } + } + + if (!dir) { + free(*bufout); + } + + free(newpath); + return dir; +} + +struct cdutils::DirEntry * cdutils::find_parent(Byte ** bufout, String path) { + char * newpath = path.strdup(); + char ** pts, * p; + struct DirEntry * dir; + + *bufout = 0; + + if ((p = strchr(newpath, '/'))) { + *p = 0; + } + if (!*newpath) { + free(newpath); + return rootDir; + } + pts = split(newpath, '/'); + + if ((pt1 <= 0) && (pt2 <= 0)) + if (!get_iso_infos()) { + free(newpath); + return 0; + } + + if ((!pt1) & (!pt2)) { + printm(M_ERROR, "No path table defined.\n"); + free(newpath); + return 0; + } + + if (!**pts) + pts++; + + for (dir = rootDir; *pts; pts++) { + free(*bufout); + if (!strlen(*pts)) + continue; + dir = find_dir_entry(bufout, dir, *pts); + if (!dir) { + free(newpath); + return dir; + } + } + + if (!dir) { + free(*bufout); + } + + free(newpath); + return dir; +} + +cdfile::cdfile(cdutils * _cd, const cdutils::DirEntry * d, int _mode) : Handle(-1), cd(_cd), sector(d->Sector), mode(_mode), size(d->Size), name(d->id) { + if (mode == GUESS) { + mode = cd->guess_type(sector); + } + dir = (cdutils::DirEntry *) malloc(d->R); + memcpy(dir, d, d->R); + itell = 0; +} + +cdfile::cdfile(cdutils * _cd, int _sector, ssize_t _size, int _mode) : Handle(-1), cd(_cd), sector(_sector), mode(_mode), size(_size), name("raw reading") { + if (_size == -1) { + size = 0; + } + if (mode == GUESS) { + mode = cd->guess_type(sector); + } + dir = 0; + itell = 0; +} + +cdfile::~cdfile() { + void * t = dir; + free(t); + dir = 0; +} + +ssize_t cdfile::read(void *buf, size_t count) throw (GeneralException) { + Byte buffer[2352]; + size_t startsec, nsec, startbyte, nstartbytes; + + count = MIN(count, (size_t) (size - itell)); + + if (!count) + return 0; + + startsec = itell / sec_sizes[mode] + sector; + startbyte = itell % sec_sizes[mode]; + nstartbytes = sec_sizes[mode] - startbyte; + nstartbytes = MIN(nstartbytes, count); + count -= nstartbytes; + + cd->read_sector(buffer, mode, startsec); + memcpy(buf, buffer + startbyte, nstartbytes); + buf = (Byte *) buf + nstartbytes; + + if (count) { + cd->read_datas((Byte *) buf, mode, startsec + 1, count); + } + + itell += count + nstartbytes; + + return count + nstartbytes; +} + +bool cdfile::CanRead() const { + return true; +} + +String cdfile::GetName() const { + return String("cdfile: ") + name; +} + +bool cdfile::CanWatch() const { + return false; +} + +ssize_t cdfile::GetSize() const { + return size; +} + +bool cdfile::CanSeek() const { + return true; +} + +off_t cdfile::seek(off_t off, int wheel) throw (GeneralException) { + switch (wheel) { + case SEEK_SET: + itell = off; + break; + case SEEK_CUR: + itell += off; + break; + case SEEK_END: + itell = size + off; + break; + } + return itell; +} diff --git a/lib/isobuilder.cpp b/lib/isobuilder.cpp new file mode 100644 index 0000000..469d612 --- /dev/null +++ b/lib/isobuilder.cpp @@ -0,0 +1,781 @@ +#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) : father(_father), mode(-1), 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);
+ }
+ 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;
+
+ 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; + } + } + }
+}
+
+void isobuilder::DirTree::setbasicsxa() {
+ have_xa = true;
+ if (dir)
+ xa_dir = true;
+ xa_form1 = true;
+}
+
+int isobuilder::DirTree::numerate(int n) {
+ DirTree * p;
+
+ 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::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(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];
+ size_t filesize;
+ int fsect;
+
+ 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;
+}
+
+void isobuilder::putdatas(Byte * _datas, size_t size, int smode, int n) {
+ Byte datas[2352];
+ size_t eating;
+ if (n >= 0) {
+ sector = n;
+ } else {
+ sector = lastdispsect;
+ }
+
+ 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);
+ }
+}
+
+void isobuilder::createsector(Byte * datas, int smode, int n) {
+ Byte dsector[2352];
+ if (n >= 0)
+ sector = n;
+
+ if (smode < 0)
+ smode = dmode;
+
+ 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;
+ }
+
+ 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);
+}
+
+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) 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;
+ 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->name = _name;
+ r->creation = p->creation;
+ r->fromdir(d);
+ if (_name != "")
+ r->name = _name;
+ r->size = size * 2048;
+ r->sector = lastdispsect;
+ r->mode = mode;
+
+ 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);
+ r->mode = mode;
+}
+
+void isobuilder::copydir(isobuilder::DirTree * r, const String & _name, cdutils * cd, cdutils::DirEntry * d, int mode) {
+ Byte datas[2048];
+ cdutils::DirEntry * p;
+ int nsectors = d->Size / 2048, ssize, c = 0;
+ int fsize, osize;
+
+ r->fromdir(d);
+ if (_name != "")
+ r->name = _name;
+
+ 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;
+ if (mode == MODE1) {
+ fmode = mode;
+ } else {
+ fmode = MODE2_FORM1;
+ osize = fsize = p->Size;
+ 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;
+ createfile(r, &cdfile(cd, p, fmode), "", p, fmode)->size = osize;
+ 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) throw (GeneralException) {
+ Byte datas[2048];
+ Byte * pdatas;
+ char * cdatas = (char *) datas;
+ int psize;
+
+ 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)) = nsectors;
+ *((Uint32 *) (datas + 84)) = cdutils::swap_dword(nsectors);
+
+ 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;
+}
|