struct IsoFile *IsoFileCloseAndDelete(struct IsoFile *file) { int i; if (file == NULL) return(NULL); if (file->handle != ACTUALHANDLENULL) { #ifdef VERBOSE_FUNCTION_ISOFILE PrintLog("CDVD isofile: IsoFileCloseAndDelete()"); #endif /* VERBOSE_FUNCTION_ISOFILE */ if (file->compress > 0) { CompressClose(file); } else { ActualFileClose(file->handle); file->handle = ACTUALHANDLENULL; } // ENDIF- Compressed File? Close (and flush) compression too. } // ENDIF- Open Handle? Close the file if (file->multi == 1) { for (i = file->multistart; i <= file->multiend; i++) { file->name[file->multipos] = '0' + i; ActualFileDelete(file->name); if (file->compress > 0) { file->tablename[file->multipos] = '0' + i; ActualFileDelete(file->tablename); } // ENDIF- Get the table file too? } // NEXT i- iterate through each multi-file name, removing it. } else { ActualFileDelete(file->name); if (file->compress > 0) { ActualFileDelete(file->tablename); } // ENDIF- Get the table file too? } // ENDIF- Do we have to remove multiple files? free(file); return(NULL); } // END IsoFileCloseAndDelete()
struct IsoFile *IsoFileClose(struct IsoFile *file) { if (file == NULL) return(NULL); if (file->handle != ACTUALHANDLENULL) { #ifdef VERBOSE_FUNCTION_ISOFILE PrintLog("CDVD isofile: IsoFileClose()"); #endif /* VERBOSE_FUNCTION_ISOFILE */ if (file->compress > 0) { CompressClose(file); } else { ActualFileClose(file->handle); file->handle = ACTUALHANDLENULL; } // ENDIF- Compressed File? Close (and flush) compression too. } // ENDIF- Open Handle? Close the file free(file); return(NULL); } // END IsoFileClose()
// External functions struct IsoFile *IsoFileOpenForRead(const char *filename) { struct IsoFile *newfile; int retval; int i; char tempblock[2448]; struct tocTN toctn; struct tocTD toctd; // union { // struct ECMA119PrimaryVolume vol; // char ch[sizeof(struct ECMA119PrimaryVolume)]; // } *volcheck; union { struct ECMA119PrimaryVolume *vol; char *ch; } volcheck; newfile = NULL; if (filename == NULL) return(NULL); #ifdef VERBOSE_FUNCTION_ISOFILE PrintLog("CDVD isofile: IsoFileOpenForRead(%s)", filename); #endif /* VERBOSE_FUNCTION_ISOFILE */ newfile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); if (newfile == NULL) return(NULL); newfile->sectorpos = 0; newfile->openforread = 1; // Read-only ISO newfile->filebytepos = 0; newfile->filesectorpos = 0; newfile->blocksize = 0; // Flags as non-detected yet (Compress vs. Image) newfile->tabledata = NULL; newfile->namepos = 0; while ((newfile->namepos < 255) && (*(filename + newfile->namepos) != 0)) { newfile->name[newfile->namepos] = *(filename + newfile->namepos); newfile->namepos++; } // ENDWHILE- copying the file name in... newfile->name[newfile->namepos] = 0; // And 0-terminate. IsoNameStripExt(newfile); // Ex: -I00.Z[.bin] // File Compression name detection newfile->compress = IsoNameStripCompress(newfile); // Ex: -I00.bin[.Z] newfile->compresspos = newfile->namepos; // Test File name compression retval = -1; if (newfile->compress > 0) { retval = CompressOpenForRead(newfile); if (retval == -1) CompressClose(newfile); } // ENDIF- Have a compression type hint? Test it out if (retval == -1) { newfile->compress = 5; while ((newfile->compress > 0) && (retval == -1)) { retval = CompressOpenForRead(newfile); if (retval == -1) { CompressClose(newfile); newfile->compress--; } // ENDIF- Failed to open? Close it... and try the next one. } // ENDWHILE- Trying to find a compression scheme that will work... if (newfile->compress == 0) { newfile->handle = ActualFileOpenForRead(newfile->name); if (newfile->handle == ACTUALHANDLENULL) { free(newfile); newfile = NULL; return(NULL); } // ENDIF- Failed to open? Abort. newfile->filebytesize = ActualFileSize(newfile->handle); } // ENDIF- No compression? Open it uncompressed. } // ENDIF- Temp- failed to open? Abort... // Compressed data file with no table? Return prematurely... // Condition detection: compress > 0, tablehandle == ACTUALHANDLENULL if (retval == -2) { #ifdef VERBOSE_FUNCTION_ISOFILE PrintLog("CDVD isofile: Data file with no table!"); #endif /* VERBOSE_FUNCTION_ISOFILE */ return(newfile); } // ENDIF- newfile->imagetype = DetectImageType(newfile); if (newfile->compress == 0) { newfile->filesectorsize = newfile->filebytesize / newfile->blocksize; } // ENDIF- Now that blocksize is known, raw file sectors can be figured out IsoNameStripExt(newfile); // Ex: -I00[.bin].Z IsoNameStripMulti(newfile); // Ex: [-I00].bin.Z #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Filename: %s", filename); if (newfile->multi > 0) PrintLog("CDVD isofile: Multiple <2GB files."); PrintLog("CDVD isofile: Compression Method: %s", compressdesc[newfile->compress]); PrintLog("CDVD isofile: Image Type: %s", newfile->imagename); PrintLog("CDVD isofile: Block Size: %lli", newfile->blocksize); PrintLog("CDVD isofile: Total Sectors (of first file): %lli", newfile->filesectorsize); #endif /* VERBOSE_DISC_INFO */ // Load a TOC from a .toc file (is there is one) retval = IsoLoadTOC(newfile); if (retval == 0) return(newfile); // Get the volume sector for disc type test retval = IsoFileSeek(newfile, 16); if (retval < 0) { newfile = IsoFileClose(newfile); return(NULL); } // ENDIF- Could not find the directory sector? Abort. retval = IsoFileRead(newfile, tempblock); if (retval < 0) { newfile = IsoFileClose(newfile); return(NULL); } // ENDIF- Could not read the directory sector? Abort. volcheck.ch = tempblock; volcheck.ch += newfile->blockoffset; if (ValidateECMA119PrimaryVolume(volcheck.vol) != 0) { #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Not an ISO9660 disc! Music CD perhaps?"); #endif /* VERBOSE_DISC_INFO */ newfile->cdvdtype = CDVD_TYPE_CDDA; } else { // Is this a playstation image? i = 0; while ((*(playstationid + i) != 0) && (*(playstationid + i) == tempblock[newfile->blockoffset + 8 + i])) i++; if (*(playstationid + i) != 0) { #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Not a Playstation Disc!"); #endif /* VERBOSE_DISC_INFO */ newfile->cdvdtype = CDVD_TYPE_DVDV; } else { newfile->cdvdtype = CDVD_TYPE_PS2DVD; } // ENDIF- Is this not a Playstation 1 image? // Sidenote: if the emulator is just playing Playstation 2 images, we could // just invalidate the image file right here. } // ENDIF- Not an ISO9660 disc? Assume Music CD. if (newfile->cdvdtype == CDVD_TYPE_PS2DVD) { // Is this a Playstation CD image? i = 0; while ((*(cdname + i) != 0) && (*(cdname + i) == tempblock[newfile->blockoffset + 1024 + i])) i++; if (*(cdname + i) == 0) { newfile->cdvdtype = CDVD_TYPE_PSCD; #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Image is a Playstation 1 CD."); #endif /* VERBOSE_DISC_INFO */ } else { if (newfile->blocksize != 2048) { newfile->cdvdtype = CDVD_TYPE_PS2CD; #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Image is a Playstation 2 CD."); #endif /* VERBOSE_DISC_INFO */ } else { #ifdef VERBOSE_DISC_INFO PrintLog("CDVD isofile: Image is a DVD."); #endif /* VERBOSE_DISC_INFO */ } // ENDIF- Is the blocksize not 2048? CD image then. } // ENDIF- Is this a PS1 CD image? } // ENDIF- Is this a Playstation image? volcheck.ch = NULL; if ((newfile->cdvdtype == CDVD_TYPE_DVDV) && (newfile->blocksize == 2352)) newfile->cdvdtype = CDVD_TYPE_CDDA; // Slap together a TOC based on the above guesswork. IsoInitTOC(newfile); if ((newfile->cdvdtype != CDVD_TYPE_PS2DVD) && (newfile->cdvdtype != CDVD_TYPE_DVDV)) { toctn.strack = 1; toctn.etrack = 1; IsoAddTNToTOC(newfile, toctn); toctd.type = 0; toctd.lsn = newfile->filesectorsize; IsoAddTDToTOC(newfile, 0xAA, toctd); toctd.type = 0; // ? if (newfile->cdvdtype == CDVD_TYPE_CDDA) { toctd.type = CDVD_AUDIO_TRACK; // Music track assumed } else { toctd.type = CDVD_MODE1_TRACK; // Data track assumed } // ENDIF- Is this track a music or data track? toctd.lsn = 0; IsoAddTDToTOC(newfile, 1, toctd); } // ENDIF- Is this a CD? Single track for all sectors return(newfile); } // END IsoFileOpenForRead()
void IsoTableRebuild(const char *filename) { struct IsoFile *datafile; struct IsoFile *tablefile; int retval; char tempblock[65536]; int stop; struct TableData table; datafile = IsoFileOpenForRead(filename); // Note: This is the start of the "Multifile" process. It's commented // out so at least we can rebuild 1 part of a multifile at a time. // IsoNameStripExt(datafile); // IsoNameStripMulti(datafile); // Prep tablefile to hold ONLY a table (no data) tablefile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); if (tablefile == NULL) { datafile = IsoFileClose(datafile); return; } // ENDIF- Failed to allocate? Abort. tablefile->sectorpos = 0; tablefile->openforread = 0; tablefile->filebytepos = 0; tablefile->filebytesize = 0; tablefile->filesectorpos = 0; tablefile->filesectorsize = 0; tablefile->handle = ACTUALHANDLENULL; tablefile->namepos = 0; while ((tablefile->namepos < 255) && (*(filename + tablefile->namepos) != 0)) { tablefile->name[tablefile->namepos] = *(filename + tablefile->namepos); tablefile->namepos++; } // ENDWHILE- Copying file name into tablefile tablefile->name[tablefile->namepos] = 0; // And 0-terminate. tablefile->imageheader = datafile->imageheader; tablefile->blocksize = datafile->blocksize; tablefile->blockoffset = datafile->blockoffset; tablefile->cdvdtype = 0; // Not important right now. tablefile->compress = datafile->compress; tablefile->compresspos = datafile->compresspos; tablefile->numsectors = datafile->numsectors; tablefile->tabledata = NULL; switch (tablefile->compress) { case 1: retval = GZipV1OpenTableForWrite(tablefile); break; case 2: retval = -1; break; case 3: retval = GZipV2OpenTableForWrite(tablefile); break; case 4: retval = BZip2V2OpenTableForWrite(tablefile); break; case 5: retval = BZip2V3OpenTableForWrite(tablefile); break; default: retval = -1; break; } // ENDSWITCH compress- Which table are we writing out? if (retval < 0) { datafile = IsoFileClose(datafile); return; } // ENDIF- Failed to open table file? Abort sprintf(tempblock, "Rebuilding table for %s", datafile->name); ProgressBoxStart(tempblock, datafile->filebytesize); stop = 0; mainbox.stop = 0; progressbox.stop = 0; while ((stop == 0) && (datafile->filebytepos < datafile->filebytesize)) { switch (datafile->compress) { case 1: retval = GZipV1Read(datafile, 0, tempblock); break; case 2: retval = -1; break; case 3: retval = GZipV2Read(datafile, 0, tempblock); break; case 4: retval = BZip2V2Read(datafile, 0, tempblock); break; case 5: retval = BZip2V3Read(datafile, 0, tempblock); break; default: retval = -1; break; } // ENDSWITCH compress- Scanning for the next complete compressed block if (retval <= 0) { #ifdef FUNCTION_WARNING_TABLEREBUILD PrintLog("CDVDiso rebuild: failed to decompress - data corrupt"); #endif /* FUNCTION_WARNING_TABLEREBUILD */ stop = 1; } else { table.offset = datafile->filebytepos - retval; table.size = retval; switch (tablefile->compress) { case 1: retval = GZipV1WriteTable(tablefile, table); break; case 2: retval = -1; break; case 3: retval = GZipV2WriteTable(tablefile, table); break; case 4: retval = BZip2V2WriteTable(tablefile, table); break; case 5: retval = BZip2V3WriteTable(tablefile, table); break; default: retval = -1; break; } // ENDSWITCH compress- Writing out the relavent table facts if (retval < 0) stop = 1; } // ENDIF- Do we have a valid record to write an entry for? ProgressBoxTick(datafile->filebytepos); // while(gtk_events_pending()) gtk_main_iteration(); if (mainbox.stop != 0) stop = 2; if (progressbox.stop != 0) stop = 2; } // ENDWHILE- Read in the data file and writing a table, 1 block at a time ProgressBoxStop(); CompressClose(tablefile); // Guarentee the table is flushed and closed. if (stop != 0) { ActualFileDelete(tablefile->tablename); } // ENDIF- Aborted or trouble? Delete the table file tablefile = IsoFileClose(tablefile); datafile = IsoFileClose(datafile); return; } // END IsoTableRebuild()