Ejemplo n.º 1
0
        private AddressMap.AddressRegion TryCreateRegion(AddressMap.AddressRegion delRegion,
                                                         int offset, int length, int addr, out AddressMap.AddResult result)
        {
            AddressMap tmpMap = mProject.AddrMap.Clone();

            if (delRegion != null && !tmpMap.RemoveEntry(delRegion.Offset, delRegion.Length))
            {
                Debug.Assert(false, "Failed to remove existing region");
                result = AddressMap.AddResult.InternalError;
                return(null);
            }

            result = tmpMap.AddEntry(offset, length, addr);
            if (result != AddressMap.AddResult.Okay)
            {
                return(null);
            }
            AddressMap.AddressRegion newRegion = tmpMap.FindRegion(offset, length);
            if (newRegion == null)
            {
                // Shouldn't happen.
                Debug.Assert(false, "Failed to find region we just created");
                result = AddressMap.AddResult.InternalError;
                return(null);
            }
            return(newRegion);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="owner">Parent window.</param>
        /// <param name="curRegion">Current region; will be null for new entries.</param>
        /// <param name="newEntry">Prototype entry to create.</param>
        /// <param name="selectionLen">Length, in bytes, of the selection.</param>
        /// <param name="isSingleLine">True if the selection is a single line.</param>
        /// <param name="project">Project reference.</param>
        /// <param name="formatter">Text formatter object.</param>
        public EditAddress(Window owner, AddressMap.AddressRegion curRegion,
                           AddressMap.AddressMapEntry newEntry, int selectionLen, bool isSingleLine,
                           DisasmProject project, Formatter formatter)
        {
            InitializeComponent();
            Owner       = owner;
            DataContext = this;

            Debug.Assert((curRegion == null) ^ (newEntry == null));     // exactly one must be true

            mProject         = project;
            mMaxAddressValue = project.CpuDef.MaxAddressValue;
            mShowBank        = !project.CpuDef.HasAddr16;
            mFormatter       = formatter;

            Configure(curRegion, newEntry, selectionLen, isSingleLine);
            UpdateControls();
        }
Ejemplo n.º 3
0
        // IGenerator
        public void OutputArDirective(CommonUtil.AddressMap.AddressChange change)
        {
            // This is similar in operation to the AsmTass64 implementation.  See comments there.
            Debug.Assert(mPcDepth >= 0);
            int nextAddress = change.Address;

            if (nextAddress == Address.NON_ADDR)
            {
                // Start non-addressable regions at zero to ensure they don't overflow bank.
                nextAddress = 0;
            }
            if (change.IsStart)
            {
                if (change.Region.HasValidPreLabel)
                {
                    string labelStr = mLocalizer.ConvLabel(change.Region.PreLabel);
                    OutputLine(labelStr, string.Empty, string.Empty, string.Empty);
                }
                if (mPcDepth == 0 && mFirstIsOpen)
                {
                    mPcDepth++;

                    // Set the "real" PC for the first address change.  If we're in "loadable"
                    // mode, just set "*=".  If we're in "streaming" mode, we set "*=" to zero
                    // and then use a pseudo-PC.
                    if (mOutputMode == OutputMode.Loadable)
                    {
                        OutputLine("*", "=", SourceFormatter.FormatHexValue(nextAddress, 4),
                                   string.Empty);
                        return;
                    }
                    else
                    {
                        // set the real PC to address zero to ensure we get a full 64KB
                        OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty);
                    }
                }
                AddressMap.AddressRegion region = change.Region;
                string addrStr;
                if (region.HasValidIsRelative)
                {
                    int    diff = nextAddress - region.PreLabelAddress;
                    string pfxStr;
                    if (diff >= 0)
                    {
                        pfxStr = "*+";
                    }
                    else
                    {
                        pfxStr = "*-";
                        diff   = -diff;
                    }
                    addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4);
                }
                else
                {
                    addrStr = SourceFormatter.FormatHexValue(nextAddress, 4);
                }
                OutputLine(string.Empty,
                           SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective),
                           addrStr + " {",
                           string.Empty);
                mPcDepth++;
            }
            else
            {
                mPcDepth--;
                if (mPcDepth > 0 || !mFirstIsOpen)
                {
                    // close previous block
                    OutputLine(string.Empty,
                               SourceFormatter.FormatPseudoOp(sDataOpNames.ArEndDirective),
                               string.Empty, string.Empty);
                    //";" + SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective));
                }
                else
                {
                    // mark initial "*=" region as closed, but don't output anything
                    mFirstIsOpen = false;
                }
            }
        }
Ejemplo n.º 4
0
        // IGenerator
        public GenerationResults GenerateSource(BackgroundWorker worker)
        {
            List <string> pathNames = new List <string>(1);

            string fileName = mFileNameBase + ASM_FILE_SUFFIX;
            string pathName = Path.Combine(mWorkDirectory, fileName);

            pathNames.Add(pathName);

            Formatter.FormatConfig config = new Formatter.FormatConfig();
            GenCommon.ConfigureFormatterFromSettings(Settings, ref config);
            SetFormatConfigValues(ref config);
            SourceFormatter = new Formatter(config);

            string msg = string.Format(Res.Strings.PROGRESS_GENERATING_FMT, pathName);

            worker.ReportProgress(0, msg);

            mLocalizer = new LabelLocalizer(Project);
            // While '.' labels are limited to the current zone, '@' labels are visible
            // between global labels.  (This is poorly documented.)
            mLocalizer.LocalPrefix            = "@";
            mLocalizer.QuirkNoOpcodeMnemonics = true;
            mLocalizer.ReservedWords          = new List <string>()
            {
                "NOT"
            };
            mLocalizer.Analyze();

            mPcDepth     = 0;
            mFirstIsOpen = true;

            // Use UTF-8 encoding, without a byte-order mark.
            using (StreamWriter sw = new StreamWriter(pathName, false, new UTF8Encoding(false))) {
                mOutStream = sw;

                if (Settings.GetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, false))
                {
                    OutputLine(SourceFormatter.FullLineCommentDelimiter +
                               string.Format(Res.Strings.GENERATED_FOR_VERSION_FMT,
                                             "acme", mAsmVersion, AsmAcme.OPTIONS));
                }

                if (HasNonZeroBankCode())
                {
                    // don't try
                    OutputLine(SourceFormatter.FullLineCommentDelimiter +
                               "ACME can't handle 65816 code that lives outside bank zero");
                    int firstAddr = Project.AddrMap.OffsetToAddress(0);
                    AddressMap.AddressRegion fakeRegion = new AddressMap.AddressRegion(0,
                                                                                       Project.FileData.Length, firstAddr);
                    OutputArDirective(new AddressMap.AddressChange(true,
                                                                   0, firstAddr, fakeRegion, true));
                    OutputDenseHex(0, Project.FileData.Length, string.Empty, string.Empty);
                    OutputArDirective(new AddressMap.AddressChange(false,
                                                                   0, firstAddr, fakeRegion, true));
                }
                else
                {
                    GenCommon.Generate(this, sw, worker);
                }
            }
            mOutStream = null;

            return(new GenerationResults(pathNames, string.Empty));
        }
Ejemplo n.º 5
0
        // IGenerator
        public void OutputArDirective(CommonUtil.AddressMap.AddressChange change)
        {
            // 64tass separates the "compile offset", which determines where the output fits
            // into the generated binary, and "program counter", which determines the code
            // the assembler generates.  Since we need to explicitly specify every byte in
            // the output file, having a distinct compile offset isn't useful here.  We want
            // to set it once before the first line of code, then leave it alone.
            //
            // Any subsequent ORG changes are made to the program counter, and take the form
            // of a pair of ops (".logical <addr>" to open, ".here" to end).  Omitting the .here
            // causes an error.
            //
            // If this is a "streamable" file, meaning it won't actually load into 64K of RAM
            // without wrapping around, then we skip the "* = addr" (same as "* = 0") and just
            // start with ".logical" segments.
            //
            // The assembler's approach is best represented by having an address region that
            // spans the entire file, with one or more "logical" regions inside.  In practice
            // (especially for multi-bank 65816 code) that may not be the case, but the
            // assembler is still expecting us to start with a "* =" and then fit everything
            // inside that.  So we treat the first region specially, whether or not it wraps
            // the rest of the file.
            Debug.Assert(mPcDepth >= 0);
            int nextAddress = change.Address;

            if (nextAddress == Address.NON_ADDR)
            {
                // Start non-addressable regions at zero to ensure they don't overflow bank.
                nextAddress = 0;
            }
            if (change.IsStart)
            {
                if (change.Region.HasValidPreLabel)
                {
                    string labelStr = mLocalizer.ConvLabel(change.Region.PreLabel);
                    OutputLine(labelStr, string.Empty, string.Empty, string.Empty);
                }
                if (mPcDepth == 0 && mFirstIsOpen)
                {
                    mPcDepth++;

                    // Set the "real" PC for the first address change.  If we're in "loadable"
                    // mode, just set "*=".  If we're in "streaming" mode, we set "*=" to zero
                    // and then use a pseudo-PC.
                    if (mOutputMode == OutputMode.Loadable)
                    {
                        OutputLine("*", "=",
                                   SourceFormatter.FormatHexValue(nextAddress, 4), string.Empty);
                        return;
                    }
                    else
                    {
                        // Set the real PC to address zero to ensure we get a full 64KB.  The
                        // assembler assumes this as a default, so it can be omitted.
                        //OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty);
                    }
                }

                AddressMap.AddressRegion region = change.Region;
                string addrStr;
                if (region.HasValidIsRelative)
                {
                    int    diff = nextAddress - region.PreLabelAddress;
                    string pfxStr;
                    if (diff >= 0)
                    {
                        pfxStr = "*+";
                    }
                    else
                    {
                        pfxStr = "*-";
                        diff   = -diff;
                    }
                    addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4);
                }
                else
                {
                    addrStr = SourceFormatter.FormatHexValue(nextAddress, 4);
                }
                OutputLine(string.Empty,
                           SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective),
                           addrStr,
                           string.Empty);
                mPcDepth++;
            }
            else
            {
                mPcDepth--;
                if (mPcDepth > 0 || !mFirstIsOpen)
                {
                    // close previous block
                    OutputLine(string.Empty,
                               SourceFormatter.FormatPseudoOp(sDataOpNames.ArEndDirective),
                               string.Empty, string.Empty);
                }
                else
                {
                    // mark initial "*=" region as closed, but don't output anything
                    mFirstIsOpen = false;
                }
            }
        }
Ejemplo n.º 6
0
        // IGenerator
        public void OutputArDirective(CommonUtil.AddressMap.AddressChange change)
        {
            int nextAddress = change.Address;

            if (nextAddress == Address.NON_ADDR)
            {
                // Start non-addressable regions at zero to ensure they don't overflow bank.
                nextAddress = 0;
            }

            if (change.IsStart)
            {
                AddressMap.AddressRegion region = change.Region;
                if (region.HasValidPreLabel || region.HasValidIsRelative)
                {
                    // Need to output the previous ORG, if one is pending.
                    if (mNextAddress >= 0)
                    {
                        OutputLine(string.Empty,
                                   SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective),
                                   SourceFormatter.FormatHexValue(mNextAddress, 4),
                                   string.Empty);
                    }
                }
                if (region.HasValidPreLabel)
                {
                    string labelStr = mLocalizer.ConvLabel(change.Region.PreLabel);
                    OutputLine(labelStr, string.Empty, string.Empty, string.Empty);
                }
                if (region.HasValidIsRelative)
                {
                    // Found a valid IsRelative.  Switch to "relative mode" if not there already.
                    mIsInRelative = true;
                }
                if (mIsInRelative)
                {
                    // Once we see a region with IsRelative set, we output regions as we
                    // find them until the next Flush.
                    string addrStr;
                    if (region.HasValidIsRelative)
                    {
                        int    diff = nextAddress - region.PreLabelAddress;
                        string pfxStr;
                        if (diff >= 0)
                        {
                            pfxStr = "*+";
                        }
                        else
                        {
                            pfxStr = "*-";
                            diff   = -diff;
                        }
                        addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4);
                    }
                    else
                    {
                        addrStr = SourceFormatter.FormatHexValue(nextAddress, 4);
                    }
                    OutputLine(string.Empty,
                               SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective),
                               addrStr, string.Empty);

                    mNextAddress = -1;
                    return;
                }
            }

            mNextAddress = nextAddress;
        }
Ejemplo n.º 7
0
        private void Configure(AddressMap.AddressRegion curRegion,
                               AddressMap.AddressMapEntry newEntry, int selectionLen, bool isSingleLine)
        {
            Debug.WriteLine("Configuring AR: reg=" + curRegion + " newEnt=" + newEntry +
                            " selLen=" + selectionLen + " isSingle=" + isSingleLine);

            ShowOption1             = ShowOption2 = true;
            EnableOption1           = EnableOption2 = true;
            CheckOption1            = true;
            EnableAttributeControls = true;

            string option1Summ;
            string option1Msg;
            string option2Summ;
            string option2Msg;

            if (curRegion != null)
            {
                // Editing an existing region.
                CanDeleteRegion    = true;
                ShowExistingRegion = true;
                mOrigPreLabel      = curRegion.PreLabel;
                mParentNonAddr     = (curRegion.PreLabelAddress == Address.NON_ADDR);

                if (curRegion.Address == Address.NON_ADDR)
                {
                    AddressText = Address.NON_ADDR_STR;
                }
                else
                {
                    AddressText = Asm65.Address.AddressToString(curRegion.Address, false);
                }
                PreLabelText          = curRegion.PreLabel;
                UseRelativeAddressing = curRegion.IsRelative;

                OperationStr       = (string)FindResource("str_HdrEdit");
                mRegionAddress     = curRegion.Address;
                mRegionStartOffset = curRegion.Offset;
                mRegionEndOffset   = curRegion.Offset + curRegion.ActualLength - 1;
                mPreLabelAddress   = curRegion.PreLabelAddress;

                if (isSingleLine)
                {
                    // Only thing selected was arstart/arend.  First action is to edit
                    // the region properties, second action is to convert floating end
                    // to fixed.
                    mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
                                                                   curRegion.Length, curRegion.Address, curRegion.PreLabel,
                                                                   curRegion.IsRelative);
                    option1Summ = (string)FindResource("str_OptEditAsIsSummary");
                    option1Msg  = (string)FindResource("str_OptEditAsIs");

                    if (curRegion.IsFloating)
                    {
                        option2Summ   = (string)FindResource("str_OptEditAndFixSummary");
                        option2Msg    = (string)FindResource("str_OptEditAndFix");
                        mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
                                                                       curRegion.ActualLength, curRegion.Address, curRegion.PreLabel,
                                                                       curRegion.IsRelative);
                    }
                    else
                    {
                        option2Summ   = string.Empty;
                        option2Msg    = (string)FindResource("str_EditFixedAlreadyFixed");
                        mResultEntry2 = null;
                        EnableOption2 = false;  // show it, but disabled
                    }
                }
                else
                {
                    // Selection started with arstart and included multiple lines.  First
                    // action is to resize region.  Second action is edit without resize.
                    // If resize is illegal (e.g. new region exactly overlaps another),
                    // first action is disabled.
                    mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
                                                                   selectionLen, curRegion.Address, curRegion.PreLabel,
                                                                   curRegion.IsRelative);
                    mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
                                                                   curRegion.Length, curRegion.Address, curRegion.PreLabel,
                                                                   curRegion.IsRelative);

                    option1Summ = (string)FindResource("str_OptResizeSummary");
                    string fmt = (string)FindResource("str_OptResize");
                    option1Msg = string.Format(fmt,
                                               mFormatter.FormatOffset24(curRegion.Offset + selectionLen - 1),
                                               FormatLength(selectionLen));
                    option2Summ = (string)FindResource("str_OptEditAsIsSummary");
                    option2Msg  = (string)FindResource("str_OptEditAsIs");

                    Debug.Assert(selectionLen > 0);
                    AddressMap.AddResult ares;
                    TryCreateRegion(curRegion, curRegion.Offset, selectionLen,
                                    curRegion.Address, out ares);
                    if (ares != AddressMap.AddResult.Okay)
                    {
                        // Can't resize the new region, so disable that option (still visible).
                        option1Summ = string.Empty;
                        string fmta = (string)FindResource("str_OptResizeFail");
                        option1Msg    = string.Format(fmta, GetErrorString(ares));
                        EnableOption1 = false;
                        CheckOption2  = true;
                    }

                    if (curRegion.ActualLength == selectionLen)
                    {
                        // The selection size matches the region's length, which means they
                        // have the entire region selected, so "resize" and "edit" do the same
                        // thing.  No real need to disable the resize option, but we can default
                        // to "edit only" to emphasize that there's no actual change.
                        CheckOption2 = true;
                    }
                }
            }
            else
            {
                // Creating a new region.  Prototype entry specifies offset, length, and address.
                // First action is to create a fixed-length region, second action is to create
                // a floating region.  Default changes for single-item selections.
                CanDeleteRegion    = false;
                ShowExistingRegion = false;
                mOrigPreLabel      = string.Empty;

                if (newEntry.Address == Address.NON_ADDR)
                {
                    AddressText = Address.NON_ADDR_STR;
                }
                else
                {
                    AddressText = Asm65.Address.AddressToString(newEntry.Address, false);
                }
                PreLabelText          = string.Empty;
                UseRelativeAddressing = false;

                OperationStr = (string)FindResource("str_HdrCreate");

                AddressMap.AddResult     ares1;
                AddressMap.AddressRegion newRegion1 = TryCreateRegion(null, newEntry.Offset,
                                                                      newEntry.Length, newEntry.Address, out ares1);
                AddressMap.AddResult     ares2;
                AddressMap.AddressRegion newRegion2 = TryCreateRegion(null, newEntry.Offset,
                                                                      AddressMap.FLOATING_LEN, newEntry.Address, out ares2);

                if (isSingleLine)
                {
                    // For single-line selection, create a floating region by default.
                    CheckOption2 = true;
                }

                // If it failed, report the error.  Most common reason will be a start offset
                // that overlaps an existing region.  You can create a fixed region inside
                // a fixed region with the same start offset, but can't create a float there.
                if (ares1 == AddressMap.AddResult.Okay)
                {
                    mResultEntry1 = new AddressMap.AddressMapEntry(newEntry.Offset,
                                                                   newRegion1.ActualLength, newEntry.Address, string.Empty, false);

                    option1Summ = (string)FindResource("str_CreateFixedSummary");
                    string fmt = (string)FindResource("str_CreateFixed");
                    option1Msg = string.Format(fmt,
                                               mFormatter.FormatOffset24(newEntry.Offset),
                                               FormatLength(newRegion1.ActualLength));
                    mPreLabelAddress = newRegion1.PreLabelAddress;

                    mParentNonAddr = (newRegion1.PreLabelAddress == Address.NON_ADDR);
                }
                else
                {
                    option1Summ = string.Empty;
                    if (ares1 == AddressMap.AddResult.StraddleExisting)
                    {
                        option1Msg = (string)FindResource("str_CreateFixedFailStraddle");
                    }
                    else
                    {
                        option1Msg = (string)FindResource("str_CreateFixedFail");
                    }
                    CheckOption2  = true;
                    EnableOption1 = false;
                }
                if (ares2 == AddressMap.AddResult.Okay)
                {
                    mResultEntry2 = new AddressMap.AddressMapEntry(newEntry.Offset,
                                                                   AddressMap.FLOATING_LEN, newEntry.Address, string.Empty, false);

                    option2Summ = (string)FindResource("str_CreateFloatingSummary");
                    string fmt = (string)FindResource("str_CreateFloating");
                    option2Msg = string.Format(fmt,
                                               mFormatter.FormatOffset24(newEntry.Offset),
                                               FormatLength(newRegion2.ActualLength));
                    mPreLabelAddress = newRegion2.PreLabelAddress;

                    mParentNonAddr = (newRegion2.PreLabelAddress == Address.NON_ADDR);
                }
                else
                {
                    option2Summ   = string.Empty;
                    option2Msg    = (string)FindResource("str_CreateFloatingFail");
                    CheckOption1  = true;
                    CheckOption2  = false;  // required for some reason
                    EnableOption2 = false;
                }
                if (ares1 != AddressMap.AddResult.Okay && ares2 != AddressMap.AddResult.Okay)
                {
                    // Unable to create region here.  Explain why not.
                    EnableAttributeControls = false;
                    CheckOption1            = CheckOption2 = false;
                    mPreLabelAddress        = Address.NON_ADDR;

                    SetErrorString(ares1);
                }
            }

            TextBlock tb1 = option1TextBlock;

            tb1.Inlines.Clear();
            if (!string.IsNullOrEmpty(option1Summ))
            {
                tb1.Inlines.Add(new Run(option1Summ + " ")
                {
                    FontWeight = FontWeights.Bold
                });
            }
            tb1.Inlines.Add(option1Msg);

            TextBlock tb2 = option2TextBlock;

            tb2.Inlines.Clear();
            if (!string.IsNullOrEmpty(option2Summ))
            {
                tb2.Inlines.Add(new Run(option2Summ + " ")
                {
                    FontWeight = FontWeights.Bold
                });
            }
            tb2.Inlines.Add(option2Msg);
        }