extern int IsoLoadTOC(struct IsoFile *isofile) { char tocext[] = ".toc\0"; char tocheader[5]; ACTUALHANDLE tochandle; char tocname[256]; int i; int j; int retval; unsigned char cdvdtype; struct tocTN toctn; struct tocTD toctd; if (isofile == NULL) return(-1); i = 0; while ((i < 256) && (isofile->name[i] != 0)) { tocname[i] = isofile->name[i]; i++; } // ENDWHILE- Copying the data name to the toc name j = 0; while ((i < 256) && (tocext[j] != 0)) { tocname[i] = tocext[j]; i++; j++; } // ENDWHILE- Append ".toc" to end of name tocname[i] = 0; // And 0-terminate tochandle = ActualFileOpenForRead(tocname); if (tochandle == ACTUALHANDLENULL) return(-1); retval = ActualFileRead(tochandle, 4, tocheader); if (retval < 4) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Trouble reading the 'toc' file? if ((tocheader[0] != 'T') || (tocheader[1] != 'O') || (tocheader[2] != 'C') || (tocheader[3] != '1')) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Not a 'toc' file after all? #ifdef VERBOSE_FUNCTION_TOC PrintLog("CDVDiso TOC: IsoLoadTOC(%s)", tocname); #endif /* VERBOSE_FUNCTION_TOC */ retval = ActualFileRead(tochandle, 1, (char *) & cdvdtype); if (retval < 1) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Trouble reading the 'toc' file? isofile->cdvdtype = cdvdtype; IsoInitTOC(isofile); if ((cdvdtype != CDVD_TYPE_PS2DVD) && (cdvdtype != CDVD_TYPE_DVDV)) { retval = ActualFileRead(tochandle, sizeof(struct tocTN), (char *) & toctn); if (retval < sizeof(struct tocTN)) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Trouble reading the 'toc' file? if ((toctn.strack > 99) || (toctn.etrack > 99)) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Track numbers out of range? #ifdef VERBOSE_FUNCTION_TOC PrintLog("CDVDiso TOC: Start Track %u End Track %u", toctn.strack, toctn.etrack); #endif /* VERBOSE_FUNCTION_TOC */ IsoAddTNToTOC(isofile, toctn); retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) & toctd); if (retval < sizeof(struct tocTD)) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Trouble reading the 'toc' file? if (toctd.type != 0) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Track numbers out of range? #ifdef VERBOSE_FUNCTION_TOC PrintLog("CDVDiso TOC: Total Sectors: %lu", toctd.lsn); #endif /* VERBOSE_FUNCTION_TOC */ IsoAddTDToTOC(isofile, 0xAA, toctd); for (i = toctn.strack; i <= toctn.etrack; i++) { retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) & toctd); if (retval < sizeof(struct tocTD)) { ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(-1); } // ENDIF- Trouble reading the 'toc' file? #ifdef VERBOSE_FUNCTION_TOC PrintLog("CDVDiso TOC: Track %u Type %u Sector Start: %lu", i, toctd.type, toctd.lsn); #endif /* VERBOSE_FUNCTION_TOC */ IsoAddTDToTOC(isofile, i, toctd); } // NEXT i- read in each track } // ENDIF- Not a DVD? (Then read in CD track data) ActualFileClose(tochandle); tochandle = ACTUALHANDLENULL; return(0); } // END IsoLoadTOC()
// 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()