示例#1
0
		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;
		}
示例#2
0
        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;
                }
            };
        }
示例#3
0
        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();
            }
        }
示例#4
0
        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);
        }
示例#5
0
 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);
 }
示例#6
0
 public async Task ParseDebugDataAsync(AsmProject project)
 {
     var debugDataTask = project.ParseDebugDataAsync();
     await debugDataTask.ContinueWith(t => { if (OnDebugDataUpdated != null)
                                             {
                                                 OnDebugDataUpdated();
                                             }
                                      });
 }
示例#7
0
 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;
 }
示例#8
0
        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);
        }
示例#9
0
 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);
 }
示例#10
0
        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);
            };
        }
示例#11
0
 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;
 }
示例#12
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";
        }
示例#13
0
		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();
		}
示例#14
0
        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);
        }
示例#15
0
 public void SetProject(AsmProject project)
 {
     _project = project;
     _project.ContentsChanged += RefreshTree;             // TODO: Retain open nodes
     RefreshTree();
 }
示例#16
0
        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);
        }