public BreakpointEditor(Breakpoint breakpoint, AsmProject project) : this(project) { if (breakpoint.File != null) return; // Editing editor breakpoints outside of the text editor windows causes too many potential issues Breakpoint = breakpoint; if (breakpoint.File != null) _breakBySourceLine.Checked = true; else if (breakpoint.Symbol != null) _breakBySymbol.Checked = true; else _breakByAddress.Checked = true; DisableInputs(); if (breakpoint.File != null) { _fileSelect.SelectedItem = breakpoint.File; _fileLineNumber.Text = breakpoint.CurrentLine.ToString(); } if (!string.IsNullOrWhiteSpace(breakpoint.Symbol)) _symbol.Text = breakpoint.Symbol; if (breakpoint.StartAddress >= 0) _fromAddress.Text = Convert.ToString(breakpoint.StartAddress, 16).ToUpper(); if (breakpoint.EndAddress.HasValue && breakpoint.EndAddress >= 0) _toAddress.Text = Convert.ToString(breakpoint.EndAddress.Value, 16).ToUpper(); _breakOnExecute.Checked = breakpoint.Type.HasFlag(Breakpoint.Types.Execute); _breakOnRead.Checked = breakpoint.Type.HasFlag(Breakpoint.Types.Read); _breakOnWrite.Checked = breakpoint.Type.HasFlag(Breakpoint.Types.Write); if (breakpoint.AddressType == Breakpoint.AddressTypes.Cpu) _addressFromCpu.Checked = true; if (breakpoint.AddressType == Breakpoint.AddressTypes.PrgRom) _addressFromRom.Checked = true; if (breakpoint.AddressType == Breakpoint.AddressTypes.Ppu) _addressFromVram.Checked = true; }
public GoToAll(AsmProject project, Events events) { _completionProvider = new AllCompletion(project, events); var dummyControl = new TextEditor(); // TODO: Create own, improved auto-completion window to remove reliance on texteditor InitializeComponent(); _searchQuery.TextChanged += (s, a) => { if (_searchQuery.Text.Length == 0) { if (_completionWindow != null) { _completionWindow.Close(); } _completionWindow = null; return; } _completionProvider.PreSelection = _searchQuery.Text; if (_completionWindow != null && !_completionWindow.IsDisposed) { _completionWindow.RefreshCompletionData(null, ' '); return; } _completionWindow = CompletionWindow.ShowCompletionWindow(this, dummyControl, _completionProvider, PointToScreen(new Point(_searchQuery.Left, _searchQuery.Bounds.Bottom))); if (_completionWindow != null) { _completionWindow.InsertCompleted += Close; } }; }
private void BuildChr(string projectFolder, AsmProject project, NesCartridge cartridge) { var outputDirectory = Path.Combine(projectFolder, cartridge.ChrBuildPath); if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } var chrFilePath = string.Format(@"{0}\{1}", outputDirectory, cartridge.ChrFile); using (var chrFile = File.Create(chrFilePath)) { foreach (var bank in cartridge.ChrBanks) { foreach (var source in bank.Sources) { if (!(source.Pipeline is ChrPipeline)) { continue; } using (var read = File.OpenRead(((ChrPipeline)source.Pipeline).ChrOutput)) { var bufferSize = (int)read.Length; var chrData = new byte[bufferSize]; read.Read(chrData, 0, bufferSize); chrFile.Write(chrData, 0, bufferSize); } } // TODO: Confirm bank size (8KB) } chrFile.Close(); } }
public Task <bool> Build(AsmProject project) { var buildProcessSource = new TaskCompletionSource <bool>(); Task.Run(() => { if (RefreshErrorList != null) { RefreshErrorList(new List <BuildError>()); } try { var errors = BuildSync(project, buildProcessSource); if (RefreshErrorList != null) { RefreshErrorList(errors); } } catch (Exception ex) { Log(new LogData("Unexpected error: " + ex.Message, LogType.Error)); buildProcessSource.SetResult(false); } }); return(buildProcessSource.Task); }
public AllCompletion(AsmProject project, Events events) { Project = project; Events = events; ImageList = new ImageList(); ImageList.Images.Add(Resources.label); ImageList.Images.Add(Resources.file); ImageList.Images.Add(Resources.macro); }
public async Task ParseDebugDataAsync(AsmProject project) { var debugDataTask = project.ParseDebugDataAsync(); await debugDataTask.ContinueWith(t => { if (OnDebugDataUpdated != null) { OnDebugDataUpdated(); } }); }
public Ca65Completion(AsmProject project, Func <string, string> getSymbolDescription, Events events) { _project = project; _getSymbolDescription = getSymbolDescription; _events = events; ImageList = new ImageList(); ImageList.Images.Add(Resources.label); ImageList.Images.Add(Resources.opcode); ImageList.Images.Add(Resources.ca65icon); ImageList.Images.Add(Resources.macro); DefaultIndex = -1; }
public ConfigurationSettings(NesCartridge configuration, AsmProject project) { InitializeComponent(); Project = project; ConfigurationName.Text = configuration.Name; OutputFile.Text = configuration.Filename; GenerateMapFile.Checked = configuration.MapFile != null; ConfigurationFile.Text = configuration.LinkerConfigFile; CalculateSnesChecksum.Checked = configuration.CalculateChecksum; Symbols.Text = string.Join(Environment.NewLine, configuration.Symbols); }
protected override void ChangeStep(int step) { if (Step == 0 && step == 1) { var directory = new DirectoryInfo(_importProjectPath.Directory); if (Project == null || Project.Directory.Name != directory.Name) { _importFiles.Project = Project = AsmProject.ImportFromDirectory(directory); } Project.Name = _importProjectPath.ProjectName; Project.ProjectFile = new FileInfo(_importProjectPath.ProjectFile); } base.ChangeStep(step); }
public ProjectSettingsWindow(AsmProject project) { Project = project; InitializeComponent(); ProjectName.Text = project.Name; foreach (var configuration in project.BuildConfigurations) { var item = new ConfigurationSelection(configuration); ConfigurationSelector.Items.Add(item); if (project.CurrentConfiguration == configuration) { ConfigurationSelector.SelectedItem = item; LoadSelection(item); } } ConfigurationSelector.Items.Add(new ConfigurationSelection(null)); ConfigurationSelector.SelectedIndexChanged += (sender, args) => { var selection = ConfigurationSelector.SelectedItem as ConfigurationSelection; if (selection == null) { return; } if (selection.Configuration == null) { using (var newConfigurationWindow = new ConfigurationManager(Project)) { newConfigurationWindow.StartPosition = FormStartPosition.CenterParent; var result = newConfigurationWindow.ShowDialog(); if (result == DialogResult.OK) { Project.BuildConfigurations.Add(newConfigurationWindow.Configuration); Project.Pristine = false; selection = new ConfigurationSelection(newConfigurationWindow.Configuration); ConfigurationSelector.Items.Insert(ConfigurationSelector.Items.Count - 1, selection); ConfigurationSelector.SelectedItem = selection; } else { ConfigurationSelector.SelectedItem = _currentSelection; return; } } } LoadSelection(selection); }; }
public NavigationData(Symbol symbol, AsmProject project, Events events) { Text = symbol.Text; Description = string.Format(@"{0}: {1},{2}", new FileInfo(symbol.Source).Name, symbol.Line, symbol.Character + 1); _navigate = () => { var file = project.Files.FirstOrDefault(f => f.File.FullName == symbol.Source); if (file == null) { return; } events.OpenFile(file, symbol.Line, symbol.Character, symbol.Text.Length); }; ImageIndex = symbol is MacroSymbol ? 2 : 0; }
public ConfigurationManager(AsmProject project) { InitializeComponent(); ConfigurationSettings.Project = project; ConfigurationSettings.ConfigurationName.Text = project.Type == ProjectType.Snes ? "SNES" : "NES"; var defaultConfigFile = project.Files.FirstOrDefault(f => f.Mode == CompileMode.LinkerConfig); if (defaultConfigFile != null) { ConfigurationSettings.ConfigurationFile.Text = defaultConfigFile.GetRelativePath(); } ConfigurationSettings.OutputFile.Text = project.Type == ProjectType.Snes ? "bin/game.sfc" : "bin/game.nes"; }
public BreakpointEditor(AsmProject project) { _project = project; InitializeComponent(); foreach (var file in project.Files.Where(f => f.Type == FileType.Source || f.Type == FileType.Include).OrderBy(f => f.GetRelativePath())) { _fileSelect.Items.Add(file); } _breakBySourceLine.CheckedChanged += (s, a) => DisableInputs(); _breakBySymbol.CheckedChanged += (s, a) => DisableInputs(); _breakByAddress.CheckedChanged += (s, a) => DisableInputs(); DisableInputs(); Breakpoint = new Breakpoint(); }
public void SetProjectState(AsmProject project, IEnumerable <EditorWindow> openWindows, IEnumerable <WatchValueData> watchData, IEnumerable <Breakpoint> breakpoints) { if (project.ProjectFile == null) { return; } var newState = new ProjectUserSettings { Filename = project.ProjectFile.FullName, CurrentConfiguration = project.CurrentConfiguration.Name, OpenFiles = openWindows.Select(w => w.ProjectFile.File.FullName).ToArray(), WatchData = watchData.ToArray(), Breakpoints = breakpoints.Select(bp => bp.GetSerializable()).ToArray() }; ProjectStates.RemoveAll(p => p.Filename == project.ProjectFile.FullName); ProjectStates.Add(newState); }
public void SetProject(AsmProject project) { _project = project; _project.ContentsChanged += RefreshTree; // TODO: Retain open nodes RefreshTree(); }
private List <BuildError> BuildSync(AsmProject project, TaskCompletionSource <bool> buildProcessSource) { var errors = new List <BuildError>(); var asmFailed = false; var cartridge = project.CurrentConfiguration; var ideFolder = Program.WorkingDirectory; var projectFolder = project.Directory.FullName; var linkerConfig = project.Files.FirstOrDefault(f => f.GetRelativePath() == cartridge.LinkerConfigFile); if (linkerConfig == null) { var configFiles = project.Files.Where(l => l.Mode == CompileMode.LinkerConfig); if (!configFiles.Any()) { buildProcessSource.SetResult(false); return(errors); } linkerConfig = configFiles.First(); } Status("Building NES cartridge..."); Log(new LogData("Building NES cartridge...", LogType.Headline)); Log(new LogData("Processing content pipeline")); var skippedCount = 0; foreach (var file in project.Files.Where(f => f.Mode == CompileMode.ContentPipeline && f.Pipeline != null)) { // Get a fresh File Info from the file system in case something was changed since we loaded the project var fileInfo = new FileInfo(file.File.FullName); // TODO: Refresh ProjectFile.File using file system watch to get LastWriteTime // ? if (!fileInfo.Exists) { var error = new BuildError( string.Format(@"File '{0}' is missing. Skipping data processing...", file.GetRelativePath()), BuildError.BuildErrorType.Warning); errors.Add(error); ErrorReceived(error); continue; } if (file.Pipeline.LastProcessed != null && file.Pipeline.LastProcessed > fileInfo.LastWriteTime) { //Log(new LogData(string.Format("Skipping '{0}'", file.GetRelativePath()))); skippedCount++; continue; } Log(new LogData(string.Format("Building {0}", string.Join(",", file.Pipeline.OutputFiles.Where(f => f != null).Select(project.GetRelativePath))))); file.Pipeline.Process(); } if (skippedCount > 0) { Log(new LogData(string.Format("Skipped {0} unchanged files", skippedCount))); } if (projectFolder == null) { throw new Exception("Project directory not found"); } var targetFile = Path.Combine(projectFolder, cartridge.Filename); var buildFolder = Path.Combine(projectFolder, cartridge.BuildPath); var prgFolder = cartridge.PrgBuildPath != null?Path.Combine(projectFolder, cartridge.PrgBuildPath) : null; var chrFolder = cartridge.ChrBuildPath != null?Path.Combine(projectFolder, cartridge.ChrBuildPath) : null; var debugFile = Path.Combine(projectFolder, cartridge.DebugFile); if (!Directory.Exists(Path.GetDirectoryName(targetFile))) { Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); } if (!Directory.Exists(buildFolder)) { Directory.CreateDirectory(buildFolder); } if (prgFolder != null && !Directory.Exists(prgFolder)) { Directory.CreateDirectory(prgFolder); } if (chrFolder != null && !Directory.Exists(chrFolder)) { Directory.CreateDirectory(chrFolder); } if (!Directory.Exists(Path.GetDirectoryName(debugFile))) { Directory.CreateDirectory(Path.GetDirectoryName(debugFile)); } if (cartridge.ChrBanks.Any() && chrFolder != null) { Log(new LogData("Building CHR from graphic banks", LogType.Headline)); BuildChr(projectFolder, project, cartridge); } Log(new LogData("Building PRG from source files", LogType.Headline)); var asmParams = GetAsmParams(projectFolder); var sourceFiles = project.Files.Where(f => f.Mode == CompileMode.IncludeInAssembly); var objectFiles = new List <string>(); foreach (var projectFile in sourceFiles) { using (var asmProcess = new Process()) { asmProcess.StartInfo = asmParams; asmProcess.EnableRaisingEvents = true; asmProcess.OutputDataReceived += OutputReceived; string multilineError = null; asmProcess.ErrorDataReceived += (s, e) => { ProcessErrorData(e.Data, errors, ref multilineError); }; var directory = Path.Combine(projectFolder, cartridge.BuildPath, projectFile.GetRelativeDirectory()); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var fileBase = projectFile.GetRelativeDirectory() + @"/" + Path.GetFileNameWithoutExtension(projectFile.File.Name); var sourceFile = projectFile.GetRelativePath(); var objectFile = cartridge.BuildPath + @"/" + fileBase + ".o"; var dependencyFile = cartridge.BuildPath + @"/" + fileBase + ".d"; objectFiles.Add(objectFile); asmProcess.StartInfo.Arguments = string.Format("\"{0}\" -o \"{1}\" --create-dep \"{2}\" -t nes --cpu {3}{4} -g -I .", sourceFile, objectFile, dependencyFile, project.GetTargetCpu(), string.Join("", cartridge.Symbols.Select(s => " -D " + s))); Log(new LogData("ca65 " + asmProcess.StartInfo.Arguments)); asmProcess.Start(); asmProcess.BeginOutputReadLine(); asmProcess.BeginErrorReadLine(); asmProcess.WaitForExit(); if (asmProcess.ExitCode != 0) { asmFailed = true; } } } if (asmFailed) { buildProcessSource.SetResult(false); return(errors); } if (File.Exists(targetFile)) { File.Delete(targetFile); } var outputFile = targetFile; if (cartridge.PrgBuildPath != null && cartridge.PrgFile != null) { outputFile = Path.Combine(projectFolder, cartridge.PrgBuildPath, cartridge.PrgFile); } using (var linkerProcess = new Process()) { linkerProcess.StartInfo = asmParams; linkerProcess.EnableRaisingEvents = true; linkerProcess.OutputDataReceived += OutputReceived; string multilineError = null; linkerProcess.ErrorDataReceived += (s, e) => { ProcessErrorData(e.Data, errors, ref multilineError); }; //linkerProcess.StartInfo.FileName = string.Format(@"{0}\cc65\bin\cl65.exe", ideFolder); //linkerProcess.StartInfo.Arguments = string.Format("-t nes -C {0} --mapfile {1} -Wl --dbgfile,{2} -o {3} {4}", cartridge.LinkerConfigFile, cartridge.MapFile, cartridge.DebugFile, prgFile, string.Join(" ", objectFiles)); linkerProcess.StartInfo.FileName = string.Format(@"{0}\cc65\bin\ld65.exe", ideFolder); linkerProcess.StartInfo.Arguments = string.Format("-o \"{3}\" -C \"{0}\" -m \"{1}\" --dbgfile \"{2}\" {4}", linkerConfig.GetRelativePath(), cartridge.MapFile, cartridge.DebugFile, outputFile, string.Join(" ", objectFiles.Select(f => string.Format("\"{0}\"", f))) ); Log(new LogData("ld65 " + linkerProcess.StartInfo.Arguments)); linkerProcess.Start(); linkerProcess.BeginOutputReadLine(); linkerProcess.BeginErrorReadLine(); linkerProcess.WaitForExit(); if (linkerProcess.ExitCode != 0) { buildProcessSource.SetResult(false); return(errors); } } if (project.Type == ProjectType.Snes && cartridge.CalculateChecksum) { using (var stream = File.Open(outputFile, FileMode.Open, FileAccess.ReadWrite)) { Log(new LogData("Calculating SNES checksum", LogType.Headline)); var prgSize = (Int32)stream.Length; // We don't expect the PRG size to ever be longer than a 32 bit int var prgData = new byte[prgSize]; var checksumData = new byte[4]; stream.Read(prgData, 0, prgSize); ushort checksum = 0; unchecked // Allow 16bit integer to overflow { for (var i = 0; i < prgSize; i++) { if (i >= 0x7FDC && i <= 0x7FDF) { continue; } checksum += prgData[i]; } checksum += 0xff; checksum += 0xff; } checksumData[2] = (byte)(checksum & 0xff); checksumData[3] = (byte)((checksum >> 8) & 0xff); checksumData[0] = (byte)(~checksum & 0xff); checksumData[1] = (byte)((~checksum >> 8) & 0xff); stream.Position = 0x7FDC; stream.Write(checksumData, 0, 4); } } if (prgFolder != null) { if (project.Type == ProjectType.Nes) { Log(new LogData("Merging into iNES file", LogType.Headline)); } using (var write = File.OpenWrite(targetFile)) { using (var read = File.OpenRead(string.Format(@"{0}\{1}", prgFolder, cartridge.PrgFile))) { var prgSize = (Int32)read.Length; // We don't expect the PRG size to ever be longer than a 32 bit int var prgData = new byte[prgSize]; read.Read(prgData, 0, prgSize); write.Write(prgData, 0, prgSize); } if (chrFolder != null) { using (var read = File.OpenRead(string.Format(@"{0}\{1}", chrFolder, cartridge.ChrFile))) { var chrSize = (Int32)read.Length; // We don't expect the CHR size to ever be longer than a 32 bit int var chrData = new byte[chrSize]; read.Read(chrData, 0, chrSize); write.Write(chrData, 0, chrSize); } } write.Close(); Log(new LogData(targetFile.Replace('/', '\\'))); } } Log(new LogData("---")); Log(new LogData("Build complete\r\n")); Status("Build complete"); Log(new LogData("Parsing debug info")); var debugDataTask = project.ParseDebugDataAsync(debugFile); debugDataTask.ContinueWith((t) => { if (t.Status != TaskStatus.RanToCompletion) { Log(new LogData("Error parsing: " + t.Exception.InnerExceptions[0].Message, LogType.Error)); buildProcessSource.SetResult(false); return; } if (OnDebugDataUpdated != null) { OnDebugDataUpdated(); } Log(new LogData("Done parsing")); project.UpdatedSinceLastBuild = false; buildProcessSource.SetResult(true); }); return(errors); }