mirror of
https://github.com/AppleCommander/bastools.git
synced 2025-02-09 00:30:32 +00:00
Adding a "wrapper" capability to help with DOS rewriting application. #24
This commit is contained in:
parent
089356a3a2
commit
5e72a68c42
@ -8,14 +8,6 @@ Generally, the usage pattern is:
|
||||
|
||||
## Code snippets
|
||||
|
||||
```java
|
||||
Configuration config = Configuration.builder()
|
||||
.sourceFile(this.sourceFile)
|
||||
.build();
|
||||
```
|
||||
|
||||
The `Configuration` class also allows the BASIC start address to be set (defaults to `0x801`), set the maximum line length (this is in bytes, and defaults to `255`, but feel free to experiment). Some of the classes report output via the debug stream, which defaults to a simple null stream (no output) - replace with `System.out` or another `PrintStream`.
|
||||
|
||||
```java
|
||||
Queue<Token> tokens = TokenReader.tokenize(config.sourceFile);
|
||||
```
|
||||
@ -29,6 +21,21 @@ Program program = parser.parse();
|
||||
|
||||
The `Program` is now the parsed version of the BASIC program. Various `Visitor`s may be used to report, gather information, or manipulate the tree in various ways.
|
||||
|
||||
```java
|
||||
Configuration config = Configuration.builder()
|
||||
.sourceFile(this.sourceFile)
|
||||
.build();
|
||||
```
|
||||
|
||||
The `Configuration` class also allows the BASIC start address to be set (defaults to `0x801`), set the maximum line length (this is in bytes, and defaults to `255`, but feel free to experiment). Some of the classes report output via the debug stream, which defaults to a simple null stream (no output) - replace with `System.out` or another `PrintStream`.
|
||||
|
||||
```java
|
||||
ByteVisitor byteVisitor = Visitors.byteVisitor(config);
|
||||
byte[] programData = byteVisitor.dump(program);
|
||||
```
|
||||
|
||||
Finally, the ByteVisitor will transform the program into the tokenized form.
|
||||
|
||||
## Directives
|
||||
|
||||
The framework allows embedding of directives.
|
||||
|
@ -63,6 +63,7 @@ public class ByteVisitor implements Visitor {
|
||||
ByteArrayOutputStream os = stack.peek();
|
||||
os.write(0x00);
|
||||
os.write(0x00);
|
||||
this.address += 2;
|
||||
return program;
|
||||
}
|
||||
|
||||
|
@ -1,47 +1,47 @@
|
||||
## Usage
|
||||
|
||||
```shell
|
||||
$ bt
|
||||
Missing required parameter: <sourceFile>
|
||||
$ bt --help
|
||||
Usage: bt [-chOVx] [--addresses] [--applesingle] [--debug] [--list] [--pretty]
|
||||
[--stdout] [--tokens] [--variables]
|
||||
[--max-line-length=<maxLineLength>] [-a=<address>] [-o=<outputFile>]
|
||||
[--stdout] [--tokens] [--variables] [--wrapper] [-a=<address>]
|
||||
[--max-line-length=<maxLineLength>] [-o=<outputFile>]
|
||||
[-f=<optimizations>[,<optimizations>...]]... <sourceFile>
|
||||
|
||||
Transforms an AppleSoft program from text back to its tokenized state.
|
||||
<sourceFile> AppleSoft BASIC program to process.
|
||||
|
||||
Options:
|
||||
--addresses Dump line number addresses out.
|
||||
--applesingle Write output in AppleSingle format
|
||||
--debug Print debug output.
|
||||
--list List structure as bastools understands it.
|
||||
--max-line-length=<maxLineLength>
|
||||
Maximum line length for generated lines.
|
||||
Default: 255
|
||||
--pretty Pretty print structure as bastools understands it.
|
||||
--stdout Send binary output to stdout.
|
||||
--tokens Dump token list to stdout for debugging.
|
||||
--variables Generate a variable report
|
||||
-a, --address=<address> Base address for program
|
||||
Default: 2049
|
||||
-c, --copy Generate a copy/paste form of output for testing in an
|
||||
emulator.
|
||||
-f= <optimizations>[,<optimizations>...]
|
||||
--addresses Dump line number addresses out.
|
||||
--applesingle Write output in AppleSingle format
|
||||
-c, --copy Generate a copy/paste form of output for testing in
|
||||
an emulator.
|
||||
--debug Print debug output.
|
||||
-f=<optimizations>[,<optimizations>...]
|
||||
Enable specific optimizations.
|
||||
* remove-empty-statements - Strip out all '::'-like
|
||||
statements.
|
||||
* remove-rem-statements - Remove all REM statements.
|
||||
* shorten-variable-names - Ensure all variables are 1 or
|
||||
2 characters long.
|
||||
* extract-constant-values - Assign all constant values
|
||||
first.
|
||||
* shorten-variable-names - Ensure all variables are
|
||||
1 or 2 characters long.
|
||||
* extract-constant-values - Assign all constant
|
||||
values first.
|
||||
* merge-lines - Merge lines.
|
||||
* renumber - Renumber program.
|
||||
-h, --help Show this help message and exit.
|
||||
--list List structure as bastools understands it.
|
||||
--max-line-length=<maxLineLength>
|
||||
Maximum line length for generated lines.
|
||||
Default: 255
|
||||
-o, --output=<outputFile> Write binary output to file.
|
||||
-O, --optimize Apply all optimizations.
|
||||
--pretty Pretty print structure as bastools understands it.
|
||||
--stdout Send binary output to stdout.
|
||||
--tokens Dump token list to stdout for debugging.
|
||||
-V, --version Print version information and exit.
|
||||
--variables Generate a variable report
|
||||
--wrapper Wrap the Applesoft program (DOS 3.3).
|
||||
-x, --hex Generate a binary hex dump for debugging.
|
||||
```
|
||||
|
||||
@ -153,3 +153,13 @@ demo.dsk /DEMO/
|
||||
ProDOS format; 139,264 bytes free; 4,096 bytes used.
|
||||
|
||||
```
|
||||
|
||||
## Wrapping the application
|
||||
|
||||
DOS 3.3 (but not ProDOS) seems to rewrite the application linked list when an Applesoft program is loaded; this rewrites the pointers and impacts any embedded (via `$embed`) machine code. With the wrapper, the application is "wrapped" with a startup Applesoft program that prevents the rewrite. The wrapper is just a simple program:
|
||||
|
||||
```basic
|
||||
10 POKE 103,24:POKE 104,8:RUN
|
||||
```
|
||||
|
||||
This is a valid program that resets to Applesoft pointer to just after the current program and runs that other program.
|
||||
|
@ -1,10 +1,6 @@
|
||||
package io.github.applecommander.bastools.tools.bt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -74,6 +70,9 @@ public class Main implements Callable<Void> {
|
||||
|
||||
@Option(names = "--max-line-length", description = "Maximum line length for generated lines.", showDefaultValue = Visibility.ALWAYS)
|
||||
private int maxLineLength = 255;
|
||||
|
||||
@Option(names = "--wrapper", description = "Wrap the Applesoft program (DOS 3.3).")
|
||||
private boolean wrapProgram;
|
||||
|
||||
@Option(names = "-f", converter = OptimizationTypeConverter.class, split = ",", description = {
|
||||
"Enable specific optimizations.",
|
||||
@ -174,17 +173,34 @@ public class Main implements Callable<Void> {
|
||||
}
|
||||
|
||||
ByteVisitor byteVisitor = Visitors.byteVisitor(config);
|
||||
byte[] data = byteVisitor.dump(program);
|
||||
byte[] wrapperData = new byte[0];
|
||||
if (wrapProgram) {
|
||||
Queue<Token> wrapperTokens = TokenReader.tokenize(new ByteArrayInputStream(
|
||||
"10 POKE 103,24:POKE 104,8:RUN".getBytes()));
|
||||
Parser wrapperParser = new Parser(wrapperTokens);
|
||||
Program wrapperProgram = wrapperParser.parse();
|
||||
wrapperData = byteVisitor.dump(wrapperProgram);
|
||||
}
|
||||
|
||||
byte[] programData = byteVisitor.dump(program);
|
||||
if (showLineAddresses) {
|
||||
byteVisitor.getLineAddresses().forEach((l,a) -> System.out.printf("%5d ... $%04x\n", l, a));
|
||||
}
|
||||
|
||||
// Merge both programs together. Note that wrapperData may be a 0 byte array.
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
output.write(wrapperData);
|
||||
output.write(programData);
|
||||
output.flush();
|
||||
byte[] data = output.toByteArray();
|
||||
|
||||
if (hexFormat) {
|
||||
HexDumper.standard().dump(address, data);
|
||||
}
|
||||
if (copyFormat) {
|
||||
HexDumper.apple2().dump(address, data);
|
||||
}
|
||||
|
||||
|
||||
saveResults(data);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user