Re-initializing repo leaving out game assets.
This commit is contained in:
commit
18eb40eda8
|
@ -0,0 +1,4 @@
|
||||||
|
*.class
|
||||||
|
*.2mg
|
||||||
|
*.swp
|
||||||
|
ASSETS
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="lib/ac.jar" sourcepath="/Users/mhaye/Dropbox/Apple II/Projects/Lawless Legends/AppleCommander-1.3.5.13-src/src"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>a2copy</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="MacRoman" standalone="no"?>
|
||||||
|
<jardesc>
|
||||||
|
<jar path="a2copy/a2copy.jar"/>
|
||||||
|
<options buildIfNeeded="true" compress="true" descriptionLocation="/a2copy/a2copy.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
|
||||||
|
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
||||||
|
<selectedProjects/>
|
||||||
|
<manifest generateManifest="true" mainClassHandleIdentifier="=a2copy/src<{A2copy.java[A2copy" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
|
||||||
|
<sealing sealJar="false">
|
||||||
|
<packagesToSeal/>
|
||||||
|
<packagesToUnSeal/>
|
||||||
|
</sealing>
|
||||||
|
</manifest>
|
||||||
|
<selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
|
||||||
|
<javaElement handleIdentifier="=a2copy/src"/>
|
||||||
|
</selectedElements>
|
||||||
|
</jardesc>
|
|
@ -0,0 +1 @@
|
||||||
|
ac.jar = AppleCommander-1.3.5.13-ac.jar with Martn's patch for proper sub-directory creation
|
Binary file not shown.
|
@ -0,0 +1,321 @@
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import com.webcodepro.applecommander.storage.DirectoryEntry;
|
||||||
|
import com.webcodepro.applecommander.storage.Disk;
|
||||||
|
import com.webcodepro.applecommander.storage.DiskFullException;
|
||||||
|
import com.webcodepro.applecommander.storage.FileEntry;
|
||||||
|
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class uses AppleCommander's command-line interface to extract an entire
|
||||||
|
* set of files and directories from an image, or build a whole image from
|
||||||
|
* files and directories.
|
||||||
|
*
|
||||||
|
* Has specific hard-coded addresses for Lawless Legends files; should fix this
|
||||||
|
* at some point to use a metadata configuration file or something like that.
|
||||||
|
*/
|
||||||
|
public class A2copy
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Main command-line driver
|
||||||
|
*/
|
||||||
|
public static void main(String[] args)
|
||||||
|
throws IOException, DiskFullException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (args[0].equals("-extract")) {
|
||||||
|
extractImg(args[1], args[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args[0].equals("-create")) {
|
||||||
|
createImg(args[1], args[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArrayIndexOutOfBoundsException e)
|
||||||
|
{ }
|
||||||
|
System.err.format("Usage: A2copy [-extract imgFile targetDir] | [-create imgFile sourceDir]\n");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to delete a file or directory and all its descendants.
|
||||||
|
* @throws IOException if something goes wrong
|
||||||
|
*/
|
||||||
|
static void delete(File f) throws IOException {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
for (File c : f.listFiles())
|
||||||
|
delete(c);
|
||||||
|
}
|
||||||
|
if (!f.delete())
|
||||||
|
throw new FileNotFoundException("Failed to delete file: " + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all the files and directories from an image file.
|
||||||
|
* @throws IOException if something goes wrong
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static void extractImg(String imgPath, String targetPath) throws IOException
|
||||||
|
{
|
||||||
|
// Ensure the target directory is empty first.
|
||||||
|
File targetDir = new File(targetPath);
|
||||||
|
if (targetDir.exists()) {
|
||||||
|
System.out.format("Note: %s will be overwritten. Continue? ", targetPath);
|
||||||
|
System.out.flush();
|
||||||
|
String response = new BufferedReader(new InputStreamReader(System.in)).readLine();
|
||||||
|
if (!response.toLowerCase().startsWith("y"))
|
||||||
|
return;
|
||||||
|
delete(targetDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the image file and process disks inside it.
|
||||||
|
Disk disk = new Disk(imgPath);
|
||||||
|
for (FormattedDisk fd : disk.getFormattedDisks())
|
||||||
|
extractFiles((List<FileEntry>)fd.getFiles(), targetDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for file/directory extraction.
|
||||||
|
* @param files set of files to extract
|
||||||
|
* @param targetDir where to put them
|
||||||
|
* @throws IOException if something goes wrong
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static void extractFiles(List<FileEntry> files, File targetDir) throws IOException
|
||||||
|
{
|
||||||
|
// Ensure the target directory exists
|
||||||
|
targetDir.mkdir();
|
||||||
|
|
||||||
|
// Process each entry in the list
|
||||||
|
for (FileEntry e : files)
|
||||||
|
{
|
||||||
|
// Skip deleted things
|
||||||
|
if (e.isDeleted())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Recursively process sub-directories
|
||||||
|
if (e.isDirectory()) {
|
||||||
|
File subDir = new File(targetDir, e.getFilename());
|
||||||
|
extractFiles(((DirectoryEntry)e).getFiles(), subDir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process regular files.
|
||||||
|
byte[] data = e.getFileData();
|
||||||
|
// Hi to lo ASCII translation
|
||||||
|
if (e.getFilename().endsWith(".S"))
|
||||||
|
data = merlinSrcToAscii(data);
|
||||||
|
FileOutputStream out = new FileOutputStream(new File(targetDir, e.getFilename()));
|
||||||
|
out.write(data);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an image file using dirs/files from the filesystem.
|
||||||
|
* @param imgPath name of the image file
|
||||||
|
* @param srcDirPath directory containing files and subdirs
|
||||||
|
* @throws DiskFullException if the image file fills up
|
||||||
|
* @throws IOException if something else goes wrong
|
||||||
|
*/
|
||||||
|
static void createImg(String imgPath, String srcDirPath)
|
||||||
|
throws IOException, DiskFullException
|
||||||
|
{
|
||||||
|
// Alert the user that we're going to blow away the image.
|
||||||
|
File imgFile = new File(imgPath);
|
||||||
|
if (imgFile.exists()) {
|
||||||
|
System.out.format("Note: %s will be overwritten. Continue? ", imgPath);
|
||||||
|
System.out.flush();
|
||||||
|
String response = new BufferedReader(new InputStreamReader(System.in)).readLine();
|
||||||
|
if (!response.toLowerCase().startsWith("y"))
|
||||||
|
return;
|
||||||
|
delete(imgFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-create the image file with a blank image.
|
||||||
|
File emptyFile = new File(imgFile.getParent(), "empty.2mg.gz");
|
||||||
|
if (!emptyFile.canRead())
|
||||||
|
throw new IOException(String.format("Cannot open template for empty image '%s'", emptyFile.toString()));
|
||||||
|
InputStream in = new BufferedInputStream(new GZIPInputStream(new FileInputStream(emptyFile)));
|
||||||
|
OutputStream out = new BufferedOutputStream(new FileOutputStream(imgFile));
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
while (true) {
|
||||||
|
int nRead = in.read(buf);
|
||||||
|
if (nRead < 0)
|
||||||
|
break;
|
||||||
|
out.write(buf, 0, nRead);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
// Open the empty image file.
|
||||||
|
Disk disk = new Disk(imgPath);
|
||||||
|
FormattedDisk fd = disk.getFormattedDisks()[0];
|
||||||
|
|
||||||
|
// And fill it up.
|
||||||
|
insertFiles(fd, fd, new File(srcDirPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for image creation.
|
||||||
|
*
|
||||||
|
* @param fd disk to insert files into
|
||||||
|
* @param targetDir directory within the disk
|
||||||
|
* @param srcDir filesystem directory to read
|
||||||
|
* @throws DiskFullException if the image file fills up
|
||||||
|
* @throws IOException if something else goes wrong
|
||||||
|
*/
|
||||||
|
private static void insertFiles(FormattedDisk fd, DirectoryEntry targetDir, File srcDir)
|
||||||
|
throws DiskFullException, IOException
|
||||||
|
{
|
||||||
|
// Process each file in the source directory
|
||||||
|
for (File srcFile : srcDir.listFiles())
|
||||||
|
{
|
||||||
|
if (srcFile.isDirectory()) {
|
||||||
|
DirectoryEntry subDir = targetDir.createDirectory(srcFile.getName().toUpperCase());
|
||||||
|
insertFiles(fd, subDir, srcFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new entry on the filesystem for this file.
|
||||||
|
FileEntry ent = targetDir.createFile();
|
||||||
|
String srcName = srcFile.getName().toUpperCase();
|
||||||
|
ent.setFilename(srcName);
|
||||||
|
|
||||||
|
// Set the file type
|
||||||
|
if (srcName.equals("PRODOS") || srcName.endsWith(".SYSTEM"))
|
||||||
|
ent.setFiletype("SYS");
|
||||||
|
else if (srcName.equals("STARTUP"))
|
||||||
|
ent.setFiletype("BAS");
|
||||||
|
else if (srcName.endsWith(".S"))
|
||||||
|
ent.setFiletype("TXT");
|
||||||
|
else
|
||||||
|
ent.setFiletype("BIN");
|
||||||
|
|
||||||
|
// Set the address if necessary
|
||||||
|
if (ent.needsAddress()) {
|
||||||
|
if (srcName.equals("STARTUP"))
|
||||||
|
ent.setAddress(0x801);
|
||||||
|
else if (srcName.equals("COPYIIPL.SYSTEM"))
|
||||||
|
ent.setAddress(0x1400);
|
||||||
|
else if (srcName.equals("ED.16"))
|
||||||
|
ent.setAddress(0x9d60);
|
||||||
|
else if (srcName.equals("ED"))
|
||||||
|
ent.setAddress(0x9db6);
|
||||||
|
else if (srcName.equals("SHELL"))
|
||||||
|
ent.setAddress(0x300);
|
||||||
|
else
|
||||||
|
ent.setAddress(0x2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the file data
|
||||||
|
FileInputStream in = new FileInputStream(srcFile);
|
||||||
|
byte[] buf = new byte[(int) srcFile.length()];
|
||||||
|
int nRead = in.read(buf);
|
||||||
|
if (nRead != srcFile.length())
|
||||||
|
throw new IOException(String.format("Error reading file '%s'", srcFile.toString()));
|
||||||
|
|
||||||
|
// Translate between hi and lo ASCII
|
||||||
|
if (srcName.endsWith(".S"))
|
||||||
|
buf = asciiToMerlinSrc(buf);
|
||||||
|
ent.setFileData(buf);
|
||||||
|
|
||||||
|
// And save the new entry.
|
||||||
|
fd.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates Merlin source code to usable code in the regular ASCII world.
|
||||||
|
* Performs weird-space to tab translation, and hi bit conversion.
|
||||||
|
*
|
||||||
|
* @param buf data to translate
|
||||||
|
* @return translated data
|
||||||
|
*/
|
||||||
|
static byte[] merlinSrcToAscii(byte[] buf)
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream ba = new ByteArrayOutputStream(buf.length);
|
||||||
|
PrintWriter out = new PrintWriter(ba);
|
||||||
|
boolean inComment = false;
|
||||||
|
for (byte b : buf)
|
||||||
|
{
|
||||||
|
// Handle newlines
|
||||||
|
if (b == (byte)0x8d) {
|
||||||
|
out.println();
|
||||||
|
inComment = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char c = (char)(b & 0x7f);
|
||||||
|
// Tabs outside comments
|
||||||
|
if (c == ';' || c == '*')
|
||||||
|
inComment = true;
|
||||||
|
if (c == '\n')
|
||||||
|
throw new RuntimeException("Newline slipped through");
|
||||||
|
if (c == ' ' && !inComment)
|
||||||
|
out.write('\t');
|
||||||
|
else
|
||||||
|
out.write(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
return ba.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms regular ASCII with tabs to Merlin source code. Handles
|
||||||
|
* tab to weird space translation, and hi-bit addition.
|
||||||
|
*
|
||||||
|
* @param buf data to translate
|
||||||
|
* @return translated data
|
||||||
|
*/
|
||||||
|
static byte[] asciiToMerlinSrc(byte[] buf)
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream ba = new ByteArrayOutputStream(buf.length);
|
||||||
|
boolean inComment = false;
|
||||||
|
for (int i=0; i<buf.length; i++)
|
||||||
|
{
|
||||||
|
// Newline translation
|
||||||
|
if (buf[i] == '\r') {
|
||||||
|
ba.write(0x8d);
|
||||||
|
if (i+1 < buf.length && buf[i+1] == '\n')
|
||||||
|
++i;
|
||||||
|
inComment = false;
|
||||||
|
}
|
||||||
|
else if (buf[i] == '\n') {
|
||||||
|
ba.write(0x8d);
|
||||||
|
if (i+1 < buf.length && buf[i+1] == '\r')
|
||||||
|
++i;
|
||||||
|
inComment = false;
|
||||||
|
}
|
||||||
|
// Tabs outside comments
|
||||||
|
else if (buf[i] == '\t')
|
||||||
|
ba.write(0xA0);
|
||||||
|
else if (buf[i] == ' ' && inComment)
|
||||||
|
ba.write(0x20);
|
||||||
|
else if (buf[i] == 0)
|
||||||
|
ba.write(0);
|
||||||
|
else {
|
||||||
|
if (buf[i] == ';' || buf[i] == '*')
|
||||||
|
inComment = true;
|
||||||
|
ba.write((((int)buf[i]) & 0xFF) | 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ba.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os, re, subprocess, sys
|
||||||
|
from os.path import join as pjoin
|
||||||
|
|
||||||
|
# This is a simple wrapper that calls the Java a2copy code.
|
||||||
|
|
||||||
|
# No matter where we run from, use the right directories.
|
||||||
|
binDir = os.path.dirname(sys.argv[0])
|
||||||
|
if not os.path.isabs(binDir):
|
||||||
|
binDir = pjoin(os.getenv("PWD", os.getcwd()), binDir)
|
||||||
|
binDir = re.sub("\/?\.?$", "", binDir)
|
||||||
|
mainDir = os.path.dirname(binDir) # binDir/..
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
def main():
|
||||||
|
""" Command-line driver. """
|
||||||
|
|
||||||
|
javaCmd = ['java',
|
||||||
|
'-cp', '%s/a2copy/lib/ac.jar:%s/a2copy/a2copy.jar' % (mainDir, mainDir),
|
||||||
|
'A2copy']
|
||||||
|
javaCmd.extend(sys.argv[1:])
|
||||||
|
proc = subprocess.Popen(javaCmd, stdout = sys.stdout, stderr = sys.stderr)
|
||||||
|
proc.communicate()
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
main()
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# This wrapper script takes everything in the 'files' directory and puts it
|
||||||
|
# into image file 'platform/LL.2mg'.
|
||||||
|
|
||||||
|
import os, re, subprocess, sys
|
||||||
|
from os.path import join as pjoin
|
||||||
|
|
||||||
|
# No matter where we run from, use the right directories.
|
||||||
|
binDir = os.path.dirname(sys.argv[0])
|
||||||
|
if not os.path.isabs(binDir):
|
||||||
|
binDir = pjoin(os.getenv("PWD", os.getcwd()), binDir)
|
||||||
|
binDir = re.sub("\/?\.?$", "", binDir)
|
||||||
|
mainDir = os.path.dirname(binDir) # binDir/..
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
def main():
|
||||||
|
""" Command-line driver. """
|
||||||
|
|
||||||
|
os.chdir(mainDir)
|
||||||
|
javaCmd = ['java',
|
||||||
|
'-cp', 'a2copy/lib/ac.jar:a2copy/a2copy.jar',
|
||||||
|
'A2copy',
|
||||||
|
'-create', 'platform/LL.2mg', 'files/']
|
||||||
|
proc = subprocess.Popen(javaCmd)
|
||||||
|
proc.communicate()
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
main()
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# This wrapper script copies out the files from 'platform/LL.2mg' into
|
||||||
|
# the 'files' directory, replacing everything that was in 'files'.
|
||||||
|
|
||||||
|
import os, re, subprocess, sys
|
||||||
|
from os.path import join as pjoin
|
||||||
|
|
||||||
|
# No matter where we run from, use the right directories.
|
||||||
|
binDir = os.path.dirname(sys.argv[0])
|
||||||
|
if not os.path.isabs(binDir):
|
||||||
|
binDir = pjoin(os.getenv("PWD", os.getcwd()), binDir)
|
||||||
|
binDir = re.sub("\/?\.?$", "", binDir)
|
||||||
|
mainDir = os.path.dirname(binDir) # binDir/..
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
def main():
|
||||||
|
""" Command-line driver. """
|
||||||
|
|
||||||
|
os.chdir(mainDir)
|
||||||
|
javaCmd = ['java',
|
||||||
|
'-cp', 'a2copy/lib/ac.jar:a2copy/a2copy.jar',
|
||||||
|
'A2copy',
|
||||||
|
'-extract', 'platform/LL.2mg', 'files/']
|
||||||
|
proc = subprocess.Popen(javaCmd)
|
||||||
|
proc.communicate()
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
main()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,202 @@
|
||||||
|
* Tiny shell
|
||||||
|
LST OFF
|
||||||
|
|
||||||
|
XC ; enable 65c02 ops
|
||||||
|
|
||||||
|
* Merlin addresses
|
||||||
|
TEXTSTART = $A
|
||||||
|
TEXTEND = $E
|
||||||
|
HIMEM = $C
|
||||||
|
OBJADDR = $E2
|
||||||
|
OBJLEN = $E4
|
||||||
|
ORGADDR = $E6
|
||||||
|
|
||||||
|
* Monitor addresses
|
||||||
|
STARTADDR = $3C
|
||||||
|
ENDADDR = $3E
|
||||||
|
DESTADDR = $42
|
||||||
|
|
||||||
|
* My zero-pg
|
||||||
|
MLICMD = $50
|
||||||
|
|
||||||
|
* I/O addresses
|
||||||
|
SETMAINZP = $C008
|
||||||
|
SETALTZP = $C009
|
||||||
|
READROM = $C082
|
||||||
|
LCBANK2 = $C08B
|
||||||
|
|
||||||
|
* Other stuff
|
||||||
|
INBUF = $200
|
||||||
|
RESETVEC = $3F2
|
||||||
|
USERVEC = $3F5
|
||||||
|
CTRLYVEC = $3F8
|
||||||
|
PRODOSBUF = $BB00
|
||||||
|
NAMEBUF = $C00
|
||||||
|
MLI = $BF00
|
||||||
|
MEMMAP = $BF58
|
||||||
|
AUXMOVE = $C311
|
||||||
|
MERLIN = $E003
|
||||||
|
PRNTAX = $F941
|
||||||
|
PRHEX = $F944
|
||||||
|
BASCALC = $FBC1
|
||||||
|
CALCRESET = $FB6F
|
||||||
|
INPUT = $FD6A
|
||||||
|
INPUTZ = $FD6F
|
||||||
|
CROUT = $FD8E
|
||||||
|
COUT = $FDED
|
||||||
|
SETVID = $FE93
|
||||||
|
PRERR = $FF2D
|
||||||
|
MONITOR = $FF69
|
||||||
|
MONSCAN = $FF70
|
||||||
|
|
||||||
|
ORG $300
|
||||||
|
|
||||||
|
INSTVECS LDA #<TOMON
|
||||||
|
STA USERVEC+1
|
||||||
|
LDA #>TOMON
|
||||||
|
STA USERVEC+2
|
||||||
|
|
||||||
|
LDA #<TOMERLIN
|
||||||
|
STA RESETVEC
|
||||||
|
STA CTRLYVEC+1
|
||||||
|
LDA #>TOMERLIN
|
||||||
|
STA RESETVEC+1
|
||||||
|
STA CTRLYVEC+2
|
||||||
|
|
||||||
|
JMP CALCRESET
|
||||||
|
|
||||||
|
* Start of resident code
|
||||||
|
RUNSHELL
|
||||||
|
; clear ProDOS memory map
|
||||||
|
LDX #$18
|
||||||
|
LDA #1
|
||||||
|
:MEMLUP
|
||||||
|
STA MEMMAP-1,X
|
||||||
|
LDA #0
|
||||||
|
DEX
|
||||||
|
BNE :MEMLUP
|
||||||
|
; display prompt
|
||||||
|
:LUP LDA PROMPT,X
|
||||||
|
BEQ :GETNAME
|
||||||
|
JSR COUT
|
||||||
|
INX
|
||||||
|
BNE :LUP
|
||||||
|
:GETNAME
|
||||||
|
JSR INPUTZ
|
||||||
|
TXA
|
||||||
|
BEQ :MON
|
||||||
|
:LOADIT
|
||||||
|
JSR LOADPROG
|
||||||
|
:MON JMP MONITOR
|
||||||
|
|
||||||
|
* Load program, name in INBUF
|
||||||
|
LOADPROG
|
||||||
|
; translate filename
|
||||||
|
LDY #0
|
||||||
|
STY MLICMD+1 ; filename lo byte
|
||||||
|
LDA #>NAMEBUF
|
||||||
|
STA MLICMD+2 ; ...and hi byte
|
||||||
|
:LUP
|
||||||
|
LDA INBUF,Y
|
||||||
|
INY
|
||||||
|
STA NAMEBUF,Y
|
||||||
|
CMP #$8D
|
||||||
|
BNE :LUP
|
||||||
|
:NAMEDONE
|
||||||
|
DEY
|
||||||
|
STY NAMEBUF
|
||||||
|
LDA #$C4 ; get info
|
||||||
|
LDX #$A
|
||||||
|
JSR DOMLI
|
||||||
|
LDA MLICMD+6 ; addr hi
|
||||||
|
PHA
|
||||||
|
LDA MLICMD+5 ; addr lo
|
||||||
|
PHA
|
||||||
|
LDA #<PRODOSBUF
|
||||||
|
STA MLICMD+3
|
||||||
|
LDA #>PRODOSBUF
|
||||||
|
STA MLICMD+4
|
||||||
|
LDA #$C8 ; open
|
||||||
|
LDX #3
|
||||||
|
JSR DOMLI
|
||||||
|
LDA MLICMD+5 ; handle
|
||||||
|
STA MLICMD+1
|
||||||
|
PLA ; addr lo
|
||||||
|
STA MLICMD+2
|
||||||
|
PLA ; addr hi
|
||||||
|
STA MLICMD+3
|
||||||
|
LDA #$CA ; read
|
||||||
|
STA MLICMD+5 ; also length (more than enough)
|
||||||
|
INX
|
||||||
|
JSR DOMLI
|
||||||
|
; fall through
|
||||||
|
CLOSE
|
||||||
|
STZ MLICMD+1 ; close all
|
||||||
|
LDA #$CC
|
||||||
|
LDX #1
|
||||||
|
; fall through
|
||||||
|
DOMLI
|
||||||
|
STA MLIOP
|
||||||
|
STX MLICMD
|
||||||
|
JSR MLI
|
||||||
|
MLIOP DFB 0
|
||||||
|
DA MLICMD
|
||||||
|
BCS :NO
|
||||||
|
:OK
|
||||||
|
RTS
|
||||||
|
:NO
|
||||||
|
LDA MLIOP
|
||||||
|
CMP #$CC
|
||||||
|
BEQ :OK
|
||||||
|
; fall through
|
||||||
|
ERR
|
||||||
|
JSR PRHEX
|
||||||
|
JSR CLOSE
|
||||||
|
JSR PRERR
|
||||||
|
JMP RUNSHELL
|
||||||
|
|
||||||
|
COPYUPPR LDX #$98
|
||||||
|
LDY #$C0
|
||||||
|
; fall through
|
||||||
|
|
||||||
|
* Copy page X-Y to page A
|
||||||
|
* Carry: clear = aux2main, set = main2aux
|
||||||
|
UNITYCOPY TXA
|
||||||
|
COPY STX STARTADDR+1
|
||||||
|
STY ENDADDR+1
|
||||||
|
STA DESTADDR+1
|
||||||
|
STZ STARTADDR
|
||||||
|
STZ ENDADDR
|
||||||
|
STZ DESTADDR
|
||||||
|
JMP AUXMOVE
|
||||||
|
|
||||||
|
TOMON
|
||||||
|
SEC
|
||||||
|
JSR COPYUPPR
|
||||||
|
STA SETMAINZP
|
||||||
|
BIT READROM
|
||||||
|
JSR INSTVECS
|
||||||
|
LDX #$FF
|
||||||
|
TXS
|
||||||
|
JSR SETVID
|
||||||
|
JMP RUNSHELL
|
||||||
|
|
||||||
|
TOMERLIN
|
||||||
|
JSR CLOSE
|
||||||
|
CLC
|
||||||
|
JSR COPYUPPR
|
||||||
|
STA SETALTZP
|
||||||
|
LDX #$FF
|
||||||
|
TXS
|
||||||
|
LDA LCBANK2
|
||||||
|
JMP MERLIN
|
||||||
|
|
||||||
|
PROMPT DFB $8D
|
||||||
|
ASC "Ld:",00
|
||||||
|
|
||||||
|
LST ON
|
||||||
|
END DFB 0
|
||||||
|
ERR \$3F0
|
||||||
|
LST OFF
|
||||||
|
|
||||||
|
SAV SHELL
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,93 @@
|
||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* PARMS *
|
||||||
|
* *
|
||||||
|
* for Merlin - ProDOS version. *
|
||||||
|
* *
|
||||||
|
* Glen E. Bredon 8/11/85 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
|
||||||
|
SAVOBJ KBD "Save the object code? (1=Y, 0=N)"
|
||||||
|
|
||||||
|
DATA
|
||||||
|
DFB 60 ;# lines/page for PRTR
|
||||||
|
DFB 0 ;Page skip (formfeed if 0)
|
||||||
|
DFB 80 ;# printer columns
|
||||||
|
DFB $80 ;- if printer does CR at
|
||||||
|
; end of # columns
|
||||||
|
|
||||||
|
DFB $83 ;80 col flag (DO NOT CHANGE)
|
||||||
|
;(Except V-bit which will
|
||||||
|
; cause ProDOS to be moved to
|
||||||
|
; aux memory and Merlin to
|
||||||
|
; load into main memory.
|
||||||
|
; I.e., use $C3 for this.)
|
||||||
|
*-------------------------------------------------
|
||||||
|
* Source address must be above $8A0. We use $901
|
||||||
|
* to maintain compatibility. It can be set higher
|
||||||
|
* to protect an area of memory for any purpose:
|
||||||
|
*-------------------------------------------------
|
||||||
|
SOURCE = $901
|
||||||
|
DA SOURCE ;Start of source
|
||||||
|
DA $AA00 ;Don't change this
|
||||||
|
DA SOURCE ;End of source
|
||||||
|
|
||||||
|
DFB <"^" ;Editor's wild card
|
||||||
|
DFB 4 ;# of symbol columns
|
||||||
|
DFB 0 ;Search chr for "Update..."
|
||||||
|
; (Question skipped if 0)
|
||||||
|
|
||||||
|
DFB 14,20,31 ;Default tabs
|
||||||
|
|
||||||
|
DFB 8 ;# obj bytes/line after 1st
|
||||||
|
|
||||||
|
DFB $45 ;High bit neg. forces infinite
|
||||||
|
; wait for key upon assembly
|
||||||
|
; errors.
|
||||||
|
;V-bit set defeats bells.
|
||||||
|
;Low nibble is Ultraterm entry
|
||||||
|
; mode (e.g., 5, $45, $85 or $C5
|
||||||
|
; gives 32x80 interlace mode)
|
||||||
|
|
||||||
|
DFB 0 ;Regular cursor if $40
|
||||||
|
;Block cursor if 0
|
||||||
|
;(Ignored if Apple card)
|
||||||
|
|
||||||
|
DFB 0 ;Default for LSTDO opcode:
|
||||||
|
;Do off areas listed if 0 or 1,
|
||||||
|
; not if >1.
|
||||||
|
;Bit 0, if clear, causes shift
|
||||||
|
; to 40 columns on a PRTR1 cmd
|
||||||
|
|
||||||
|
DFB 80-8 ;Column for cycle count
|
||||||
|
|
||||||
|
DFB $EC ;Ultraterm cursor in default
|
||||||
|
; mode. (This must be changed
|
||||||
|
; if the ultraterm mode is
|
||||||
|
; changed.)
|
||||||
|
|
||||||
|
ERR *-DATA-23 ;23 data bytes to here.
|
||||||
|
|
||||||
|
* User file type names (change to fit your desires):
|
||||||
|
|
||||||
|
ASC "$F1"
|
||||||
|
ASC "$F2"
|
||||||
|
ASC "$F3"
|
||||||
|
ASC "$F4"
|
||||||
|
ASC "$F5"
|
||||||
|
ASC "$F6"
|
||||||
|
ASC "$F7"
|
||||||
|
|
||||||
|
ERR *-DATA-44 ;44 bytes in all
|
||||||
|
; no more, no less
|
||||||
|
|
||||||
|
*----------------------------------------------
|
||||||
|
* Be sure to change the following pathname if
|
||||||
|
* you want this on a volume with another name.
|
||||||
|
* The PARMS file must be in the MAIN DIRECTORY!
|
||||||
|
*----------------------------------------------
|
||||||
|
|
||||||
|
DO SAVOBJ
|
||||||
|
SAV /LL/PARMS
|
||||||
|
FIN
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue