#include "common.h" #include "stdclass.h" #include "oslib/storage.h" #include Disc* load_gdi(const char* file, std::vector *digest) { FILE *t = hostfs::storage().openFile(file, "rb"); if (t == nullptr) { WARN_LOG(COMMON, "Cannot open file '%s' errno %d", file, errno); throw FlycastException(std::string("Cannot open GDI file ") + file); } hostfs::FileInfo fileInfo = hostfs::storage().getFileInfo(file); size_t gdi_len = fileInfo.size; char gdi_data[8193] = { 0 }; if (gdi_len >= sizeof(gdi_data)) { std::fclose(t); throw FlycastException("GDI file too big"); } if (std::fread(gdi_data, 1, gdi_len, t) != gdi_len) WARN_LOG(GDROM, "Failed or truncated read of gdi file '%s'", file); std::fclose(t); std::istringstream gdi(gdi_data); u32 iso_tc = 0; gdi >> iso_tc; if (iso_tc == 0) throw FlycastException("GDI: empty or invalid GDI file"); INFO_LOG(GDROM, "GDI : %d tracks", iso_tc); std::string basepath = hostfs::storage().getParentPath(file); MD5Sum md5; Disc* disc = new Disc(); u32 TRACK=0,FADS=0,CTRL=0,SSIZE=0; s32 OFFSET=0; for (u32 i=0;i> TRACK; gdi >> FADS; gdi >> CTRL; gdi >> SSIZE; char last; do { gdi >> last; } while (isspace(last)); if (last == '"') { gdi >> std::noskipws; for(;;) { gdi >> last; if (last == '"') break; track_filename += last; } gdi >> std::skipws; } else { gdi >> track_filename; track_filename = last + track_filename; } gdi >> OFFSET; DEBUG_LOG(GDROM, "file[%d] \"%s\": FAD:%d, CTRL:%d, SSIZE:%d, OFFSET:%d", TRACK, track_filename.c_str(), FADS, CTRL, SSIZE, OFFSET); Track t; t.StartFAD = FADS + 150; t.CTRL = CTRL; if (SSIZE != 0) { std::string path = hostfs::storage().getSubPath(basepath, track_filename); FILE *file = hostfs::storage().openFile(path, "rb"); if (file == nullptr) { delete disc; throw FlycastException("GDI file: Cannot open track " + path); } if (digest != nullptr) md5.add(file); t.file = new RawTrackFile(file, OFFSET, t.StartFAD, SSIZE); hostfs::FileInfo fileInfo = hostfs::storage().getFileInfo(path); if ((fileInfo.size - OFFSET) % SSIZE != 0) WARN_LOG(GDROM, "Warning: Size of track %s is not multiple of sector size %d", track_filename.c_str(), SSIZE); t.EndFAD = t.StartFAD + (u32)(fileInfo.size - OFFSET) / SSIZE - 1; } disc->tracks.push_back(t); } if (disc->tracks.size() < 3) { delete disc; throw FlycastException("GDI parse error: less than 3 tracks"); } disc->FillGDSession(); if (digest != nullptr) *digest = md5.getDigest(); return disc; } Disc* gdi_parse(const char* file, std::vector *digest) { if (get_file_extension(file) != "gdi") return nullptr; return load_gdi(file, digest); }