1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-30 15:29:01 +00:00
6502bench/docs/sgtutorial/extension-scripts.html
Andy McFadden 992e008e7d Add multi-inline extension script to tutorial
It's useful to have an example of an extension script that handles
multiple types of things.  It's also good to show that scripts can
handle data types other than strings, and can chase an address to
format data items elsewhere in the code.

This required updating the tutorial binary, adding the new script,
and updating the tutorial text and associated screen shots.
2021-08-15 10:00:00 -07:00

283 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<!-- START: /incl-head.html -->
<!-- common head elements -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"
integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="../main.css"/>
<!-- END: /incl-head.html -->
<title>Extension Scripts - SourceGen Tutorial</title>
</head>
<body>
<!-- START: /incl-masthead.html -->
<div id="masthead">
<!--<div class="masthead-title" style="background-image: url('images/screenshot-mainwin.png');">-->
<div class="masthead-title">
6502bench
</div>
</div>
<!-- END: /incl-masthead.html -->
<!-- START: /incl-topnav.html active:#topnav-sgtutorial -->
<div id="topnav">
<!-- top navigation bar contents -->
<nav>
<a id="topnav-home" href=".././">HOME</a>
<a id="topnav-sgtutorial" class="active" href="../sgtutorial">SourceGen Tutorial</a>
<a id="topnav-menuicon" href="javascript:void(0);" class="icon" onclick="toggleSidenav()">
<i class="fa fa-bars"></i>
</a>
</nav>
<script>
// Sidenav toggle function.
//
// Use a jQuery function to toggle the sidenav bar. The initial state
// is undefined / inherited, so it will pop in and out as the screen
// resizes around the "large" breakpoint.
function toggleSidenav() {
$("#sidenav").toggle("fast");
}
</script>
</div>
<!-- END: /incl-topnav.html -->
<!-- START: incl-sidenav.html active:#sidenav-extension-scripts -->
<div id="sidenav">
<!-- side navigation bar contents -->
<ul>
<li id="sidenav-index"><a href="./">Introduction</a></li>
<li id="sidenav-about-disasm"><a href="about-disasm.html">About Disassembly</a></li>
<li id="sidenav-using-sourcegen"><a href="using-sourcegen.html">Using SourceGen</a>
<ul>
<li id="sidenav-moving-around"><a href="moving-around.html">Moving Around</a></li>
<li id="sidenav-simple-edits"><a href="simple-edits.html">Simple Edits</a></li>
<li id="sidenav-labels-symbols"><a href="labels-symbols.html">Labels &amp; Symbols</a></li>
<li id="sidenav-editing-data"><a href="editing-data.html">Editing Data Operands</a></li>
<li id="sidenav-generating-code"><a href="generating-code.html">Generating Code</a></li>
</ul></li>
<li id="sidenav-digging-deeper"><a href="digging-deeper.html">Digging Deeper</a>
<ul>
<li id="sidenav-string-formatting"><a href="string-formatting.html">String Formatting</a></li>
<li id="sidenav-local-variables"><a href="local-variables.html">Local Variables</a></li>
<li id="sidenav-inline-data"><a href="inline-data.html">Inline Data</a></li>
<li id="sidenav-odds-ends"><a href="odds-ends.html">Odds &amp; Ends</a></li>
</ul></li>
<li id="sidenav-advanced-topics"><a href="advanced-topics.html">Advanced Topics</a>
<ul>
<li id="sidenav-address-tables"><a href="address-tables.html">Address Tables</a></li>
<li id="sidenav-extension-scripts" class="active"><a href="extension-scripts.html">Extension Scripts</a></li>
<li id="sidenav-visualizations"><a href="visualizations.html">Visualizations</a></li>
</ul></li>
<li id="sidenav-suggestions"><a href="suggestions.html">Suggestions</a></li>
</ul>
</div>
<!-- END: incl-sidenav.html -->
<div id="main">
<h2>Extension Scripts</h2>
<div class="grid-container">
<div class="grid-item-text">
<p>Some repetitive formatting tasks can be handled with automatic scripts.
This is especially useful for inline data, which can confuse the code
analyzer.</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 the <samp>Generic 6502</samp> profile, and
in the SourceGen Examples/Tutorial directory select "Tutorial4".</p>
<p>We'll need to load scripts from the project directory, so we have to
save the project. <samp>File &gt; Save</samp>,
use the default name ("Tutorial4.dis65").</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-add-inlinel1.png" alt="t4-add-inlinel1"/>
</div>
<div class="grid-item-text">
<p>Take a look at the disassembly listing. The file starts with a
<code>JSR</code> followed by a string that begins with a small number.
This appears to be a string with a leading length byte. We want to load
a script that can handle that, so use
<samp>Edit &gt; Project Properties</samp>, select the
<samp>Extension Scripts</samp> tab, and click
<samp>Add Scripts from Project</samp>. The file
browser opens in the project directory. Select the file
"InlineL1String.cs", click <samp>Open</samp>, then <samp>OK</samp>.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinel1-src.png" alt="t4-inlinel1-src"/>
</div>
<div class="grid-item-text">
<p>Nothing happened. If you look at the script with an editor (and you
know some C#), you'll see that it's looking for a <code>JSR</code> to a
function called <code>PrintInlineL1String</code>. So let's give it one.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-text">
<p>Double-click the <code>JSR</code> opcode on line $1000
to jump to address $1036. The only thing there is an <code>RTS</code>.
It's supposed to be a routine that prints a string with a leading length
byte, but for the sake of keeping the example code short it's just a
place-holder. Use the curly toolbar arrow
(or <kbd class="key">Alt+LeftArrow</kbd>) to jump back to $1000.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinel1-edit.png" alt="t4-inlinel1-edit"/>
</div>
<div class="grid-item-text">
<p>This time, double-click the <code>JSR</code> <i>operand</i>
("<samp>L1036</samp>") to edit the operand.
Click <samp>Create Label</samp>, and enter <kbd>PrintInlineL1String</kbd>.
Remember that labels are case-sensitive;
you must enter it exactly as shown. Hit <samp>OK</samp> to accept the label,
and <samp>OK</samp> to close the operand editor.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinel1-done.png" alt="t4-inlinel1-done"/>
</div>
<div class="grid-item-text">
<p>If all went well, address $1003
should now be an L1 string "<code>How long?</code>", and address $100D
should be another <code>JSR</code>.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-text">
<p>The next <code>JSR</code> appears to be followed by a null-terminated string, so
we'll need something that handles that.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinenull-src.png" alt="t4-inlinenull-src"/>
</div>
<div class="grid-item-text">
<p>Go back into Project Properties
and add the script called "InlineNullTermString.cs" from the project directory.
This script is slightly different, in that it handles any <code>JSR</code> to a label
that starts with <code>PrintInlineNullString</code>. So let's give it a couple of
those.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinenull-done.png" alt="t4-inlinenull-done"/>
</div>
<div class="grid-item-text">
<p>Double-click the operand on line $100D ("<code>L1037</code>"),
click <samp>Create Label</samp>,
and set the label to "<kbd>PrintInlineNullStringOne</kbd>".
Hit <samp>OK</samp> twice. That formatted the first one and got us
to the next <code>JSR</code>. Repeat the process on line $1019
("<code>L1038</code>"), setting the label to "<kbd>PrintInlineNullStringTwo</kbd>".</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinemulti-before.png" alt="t4-inlinemulti-before"/>
</div>
<div class="grid-item-text">
<p>Things are looking good, but we've got one left, and it's got a
twist. Instead of a string, the <code>JSR</code> at $1025 is followed by a
pointer to a string. We'd like to format the pointer as an address,
and then format the string it points to.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinemulti-src.png" alt="t4-inlinemulti-src"/>
</div>
<div class="grid-item-text">
<p>We're going to add a third extension script. Sometimes it's
convenient to collect all inline data handlers for a project into a
single script, so we'll demonstrate that here. The new script handles
the previous two cases as well as this new case.
Go into Project
Properties, click the Extension Scripts tab, select the two scripts
you added earlier, and click Remove. Then add the script "InlineMulti.cs"
from the project directory. Click <samp>OK</samp> twice. Note that
the strings formatted earlier remain formatted.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-image">
<img src="images/t4-inlinemulti-done.png" alt="t4-inlinemulti-done"/>
</div>
<div class="grid-item-text">
<p>Double-click the operand on line $1025 ("<code>L1039</code>"),
click <samp>Create Label</samp>,
and set the label to "<kbd>PrintInlineAddrString</kbd>".
Hit <samp>OK</samp> twice. This formatted the address at $1028,
and also formatted the string at $102b as a null-terminated string.
Because the bytes were formatted as an address and not a just a
16-bit value, a label was generated automatically.</p>
</div>
</div>
<div class="grid-container">
<div class="grid-item-text">
<p>The entire project is now nicely formatted. In a real project the
"Print Inline" locations would be actual print functions, not just <code>RTS</code>
instructions. There would likely be multiple <code>JSR</code>s to the print function,
so labeling a single function entry point could format dozens of inline
strings and clean up the disassembly automatically. The reason for
allowing wildcard names is that some functions may have multiple
entry points or chain through different locations.</p>
<p>Extension scripts can make your life much easier, but they do require
some programming experience. See the SourceGen manual for more details.</p>
</div>
</div>
</div> <!-- #main -->
<div id="prevnext">
<a href="address-tables.html" class="btn-previous">&laquo; Previous</a>
<a href="visualizations.html" class="btn-next">Next &raquo;</a>
</div>
<!-- START: /incl-footer.html -->
<div id="footer">
<hr/>
<p>Copyright 2021 faddenSoft</p>
<!-- <p id="screen-size"></p>
<script>
var w = window.innerWidth;
var h = window.innerHeight;
var x = document.getElementById("screen-size");
x.innerHTML = "DEBUG: initial window size " + w + "x" + h;
</script> -->
</div>
<!-- END: /incl-footer.html -->
</body>
</html>