From 4b46b78e34624477d4ead7c736c237fafc7cda85 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Wed, 30 Oct 2019 09:49:11 -0700 Subject: [PATCH] Rearrange the tutorial files Copied the extension script tutorial files out of the Scripts directory and into the Tutorial directory. This makes more sense, and makes it possible to expand the script sample without altering the tutorial. Reverted the Scripts sample to be an actual sample, rather than a tutorial. Renumbered the last two tutorials and added them to the ToC. This gives them actual numbers rather than treating them as add-ons to the advanced tutorial. Moved the source files for the tutorial binaries into a subdirectory to reduce clutter. This does mean we have two separate copies of the inline string sample plugins, but that's an artifact of our attempts at security. --- SourceGen/Examples/Scripts/Sample.S | 5 ++ .../{FinishedSample.dis65 => Sample.dis65} | 2 +- SourceGen/Examples/Tutorial/InlineL1String.cs | 73 +++++++++++++++++ .../Examples/Tutorial/InlineNullTermString.cs | 76 ++++++++++++++++++ .../Tutorial/{ => Source}/Tutorial1.S | 0 .../Tutorial/{ => Source}/Tutorial2.S | 0 .../Examples/Tutorial/Source/Tutorial4.S | 23 ++++++ SourceGen/Examples/Tutorial/Tutorial4 | Bin 0 -> 41 bytes SourceGen/RuntimeData/Help/index.html | 2 + SourceGen/RuntimeData/Help/tutorials.html | 24 +++--- 10 files changed, 194 insertions(+), 11 deletions(-) rename SourceGen/Examples/Scripts/{FinishedSample.dis65 => Sample.dis65} (93%) create mode 100644 SourceGen/Examples/Tutorial/InlineL1String.cs create mode 100644 SourceGen/Examples/Tutorial/InlineNullTermString.cs rename SourceGen/Examples/Tutorial/{ => Source}/Tutorial1.S (100%) rename SourceGen/Examples/Tutorial/{ => Source}/Tutorial2.S (100%) create mode 100644 SourceGen/Examples/Tutorial/Source/Tutorial4.S create mode 100644 SourceGen/Examples/Tutorial/Tutorial4 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 0000000000000000000000000000000000000000..c8968a968d68c85b7d654d985cf3a1eca9e24be2 GIT binary patch literal 41 qcmY#T6X5j7FIULP&r7#gP!|YEEiO^W&r4-c(15T@%JUf#fB*pLtqbS? literal 0 HcmV?d00001 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