int WriteOutput(string disassembly) { // no errors finish up // save to disk var section = _services.Options.OutputSection; var outputFile = _services.Options.OutputFile; var objectCode = _services.Output.GetCompilation(section); if (!string.IsNullOrEmpty(_services.Options.Patch)) { if (!string.IsNullOrEmpty(_services.Options.OutputFile) || !string.IsNullOrEmpty(_services.Options.Format)) { _services.Log.LogEntrySimple("Output options ignored for patch mode.", false); } if (_services.Options.LabelsAddressesOnly && string.IsNullOrEmpty(_services.Options.LabelFile)) { _services.Log.LogEntrySimple("Label listing not specified; option '-labels-addresses-only' ignored.", false); } try { var offsetLine = new Preprocessor(_processorOptions).ProcessDefine("patch=" + _services.Options.Patch); var patchExp = offsetLine.Operands.GetIterator(); var offset = _services.Evaluator.Evaluate(patchExp, 0, ushort.MaxValue); if (patchExp.Current != null || _services.PassNeeded) { throw new Exception(); } var filePath = Preprocessor.GetFullPath(outputFile, _services.Options.IncludePath); var fileBytes = File.ReadAllBytes(filePath); Array.Copy(objectCode.ToArray(), 0, fileBytes, (int)offset, objectCode.Count); File.WriteAllBytes(filePath, fileBytes); } catch { throw new Exception($"Cannot patch file \"{outputFile}\". One or more arguments is not valid."); } } else { var formatProvider = _services.FormatSelector?.Invoke(_services.CPU, _services.OutputFormat); if (formatProvider != null) { var startAddress = _services.Output.ProgramStart; if (!string.IsNullOrEmpty(section)) { startAddress = _services.Output.GetSectionStart(section); } var format = _services.Options.CaseSensitive ? _services.OutputFormat : _services.OutputFormat.ToLower(); var info = new FormatInfo(outputFile, format, startAddress, objectCode); File.WriteAllBytes(outputFile, formatProvider.GetFormat(info).ToArray()); } else { File.WriteAllBytes(outputFile, objectCode.ToArray()); } } // write disassembly if (!string.IsNullOrEmpty(disassembly) && !string.IsNullOrEmpty(_services.Options.ListingFile)) { File.WriteAllText(_services.Options.ListingFile, disassembly); } // write labels if (!string.IsNullOrEmpty(_services.Options.LabelFile)) { File.WriteAllText(_services.Options.LabelFile, _services.SymbolManager.ListLabels(!_services.Options.LabelsAddressesOnly)); } if (_services.Log.HasWarnings) { _services.Log.DumpWarnings(); } if (!_services.Options.NoStats) { Console.WriteLine("\n*********************************"); Console.WriteLine($"Assembly start: ${_services.Output.ProgramStart:X4}"); if (_services.Output.ProgramEnd > BinaryOutput.MaxAddress && _services.Options.LongAddressing) { Console.WriteLine($"Assembly end: ${_services.Output.ProgramEnd:X6}"); } else { Console.WriteLine($"Assembly end: ${_services.Output.ProgramEnd & BinaryOutput.MaxAddress:X4}"); } Console.WriteLine($"Passes: {_services.CurrentPass + 1}"); } return(objectCode.Count); }