1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-09-30 23:55:09 +00:00

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.
This commit is contained in:
Andy McFadden 2019-10-30 09:49:11 -07:00
parent 51081c5db0
commit 4b46b78e34
10 changed files with 194 additions and 11 deletions

View File

@ -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

View File

@ -10,7 +10,7 @@
"Low":0,"High":0,"Hint":"Code"}],"StatusFlagOverrides":{
},
"Comments":{
},
"0":"requires exact name match","13":"requires name prefix match"},
"LongComments":{
},
"Notes":{

View File

@ -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 {
/// <summary>
/// Sample class for handling a JSR followed by a string prefixed with a 1-byte length.
/// </summary>
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<PlSymbol> 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);
}
}
}

View File

@ -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 {
/// <summary>
/// Sample class for handling a JSR followed by an inline null-terminated string. Any
/// label that starts with "PrintLineNullString" is matched.
/// </summary>
public class InlineNullTermString : MarshalByRefObject, IPlugin, IPlugin_SymbolList,
IPlugin_InlineJsr {
private IApplication mAppRef;
private byte[] mFileData;
private const string LABEL_PREFIX = "PrintInlineNullString";
private Dictionary<int, PlSymbol> mNullStringAddrs = new Dictionary<int, PlSymbol>();
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<PlSymbol> 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);
}
}
}

View File

@ -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

Binary file not shown.

View File

@ -164,6 +164,8 @@ and 65816 code. The official web site is
<ul>
<li><a href="tutorials.html#basic-features">Tutorial #1: Basic Features</a></li>
<li><a href="tutorials.html#advanced-features">Tutorial #2: Advanced Features</a></li>
<li><a href="tutorials.html#address-tables">Tutorial #3: Address Table Formatting</a></li>
<li><a href="tutorials.html#extension-scripts">Tutorial #4: Extension Scripts</a></li>
</ul></li>
</ul>

View File

@ -21,8 +21,8 @@ manual is recommended.</p>
<ul>
<li><a href="#basic-features">#1: Basic Features</a></li>
<li><a href="#advanced-features">#2: Advanced Features</a></li>
<li><a href="#address-table">#2a: Address Table Formatting</a></li>
<li><a href="#extension-scripts">#2b: Extension Scripts</a></li>
<li><a href="#address-tables">#3: Address Table Formatting</a></li>
<li><a href="#extension-scripts">#4: Extension Scripts</a></li>
</ul>
@ -539,7 +539,7 @@ extra symbol in the opcode field, you need to look closely at what's going
on.</p>
<h2><a name="address-table">Tutorial #2a: Address Table Formatting</a></h2>
<h2><a name="address-tables">Tutorial #3: Address Table Formatting</a></h2>
<p><i>This tutorial covers one specific feature.</i></p>
@ -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 <code>.FILL 12,$1e</code>). Select
Actions &gt; Format Address Table.</p>
<p>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.</p>
<p>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.</p>
SourceGen asks for confirmation, click Discard & Continue.</p>
<h2><a name="extension-scripts">Tutorial #2b: Extension Scripts</a></h2>
<h2><a name="extension-scripts">Tutorial #4: Extension Scripts</a></h2>
<p><i>This tutorial covers one specific feature.</i></p>
@ -624,10 +629,9 @@ because code is expected.</p>
<p>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".</p>
Tutorial directory select "Tutorial4".</p>
<p>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).</p>
save the project. File > Save, use the default name ("Tutorial4.dis65").</p>
<p>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".</p>
<p>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.</p>
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.</p>
<p>Extension scripts can make your life much easier, but they do require
some programming experience. See the