From 4537f2495823e29a530324c7df1a071296f15a7c Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sun, 14 Nov 2021 09:02:53 -0800 Subject: [PATCH] Rework tutorial for changes in v1.8 Biggest changes were to the address region handling in Tutorial1 and the use of StdInline.cs for the inline strings in Tutorial4. Also, fixed the off-by-one error in Tutorial1. --- SourceGen/Examples/Tutorial/InlineL1String.cs | 77 -------- SourceGen/Examples/Tutorial/InlineMulti.cs | 153 --------------- .../Examples/Tutorial/InlineNullTermString.cs | 81 -------- .../Examples/Tutorial/Source/Tutorial1.S | 123 ++++++------ SourceGen/Examples/Tutorial/Tutorial1 | Bin 136 -> 136 bytes docs/sgtutorial/about-disasm.html | 2 +- docs/sgtutorial/address-tables.html | 2 +- docs/sgtutorial/advanced-topics.html | 2 +- docs/sgtutorial/digging-deeper.html | 12 +- docs/sgtutorial/editing-data.html | 2 +- docs/sgtutorial/extension-scripts.html | 107 ++++------- docs/sgtutorial/generating-code.html | 2 +- docs/sgtutorial/images/t1-1000-comment.png | Bin 0 -> 8479 bytes docs/sgtutorial/images/t1-2003-done.png | Bin 8479 -> 0 bytes docs/sgtutorial/images/t1-addr-chg-1017.png | Bin 14433 -> 14433 bytes docs/sgtutorial/images/t1-all-columns.png | Bin 14415 -> 22031 bytes docs/sgtutorial/images/t1-asmgen-asmout.png | Bin 15256 -> 19676 bytes docs/sgtutorial/images/t1-asmgen-preview.png | Bin 19635 -> 19731 bytes docs/sgtutorial/images/t1-click-1002.png | Bin 52475 -> 73061 bytes docs/sgtutorial/images/t1-click-1017.png | Bin 29137 -> 44734 bytes docs/sgtutorial/images/t1-code-list-1000.png | Bin 0 -> 5462 bytes docs/sgtutorial/images/t1-edit-2000-done.png | Bin 20452 -> 20632 bytes docs/sgtutorial/images/t1-pre-sym-2000.png | Bin 5621 -> 5621 bytes docs/sgtutorial/images/t1-prelabel-after.png | Bin 0 -> 21583 bytes docs/sgtutorial/images/t1-prelabel-before.png | Bin 0 -> 4071 bytes docs/sgtutorial/images/t1-prelabel-edit.png | Bin 0 -> 22476 bytes docs/sgtutorial/images/t1-select-info.png | Bin 0 -> 5043 bytes docs/sgtutorial/images/t1-set-addr-1017.png | Bin 30041 -> 56783 bytes docs/sgtutorial/images/t1-set-addr-fixed.png | Bin 0 -> 40388 bytes .../images/t1-simple-instr-edit.png | Bin 47065 -> 51828 bytes docs/sgtutorial/images/t1-symbol-filters.png | Bin 6958 -> 7110 bytes docs/sgtutorial/images/t2-1000-edit1.png | Bin 6155 -> 6155 bytes docs/sgtutorial/images/t2-1000-edit2.png | Bin 6680 -> 6680 bytes docs/sgtutorial/images/t2-1000-fmt-word.png | Bin 6404 -> 6404 bytes docs/sgtutorial/images/t2-1000-ready.png | Bin 12509 -> 12509 bytes docs/sgtutorial/images/t2-1000-setcode.png | Bin 8557 -> 8663 bytes docs/sgtutorial/images/t2-tutorial-top.png | Bin 10401 -> 11572 bytes docs/sgtutorial/images/t4-inlinel1-done.png | Bin 8358 -> 8358 bytes docs/sgtutorial/images/t4-inlinel1-edit.png | Bin 54123 -> 54123 bytes docs/sgtutorial/images/t4-inlinel1-src.png | Bin 2926 -> 0 bytes .../images/t4-inlinemulti-before.png | Bin 8745 -> 0 bytes .../sgtutorial/images/t4-inlinemulti-done.png | Bin 25494 -> 25494 bytes docs/sgtutorial/images/t4-inlinemulti-src.png | Bin 4599 -> 0 bytes docs/sgtutorial/images/t4-inlinenull-done.png | Bin 19329 -> 19329 bytes docs/sgtutorial/images/t4-inlinenull-src.png | Bin 2140 -> 0 bytes docs/sgtutorial/images/t4-stdinline-src.png | Bin 0 -> 4918 bytes docs/sgtutorial/incl-sidenav.html | 2 +- docs/sgtutorial/index.html | 2 +- docs/sgtutorial/inline-data.html | 2 +- docs/sgtutorial/labels-symbols.html | 57 +++++- docs/sgtutorial/local-variables.html | 4 +- .../{simple-edits.html => making-edits.html} | 176 +++++++++++++----- docs/sgtutorial/moving-around.html | 27 ++- docs/sgtutorial/odds-ends.html | 2 +- docs/sgtutorial/prevnext.py | 2 +- docs/sgtutorial/string-formatting.html | 2 +- docs/sgtutorial/suggestions.html | 51 +++-- docs/sgtutorial/using-sourcegen.html | 2 +- docs/sgtutorial/visualizations.html | 2 +- 59 files changed, 349 insertions(+), 545 deletions(-) delete mode 100644 SourceGen/Examples/Tutorial/InlineL1String.cs delete mode 100644 SourceGen/Examples/Tutorial/InlineMulti.cs delete mode 100644 SourceGen/Examples/Tutorial/InlineNullTermString.cs create mode 100644 docs/sgtutorial/images/t1-1000-comment.png delete mode 100644 docs/sgtutorial/images/t1-2003-done.png create mode 100644 docs/sgtutorial/images/t1-code-list-1000.png create mode 100644 docs/sgtutorial/images/t1-prelabel-after.png create mode 100644 docs/sgtutorial/images/t1-prelabel-before.png create mode 100644 docs/sgtutorial/images/t1-prelabel-edit.png create mode 100644 docs/sgtutorial/images/t1-select-info.png create mode 100644 docs/sgtutorial/images/t1-set-addr-fixed.png delete mode 100644 docs/sgtutorial/images/t4-inlinel1-src.png delete mode 100644 docs/sgtutorial/images/t4-inlinemulti-before.png delete mode 100644 docs/sgtutorial/images/t4-inlinemulti-src.png delete mode 100644 docs/sgtutorial/images/t4-inlinenull-src.png create mode 100644 docs/sgtutorial/images/t4-stdinline-src.png rename docs/sgtutorial/{simple-edits.html => making-edits.html} (60%) diff --git a/SourceGen/Examples/Tutorial/InlineL1String.cs b/SourceGen/Examples/Tutorial/InlineL1String.cs deleted file mode 100644 index 7953a89..0000000 --- a/SourceGen/Examples/Tutorial/InlineL1String.cs +++ /dev/null @@ -1,77 +0,0 @@ -// 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 label. - 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 Unprepare() { - mAppRef = null; - mFileData = null; - } - - 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[offset + 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/InlineMulti.cs b/SourceGen/Examples/Tutorial/InlineMulti.cs deleted file mode 100644 index 2a10fda..0000000 --- a/SourceGen/Examples/Tutorial/InlineMulti.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2021 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 { - /// - /// Formats three different kinds of inline functions: - /// - /// PrintInlineL1String: format following data as L1 string - /// PrintInlineNullString*: format following data as null-term string. - /// PrintInlineAddrString*: format following data as 16-bit pointer to null-term string. - /// - public class InlineMultiData : MarshalByRefObject, IPlugin, IPlugin_SymbolList, - IPlugin_InlineJsr { - private IApplication mAppRef; - private byte[] mFileData; - private AddressTranslate mAddrTrans; - - private const string L1STR_NAME = "PrintInlineL1String"; - private const string NULLSTR_PREFIX = "PrintInlineNullString"; - private const string ADDRSTR_PREFIX = "PrintInlineAddrString"; - private enum InlineKind { Unknown = 0, L1Str, NullStr, AddrStr }; - - private Dictionary mInlineLabels = new Dictionary(); - - public string Identifier { - get { - return "Inline multi-data formatter"; - } - } - - public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) { - mAppRef = appRef; - mFileData = fileData; - mAddrTrans = addrTrans; - - mAppRef.DebugLog("InlineMultiData(id=" + - AppDomain.CurrentDomain.Id + "): prepare()"); - } - - public void Unprepare() { - mAppRef = null; - mFileData = null; - mAddrTrans = null; - } - - public void UpdateSymbolList(List plSyms) { - mInlineLabels.Clear(); - - // Find matching symbols. Save the symbol's value (its address) and the type. - // We want an exact match on L1STR_NAME, and prefix matches on the other two. - foreach (PlSymbol sym in plSyms) { - if (sym.Label.Equals(L1STR_NAME)) { - mInlineLabels.Add(sym.Value, InlineKind.L1Str); - } else if (sym.Label.StartsWith(NULLSTR_PREFIX)) { - mInlineLabels.Add(sym.Value, InlineKind.NullStr); - } else if (sym.Label.StartsWith(ADDRSTR_PREFIX)) { - mInlineLabels.Add(sym.Value, InlineKind.AddrStr); - } - } - mAppRef.DebugLog("Found matches for " + mInlineLabels.Count + " labels"); - } - - public bool IsLabelSignificant(string beforeLabel, string afterLabel) { - return DoesLabelMatch(beforeLabel) || DoesLabelMatch(afterLabel); - } - private static bool DoesLabelMatch(string label) { - return (label.Equals(L1STR_NAME) || - label.StartsWith(NULLSTR_PREFIX) || - label.StartsWith(ADDRSTR_PREFIX)); - } - - public void CheckJsr(int offset, int operand, out bool noContinue) { - noContinue = false; - - InlineKind kind; - if (!mInlineLabels.TryGetValue(operand, out kind)) { - return; - } - - switch (kind) { - case InlineKind.L1Str: - // Length-delimited ASCII string - FormatL1String(offset + 3); - break; - case InlineKind.NullStr: - // Null-terminated ASCII string. - FormatNullTermString(offset + 3); - break; - case InlineKind.AddrStr: - // Pointer to data. Format as address. Start by confirming next two - // bytes are inside the file bounds. - if (!Util.IsInBounds(mFileData, offset + 3, 2)) { - return; - } - // Format 16-bit value as an address. - mAppRef.SetInlineDataFormat(offset + 3, 2, - DataType.NumericLE, DataSubType.Address, null); - - // Now format the string that the address points to. Extract the - // address from the operand. - int strAddr = Util.GetWord(mFileData, offset + 3, 2, false); - // Convert the address to a file offset. Returns -1 if not in file bounds. - int strOff = mAddrTrans.AddressToOffset(offset, strAddr); - // Format it if it's in bounds. - FormatNullTermString(strOff); - break; - } - } - - private void FormatL1String(int offset) { - if (offset < 0 || offset >= mFileData.Length) { - return; // length byte is not inside file - } - int len = mFileData[offset]; - if (offset + 1 + len > mFileData.Length) { - mAppRef.DebugLog("L1 string ran off end of file at +" + - (offset + 1).ToString("x6")); - return; - } - - // Assuming ASCII. - mAppRef.SetInlineDataFormat(offset, len + 1, - DataType.StringL8, DataSubType.Ascii, null); - } - - private void FormatNullTermString(int offset) { - if (offset < 0 || offset >= mFileData.Length) { - return; // start is not inside file - } - // search for the terminating null byte - int nullOff = offset; - while (nullOff < mFileData.Length) { - if (mFileData[nullOff] == 0x00) { - break; - } - nullOff++; - } - if (nullOff == mFileData.Length) { - mAppRef.DebugLog("Unable to find end of null-terminated string at +" + - offset.ToString("x6")); - return; - } - - // Assuming ASCII. - mAppRef.SetInlineDataFormat(offset, nullOff - offset + 1, - DataType.StringNullTerm, DataSubType.Ascii, null); - } - } -} diff --git a/SourceGen/Examples/Tutorial/InlineNullTermString.cs b/SourceGen/Examples/Tutorial/InlineNullTermString.cs deleted file mode 100644 index 4ddd2b5..0000000 --- a/SourceGen/Examples/Tutorial/InlineNullTermString.cs +++ /dev/null @@ -1,81 +0,0 @@ -// 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 Unprepare() { - mAppRef = null; - mFileData = null; - } - - public void UpdateSymbolList(List plSyms) { - mNullStringAddrs.Clear(); - - // Find matching symbols. - 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] == 0x00) { - 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/Source/Tutorial1.S b/SourceGen/Examples/Tutorial/Source/Tutorial1.S index dda99b7..26093c8 100644 --- a/SourceGen/Examples/Tutorial/Source/Tutorial1.S +++ b/SourceGen/Examples/Tutorial/Source/Tutorial1.S @@ -1,62 +1,61 @@ -; Copyright 2018 faddenSoft. All Rights Reserved. -; See the LICENSE.txt file for distribution terms (Apache 2.0). -; -; Assembler: Merlin 32 - -INPUT equ $3000 -OUTPUT equ $0400 - - org $1000 - - ldy #END-AFTER -copy lda BEFORE,y - sta AFTER,y - dey - bmi done - bpl copy - - dfb $00 -stuff asc 'hello!' - -done jmp AFTER - -BEFORE - org $2000 -AFTER - - lda INPUT ;expecting 0-3 - cmp #4 - blt :valid - lda #4 ;error message -:valid asl A - tax - lda stringtab,x ;set load to address - sta _load+1 - lda stringtab+1,x - sta _load+2 - - ldy #12 ;fixed-width strings -_load lda $0000,y ;self-modifying code - ora #$80 - sta OUTPUT,y - dey - bpl _load - - rts - -stringtab - dw string0 - dw string1 - dw string2 - dw string3 - dw stringX - dfb $00 - -string0 asc 'string zero ' -string1 asc 'string one ' -string2 asc 'string two ' -string3 asc 'string three ' -stringX asc 'invalid index' - -END - +; Copyright 2018 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + +INPUT equ $3000 +OUTPUT equ $0400 + + org $1000 + + ldy #END-AFTER-1 +copy lda BEFORE,y + sta AFTER,y + dey + bpl copy + bmi done + + dfb $00 +stuff asc 'hello!' + +done jmp AFTER + +BEFORE + org $2000 +AFTER + + lda INPUT ;expecting 0-3 + cmp #4 + blt :valid + lda #4 ;error message +:valid asl A + tax + lda stringtab,x ;set load to address + sta _load+1 + lda stringtab+1,x + sta _load+2 + + ldy #12 ;fixed-width strings +_load lda $0000,y ;self-modifying code + ora #$80 + sta OUTPUT,y + dey + bpl _load + + rts + +stringtab + dw string0 + dw string1 + dw string2 + dw string3 + dw stringX + dfb $00 + +string0 asc 'string zero ' +string1 asc 'string one ' +string2 asc 'string two ' +string3 asc 'string three ' +stringX asc 'invalid index' + +END diff --git a/SourceGen/Examples/Tutorial/Tutorial1 b/SourceGen/Examples/Tutorial/Tutorial1 index 79009e8d74cd57e864a357b6991c2b23964323b1..dc520f6089f37735b9a2be497d3035d24b2c5ee6 100644 GIT binary patch delta 21 ccmeBR>|o?wP_R>6U?zh?hro9O_KCdJ07!BMr~m)} delta 21 ccmeBR>|o?wP`FcEU?zh?hXJR+*NME<07m5osQ>@~ diff --git a/docs/sgtutorial/about-disasm.html b/docs/sgtutorial/about-disasm.html index 0ef2b05..2496f3a 100644 --- a/docs/sgtutorial/about-disasm.html +++ b/docs/sgtutorial/about-disasm.html @@ -58,7 +58,7 @@
  • Using SourceGen