示例#1
0
        public static void ApplyExpansionPatch(byte[] targetRom)
        {
            // Apply expansion code prior to expansion
            // (for ease... atm expansion code targets the fixed bank at $F instead of $1F)

            // manually include defines
            string asm = Projects.ProjectResources.DefaultDefinesFile + Environment.NewLine + Mmc3Resources.ExpansionASM;

            asm = NopOutScreenLoad(asm);
            snarfblasm.Assembler assm = new snarfblasm.Assembler("mmc3Expander", asm, null);
            var output = assm.Assemble();
            var errors = assm.GetErrors();

            if (errors != null && errors.Count > 0)
            {
                // todo: more specific exception
                string error = "Assembler error: " + errors[0].File + " line " + errors[0].LineNumber + ": " + errors[0].Message;
                if (errors.Count > 1)
                {
                    error += " (additional errors: " + (errors.Count - 1).ToString() + ")";
                }
                throw new Exception(error);
            }

            var patches = assm.GetPatchSegments();

            for (int i = 0; i < patches.Count; i++)
            {
                var patch       = patches[i];
                int patchLength = patch.Length;
                if (patchLength < 0)
                {
                    patchLength = output.Length - patch.Start;
                }
                Array.Copy(output, patch.Start, targetRom, patch.PatchOffset, patchLength);
            }
        }
示例#2
0
            private void Assemble()
            {
                ClearScreenExtraBytes();

                // Assemble (first pass (1)) to calculate size of each screen's code
                {
                    string buildFile               = ConstructBuildFile(1);
                    var    buildFileAsBin          = System.Text.Encoding.UTF8.GetBytes(buildFile);
                    snarfblasm.Assembler assembler = new snarfblasm.Assembler("Main File", new MemoryStream(buildFileAsBin), new FileProvider(this));
                    assembler.AllowInvalidOpcodes    = false;
                    assembler.OverflowChecking       = snarfblasm.OverflowChecking.None;
                    assembler.RequireColonOnLabels   = true;
                    assembler.RequireDotOnDirectives = true;

                    var assembledBytes = assembler.Assemble();

                    ProcessAssembleErrors(assembler.GetErrors(), 1);
                    if (FatalError)
                    {
                        return;
                    }

                    // Added first-pass-code to screens
                    var patchSegments = assembler.GetPatchSegments();
                    ApplyPatches(assembledBytes, patchSegments, false);
                    if (FatalError)
                    {
                        return;
                    }

                    // Serializing data causes ROM data layout to be updated, which is then used to set the base address for each screen's code
                    CheckForOverrun();
                    if (FatalError)
                    {
                        return;
                    }
                    outputRom.SerializeAllData();
                    ApplyScreenCodeBases();
                }

                // Assemble (second pass) with correct base addresses
                {
                    string buildFile      = ConstructBuildFile(0); // Reconstruct with correct base addresses
                    byte[] buildFileAsBin = System.Text.Encoding.UTF8.GetBytes(buildFile);
                    var    assembler      = new snarfblasm.Assembler("Main File", new MemoryStream(buildFileAsBin), new FileProvider(this));
                    assembler.Labels = new snarfblasm.AddressLabels();
                    assembler.AllowInvalidOpcodes    = false;
                    assembler.OverflowChecking       = snarfblasm.OverflowChecking.Unsigned;
                    assembler.RequireColonOnLabels   = true;
                    assembler.RequireDotOnDirectives = true;
                    var assembledBytes = assembler.Assemble();

                    ProcessAssembleErrors(assembler.GetErrors(), 0);
                    if (FatalError)
                    {
                        return;
                    }

                    if (project.GenerateDebugFiles && !string.IsNullOrEmpty(project.DebugOutputDirectory.Trim()))
                    {
                        BuildDebugFiles(assembler.Labels);
                    }

                    // Re-apply updated patch
                    var patchSegments = assembler.GetPatchSegments();
                    ApplyPatches(assembledBytes, patchSegments, true);
                    if (FatalError)
                    {
                        return;
                    }

                    // This causes updated asm bytes to be written to ROM
                    outputRom.SerializeAllData();
                    CheckForOverrun();
                    if (FatalError)
                    {
                        return;
                    }
                }
            }