Example #1
0
        // IAssembler
        public AssemblerVersion QueryVersion()
        {
            AssemblerConfig config =
                AssemblerConfig.GetConfig(AppSettings.Global, AssemblerInfo.Id.Tass64);

            if (config == null || string.IsNullOrEmpty(config.ExecutablePath))
            {
                return(null);
            }

            ShellCommand cmd = new ShellCommand(config.ExecutablePath, "--version",
                                                Directory.GetCurrentDirectory(), null);

            cmd.Execute();
            if (string.IsNullOrEmpty(cmd.Stdout))
            {
                return(null);
            }

            // Windows - Stdout: "64tass Turbo Assembler Macro V1.53.1515\r\n"
            // Linux - Stdout:   "64tass Turbo Assembler Macro V1.53.1515?\n"

            const string PREFIX = "Macro V";
            string       str    = cmd.Stdout;
            int          start  = str.IndexOf(PREFIX);
            int          end    = (start < 0) ? -1 : str.IndexOfAny(new char[] { '?', '\r', '\n' }, start + 1);

            if (start < 0 || end < 0 || start + PREFIX.Length >= end)
            {
                Debug.WriteLine("Couldn't find version in " + str);
                return(null);
            }
            start += PREFIX.Length;
            string versionStr = str.Substring(start, end - start);

            CommonUtil.Version version = CommonUtil.Version.Parse(versionStr);
            if (!version.IsValid)
            {
                return(null);
            }
            return(new AssemblerVersion(versionStr, version));
        }
Example #2
0
        // IAssembler
        public AssemblerVersion QueryVersion()
        {
            AssemblerConfig config =
                AssemblerConfig.GetConfig(AppSettings.Global, AssemblerInfo.Id.Merlin32);

            if (config == null || string.IsNullOrEmpty(config.ExecutablePath))
            {
                return(null);
            }

            ShellCommand cmd = new ShellCommand(config.ExecutablePath, string.Empty,
                                                Directory.GetCurrentDirectory(), null);

            cmd.Execute();
            if (string.IsNullOrEmpty(cmd.Stdout))
            {
                return(null);
            }

            // Stdout: "C:\Src\WorkBench\Merlin32.exe v 1.0, (c) Brutal Deluxe ..."
            // Other platforms may not have the ".exe".  Find first occurrence of " v ".

            const string PREFIX = " v ";    // not expecting this to appear in the path
            string       str    = cmd.Stdout;
            int          start  = str.IndexOf(PREFIX);
            int          end    = (start < 0) ? -1 : str.IndexOf(',', start);

            if (start < 0 || end < 0 || start + PREFIX.Length >= end)
            {
                Debug.WriteLine("Couldn't find version in " + str);
                return(null);
            }
            start += PREFIX.Length;
            string versionStr = str.Substring(start, end - start);

            CommonUtil.Version version = CommonUtil.Version.Parse(versionStr);
            if (!version.IsValid)
            {
                return(null);
            }
            return(new AssemblerVersion(versionStr, version));
        }
Example #3
0
        // IAssembler
        public AssemblerVersion QueryVersion()
        {
            AssemblerConfig config =
                AssemblerConfig.GetConfig(AppSettings.Global, AssemblerInfo.Id.Acme);

            if (config == null || string.IsNullOrEmpty(config.ExecutablePath))
            {
                return(null);
            }

            ShellCommand cmd = new ShellCommand(config.ExecutablePath, "--version",
                                                Directory.GetCurrentDirectory(), null);

            cmd.Execute();
            if (string.IsNullOrEmpty(cmd.Stdout))
            {
                return(null);
            }

            // Windows - Stdout: "This is ACME, release 0.96.4 ("Fenchurch"), 22 Dec 2017 ..."
            // Linux - Stderr:   "This is ACME, release 0.96.4 ("Fenchurch"), 20 Apr 2019 ..."

            const string PREFIX = "release ";
            string       str    = cmd.Stdout;
            int          start  = str.IndexOf(PREFIX);
            int          end    = (start < 0) ? -1 : str.IndexOf(' ', start + PREFIX.Length + 1);

            if (start < 0 || end < 0 || start + PREFIX.Length >= end)
            {
                Debug.WriteLine("Couldn't find version in " + str);
                return(null);
            }
            start += PREFIX.Length;
            string versionStr = str.Substring(start, end - start);

            CommonUtil.Version version = CommonUtil.Version.Parse(versionStr);
            if (!version.IsValid)
            {
                return(null);
            }
            return(new AssemblerVersion(versionStr, version));
        }
Example #4
0
        // IGenerator
        public void Configure(DisasmProject project, string workDirectory, string fileNameBase,
                              AssemblerVersion asmVersion, AppSettings settings)
        {
            Debug.Assert(project != null);
            Debug.Assert(!string.IsNullOrEmpty(workDirectory));
            Debug.Assert(!string.IsNullOrEmpty(fileNameBase));

            Project = project;
            Quirks  = new AssemblerQuirks();
            if (asmVersion != null)
            {
                // Use the actual version.  If it's > 2.17 we'll try to take advantage of
                // bug fixes.
                mAsmVersion = asmVersion.Version;
            }
            else
            {
                // No assembler installed.  Use 2.17.
                mAsmVersion = V2_17;
            }
            if (mAsmVersion <= V2_17)
            {
                // cc65 v2.17: https://github.com/cc65/cc65/issues/717
                Quirks.BlockMoveArgsReversed = true;
                // cc65 v2.17: https://github.com/cc65/cc65/issues/754
                Quirks.NoPcRelBankWrap = true;
            }
            Quirks.SinglePassAssembler = true;

            mWorkDirectory = workDirectory;
            mFileNameBase  = fileNameBase;
            Settings       = settings;

            mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);

            AssemblerConfig config = AssemblerConfig.GetConfig(settings,
                                                               AssemblerInfo.Id.Cc65);

            mColumnWidths = (int[])config.ColumnWidths.Clone();
        }
Example #5
0
        // IGenerator
        public void Configure(DisasmProject project, string workDirectory, string fileNameBase,
                              AssemblerVersion asmVersion, AppSettings settings)
        {
            Debug.Assert(project != null);
            Debug.Assert(!string.IsNullOrEmpty(workDirectory));
            Debug.Assert(!string.IsNullOrEmpty(fileNameBase));

            Project = project;
            Quirks  = new AssemblerQuirks();
            if (asmVersion != null)
            {
                mAsmVersion = asmVersion.Version;       // Use the actual version.
            }
            else
            {
                mAsmVersion = V0_97;                    // No assembler installed, use default.
            }

            // ACME isn't a single-pass assembler, but the code that determines label widths
            // only runs in the first pass and doesn't get corrected.  So unlike cc65, which
            // generates correct zero-page acceses once the label's value is known, ACME
            // uses 16-bit addressing to zero-page labels for backward references if there
            // are any forward references at all.  The easy way to deal with this is to make
            // all zero-page label references have explicit widths.
            //
            // Example:
            // *       =       $1000
            //         jmp     zero
            //         !pseudopc $0000 {
            // zero    nop
            //         lda     zero
            //         rts
            //         }
            Quirks.SinglePassAssembler         = true;
            Quirks.SinglePassNoLabelCorrection = true;
            if (mAsmVersion < V0_97)
            {
                Quirks.BlockMoveArgsNoHash = true;
                mBackslashEscapes          = false;
            }

            mWorkDirectory = workDirectory;
            mFileNameBase  = fileNameBase;
            Settings       = settings;

            mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);

            AssemblerConfig config = AssemblerConfig.GetConfig(settings,
                                                               AssemblerInfo.Id.Acme);

            mColumnWidths = (int[])config.ColumnWidths.Clone();

            // ACME wants the entire file to be loadable into a 64KB memory area.  If the
            // initial address is too large, a file smaller than 64KB might overrun the bank
            // boundary and cause a failure.  In that case we want to set the initial address
            // to zero and "stream" the rest.
            int firstAddr = project.AddrMap.OffsetToAddress(0);

            if (firstAddr == Address.NON_ADDR)
            {
                firstAddr = 0;
            }
            if (firstAddr + project.FileDataLength > 65536)
            {
                mOutputMode = OutputMode.Streamable;
            }
            else
            {
                mOutputMode = OutputMode.Loadable;
            }
        }
Example #6
0
        // IGenerator
        public void Configure(DisasmProject project, string workDirectory, string fileNameBase,
                              AssemblerVersion asmVersion, AppSettings settings)
        {
            Debug.Assert(project != null);
            Debug.Assert(!string.IsNullOrEmpty(workDirectory));
            Debug.Assert(!string.IsNullOrEmpty(fileNameBase));

            Project = project;
            Quirks  = new AssemblerQuirks();
            if (asmVersion != null)
            {
                mAsmVersion = asmVersion.Version;       // Use the actual version.
            }
            else
            {
                mAsmVersion = V1_56;                    // No assembler installed, use default.
            }

            Quirks.StackIntOperandIsImmediate = true;
            Quirks.LeadingUnderscoreSpecial   = true;
            Quirks.Need24BitsForAbsPBR        = true;
            Quirks.BitNumberIsArg             = true;
            Quirks.BankZeroAbsPBRRestrict     = true;

            mWorkDirectory = workDirectory;
            mFileNameBase  = fileNameBase;
            Settings       = settings;

            mLongLabelNewLine = Settings.GetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);

            AssemblerConfig config = AssemblerConfig.GetConfig(settings,
                                                               AssemblerInfo.Id.Tass64);

            mColumnWidths = (int[])config.ColumnWidths.Clone();

            // 64tass emulates a loader on a 64K system.  The address you specify with
            // "* = <addr>" tells the loader where the code lives.  If the project runs off the
            // end of memory, you get a warning message and an output file that has the last
            // part as the first part, because the loader wraps around.
            //
            // If (start_addr + total_len) doesn't fit without wrapping, we want to start
            // the code with "* = 0" (or omit it entirely) and use ".logical" for the first.
            // chunk.  This allows us to generate the full 64K.  Note that 65816 code that
            // starts outside bank 0 will always fail this test.
            //
            // Thus there are two modes: "loadable" and "streamable".  We could output everything
            // as streamable but that's kind of ugly and prevents the PRG optimization.
            //
            // If the file has more than 64K of data in it, we need to add "--long-address" to
            // the command-line arguments.

            // Get start address.  If this is a PRG file, the start address is the address
            // of offset +000002.
            bool hasPrgHeader = GenCommon.HasPrgHeader(project);
            int  offAdj       = hasPrgHeader ? 2 : 0;
            int  startAddr    = project.AddrMap.OffsetToAddress(offAdj);

            if (startAddr + project.FileDataLength - offAdj > 65536)
            {
                // Does not fit into memory at load address.
                mOutputMode   = OutputMode.Streamable;
                mHasPrgHeader = false;
            }
            else
            {
                mOutputMode   = OutputMode.Loadable;
                mHasPrgHeader = hasPrgHeader;
            }
            //Debug.WriteLine("startAddr=$" + startAddr.ToString("x6") +
            //    " outputMode=" + mOutputMode + " hasPrg=" + mHasPrgHeader);
        }