void LoadFromString(ParseCueJob job) { string cueString = job.IN_CueString; TextReader tr = new StringReader(cueString); for (; ; ) { job.CurrentLine++; string line = tr.ReadLine(); if (line == null) break; line = line.Trim(); if (line == "") continue; var clp = new CueLineParser(line); string key = clp.ReadToken().ToUpperInvariant(); if (key.StartsWith(";")) { clp.EOF = true; OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = line }); } else switch (key) { default: job.Warn("Unknown command: " + key); break; case "CATALOG": if (OUT_CueFile.GlobalDiscInfo.Catalog != null) job.Warn("Multiple CATALOG commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CATALOG command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.Catalog = new CUE_File.Command.CATALOG() { Value = clp.ReadToken() }); break; case "CDTEXTFILE": if (OUT_CueFile.GlobalDiscInfo.CDTextFile != null) job.Warn("Multiple CDTEXTFILE commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CDTEXTFILE command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.CDTextFile = new CUE_File.Command.CDTEXTFILE() { Path = clp.ReadPath() }); break; case "FILE": { var path = clp.ReadPath(); CueFileType ft; if (clp.EOF) { job.Error("FILE command is missing file type."); ft = CueFileType.Unspecified; } else { var strType = clp.ReadToken().ToUpperInvariant(); switch (strType) { default: job.Error("Unknown FILE type: " + strType); ft = CueFileType.Unspecified; break; case "BINARY": ft = CueFileType.BINARY; break; case "MOTOROLA": ft = CueFileType.MOTOROLA; break; case "BINARAIFF": ft = CueFileType.AIFF; break; case "WAVE": ft = CueFileType.WAVE; break; case "MP3": ft = CueFileType.MP3; break; } } OUT_CueFile.Commands.Add(new CUE_File.Command.FILE() { Path = path, Type = ft }); } break; case "FLAGS": { var cmd = new CUE_File.Command.FLAGS(); OUT_CueFile.Commands.Add(cmd); while (!clp.EOF) { var flag = clp.ReadToken().ToUpperInvariant(); switch (flag) { case "DATA": default: job.Warn("Unknown FLAG: " + flag); break; case "DCP": cmd.Flags |= CueTrackFlags.DCP; break; case "4CH": cmd.Flags |= CueTrackFlags._4CH; break; case "PRE": cmd.Flags |= CueTrackFlags.PRE; break; case "SCMS": cmd.Flags |= CueTrackFlags.SCMS; break; } } if (cmd.Flags == CueTrackFlags.None) job.Warn("Empty FLAG command"); } break; case "INDEX": { if (clp.EOF) { job.Error("Incomplete INDEX command"); break; } string strindexnum = clp.ReadToken(); int indexnum; if (!int.TryParse(strindexnum, out indexnum) || indexnum < 0 || indexnum > 99) { job.Error("Invalid INDEX number: " + strindexnum); break; } string str_timestamp = clp.ReadToken(); var ts = new Timestamp(str_timestamp); if (!ts.Valid) { job.Error("Invalid INDEX timestamp: " + str_timestamp); break; } OUT_CueFile.Commands.Add(new CUE_File.Command.INDEX() { Number = indexnum, Timestamp = ts }); } break; case "ISRC": if (OUT_CueFile.GlobalDiscInfo.ISRC != null) job.Warn("Multiple ISRC commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty ISRC command"); else { var isrc = clp.ReadToken(); if (isrc.Length != 12) job.Warn("Invalid ISRC code ignored: " + isrc); else { OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.ISRC = new CUE_File.Command.ISRC() { Value = isrc }); } } break; case "PERFORMER": OUT_CueFile.Commands.Add(new CUE_File.Command.PERFORMER() { Value = clp.ReadPath() ?? "" }); break; case "POSTGAP": case "PREGAP": { var str_msf = clp.ReadToken(); var msf = new Timestamp(str_msf); if (!msf.Valid) job.Error("Ignoring {0} with invalid length MSF: " + str_msf, key); else { if (key == "POSTGAP") OUT_CueFile.Commands.Add(new CUE_File.Command.POSTGAP() { Length = msf }); else OUT_CueFile.Commands.Add(new CUE_File.Command.PREGAP() { Length = msf }); } } break; case "REM": OUT_CueFile.Commands.Add(new CUE_File.Command.REM() { Value = clp.ReadLine() }); break; case "SONGWRITER": OUT_CueFile.Commands.Add(new CUE_File.Command.SONGWRITER() { Value = clp.ReadPath() ?? "" }); break; case "TITLE": OUT_CueFile.Commands.Add(new CUE_File.Command.TITLE() { Value = clp.ReadPath() ?? "" }); break; case "TRACK": { if (clp.EOF) { job.Error("Incomplete TRACK command"); break; } string str_tracknum = clp.ReadToken(); int tracknum; if (!int.TryParse(str_tracknum, out tracknum) || tracknum < 1 || tracknum > 99) { job.Error("Invalid TRACK number: " + str_tracknum); break; } //TODO - check sequentiality? maybe as a warning CueTrackType tt; var str_trackType = clp.ReadToken(); switch (str_trackType.ToUpperInvariant()) { default: job.Error("Unknown TRACK type: " + str_trackType); tt = CueTrackType.Unknown; break; case "AUDIO": tt = CueTrackType.Audio; break; case "CDG": tt = CueTrackType.CDG; break; case "MODE1/2048": tt = CueTrackType.Mode1_2048; break; case "MODE1/2352": tt = CueTrackType.Mode1_2352; break; case "MODE2/2336": tt = CueTrackType.Mode2_2336; break; case "MODE2/2352": tt = CueTrackType.Mode2_2352; break; case "CDI/2336": tt = CueTrackType.CDI_2336; break; case "CDI/2352": tt = CueTrackType.CDI_2352; break; } OUT_CueFile.Commands.Add(new CUE_File.Command.TRACK() { Number = tracknum, Type = tt }); } break; } if (!clp.EOF) { var remainder = clp.ReadLine(); if (remainder.TrimStart().StartsWith(";")) { //add a comment OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = remainder }); } else job.Warn("Unknown text at end of line after processing command: " + key); } } //end cue parsing loop job.FinishLog(); } //LoadFromString
} //LoadFromString public void Run(ParseCueJob job) { job.OUT_CueFile = new CUE_File(); job.LoadFromString(job); }
void LoadFromString(ParseCueJob job) { string cueString = job.IN_CueString; TextReader tr = new StringReader(cueString); for (; ; ) { job.CurrentLine++; string line = tr.ReadLine(); if (line == null) break; line = line.Trim(); if (line == "") continue; var clp = new CueLineParser(line); string key = clp.ReadToken().ToUpperInvariant(); //remove nonsense at beginning if (!IN_Strict) { while (key.Length > 0) { char c = key[0]; if(c == ';') break; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) break; key = key.Substring(1); } } bool startsWithSemicolon = key.StartsWith(";"); if (startsWithSemicolon) { clp.EOF = true; OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = line }); } else switch (key) { default: job.Warn("Unknown command: " + key); break; case "CATALOG": if (OUT_CueFile.GlobalDiscInfo.Catalog != null) job.Warn("Multiple CATALOG commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CATALOG command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.Catalog = new CUE_File.Command.CATALOG() { Value = clp.ReadToken() }); break; case "CDTEXTFILE": if (OUT_CueFile.GlobalDiscInfo.CDTextFile != null) job.Warn("Multiple CDTEXTFILE commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CDTEXTFILE command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.CDTextFile = new CUE_File.Command.CDTEXTFILE() { Path = clp.ReadPath() }); break; case "FILE": { var path = clp.ReadPath(); CueFileType ft; if (clp.EOF) { job.Error("FILE command is missing file type."); ft = CueFileType.Unspecified; } else { var strType = clp.ReadToken().ToUpperInvariant(); switch (strType) { default: job.Error("Unknown FILE type: " + strType); ft = CueFileType.Unspecified; break; case "BINARY": ft = CueFileType.BINARY; break; case "MOTOROLA": ft = CueFileType.MOTOROLA; break; case "BINARAIFF": ft = CueFileType.AIFF; break; case "WAVE": ft = CueFileType.WAVE; break; case "MP3": ft = CueFileType.MP3; break; } } OUT_CueFile.Commands.Add(new CUE_File.Command.FILE() { Path = path, Type = ft }); } break; case "FLAGS": { var cmd = new CUE_File.Command.FLAGS(); OUT_CueFile.Commands.Add(cmd); while (!clp.EOF) { var flag = clp.ReadToken().ToUpperInvariant(); switch (flag) { case "DATA": default: job.Warn("Unknown FLAG: " + flag); break; case "DCP": cmd.Flags |= CueTrackFlags.DCP; break; case "4CH": cmd.Flags |= CueTrackFlags._4CH; break; case "PRE": cmd.Flags |= CueTrackFlags.PRE; break; case "SCMS": cmd.Flags |= CueTrackFlags.SCMS; break; } } if (cmd.Flags == CueTrackFlags.None) job.Warn("Empty FLAG command"); } break; case "INDEX": { if (clp.EOF) { job.Error("Incomplete INDEX command"); break; } string strindexnum = clp.ReadToken(); int indexnum; if (!int.TryParse(strindexnum, out indexnum) || indexnum < 0 || indexnum > 99) { job.Error("Invalid INDEX number: " + strindexnum); break; } string str_timestamp = clp.ReadToken(); var ts = new Timestamp(str_timestamp); if (!ts.Valid && !IN_Strict) { //try cleaning it up str_timestamp = Regex.Replace(str_timestamp, "[^0-9:]", ""); ts = new Timestamp(str_timestamp); } if (!ts.Valid) { if (IN_Strict) job.Error("Invalid INDEX timestamp: " + str_timestamp); break; } OUT_CueFile.Commands.Add(new CUE_File.Command.INDEX() { Number = indexnum, Timestamp = ts }); } break; case "ISRC": if (OUT_CueFile.GlobalDiscInfo.ISRC != null) job.Warn("Multiple ISRC commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty ISRC command"); else { var isrc = clp.ReadToken(); if (isrc.Length != 12) job.Warn("Invalid ISRC code ignored: " + isrc); else { OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.ISRC = new CUE_File.Command.ISRC() { Value = isrc }); } } break; case "PERFORMER": OUT_CueFile.Commands.Add(new CUE_File.Command.PERFORMER() { Value = clp.ReadPath() ?? "" }); break; case "POSTGAP": case "PREGAP": { var str_msf = clp.ReadToken(); var msf = new Timestamp(str_msf); if (!msf.Valid) job.Error("Ignoring {0} with invalid length MSF: " + str_msf, key); else { if (key == "POSTGAP") OUT_CueFile.Commands.Add(new CUE_File.Command.POSTGAP() { Length = msf }); else OUT_CueFile.Commands.Add(new CUE_File.Command.PREGAP() { Length = msf }); } } break; case "REM": OUT_CueFile.Commands.Add(new CUE_File.Command.REM() { Value = clp.ReadLine() }); break; case "SONGWRITER": OUT_CueFile.Commands.Add(new CUE_File.Command.SONGWRITER() { Value = clp.ReadPath() ?? "" }); break; case "TITLE": OUT_CueFile.Commands.Add(new CUE_File.Command.TITLE() { Value = clp.ReadPath() ?? "" }); break; case "TRACK": { if (clp.EOF) { job.Error("Incomplete TRACK command"); break; } string str_tracknum = clp.ReadToken(); int tracknum; if (!int.TryParse(str_tracknum, out tracknum) || tracknum < 1 || tracknum > 99) { job.Error("Invalid TRACK number: " + str_tracknum); break; } //TODO - check sequentiality? maybe as a warning CueTrackType tt; var str_trackType = clp.ReadToken(); switch (str_trackType.ToUpperInvariant()) { default: job.Error("Unknown TRACK type: " + str_trackType); tt = CueTrackType.Unknown; break; case "AUDIO": tt = CueTrackType.Audio; break; case "CDG": tt = CueTrackType.CDG; break; case "MODE1/2048": tt = CueTrackType.Mode1_2048; break; case "MODE1/2352": tt = CueTrackType.Mode1_2352; break; case "MODE2/2336": tt = CueTrackType.Mode2_2336; break; case "MODE2/2352": tt = CueTrackType.Mode2_2352; break; case "CDI/2336": tt = CueTrackType.CDI_2336; break; case "CDI/2352": tt = CueTrackType.CDI_2352; break; } OUT_CueFile.Commands.Add(new CUE_File.Command.TRACK() { Number = tracknum, Type = tt }); } break; } if (!clp.EOF) { var remainder = clp.ReadLine(); if (remainder.TrimStart().StartsWith(";")) { //add a comment OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = remainder }); } else job.Warn("Unknown text at end of line after processing command: " + key); } } //end cue parsing loop job.FinishLog(); } //LoadFromString
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 - 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; parseJob.Run(parseJob); //TODO - need better handling of log output if (!string.IsNullOrEmpty(parseJob.OUT_Log)) Console.WriteLine(parseJob.OUT_Log); ConcatenateJobLog(parseJob); //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; compileJob.Run(); //TODO - need better handling of log output if (!string.IsNullOrEmpty(compileJob.OUT_Log)) Console.WriteLine(compileJob.OUT_Log); ConcatenateJobLog(compileJob); //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) //apply SBI if it exists (TODO - for formats other than cue?) var sbiPath = Path.ChangeExtension(IN_FromPath, ".sbi"); if (File.Exists(sbiPath) && SBI.SBIFormat.QuickCheckISSBI(sbiPath)) { var loadSbiJob = new SBI.LoadSBIJob() { IN_Path = sbiPath }; loadSbiJob.Run(); var applySbiJob = new ApplySBIJob(); applySbiJob.Run(OUT_Disc, loadSbiJob.OUT_Data, IN_DiscMountPolicy.SBI_As_Mednafen); } } else if (ext == ".ccd") { CCD_Format ccdLoader = new CCD_Format(); OUT_Disc = ccdLoader.LoadCCDToDisc(IN_FromPath, IN_DiscMountPolicy); } DONE: ; }
private void LoadFromString(ParseCueJob job) { string cueString = job.IN_CueString; TextReader tr = new StringReader(cueString); for (; ; ) { job.CurrentLine++; string line = tr.ReadLine(); if (line == null) break; line = line.Trim(); if (line == "") continue; var clp = new CueLineParser(line); string key = clp.ReadToken().ToUpperInvariant(); //remove nonsense at beginning if (!IN_Strict) { while (key.Length > 0) { char c = key[0]; if(c == ';') break; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) break; key = key.Substring(1); } } bool startsWithSemicolon = key.StartsWith(";"); if (startsWithSemicolon) { clp.EOF = true; OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT(line)); } else switch (key) { default: job.Warn($"Unknown command: {key}"); break; case "CATALOG": if (OUT_CueFile.GlobalDiscInfo.Catalog != null) job.Warn("Multiple CATALOG commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CATALOG command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.Catalog = new CUE_File.Command.CATALOG(clp.ReadToken())); break; case "CDTEXTFILE": if (OUT_CueFile.GlobalDiscInfo.CDTextFile != null) job.Warn("Multiple CDTEXTFILE commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty CDTEXTFILE command"); else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.CDTextFile = new CUE_File.Command.CDTEXTFILE(clp.ReadPath())); break; case "FILE": { var path = clp.ReadPath(); CueFileType ft; if (clp.EOF) { job.Error("FILE command is missing file type."); ft = CueFileType.Unspecified; } else { var strType = clp.ReadToken().ToUpperInvariant(); switch (strType) { default: job.Error($"Unknown FILE type: {strType}"); ft = CueFileType.Unspecified; break; case "BINARY": ft = CueFileType.BINARY; break; case "MOTOROLA": ft = CueFileType.MOTOROLA; break; case "BINARAIFF": ft = CueFileType.AIFF; break; case "WAVE": ft = CueFileType.WAVE; break; case "MP3": ft = CueFileType.MP3; break; } } OUT_CueFile.Commands.Add(new CUE_File.Command.FILE(path, ft)); } break; case "FLAGS": { CueTrackFlags flags = default; while (!clp.EOF) { var flag = clp.ReadToken().ToUpperInvariant(); switch (flag) { case "DATA": default: job.Warn($"Unknown FLAG: {flag}"); break; case "DCP": flags |= CueTrackFlags.DCP; break; case "4CH": flags |= CueTrackFlags._4CH; break; case "PRE": flags |= CueTrackFlags.PRE; break; case "SCMS": flags |= CueTrackFlags.SCMS; break; } } if (flags == CueTrackFlags.None) job.Warn("Empty FLAG command"); OUT_CueFile.Commands.Add(new CUE_File.Command.FLAGS(flags)); } break; case "INDEX": { if (clp.EOF) { job.Error("Incomplete INDEX command"); break; } string strindexnum = clp.ReadToken(); if (!int.TryParse(strindexnum, out var indexnum) || indexnum < 0 || indexnum > 99) { job.Error($"Invalid INDEX number: {strindexnum}"); break; } string str_timestamp = clp.ReadToken(); var ts = new Timestamp(str_timestamp); if (!ts.Valid && !IN_Strict) { //try cleaning it up str_timestamp = Regex.Replace(str_timestamp, "[^0-9:]", ""); ts = new Timestamp(str_timestamp); } if (!ts.Valid) { if (IN_Strict) job.Error($"Invalid INDEX timestamp: {str_timestamp}"); break; } OUT_CueFile.Commands.Add(new CUE_File.Command.INDEX(indexnum, ts)); } break; case "ISRC": if (OUT_CueFile.GlobalDiscInfo.ISRC != null) job.Warn("Multiple ISRC commands detected. Subsequent ones are ignored."); else if (clp.EOF) job.Warn("Ignoring empty ISRC command"); else { var isrc = clp.ReadToken(); if (isrc.Length != 12) job.Warn($"Invalid ISRC code ignored: {isrc}"); else { OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.ISRC = new CUE_File.Command.ISRC(isrc)); } } break; case "PERFORMER": OUT_CueFile.Commands.Add(new CUE_File.Command.PERFORMER(clp.ReadPath() ?? "")); break; case "POSTGAP": case "PREGAP": { var str_msf = clp.ReadToken(); var msf = new Timestamp(str_msf); if (!msf.Valid) job.Error($"Ignoring {{0}} with invalid length MSF: {str_msf}", key); else { if (key == "POSTGAP") OUT_CueFile.Commands.Add(new CUE_File.Command.POSTGAP(msf)); else OUT_CueFile.Commands.Add(new CUE_File.Command.PREGAP(msf)); } } break; case "REM": OUT_CueFile.Commands.Add(new CUE_File.Command.REM(clp.ReadLine())); break; case "SONGWRITER": OUT_CueFile.Commands.Add(new CUE_File.Command.SONGWRITER(clp.ReadPath() ?? "")); break; case "TITLE": OUT_CueFile.Commands.Add(new CUE_File.Command.TITLE(clp.ReadPath() ?? "")); break; case "TRACK": { if (clp.EOF) { job.Error("Incomplete TRACK command"); break; } string str_tracknum = clp.ReadToken(); if (!int.TryParse(str_tracknum, out int tracknum) || tracknum < 1 || tracknum > 99) { job.Error($"Invalid TRACK number: {str_tracknum}"); break; } // TODO - check sequentiality? maybe as a warning CueTrackType tt; var str_trackType = clp.ReadToken(); switch (str_trackType.ToUpperInvariant()) { default: job.Error($"Unknown TRACK type: {str_trackType}"); tt = CueTrackType.Unknown; break; case "AUDIO": tt = CueTrackType.Audio; break; case "CDG": tt = CueTrackType.CDG; break; case "MODE1/2048": tt = CueTrackType.Mode1_2048; break; case "MODE1/2352": tt = CueTrackType.Mode1_2352; break; case "MODE2/2336": tt = CueTrackType.Mode2_2336; break; case "MODE2/2352": tt = CueTrackType.Mode2_2352; break; case "CDI/2336": tt = CueTrackType.CDI_2336; break; case "CDI/2352": tt = CueTrackType.CDI_2352; break; } OUT_CueFile.Commands.Add(new CUE_File.Command.TRACK(tracknum, tt)); } break; } if (!clp.EOF) { var remainder = clp.ReadLine(); if (remainder.TrimStart().StartsWith(";")) { //add a comment OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT(remainder)); } else job.Warn($"Unknown text at end of line after processing command: {key}"); } } //end cue parsing loop job.FinishLog(); } //LoadFromString
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; } }