public static LoadResults LoadCCDPath(string path) { var ret = new LoadResults { CcdPath = path, ImgPath = Path.ChangeExtension(path, ".img"), SubPath = Path.ChangeExtension(path, ".sub") }; try { if (!File.Exists(path)) { throw new CCDParseException("Malformed CCD format: nonexistent CCD file!"); } CCDFile ccdf; using (var infCCD = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) ccdf = new CCD_Format().ParseFrom(infCCD); ret.ParsedCCDFile = ccdf; ret.Valid = true; } catch (CCDParseException ex) { ret.FailureException = ex; } return(ret); }
public static LoadResults LoadCCDPath(string path) { LoadResults ret = new LoadResults(); ret.CcdPath = path; ret.ImgPath = Path.ChangeExtension(path, ".img"); ret.SubPath = Path.ChangeExtension(path, ".sub"); try { if (!File.Exists(path)) { throw new CCDParseException("Malformed CCD format: nonexistent CCD file!"); } if (!File.Exists(ret.ImgPath)) { throw new CCDParseException("Malformed CCD format: nonexistent IMG file!"); } if (!File.Exists(ret.SubPath)) { throw new CCDParseException("Malformed CCD format: nonexistent SUB file!"); } //quick check of .img and .sub sizes long imgLen = new FileInfo(ret.ImgPath).Length; long subLen = new FileInfo(ret.SubPath).Length; if (imgLen % 2352 != 0) { throw new CCDParseException("Malformed CCD format: IMG file length not multiple of 2352"); } ret.NumImgSectors = (int)(imgLen / 2352); if (subLen != ret.NumImgSectors * 96) { throw new CCDParseException("Malformed CCD format: SUB file length not matching IMG"); } CCDFile ccdf; using (var infCCD = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) ccdf = new CCD_Format().ParseFrom(infCCD); ret.ParsedCCDFile = ccdf; ret.Valid = true; } catch (CCDParseException ex) { ret.FailureException = ex; } return(ret); }
public static bool HawkAndWriteFile(string inputPath, Action <string> errorCallback, DiscInterface discInterface = DiscInterface.BizHawk) { DiscMountJob job = new(inputPath, discInterface); job.Run(); var disc = job.OUT_Disc; if (job.OUT_ErrorLevel) { errorCallback(job.OUT_Log); return(false); } var baseName = Path.GetFileNameWithoutExtension(inputPath); var outfile = Path.Combine(Path.GetDirectoryName(inputPath), $"{baseName}_hawked.ccd"); CCD_Format.Dump(disc, outfile); return(true); }
void RunBizHawk() { string infile = IN_FromPath; string cue_content = null; var cfr = new CueFileResolver(); RERUN: var ext = Path.GetExtension(infile).ToLowerInvariant(); if (ext == ".iso") { //make a fake cue file to represent this iso file and rerun it as a cue string filebase = Path.GetFileName(infile); cue_content = string.Format(@" FILE ""{0}"" BINARY TRACK 01 MODE1/2048 INDEX 01 00:00:00" , filebase); infile = Path.ChangeExtension(infile, ".cue"); goto RERUN; } if (ext == ".cue") { //TODO - major renovation of error handling needed //TODO - make sure code is designed so no matter what happens, a disc is disposed in case of errors. //perhaps the CUE_Format2 (once renamed to something like Context) can handle that var cuePath = IN_FromPath; var cueContext = new CUE_Context(); cueContext.DiscMountPolicy = IN_DiscMountPolicy; cueContext.Resolver = cfr; if (!cfr.IsHardcodedResolve) { cfr.SetBaseDirectory(Path.GetDirectoryName(infile)); } //parse the cue file var parseJob = new ParseCueJob(); if (cue_content == null) { cue_content = File.ReadAllText(cuePath); } parseJob.IN_CueString = cue_content; bool okParse = true; try { parseJob.Run(parseJob); } catch (DiscJobAbortException) { okParse = false; parseJob.FinishLog(); } if (!string.IsNullOrEmpty(parseJob.OUT_Log)) { Console.WriteLine(parseJob.OUT_Log); } ConcatenateJobLog(parseJob); if (!okParse) { goto DONE; } //compile the cue file: //includes this work: resolve required bin files and find out what it's gonna take to load the cue var compileJob = new CompileCueJob(); compileJob.IN_CueContext = cueContext; compileJob.IN_CueFile = parseJob.OUT_CueFile; bool okCompile = true; try { compileJob.Run(); } catch (DiscJobAbortException) { okCompile = false; compileJob.FinishLog(); } if (!string.IsNullOrEmpty(compileJob.OUT_Log)) { Console.WriteLine(compileJob.OUT_Log); } ConcatenateJobLog(compileJob); if (!okCompile || compileJob.OUT_ErrorLevel) { goto DONE; } //check slow loading threshold if (compileJob.OUT_LoadTime > IN_SlowLoadAbortThreshold) { Warn("Loading terminated due to slow load threshold"); OUT_SlowLoadAborted = true; goto DONE; } //actually load it all up var loadJob = new LoadCueJob(); loadJob.IN_CompileJob = compileJob; loadJob.Run(); //TODO - need better handling of log output if (!string.IsNullOrEmpty(loadJob.OUT_Log)) { Console.WriteLine(loadJob.OUT_Log); } ConcatenateJobLog(loadJob); OUT_Disc = loadJob.OUT_Disc; //OUT_Disc.DiscMountPolicy = IN_DiscMountPolicy; //NOT SURE WE NEED THIS (only makes sense for cue probably) } else if (ext == ".ccd") { CCD_Format ccdLoader = new CCD_Format(); OUT_Disc = ccdLoader.LoadCCDToDisc(IN_FromPath, IN_DiscMountPolicy); } DONE: //setup the lowest level synth provider if (OUT_Disc != null) { var sssp = new ArraySectorSynthProvider() { Sectors = OUT_Disc._Sectors, FirstLBA = -150 }; OUT_Disc.SynthProvider = sssp; } }
private void RunBizHawk() { void LoadCue(string cueDirPath, string cueContent) { //TODO major renovation of error handling needed //TODO make sure code is designed so no matter what happens, a disc is disposed in case of errors. // perhaps the CUE_Format2 (once renamed to something like Context) can handle that var cfr = new CueFileResolver(); var cueContext = new CUE_Context { DiscMountPolicy = IN_DiscMountPolicy, Resolver = cfr }; if (!cfr.IsHardcodedResolve) { cfr.SetBaseDirectory(cueDirPath); } // parse the cue file var parseJob = new ParseCueJob(); parseJob.IN_CueString = cueContent; var okParse = true; try { parseJob.Run(); } catch (DiscJobAbortException) { okParse = false; parseJob.FinishLog(); } if (!string.IsNullOrEmpty(parseJob.OUT_Log)) { Console.WriteLine(parseJob.OUT_Log); } ConcatenateJobLog(parseJob); if (!okParse) { return; } // compile the cue file // includes resolving required bin files and finding out what would processing would need to happen in order to load the cue var compileJob = new CompileCueJob { IN_CueContext = cueContext, IN_CueFile = parseJob.OUT_CueFile }; var okCompile = true; try { compileJob.Run(); } catch (DiscJobAbortException) { okCompile = false; compileJob.FinishLog(); } if (!string.IsNullOrEmpty(compileJob.OUT_Log)) { Console.WriteLine(compileJob.OUT_Log); } ConcatenateJobLog(compileJob); if (!okCompile || compileJob.OUT_ErrorLevel) { return; } // check slow loading threshold if (compileJob.OUT_LoadTime > IN_SlowLoadAbortThreshold) { Warn("Loading terminated due to slow load threshold"); OUT_SlowLoadAborted = true; return; } // actually load it all up var loadJob = new LoadCueJob { IN_CompileJob = compileJob }; loadJob.Run(); //TODO need better handling of log output if (!string.IsNullOrEmpty(loadJob.OUT_Log)) { Console.WriteLine(loadJob.OUT_Log); } ConcatenateJobLog(loadJob); OUT_Disc = loadJob.OUT_Disc; // OUT_Disc.DiscMountPolicy = IN_DiscMountPolicy; // NOT SURE WE NEED THIS (only makes sense for cue probably) } switch (Path.GetExtension(IN_FromPath).ToLowerInvariant()) { case ".ccd": OUT_Disc = new CCD_Format().LoadCCDToDisc(IN_FromPath, IN_DiscMountPolicy); break; case ".cue": LoadCue(Path.GetDirectoryName(IN_FromPath), File.ReadAllText(IN_FromPath)); break; case ".iso": { // make a fake .cue file to represent this .iso and mount that //however... to save many users from a stupid mistake, check if the size is NOT a multiple of 2048 (but IS a multiple of 2352) and in that case consider it a mode2 disc //TODO - try it both ways and check the disc type to use whichever one succeeds in identifying a disc type var len = new FileInfo(IN_FromPath).Length; string mode1cue = $@" FILE ""{Path.GetFileName(IN_FromPath)}"" BINARY TRACK 01 MODE1/2048 INDEX 01 00:00:00" ; string mode2cue = $@" FILE ""{Path.GetFileName(IN_FromPath)}"" BINARY TRACK 01 MODE2/2352 INDEX 01 00:00:00" ; if (len % 2048 != 0 && len % 2352 == 0) { LoadCue(Path.GetDirectoryName(IN_FromPath), mode2cue); } else { LoadCue(Path.GetDirectoryName(IN_FromPath), mode1cue); } break; } case ".mds": OUT_Disc = new MDS_Format().LoadMDSToDisc(IN_FromPath, IN_DiscMountPolicy); break; } // set up the lowest level synth provider if (OUT_Disc != null) { OUT_Disc.SynthProvider = new ArraySectorSynthProvider { Sectors = OUT_Disc._Sectors, FirstLBA = -150 } } ; } }
public static Disc FromCCDPath(string ccdPath) { CCD_Format ccdLoader = new CCD_Format(); return(ccdLoader.LoadCCDToDisc(ccdPath)); }