diff --git a/SourceGen/Examples/Scripts/Sample.S b/SourceGen/Examples/Scripts/Sample.S index 8c2f85a..fa03b54 100644 --- a/SourceGen/Examples/Scripts/Sample.S +++ b/SourceGen/Examples/Scripts/Sample.S @@ -1,3 +1,8 @@ +; Copyright 2019 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + org $1000 jsr PrintInlineL1String diff --git a/SourceGen/Examples/Scripts/FinishedSample.dis65 b/SourceGen/Examples/Scripts/Sample.dis65 similarity index 93% rename from SourceGen/Examples/Scripts/FinishedSample.dis65 rename to SourceGen/Examples/Scripts/Sample.dis65 index 0f7e6d2..3cd1e55 100644 --- a/SourceGen/Examples/Scripts/FinishedSample.dis65 +++ b/SourceGen/Examples/Scripts/Sample.dis65 @@ -10,7 +10,7 @@ "Low":0,"High":0,"Hint":"Code"}],"StatusFlagOverrides":{ }, "Comments":{ -}, +"0":"requires exact name match","13":"requires name prefix match"}, "LongComments":{ }, "Notes":{ diff --git a/SourceGen/Examples/Tutorial/InlineL1String.cs b/SourceGen/Examples/Tutorial/InlineL1String.cs new file mode 100644 index 0000000..508aa90 --- /dev/null +++ b/SourceGen/Examples/Tutorial/InlineL1String.cs @@ -0,0 +1,73 @@ +// Copyright 2019 faddenSoft. All Rights Reserved. +// See the LICENSE.txt file for distribution terms (Apache 2.0). + +using System; +using System.Collections.Generic; + +using PluginCommon; + +namespace ExtensionScriptSample { + /// + /// Sample class for handling a JSR followed by a string prefixed with a 1-byte length. + /// + public class InlineL1String: MarshalByRefObject, IPlugin, IPlugin_SymbolList, + IPlugin_InlineJsr { + private IApplication mAppRef; + private byte[] mFileData; + + // Only one call. + private const string CALL_LABEL = "PrintInlineL1String"; + private int mInlineL1StringAddr; // jsr + + public string Identifier { + get { + return "Inline L1 ASCII string handler"; + } + } + + public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) { + mAppRef = appRef; + mFileData = fileData; + + mAppRef.DebugLog("InlineL1String(id=" + + AppDomain.CurrentDomain.Id + "): prepare()"); + } + + public void UpdateSymbolList(List plSyms) { + // reset this every time, in case they remove the symbol + mInlineL1StringAddr = -1; + + foreach (PlSymbol sym in plSyms) { + if (sym.Label == CALL_LABEL) { + mInlineL1StringAddr = sym.Value; + break; + } + } + mAppRef.DebugLog(CALL_LABEL + " @ $" + mInlineL1StringAddr.ToString("x6")); + } + public bool IsLabelSignificant(string beforeLabel, string afterLabel) { + return beforeLabel == CALL_LABEL || afterLabel == CALL_LABEL; + } + + public void CheckJsr(int offset, int operand, out bool noContinue) { + noContinue = false; + if (operand != mInlineL1StringAddr) { + return; + } + if (offset + 3 >= mFileData.Length) { + return; // length byte is off end + } + int len = mFileData[3]; // first byte past JSR + if (offset + 4 + len > mFileData.Length) { + mAppRef.DebugLog("L1 string ran off end of file at +" + + (offset + 4).ToString("x6")); + return; + } + + // Assuming ASCII. This can be hard-coded, use auto-detection, or look + // up a value in a project constant. + mAppRef.SetInlineDataFormat(offset + 3, len + 1, + DataType.StringL8, DataSubType.Ascii, null); + } + } +} diff --git a/SourceGen/Examples/Tutorial/InlineNullTermString.cs b/SourceGen/Examples/Tutorial/InlineNullTermString.cs new file mode 100644 index 0000000..d568331 --- /dev/null +++ b/SourceGen/Examples/Tutorial/InlineNullTermString.cs @@ -0,0 +1,76 @@ +// Copyright 2019 faddenSoft. All Rights Reserved. +// See the LICENSE.txt file for distribution terms (Apache 2.0). + +using System; +using System.Collections.Generic; + +using PluginCommon; + +namespace ExtensionScriptSample { + /// + /// Sample class for handling a JSR followed by an inline null-terminated string. Any + /// label that starts with "PrintLineNullString" is matched. + /// + public class InlineNullTermString : MarshalByRefObject, IPlugin, IPlugin_SymbolList, + IPlugin_InlineJsr { + private IApplication mAppRef; + private byte[] mFileData; + + private const string LABEL_PREFIX = "PrintInlineNullString"; + private Dictionary mNullStringAddrs = new Dictionary(); + + public string Identifier { + get { + return "Inline null-terminated ASCII string handler"; + } + } + + public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) { + mAppRef = appRef; + mFileData = fileData; + + mAppRef.DebugLog("InlineNullStringHandler(id=" + + AppDomain.CurrentDomain.Id + "): prepare()"); + } + + public void UpdateSymbolList(List plSyms) { + mNullStringAddrs.Clear(); + + foreach (PlSymbol sym in plSyms) { + if (sym.Label.StartsWith(LABEL_PREFIX)) { + mNullStringAddrs.Add(sym.Value, sym); + } + } + mAppRef.DebugLog(LABEL_PREFIX + " matched " + mNullStringAddrs.Count + " labels"); + } + public bool IsLabelSignificant(string beforeLabel, string afterLabel) { + return beforeLabel.StartsWith(LABEL_PREFIX) || afterLabel.StartsWith(LABEL_PREFIX); + } + + public void CheckJsr(int offset, int operand, out bool noContinue) { + noContinue = false; + if (!mNullStringAddrs.ContainsKey(operand)) { + return; + } + + // search for the terminating null byte + int nullOff = offset + 3; + while (nullOff < mFileData.Length) { + if (mFileData[nullOff] == 0) { + break; + } + nullOff++; + } + if (nullOff == mFileData.Length) { + mAppRef.DebugLog("Unable to find end of null-terminated string at +" + + (offset+3).ToString("x6")); + return; + } + + // Assuming ASCII. This can be hard-coded, use auto-detection, or look + // up a value in a project constant. + mAppRef.SetInlineDataFormat(offset + 3, nullOff - (offset + 3) + 1, + DataType.StringNullTerm, DataSubType.Ascii, null); + } + } +} diff --git a/SourceGen/Examples/Tutorial/Tutorial1.S b/SourceGen/Examples/Tutorial/Source/Tutorial1.S similarity index 100% rename from SourceGen/Examples/Tutorial/Tutorial1.S rename to SourceGen/Examples/Tutorial/Source/Tutorial1.S diff --git a/SourceGen/Examples/Tutorial/Tutorial2.S b/SourceGen/Examples/Tutorial/Source/Tutorial2.S similarity index 100% rename from SourceGen/Examples/Tutorial/Tutorial2.S rename to SourceGen/Examples/Tutorial/Source/Tutorial2.S diff --git a/SourceGen/Examples/Tutorial/Source/Tutorial4.S b/SourceGen/Examples/Tutorial/Source/Tutorial4.S new file mode 100644 index 0000000..fa03b54 --- /dev/null +++ b/SourceGen/Examples/Tutorial/Source/Tutorial4.S @@ -0,0 +1,23 @@ +; Copyright 2019 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + + org $1000 + + jsr PrintInlineL1String + str 'How long?' + + jsr PrintInlineZString1 + asc 'Test one',00 + + jsr PrintInlineZString2 + asc 'Test two',00 + rts + +PrintInlineL1String + rts +PrintInlineZString1 + rts +PrintInlineZString2 + rts diff --git a/SourceGen/Examples/Tutorial/Tutorial4 b/SourceGen/Examples/Tutorial/Tutorial4 new file mode 100644 index 0000000..c8968a9 Binary files /dev/null and b/SourceGen/Examples/Tutorial/Tutorial4 differ diff --git a/SourceGen/RuntimeData/Help/index.html b/SourceGen/RuntimeData/Help/index.html index 23c4e6c..45e5157 100644 --- a/SourceGen/RuntimeData/Help/index.html +++ b/SourceGen/RuntimeData/Help/index.html @@ -164,6 +164,8 @@ and 65816 code. The official web site is diff --git a/SourceGen/RuntimeData/Help/tutorials.html b/SourceGen/RuntimeData/Help/tutorials.html index 0a01871..897427d 100644 --- a/SourceGen/RuntimeData/Help/tutorials.html +++ b/SourceGen/RuntimeData/Help/tutorials.html @@ -21,8 +21,8 @@ manual is recommended.

@@ -539,7 +539,7 @@ extra symbol in the opcode field, you need to look closely at what's going on.

-

Tutorial #2a: Address Table Formatting

+

Tutorial #3: Address Table Formatting

This tutorial covers one specific feature.

@@ -591,6 +591,11 @@ You could repeat these steps for the remaining items, but there's a faster way. Click on the line at address $1d97, then shift-click the line at address $1da9 (which should be .FILL 12,$1e). Select Actions > Format Address Table.

+

Contrary to first impressions, this imposing dialog does not allow you +to launch objects into orbit. There are a variety of common ways to +structure an address table, all of which are handled here. You can +configure the various parameters and see the effects as you make +each change.

The message at the top should indicate that there are 30 bytes selected. In Address Characteristics, click the "Parts are split across sub-tables" checkbox and the "adjusted for RTS/RTL" @@ -614,7 +619,7 @@ code entry point hint -- but did several of them at once.

SourceGen asks for confirmation, click Discard & Continue.

-

Tutorial #2b: Extension Scripts

+

Tutorial #4: Extension Scripts

This tutorial covers one specific feature.

@@ -624,10 +629,9 @@ because code is expected.

An earlier tutorial demonstrated how to manually mark bytes as inline data. We're going to do it a faster way. For this tutorial, start a new project with "Generic 6502", and in the SourceGen -installation directory find the Examples directory, open the Scripts -subdirectory, and select "Sample".

+Tutorial directory select "Tutorial4".

We'll need to load scripts from the project directory, so we have to -save the project. File > Save, call it the default name (Sample.dis65).

+save the project. File > Save, use the default name ("Tutorial4.dis65").

Take a look at the disassembly listing. The file starts with a JSR followed by a string that begins with a small number. This appears to be @@ -657,9 +661,9 @@ on line $1019 ("L1028"), setting the label to "PrintInlineNullStringTwo".

The entire project is now nicely formatted. In a real project the "Print Inline" locations would be actual print functions, not just RTS -instructions, and there would be multiple JSRs to a single function. -So labeling a single print function could format dozens of inline strings -and clean up the disassembly automatically.

+instructions. There would likely be multiple JSRs to the print function, +so labeling a single function entry point could format dozens of inline +strings and clean up the disassembly automatically.

Extension scripts can make your life much easier, but they do require some programming experience. See the