// This function is invoked by the front-end when opening an ISO // file for playback static long CALLBACK ISOopen(void) { u32 modeTest = 0; if (cdHandle != NULL) { return 0; // it's already open } cdHandle = fopen(GetIsoFile(), "rb"); if (cdHandle == NULL) { return -1; } SysPrintf(_("Loaded CD Image: %s"), GetIsoFile()); cddaBigEndian = FALSE; subChanMixed = FALSE; subChanRaw = FALSE; isMode1ISO = FALSE; if (parseccd(GetIsoFile()) == 0) { SysPrintf("[+ccd]"); } else if (parsemds(GetIsoFile()) == 0) { SysPrintf("[+mds]"); } else if (parsecue(GetIsoFile()) == 0) { SysPrintf("[+cue]"); } else if (parsetoc(GetIsoFile()) == 0) { SysPrintf("[+toc]"); } else { //guess whether it is mode1/2048 fseek(cdHandle, 0, SEEK_END); if(ftell(cdHandle) % 2048 == 0) { fseek(cdHandle, 0, SEEK_SET); fread(&modeTest, 4, 1, cdHandle); if(SWAP32(modeTest)!=0xffffff00) isMode1ISO = TRUE; } fseek(cdHandle, 0, SEEK_SET); } if (!subChanMixed && opensubfile(GetIsoFile()) == 0) { SysPrintf("[+sub]"); } SysPrintf(".\n"); PrintTracks(); return 0; }
// this function tries to get the .cue file of the given .bin // the necessary data is put into the ti (trackinformation)-array static int parsecue(const char *isofile) { char cuename[MAXPATHLEN]; char filepath[MAXPATHLEN]; char *incue_fname; FILE *fi; char *token; char time[20]; char *tmp; char linebuf[256], tmpb[256], dummy[256]; unsigned int incue_max_len; unsigned int t, file_len, mode, sector_offs; unsigned int sector_size = 2352; numtracks = 0; // copy name of the iso and change extension from .bin to .cue strncpy(cuename, isofile, sizeof(cuename)); cuename[MAXPATHLEN - 1] = '\0'; if (strlen(cuename) >= 4) { strcpy(cuename + strlen(cuename) - 4, ".cue"); } else { return -1; } if ((fi = fopen(cuename, "r")) == NULL) { return -1; } // Some stupid tutorials wrongly tell users to use cdrdao to rip a // "bin/cue" image, which is in fact a "bin/toc" image. So let's check // that... if (fgets(linebuf, sizeof(linebuf), fi) != NULL) { if (!strncmp(linebuf, "CD_ROM_XA", 9)) { // Don't proceed further, as this is actually a .toc file rather // than a .cue file. fclose(fi); return parsetoc(isofile); } fseek(fi, 0, SEEK_SET); } // build a path for files referenced in .cue strncpy(filepath, cuename, sizeof(filepath)); tmp = strrchr(filepath, '/'); if (tmp == NULL) tmp = strrchr(filepath, '\\'); if (tmp != NULL) tmp++; else tmp = filepath; *tmp = 0; filepath[sizeof(filepath) - 1] = 0; incue_fname = tmp; incue_max_len = sizeof(filepath) - (tmp - filepath) - 1; memset(&ti, 0, sizeof(ti)); file_len = 0; sector_offs = 2 * 75; while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { strncpy(dummy, linebuf, sizeof(linebuf)); token = strtok(dummy, " "); if (token == NULL) { continue; } if (!strcmp(token, "TRACK")) { numtracks++; sector_size = 0; if (strstr(linebuf, "AUDIO") != NULL) { ti[numtracks].type = CDDA; sector_size = 2352; } else if (sscanf(linebuf, " TRACK %u MODE%u/%u", &t, &mode, §or_size) == 3) ti[numtracks].type = DATA; else { SysPrintf(".cue: failed to parse TRACK\n"); ti[numtracks].type = numtracks == 1 ? DATA : CDDA; } if (sector_size == 0) sector_size = 2352; } else if (!strcmp(token, "INDEX")) { if (sscanf(linebuf, " INDEX %02d %8s", &t, time) != 2) SysPrintf(".cue: failed to parse INDEX\n"); tok2msf(time, (char *)&ti[numtracks].start); t = msf2sec(ti[numtracks].start); ti[numtracks].start_offset = t * sector_size; t += sector_offs; sec2msf(t, ti[numtracks].start); // default track length to file length t = file_len - ti[numtracks].start_offset / sector_size; sec2msf(t, ti[numtracks].length); if (numtracks > 1 && ti[numtracks].handle == NULL) { // this track uses the same file as the last, // start of this track is last track's end t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start); sec2msf(t, ti[numtracks - 1].length); } if (numtracks > 1 && pregapOffset == -1) pregapOffset = ti[numtracks].start_offset / sector_size; } else if (!strcmp(token, "PREGAP")) { if (sscanf(linebuf, " PREGAP %8s", time) == 1) { tok2msf(time, dummy); sector_offs += msf2sec(dummy); } pregapOffset = -1; // mark to fill track start_offset } else if (!strcmp(token, "FILE")) { t = sscanf(linebuf, " FILE \"%256[^\"]\"", tmpb); if (t != 1) sscanf(linebuf, " FILE %256s", tmpb); // absolute path? ti[numtracks + 1].handle = fopen(tmpb, "rb"); if (ti[numtracks + 1].handle == NULL) { // relative to .cue? tmp = strrchr(tmpb, '\\'); if (tmp == NULL) tmp = strrchr(tmpb, '/'); if (tmp != NULL) tmp++; else tmp = tmpb; strncpy(incue_fname, tmp, incue_max_len); ti[numtracks + 1].handle = fopen(filepath, "rb"); } // update global offset if this is not first file in this .cue if (numtracks + 1 > 1) { multifile = 1; sector_offs += file_len; } file_len = 0; if (ti[numtracks + 1].handle == NULL) { SysPrintf(_("\ncould not open: %s\n"), filepath); continue; } fseek(ti[numtracks + 1].handle, 0, SEEK_END); file_len = ftell(ti[numtracks + 1].handle) / 2352; if (numtracks == 0 && strlen(isofile) >= 4 && strcmp(isofile + strlen(isofile) - 4, ".cue") == 0) { // user selected .cue as image file, use it's data track instead fclose(cdHandle); cdHandle = fopen(filepath, "rb"); } } } fclose(fi); return 0; }
// This function is invoked by the front-end when opening an ISO // file for playback static long CALLBACK ISOopen(void) { boolean isMode1ISO = FALSE; char alt_bin_filename[MAXPATHLEN]; const char *bin_filename; if (cdHandle != NULL) { return 0; // it's already open } cdHandle = fopen(GetIsoFile(), "rb"); if (cdHandle == NULL) { SysPrintf(_("Could't open '%s' for reading: %s\n"), GetIsoFile(), strerror(errno)); return -1; } SysPrintf(_("Loaded CD Image: %s"), GetIsoFile()); cddaBigEndian = FALSE; subChanMixed = FALSE; subChanRaw = FALSE; pregapOffset = 0; cdrIsoMultidiskCount = 1; multifile = 0; CDR_getBuffer = ISOgetBuffer; cdimg_read_func = cdread_normal; if (parsetoc(GetIsoFile()) == 0) { SysPrintf("[+toc]"); } else if (parseccd(GetIsoFile()) == 0) { SysPrintf("[+ccd]"); } else if (parsemds(GetIsoFile()) == 0) { SysPrintf("[+mds]"); } else if (parsecue(GetIsoFile()) == 0) { SysPrintf("[+cue]"); } if (handlepbp(GetIsoFile()) == 0) { SysPrintf("[pbp]"); CDR_getBuffer = ISOgetBuffer_compr; cdimg_read_func = cdread_compressed; } else if (handlecbin(GetIsoFile()) == 0) { SysPrintf("[cbin]"); CDR_getBuffer = ISOgetBuffer_compr; cdimg_read_func = cdread_compressed; } if (!subChanMixed && opensubfile(GetIsoFile()) == 0) { SysPrintf("[+sub]"); } if (opensbifile(GetIsoFile()) == 0) { SysPrintf("[+sbi]"); } fseek(cdHandle, 0, SEEK_END); // maybe user selected metadata file instead of main .bin .. bin_filename = GetIsoFile(); if (ftell(cdHandle) < 2352 * 0x10) { static const char *exts[] = { ".bin", ".BIN", ".img", ".IMG" }; FILE *tmpf = NULL; size_t i; char *p; strncpy(alt_bin_filename, bin_filename, sizeof(alt_bin_filename)); alt_bin_filename[MAXPATHLEN - 1] = '\0'; if (strlen(alt_bin_filename) >= 4) { p = alt_bin_filename + strlen(alt_bin_filename) - 4; for (i = 0; i < sizeof(exts) / sizeof(exts[0]); i++) { strcpy(p, exts[i]); tmpf = fopen(alt_bin_filename, "rb"); if (tmpf != NULL) break; } } if (tmpf != NULL) { bin_filename = alt_bin_filename; fclose(cdHandle); cdHandle = tmpf; fseek(cdHandle, 0, SEEK_END); } } // guess whether it is mode1/2048 if (ftell(cdHandle) % 2048 == 0) { unsigned int modeTest = 0; fseek(cdHandle, 0, SEEK_SET); fread(&modeTest, 4, 1, cdHandle); if (SWAP32(modeTest) != 0xffffff00) { SysPrintf("[2048]"); isMode1ISO = TRUE; } } fseek(cdHandle, 0, SEEK_SET); SysPrintf(".\n"); PrintTracks(); if (subChanMixed) cdimg_read_func = cdread_sub_mixed; else if (isMode1ISO) cdimg_read_func = cdread_2048; // make sure we have another handle open for cdda if (numtracks > 1 && ti[1].handle == NULL) { ti[1].handle = fopen(bin_filename, "rb"); } cdda_cur_sector = 0; cdda_file_offset = 0; return 0; }
// this function tries to get the .cue file of the given .bin // the necessary data is put into the ti (trackinformation)-array static int parsecue(const char *isofile) { char cuename[MAXPATHLEN]; FILE *fi; char *token; char time[20]; char *tmp; char linebuf[256], dummy[256]; unsigned int t; numtracks = 0; // copy name of the iso and change extension from .bin to .cue strncpy(cuename, isofile, sizeof(cuename)); cuename[MAXPATHLEN - 1] = '\0'; if (strlen(cuename) >= 4) { strcpy(cuename + strlen(cuename) - 4, ".cue"); } else { return -1; } if ((fi = fopen(cuename, "r")) == NULL) { return -1; } // Some stupid tutorials wrongly tell users to use cdrdao to rip a // "bin/cue" image, which is in fact a "bin/toc" image. So let's check // that... if (fgets(linebuf, sizeof(linebuf), fi) != NULL) { if (!strncmp(linebuf, "CD_ROM_XA", 9)) { // Don't proceed further, as this is actually a .toc file rather // than a .cue file. fclose(fi); return parsetoc(isofile); } fseek(fi, 0, SEEK_SET); } memset(&ti, 0, sizeof(ti)); while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { strncpy(dummy, linebuf, sizeof(linebuf)); token = strtok(dummy, " "); if (token == NULL) { continue; } if (!strcmp(token, "TRACK")){ numtracks++; if (strstr(linebuf, "AUDIO") != NULL) { ti[numtracks].type = CDDA; } else if (strstr(linebuf, "MODE1/2352") != NULL || strstr(linebuf, "MODE2/2352") != NULL) { ti[numtracks].type = DATA; } } else if (!strcmp(token, "INDEX")) { tmp = strstr(linebuf, "INDEX"); if (tmp != NULL) { tmp += strlen("INDEX") + 3; // 3 - space + numeric index while (*tmp == ' ') tmp++; if (*tmp != '\n') sscanf(tmp, "%8s", time); } tok2msf((char *)&time, (char *)&ti[numtracks].start); t = msf2sec(ti[numtracks].start) + 2 * 75; sec2msf(t, ti[numtracks].start); // If we've already seen another track, this is its end if (numtracks > 1) { t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start); sec2msf(t, ti[numtracks - 1].length); } } } fclose(fi); // Fill out the last track's end based on size if (numtracks >= 1) { fseek(cdHandle, 0, SEEK_END); t = ftell(cdHandle) / 2352 - msf2sec(ti[numtracks].start) + 2 * 75; sec2msf(t, ti[numtracks].length); } return 0; }
// This function is invoked by the front-end when opening an ISO // file for playback static long ISOopen(void) { boolean isMode1ISO = FALSE; if (cdHandle != NULL) { return 0; // it's already open } cdHandle = fopen(GetIsoFile(), "rb"); if (cdHandle == NULL) { return -1; } SysPrintf("Loaded CD Image: %s", GetIsoFile()); cddaBigEndian = FALSE; subChanMixed = FALSE; subChanRaw = FALSE; pregapOffset = 0; CDR_getBuffer = ISOgetBuffer; cdimg_read_func = cdread_normal; if (parsecue(GetIsoFile()) == 0) { SysPrintf("[+cue]"); } else if (parsetoc(GetIsoFile()) == 0) { SysPrintf("[+toc]"); } else if (parseccd(GetIsoFile()) == 0) { SysPrintf("[+ccd]"); } else if (parsemds(GetIsoFile()) == 0) { SysPrintf("[+mds]"); } else if (parsepbp(GetIsoFile()) == 0) { SysPrintf("[pbp]"); CDR_getBuffer = ISOgetBuffer_compr; cdimg_read_func = cdread_compressed; } if (!subChanMixed && opensubfile(GetIsoFile()) == 0) { SysPrintf("[+sub]"); } if (opensbifile(GetIsoFile()) == 0) { SysPrintf("[+sbi]"); } // guess whether it is mode1/2048 fseek(cdHandle, 0, SEEK_END); if (ftell(cdHandle) % 2048 == 0) { unsigned int modeTest = 0; fseek(cdHandle, 0, SEEK_SET); fread(&modeTest, 4, 1, cdHandle); if (SWAP32(modeTest) != 0xffffff00) { SysPrintf("[2048]"); isMode1ISO = TRUE; } } fseek(cdHandle, 0, SEEK_SET); SysPrintf(".\n"); PrintTracks(); if (subChanMixed) cdimg_read_func = cdread_sub_mixed; else if (isMode1ISO) cdimg_read_func = cdread_2048; // make sure we have another handle open for cdda if (numtracks > 1 && ti[1].handle == NULL) { ti[1].handle = fopen(GetIsoFile(), "rb"); } cdda_cur_sector = cdda_start_sector = 0; return 0; }