mirror of
https://github.com/fadden/6502bench.git
synced 2024-08-29 11:29:35 +00:00
Project symbol address values are now limited to positive 24-bit integers, just as they are for platform symbols. Constants may still be 32-bit values.
347 lines
16 KiB
HTML
347 lines
16 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
|
|
<head>
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<link href="main.css" rel="stylesheet" type="text/css" />
|
|
<title>Advanced Topics - 6502bench SourceGen</title>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="content">
|
|
<h1>6502bench SourceGen: Advanced Topics</h1>
|
|
<p><a href="index.html">Back to index</a></p>
|
|
|
|
|
|
<h2><a name="platform-symbols">Platform Symbol Files (.sym65)</a></h2>
|
|
|
|
<p>Platform symbol files contain lists of symbols, each of which has a
|
|
label and a value. SourceGen comes with a collection of symbols for
|
|
popular systems, but you can create your own. This can be handy if a
|
|
few different projects are coded against a common library.</p>
|
|
|
|
<p>If two symbols have the same value, the older symbol is replaced by
|
|
the newer one. This is why the order in which symbol files are loaded
|
|
matters.</p>
|
|
|
|
<p>Platform symbol files consist of comments, commands, and symbols.
|
|
Blank lines, and lines that begin with a semicolon (';'), are ignored. Lines
|
|
that begin with an asterisk ('*') are commands. Three are currently
|
|
defined:</p>
|
|
<ul>
|
|
<li><code>*SYNOPSIS</code> - a short summary of the file contents.</li>
|
|
<li><code>*TAG</code> - a tag string to apply to all symbols that follow
|
|
in this file.</li>
|
|
<li><code>*MULTI_MASK</code> - specify a mask for symbols that appear
|
|
at multiple addresses.</li>
|
|
</ul>
|
|
|
|
<p>Tags can be used by extension scripts to identify a subset of symbols.
|
|
The symbols are still part of the global set; the tag just provides a
|
|
way to extract a subset. Tags should be comprised of non-whitespace ASCII
|
|
characters. Tags are global, so use a long, descriptive string. If
|
|
<code>*TAG</code> is not followed by a string, the symbols that follow
|
|
are treated as untagged.</p>
|
|
|
|
<p>All other lines are symbols, which have the form:</p>
|
|
<pre>
|
|
LABEL {=|@|<|>} VALUE [WIDTH] [;COMMENT]
|
|
</pre>
|
|
|
|
<p>The LABEL must be at least two characters long, begin with a letter or
|
|
underscore, and consist entirely of alphanumeric ASCII characters
|
|
(A-Z, a-z, 0-9) and the underscore ('_'). (This is the same format
|
|
required for line labels in SourceGen.)</p>
|
|
<p>The next token can be one of:</p>
|
|
<ul>
|
|
<li>@: general addresses</li>
|
|
<li><: read-only addresses</li>
|
|
<li>>: write-only addresses</li>
|
|
<li>=: constants</li>
|
|
</ul>
|
|
<p>If an instruction references an address, and that address is outside
|
|
the bounds of the file, the list of address symbols (i.e. everything
|
|
that's not a constant) will be scanned for a match.
|
|
If found, the symbol is applied automatically. You normally want to
|
|
use '@', but can use '<' and '>' for memory-mapped I/O locations
|
|
that have different behavior depending on whether they are read or
|
|
written.</p>
|
|
|
|
<p>The VALUE is a number in decimal, hexadecimal (with a leading '$'), or
|
|
binary (with a leading '%'). The numeric base will be recorded and used when
|
|
formatting the symbol in generated output, so use whichever form is most
|
|
appropriate. Values are unsigned 24-bit numbers. The special value
|
|
"erase" may be used for an address to erase a symbol defined in an earlier
|
|
platform file.</p>
|
|
|
|
<p>The WIDTH is optional, and ignored for constants. It must be a
|
|
decimal or hexadecimal value between 1 and 65536, inclusive. If omitted,
|
|
the default width is 1.</p>
|
|
|
|
<p>The COMMENT is optional. If present, it will be saved and used as the
|
|
end-of-line comment on the .EQ directive if the symbol is used.</p>
|
|
|
|
<h4>Using MULTI_MASK</h4>
|
|
|
|
<p>The multi-address mask is used for systems like the Atari 2600, where
|
|
RAM, ROM, and I/O registers appear at multiple addresses. The hardware
|
|
looks for certain address lines to be set or clear, and if the pattern
|
|
matches, another set of bits is examined to determine which register or
|
|
RAM address is being accessed.</p>
|
|
<p>This is expressed in symbol files with the MULTI_MASK statement.
|
|
Address symbol declarations that follow have the mask set applied. Symbols
|
|
whose addresses don't fit the pattern cause a warning and will be
|
|
ignored. Constants are not affected.</p>
|
|
|
|
<p>The mask set is best explained with an example. Suppose the address
|
|
pattern for a set of registers is <code>???0 ??1? 1??x xxxx</code>
|
|
(where '?' can be any value, 0/1 must be that value, and 'x' means the bit
|
|
is used to determine the register).
|
|
So any address between $0280-029F matches, as does $23C0-23DF, but
|
|
$0480 and $1280 don't. The register number is found in the low five bits.</p>
|
|
<p>The corresponding MULTI_MASK line, with values specifed in binary,
|
|
would be:</p>
|
|
<pre> *MULTI_MASK %0001001010000000 %0000001010000000 %0000000000011111</pre>
|
|
<p>The values are CompareMask, CompareValue, and AddressMask. To
|
|
determine if an address is in the register set, we check to see if
|
|
<code>(address & CompareMask) == CompareValue</code>. If so, we can
|
|
extract the register number with <code>(address & AddressMask)</code>.</p>
|
|
|
|
<p>We don't want to have a huge collection of equates at the top of the
|
|
generated source file, so whatever value is used in the symbol declaration
|
|
is considered the "canonical" value. All other matching values are output
|
|
with an offset.</p>
|
|
<p>All mask values must fall between 0 and $00FFFFFF. The set bits in
|
|
CompareMask and AddressMask must not overlap, and CompareValue must not
|
|
have any bits set that aren't also set in CompareMask.</p>
|
|
<p>If an address can be mapped to a masked value and an unmasked value,
|
|
the unmasked value takes precedence for exact matches. In the example
|
|
above, if you declare <code>REG1 @ $0281</code> outside the MULTI_MASK
|
|
declaration, the disassembler will use <code>REG1</code> for all operands
|
|
that reference $0281. If other code accesses the same register as $23C1,
|
|
the symbol established for the masked value will be used instead.</p>
|
|
<p>If there are multiple masked values for a given address, the precedence
|
|
is undefined.</p>
|
|
<p>To disable the MULTI_MASK and resume normal declarations, write the
|
|
tag without arguments:
|
|
<pre> *MULTI_MASK</pre></p>
|
|
|
|
|
|
<h3>Creating a Project-Specific Symbol File</h3>
|
|
|
|
<p>To create a platform symbol file for your project, just create a new
|
|
text file, named with a ".sym65" extension. (If your text editor of choice
|
|
doesn't like that, you can put a ".txt" on the end while you're editing.)
|
|
Make sure you create it in the same directory where your project file
|
|
(the file that ends with ".dis65") lives. Add a <code>*SYNOPSIS</code>,
|
|
then add the desired symbols.</p>
|
|
<p>Finally, add it to your project. Select Edit > Project Properties,
|
|
switch to the Symbol Files tab, click Add Symbol Files from Project, and
|
|
select your symbol file. It should appear in the list with a
|
|
"PROJ:" prefix.</p>
|
|
|
|
<p>If an example helps, the A2-Amper-fdraw project in the Examples
|
|
directory has a project-local symbol file, called "fdraw-exports".
|
|
(fdraw-exports is a list of exported symbols from the fdraw library,
|
|
for which Amper-fdraw provides an Applesoft BASIC interface.)
|
|
|
|
<p>NOTE: in the current version of SourceGen, changes to .sym65 files are
|
|
not detected automatically. Closing and re-opening the project
|
|
(File > Recent Projects, then select the first entry) will reload
|
|
them.</p>
|
|
|
|
|
|
<h2><a name="extension-scripts">Extension Scripts</a></h2>
|
|
|
|
<p>Extension scripts, also called "plugins", are C# programs with access to
|
|
the full .NET Standard 2.0 APIs. They're compiled at run time by SourceGen
|
|
and executed in a sandbox with security restrictions.</p>
|
|
|
|
<p>SourceGen defines an interface that plugins must implement, and an
|
|
interface that plugins can use to interact with SourceGen. See
|
|
Interfaces.cs in the PluginCommon directory. <b>Bear in mind that this
|
|
feature is still evolving, and the interfaces may change significantly
|
|
in the near future.</b></p>
|
|
|
|
<p>The current interfaces can be used to identify inline data that follows
|
|
JSR, JSL, or BRK instructions, and to format operands. The latter can be
|
|
useful for replacing immediate load operands with symbolic constants.</p>
|
|
|
|
<p>Scripts may be loaded from the RuntimeData directory, or from the directory
|
|
where the project file lives. Attempts to load them from other locations
|
|
will fail.</p>
|
|
<p>A project may load multiple scripts. The order in which they are
|
|
invoked is not defined.</p>
|
|
|
|
<h4>Known Issues and Limitations</h4>
|
|
|
|
<p>When a project is opened, any errors encountered by the script compiler
|
|
are reported to the user. If the project is already open, and a script
|
|
is added to the project through the Project Properties editor, compiler
|
|
messages are silently discarded. (This also applies if you undo/redo across
|
|
the property edit.)</p>
|
|
|
|
<h4>Development</h4>
|
|
|
|
<p>The easiest way to develop extension scripts is inside the 6502bench
|
|
solution in Visual Studio. This way you have the interfaces available
|
|
for IntelliSense completion, and get all the usual syntax and compile
|
|
checking in the editor. (This is why there's a RuntimeData project for
|
|
Visual Studio.)</p>
|
|
|
|
<p>If you have the solution configured for debug builds, SourceGen will set
|
|
the IncludeDebugInformation flag to true when compiling scripts. This
|
|
causes a .PDB file to be created. While this can help with debugging,
|
|
it can sometimes get in the way: if you edit the script source code and
|
|
reload the project, SourceGen will recompile the script, but the old .PDB
|
|
file will still be open by VisualStudio and you'll get error messages.</p>
|
|
|
|
<p>Some commonly useful functions are defined in the PluginCommon.Util class,
|
|
which is available to plugins. These call into the CommonUtil library,
|
|
which is shared with SourceGen.
|
|
While plugins can use CommonUtil directly, they should avoid doing so. The
|
|
APIs there are not guaranteed to be stable, so plugins that rely on them
|
|
may break in a subsequent release of SourceGen.</p>
|
|
|
|
<h4>PluginDll Directory</h4>
|
|
|
|
<p>Extension scripts are compiled into .DLLs, and saved in the PluginDll
|
|
directory, which lives next to the application executable and RuntimeData.
|
|
If the extension script is the same age or older than the DLL, SourceGen
|
|
will continue to use the existing DLL.</p>
|
|
|
|
<p>The DLLs names are a combination of the script filename and script location.
|
|
The compiled name for "MyPlatform/MyScript.cs" in the RuntimeData directory
|
|
will be "RT_MyPlatform_MyScript.dll". For a project-specific script, it
|
|
would look like "PROJ_MyProject_MyScript.dll".</p>
|
|
|
|
<p>The PluginCommon and CommonUtil DLLs will be copied into the directory, so
|
|
that code in the sandbox has access to them.</p>
|
|
|
|
<h4>Sandboxing</h4>
|
|
|
|
<p>Extension scripts are executed in an App Domain sandbox. App domains are
|
|
a .NET feature that creates a partition inside the virtual machine, isolating
|
|
code. It still runs in the same address space, on the same threads, so the
|
|
isolation is only effective for "partially trusted" code that has been
|
|
declared safe by the bytecode verifier.</p>
|
|
|
|
<p>SourceGen disallows most actions, notably file access. An exception is
|
|
made for reading files from the directory where the plugin DLLs live, but
|
|
scripts are otherwise unable to read or write from the filesystem. (A
|
|
future version of SourceGen may provide an API that allows limited access
|
|
to data files.)</p>
|
|
|
|
<p>App domain security is not absolute. I don't really expect SourceGen to
|
|
be used as a malware vector, so there's no value in forcing scripts to
|
|
execute in an isolated server process, or to jump through the other hoops
|
|
required to really lock things down. I do believe there's value in
|
|
defining the API in such a way that we <b>could</b> implement full security if
|
|
circumstances change, so I'm using app domains as a way to keep the API
|
|
honest.</p>
|
|
|
|
|
|
<h2><a name="multi-bin">Working With Multiple Binaries</a></h2>
|
|
|
|
<p>Sometimes a program is split into multiple files on disk. They
|
|
may be all loaded at once, or some may be loaded into the same place
|
|
at different times. In such situations it's not uncommon for one
|
|
file to provide a set of interfaces that other files use. It's
|
|
useful to have symbols for these interfaces be available to all
|
|
projects.</p>
|
|
<p>There are two ways to do this: (1) define a common platform symbol
|
|
file with the relevant addresses, and keep it up to date as you work;
|
|
or (2) declare the labels as global and exported, and import them
|
|
as project symbols into the other projects.</p>
|
|
<p>Support for this is currently somewhat weak, requiring a manual
|
|
symbol-import step in every interested project. This step must be
|
|
repeated whenever the labels are updated.</p>
|
|
<p>A different but related problem is typified by arcade ROM sets,
|
|
where files are split apart because each file must be burned into a
|
|
separate PROM. All files are expected to be present in memory at
|
|
once, so there's no reason to treat them as separate projects. Currently,
|
|
the best way to deal with this is to concatenate the files into a single
|
|
file, and operate on that.</p>
|
|
|
|
<h2><a name="overlap">Overlapping Address Spaces</a></h2>
|
|
<p>Some programs use memory overlays, where multiple parts of the
|
|
code run in the same address in RAM. Others use bank switching to access
|
|
parts of the program that reside in separate physical RAM, but appear at
|
|
the same address.</p>
|
|
<p>SourceGen allows you to set the same address on multiple parts of
|
|
a file. Branches to a given address are resolved against the current
|
|
segment first. For example, consider this:</p>
|
|
<pre>
|
|
.ORG $1000
|
|
JMP L1100
|
|
|
|
.ORG $1100
|
|
L1100 BIT L1100
|
|
L1103 LDA #$11
|
|
BRA L1103
|
|
|
|
.ORG $1100
|
|
L1100_0 BIT L1100_0
|
|
L1103_0 LDA #$22
|
|
JMP L1103_0
|
|
</pre>
|
|
|
|
<p>Both sections start at $1100, and have branches to $1103. The branch
|
|
in the first section resolves to the label in the first version of
|
|
that address chunk, while the branch in the second section resolves to
|
|
the label in the second chunk. When branches originate outside the current
|
|
address chunk, the first chunk that includes that address is used, as
|
|
it is with the <code>JMP $1000</code> at the start of the file.</p>
|
|
|
|
|
|
<h2><a name="debug">Debug Menu Options</a></h2>
|
|
|
|
<p>The DEBUG menu is hidden by default in release builds, but can be
|
|
exposed by checking the "enable DEBUG menu" box in the application
|
|
settings. These features are used for debugging SourceGen. They will
|
|
not help you debug 6502 projects.</p>
|
|
|
|
<p>Features:</p>
|
|
<ul>
|
|
<li>Re-analyze (F5). Causes a full re-analysis. Useful if you think
|
|
the display is out of sync.</li>
|
|
<li>Show Problem List Viewer. Opens a floating window that shows some
|
|
of the problems encountered during the last analysis pass.</li>
|
|
<li>Show Undo/Redo History. Opens a floating window that lets you
|
|
watch the contents of the undo buffer while you work.</li>
|
|
<li>Show Analyzer Output. Opens a floating window with a text log from
|
|
the most recent analysis pass. The exact contents will vary depending
|
|
on how the verbosity level is configured internally. Debug messages
|
|
from extension scripts appear here.</li>
|
|
<li>Show Analysis Timers. Opens a floating window with a dump of
|
|
timer results from the most recent analysis pass. Times for individual
|
|
stages are noted, as are times for groups of functions. This
|
|
provides a crude sense of where time is being spent.</li>
|
|
<li>Extension Script Info. Shows a bit about the currently-loaded
|
|
extension scripts.</li>
|
|
<li>Toggle Comment Rulers. Adds a string of digits above every
|
|
multi-line comment (long comment, note). Useful for confirming that
|
|
the width limitation is being obeyed. These are added exactly
|
|
as shown, without comment delimiters, into generated assembly output,
|
|
which doesn't work out well if you run the assembler.</li>
|
|
<li>Use Keep-Alive Hack. If set, a "ping" is sent to the extension
|
|
script sandbox every 60 seconds. This seems to be required to avoid
|
|
an infrequently-encountered Windows bug. (See code for notes and
|
|
stackoverflow.com links.)</li>
|
|
<li>Source Generation Tests. Opens the regression test harness. See
|
|
the README.md in the SGTestData directory for more information. If
|
|
the regression tests weren't included in the SourceGen distribution,
|
|
this will have nothing to do.</li>
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
<div id="footer">
|
|
<p><a href="index.html">Back to index</a></p>
|
|
</div>
|
|
</body>
|
|
<!-- Copyright 2018 faddenSoft -->
|
|
</html>
|