mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-08-12 02:25:10 +00:00
Now loading and successfully relocating ProRWTS and PLASMA.
This commit is contained in:
BIN
Platform/Apple/tools/PLASMA/src/PLVM02#4000
Normal file
BIN
Platform/Apple/tools/PLASMA/src/PLVM02#4000
Normal file
Binary file not shown.
@@ -113,9 +113,6 @@ INTERP = $03D0
|
|||||||
LDA #$BF
|
LDA #$BF
|
||||||
STA PPH
|
STA PPH
|
||||||
STA IFPH
|
STA IFPH
|
||||||
LDX #$FE ; INIT STACK POINTER (YES, $FE. SEE GETS)
|
|
||||||
TXS
|
|
||||||
LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX
|
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
PAGE0 = *
|
PAGE0 = *
|
||||||
|
@@ -28,7 +28,8 @@
|
|||||||
<include name="virtual/src/**/*.i"/>
|
<include name="virtual/src/**/*.i"/>
|
||||||
<include name="virtual/src/**/*.ct"/>
|
<include name="virtual/src/**/*.ct"/>
|
||||||
<include name="virtual/data/disks/*.gz"/>
|
<include name="virtual/data/disks/*.gz"/>
|
||||||
<include name="tools/PLASMA/src/PLVM02.SYSTEM.sys"/>
|
<include name="tools/PLASMA/src/PLVM02#4000"/>
|
||||||
|
<include name="tools/ProRWTS/PRORWTS2#4000"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
|
@@ -1205,6 +1205,14 @@ class A2PackPartitions
|
|||||||
return wrapByteArray(arr)
|
return wrapByteArray(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unwrapByteBuffer(buf) {
|
||||||
|
def len = buf.position()
|
||||||
|
def out = new byte[len]
|
||||||
|
buf.position(0)
|
||||||
|
buf.get(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
def readFont(name, path)
|
def readFont(name, path)
|
||||||
{
|
{
|
||||||
def num = fonts.size() + 1
|
def num = fonts.size() + 1
|
||||||
@@ -1231,7 +1239,7 @@ class A2PackPartitions
|
|||||||
//def uncomp = new byte[inLen]
|
//def uncomp = new byte[inLen]
|
||||||
//lx47.decompress(outputData, 0, uncomp, 0, inLen)
|
//lx47.decompress(outputData, 0, uncomp, 0, inLen)
|
||||||
//assert uncomp == inputData
|
//assert uncomp == inputData
|
||||||
|
|
||||||
// Verify the stream comes out right with overlapped decompression
|
// Verify the stream comes out right with overlapped decompression
|
||||||
def underlap = 2
|
def underlap = 2
|
||||||
def buf = new byte[inLen+underlap]
|
def buf = new byte[inLen+underlap]
|
||||||
@@ -1240,7 +1248,7 @@ class A2PackPartitions
|
|||||||
lx47.decompress(buf, initialOffset, buf, 0, inLen)
|
lx47.decompress(buf, initialOffset, buf, 0, inLen)
|
||||||
def uncomp = Arrays.copyOfRange(buf, 0, inLen)
|
def uncomp = Arrays.copyOfRange(buf, 0, inLen)
|
||||||
assert uncomp == inputData
|
assert uncomp == inputData
|
||||||
|
|
||||||
uncompTotal += inLen
|
uncompTotal += inLen
|
||||||
lx47Savings += savings
|
lx47Savings += savings
|
||||||
lz4Total += lz4Len
|
lz4Total += lz4Len
|
||||||
@@ -1252,7 +1260,7 @@ class A2PackPartitions
|
|||||||
println String.format("lz47 usize=%d savings=%d SKIP", inLen, savings)
|
println String.format("lz47 usize=%d savings=%d SKIP", inLen, savings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform the LZ4 format to something we call "LZ4M", where the small offsets are stored
|
// Transform the LZ4 format to something we call "LZ4M", where the small offsets are stored
|
||||||
// as one byte instead of two. In our data, that's about 1/3 of the offsets.
|
// as one byte instead of two. In our data, that's about 1/3 of the offsets.
|
||||||
//
|
//
|
||||||
@@ -1354,9 +1362,7 @@ class A2PackPartitions
|
|||||||
{
|
{
|
||||||
// First, grab the uncompressed data into a byte array
|
// First, grab the uncompressed data into a byte array
|
||||||
def uncompressedLen = buf.position()
|
def uncompressedLen = buf.position()
|
||||||
def uncompressedData = new byte[uncompressedLen]
|
def uncompressedData = unwrapByteBuffer(buf)
|
||||||
buf.position(0)
|
|
||||||
buf.get(uncompressedData)
|
|
||||||
|
|
||||||
// Now compress it with LZ4
|
// Now compress it with LZ4
|
||||||
assert uncompressedLen < 327678 : "data block too big"
|
assert uncompressedLen < 327678 : "data block too big"
|
||||||
@@ -1369,7 +1375,7 @@ class A2PackPartitions
|
|||||||
|
|
||||||
// Then recompress to LZ4M (pretty much always smaller)
|
// Then recompress to LZ4M (pretty much always smaller)
|
||||||
def recompressedLen = recompress(compressedData, compressedLen, uncompressedData, uncompressedLen)
|
def recompressedLen = recompress(compressedData, compressedLen, uncompressedData, uncompressedLen)
|
||||||
testLx47(uncompressedData, uncompressedLen, recompressedLen)
|
//testLx47(uncompressedData, uncompressedLen, recompressedLen)
|
||||||
|
|
||||||
// If we saved at least 20 bytes, take the compressed version.
|
// If we saved at least 20 bytes, take the compressed version.
|
||||||
if ((uncompressedLen - recompressedLen) >= 20) {
|
if ((uncompressedLen - recompressedLen) >= 20) {
|
||||||
@@ -1448,12 +1454,9 @@ class A2PackPartitions
|
|||||||
hdrBuf.put((byte)(hdrEnd & 0xFF))
|
hdrBuf.put((byte)(hdrEnd & 0xFF))
|
||||||
hdrBuf.put((byte)(hdrEnd >> 8))
|
hdrBuf.put((byte)(hdrEnd >> 8))
|
||||||
hdrBuf.position(hdrEnd)
|
hdrBuf.position(hdrEnd)
|
||||||
def hdrData = new byte[hdrEnd]
|
|
||||||
hdrBuf.position(0)
|
|
||||||
hdrBuf.get(hdrData)
|
|
||||||
|
|
||||||
// Finally, write out each chunk's data, including the header.
|
// Finally, write out each chunk's data, including the header.
|
||||||
stream.write(hdrData)
|
stream.write(unwrapByteBuffer(hdrBuf))
|
||||||
chunks.each {
|
chunks.each {
|
||||||
stream.write(it.buf.data, 0, it.buf.len)
|
stream.write(it.buf.data, 0, it.buf.len)
|
||||||
}
|
}
|
||||||
@@ -1467,6 +1470,7 @@ class A2PackPartitions
|
|||||||
def prevUserDir = System.getProperty("user.dir")
|
def prevUserDir = System.getProperty("user.dir")
|
||||||
def result
|
def result
|
||||||
def errBuf = new ByteArrayOutputStream()
|
def errBuf = new ByteArrayOutputStream()
|
||||||
|
println "Nested: prog=$programName inDir=$inDir inDir=$inDir inFile=$inFile outFile=$outFile"
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
System.setProperty("user.dir", new File(inDir).getAbsolutePath())
|
System.setProperty("user.dir", new File(inDir).getAbsolutePath())
|
||||||
@@ -1620,18 +1624,50 @@ class A2PackPartitions
|
|||||||
def assembleCore(inDir)
|
def assembleCore(inDir)
|
||||||
{
|
{
|
||||||
if (binaryStubsOnly)
|
if (binaryStubsOnly)
|
||||||
return addToCache("sysCode", sysCode, "mem", 1, ByteBuffer.allocate(1))
|
return addToCache("sysCode", sysCode, "core", 1, ByteBuffer.allocate(1))
|
||||||
|
|
||||||
|
// Read in all the parts of the LegendOS core system and combine them together
|
||||||
|
// with block headers.
|
||||||
inDir = "build/" + inDir
|
inDir = "build/" + inDir
|
||||||
def hash = getLastDep(new File(inDir, "mem.s"))
|
new File(inDir + "build").mkdirs()
|
||||||
if (grabFromCache("sysCode", sysCode, "mem", hash))
|
println "Created dir ${new File(inDir + "build")}"
|
||||||
return
|
def outBuf = ByteBuffer.allocate(50000)
|
||||||
|
def compressor = new Lx47Algorithm()
|
||||||
println "Assembling mem.s"
|
["loader", "decomp", "PRORWTS", "PLVM02", "mem"].each { name ->
|
||||||
new File(inDir + "build").mkdir()
|
def code
|
||||||
String[] args = ["acme", "-o", "build/cmd.sys#2000", "mem.s"]
|
if (name == "PRORWTS")
|
||||||
runNestedvm(acme.Acme.class, "ACME assembler", args, inDir, null, null)
|
code = readBinary(jitCopy(new File("build/tools/ProRWTS/PRORWTS2#4000")).toString())
|
||||||
addToCache("sysCode", sysCode, "mem", hash, readBinary(inDir + "build/cmd.sys#2000"))
|
else if (name == "PLVM02")
|
||||||
|
code = readBinary(jitCopy(new File("build/tools/PLASMA/src/PLVM02#4000")).toString())
|
||||||
|
else {
|
||||||
|
def hash = getLastDep(new File(inDir, "${name}.s"))
|
||||||
|
if (!grabFromCache("sysCode", sysCode, name, hash)) {
|
||||||
|
println "Assembling ${name}.s"
|
||||||
|
String[] args = ["acme", "-o", "build/$name", "${name}.s"]
|
||||||
|
runNestedvm(acme.Acme.class, "ACME assembler", args, inDir, null, null)
|
||||||
|
addToCache("sysCode", sysCode, name, hash, readBinary(inDir + "build/$name"))
|
||||||
|
}
|
||||||
|
code = sysCode[name].buf
|
||||||
|
}
|
||||||
|
println "Processing $name."
|
||||||
|
def compressed = (name ==~ /loader|decomp/) ?
|
||||||
|
code : wrapByteArray(compressor.compress(unwrapByteBuffer(code)))
|
||||||
|
if (name != "loader") {
|
||||||
|
// Uncompressed size first
|
||||||
|
outBuf.put((byte) (code.position() & 0xFF))
|
||||||
|
outBuf.put((byte) (code.position() >> 8))
|
||||||
|
// Then compressed size
|
||||||
|
outBuf.put((byte) (compressed.position() & 0xFF))
|
||||||
|
outBuf.put((byte) (compressed.position() >> 8))
|
||||||
|
}
|
||||||
|
compressed.flip()
|
||||||
|
outBuf.put(compressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out the result
|
||||||
|
new File("build/src/core/build/LEGENDOS.SYSTEM.sys#2000").withOutputStream { stream ->
|
||||||
|
stream.write(unwrapByteBuffer(outBuf))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def compileModule(moduleName, codeDir, verbose = true)
|
def compileModule(moduleName, codeDir, verbose = true)
|
||||||
@@ -2699,11 +2735,9 @@ end
|
|||||||
|
|
||||||
def createImage()
|
def createImage()
|
||||||
{
|
{
|
||||||
// Copy the PLASMA VM file to the output directory
|
// Copy the combined core executable to the output directory
|
||||||
copyIfNewer(jitCopy(new File("build/tools/PLASMA/src/PLVM02.SYSTEM.sys")), new File("build/root/PLVM02.SYSTEM.sys"))
|
copyIfNewer(new File("build/src/core/build/LEGENDOS.SYSTEM.sys#2000"),
|
||||||
|
new File("build/root/LEGENDOS.SYSTEM.sys#2000"))
|
||||||
// Copy the memory manager to the output directory
|
|
||||||
copyIfNewer(new File("build/src/core/build/cmd.sys#2000"), new File("build/root/cmd.sys#2000"))
|
|
||||||
|
|
||||||
// If we preserved a previous save game, copy it to the new image.
|
// If we preserved a previous save game, copy it to the new image.
|
||||||
def prevSave = new File("build/prevGame/game.1.save.\$f1")
|
def prevSave = new File("build/prevGame/game.1.save.\$f1")
|
||||||
|
@@ -19,7 +19,7 @@ public class Lx47Algorithm
|
|||||||
|
|
||||||
void addDebug(String format, Object... arguments) {
|
void addDebug(String format, Object... arguments) {
|
||||||
String str = String.format(format, arguments);
|
String str = String.format(format, arguments);
|
||||||
//System.out.println("Gen: " + str);
|
System.out.println("Gen: " + str);
|
||||||
debugs.add(str);
|
debugs.add(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,10 +275,10 @@ public class Lx47Algorithm
|
|||||||
int pos = input_index - optimal[input_index].lits + 1;
|
int pos = input_index - optimal[input_index].lits + 1;
|
||||||
while (optimal[input_index].lits > 0) {
|
while (optimal[input_index].lits > 0) {
|
||||||
int n = Math.min(255, optimal[input_index].lits);
|
int n = Math.min(255, optimal[input_index].lits);
|
||||||
addDebug("lits l=%d", n);
|
addDebug("lits l=$%02x", n);
|
||||||
w.writeLiteralLen(n);
|
w.writeLiteralLen(n);
|
||||||
for (i = 0; i < n; i++, pos++) {
|
for (i = 0; i < n; i++, pos++) {
|
||||||
addDebug("lit $%x", input_data[pos]);
|
addDebug("lit $%02x", input_data[pos]);
|
||||||
w.writeByte(input_data[pos]);
|
w.writeByte(input_data[pos]);
|
||||||
}
|
}
|
||||||
optimal[input_index].lits -= n;
|
optimal[input_index].lits -= n;
|
||||||
@@ -289,12 +289,12 @@ public class Lx47Algorithm
|
|||||||
|
|
||||||
// Sequence. If two in a row, insert a zero-length lit str
|
// Sequence. If two in a row, insert a zero-length lit str
|
||||||
if (!prevIsLit) {
|
if (!prevIsLit) {
|
||||||
addDebug("lits l=0");
|
addDebug("lits l=$00");
|
||||||
w.writeBit(0);
|
w.writeBit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now write sequence info
|
// Now write sequence info
|
||||||
addDebug("seq l=%d o=%d", optimal[input_index].len, optimal[input_index].offset);
|
addDebug("seq l=$%02x o=$%04x", optimal[input_index].len, optimal[input_index].offset);
|
||||||
w.writeCodePair(optimal[input_index].len, optimal[input_index].offset);
|
w.writeCodePair(optimal[input_index].len, optimal[input_index].offset);
|
||||||
prevIsLit = false;
|
prevIsLit = false;
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ public class Lx47Algorithm
|
|||||||
|
|
||||||
// EOF marker
|
// EOF marker
|
||||||
if (!prevIsLit) {
|
if (!prevIsLit) {
|
||||||
addDebug("lits l=0");
|
addDebug("lits l=$00");
|
||||||
w.writeBit(0);
|
w.writeBit(0);
|
||||||
}
|
}
|
||||||
addDebug("EOF");
|
addDebug("EOF");
|
||||||
@@ -393,10 +393,10 @@ public class Lx47Algorithm
|
|||||||
// Check for literal string
|
// Check for literal string
|
||||||
while (true) {
|
while (true) {
|
||||||
len = r.readLiteralLen();
|
len = r.readLiteralLen();
|
||||||
chkDebug("lits l=%d", len);
|
chkDebug("lits l=$%02x", len);
|
||||||
for (int i=0; i<len; i++) {
|
for (int i=0; i<len; i++) {
|
||||||
output_data[outPos++] = (byte) r.readByte();
|
output_data[outPos++] = (byte) r.readByte();
|
||||||
chkDebug("lit $%x", output_data[outPos-1]);
|
chkDebug("lit $%02x", output_data[outPos-1]);
|
||||||
}
|
}
|
||||||
if (len != 255)
|
if (len != 255)
|
||||||
break;
|
break;
|
||||||
@@ -410,7 +410,7 @@ public class Lx47Algorithm
|
|||||||
int codePair = r.readCodePair();
|
int codePair = r.readCodePair();
|
||||||
len = codePair & 0xFFFF;
|
len = codePair & 0xFFFF;
|
||||||
int off = codePair >> 16;
|
int off = codePair >> 16;
|
||||||
chkDebug("seq l=%d o=%d", len, off);
|
chkDebug("seq l=$%02x o=$%04x", len, off);
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
output_data[outPos] = output_data[outPos - off];
|
output_data[outPos] = output_data[outPos - off];
|
||||||
++outPos;
|
++outPos;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
.SUFFIXES =
|
.SUFFIXES =
|
||||||
PRORWTS = PRORWTS2\#800
|
PRORWTS = PRORWTS2\#4000
|
||||||
|
|
||||||
all: $(PRORWTS)
|
all: $(PRORWTS)
|
||||||
|
|
||||||
|
BIN
Platform/Apple/tools/ProRWTS/PRORWTS2#4000
Normal file
BIN
Platform/Apple/tools/ProRWTS/PRORWTS2#4000
Normal file
Binary file not shown.
@@ -3,7 +3,7 @@
|
|||||||
;license:BSD-3-Clause
|
;license:BSD-3-Clause
|
||||||
|
|
||||||
!cpu 6502
|
!cpu 6502
|
||||||
*=$800
|
*=$4000
|
||||||
|
|
||||||
;place no code before init label below.
|
;place no code before init label below.
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
;i.e. running from main if accessing main, running from aux if accessing aux
|
;i.e. running from main if accessing main, running from aux if accessing aux
|
||||||
bounds_check = 0 ;set to 1 to prevent access beyond the end of the file
|
bounds_check = 0 ;set to 1 to prevent access beyond the end of the file
|
||||||
;but limits file size to 64k-2 bytes.
|
;but limits file size to 64k-2 bytes.
|
||||||
load_high = 1 ;set to 1 to load to top of RAM (either main or banked, enables a himem check)
|
load_high = 0 ;set to 1 to load to top of RAM (either main or banked, enables a himem check)
|
||||||
load_banked = 1 ;set to 1 to load into banked RAM instead of main RAM
|
load_banked = 1 ;set to 1 to load into banked RAM instead of main RAM
|
||||||
lc_bank = 1 ;load into specified bank (1 or 2) if load_banked=1
|
lc_bank = 1 ;load into specified bank (1 or 2) if load_banked=1
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
reloc = $fb00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch
|
reloc = $fb00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch
|
||||||
} ;PASS2
|
} ;PASS2
|
||||||
} else { ;load_high
|
} else { ;load_high
|
||||||
reloc = $d000 ;page-aligned, but otherwise wherever you want
|
reloc = $ef00 ;page-aligned, but otherwise wherever you want
|
||||||
} ;load_high
|
} ;load_high
|
||||||
} else { ;load_banked
|
} else { ;load_banked
|
||||||
!if load_high = 1 {
|
!if load_high = 1 {
|
||||||
|
@@ -9,18 +9,10 @@
|
|||||||
;****************************************************************************************
|
;****************************************************************************************
|
||||||
|
|
||||||
;@com.wudsn.ide.asm.hardware=APPLE2
|
;@com.wudsn.ide.asm.hardware=APPLE2
|
||||||
; Memory manager
|
; Lx47 Decompressor
|
||||||
; ------------------
|
; ------------------
|
||||||
;
|
|
||||||
; See detailed description in mem.i
|
|
||||||
|
|
||||||
* = $2000 ; PLASMA loader loads us initially at $2000
|
* = $DF00
|
||||||
|
|
||||||
; Use hi-bit ASCII for Apple II
|
|
||||||
!convtab "../include/hiBitAscii.ct"
|
|
||||||
|
|
||||||
; Global definitions
|
|
||||||
!source "../include/global.i"
|
|
||||||
|
|
||||||
tmp = $2 ; len 2
|
tmp = $2 ; len 2
|
||||||
pTmp = $4 ; len 2
|
pTmp = $4 ; len 2
|
||||||
@@ -30,6 +22,13 @@ pSrc = $C ; len 2
|
|||||||
pDst = $E ; len 2
|
pDst = $E ; len 2
|
||||||
pEnd = $10 ; len 2
|
pEnd = $10 ; len 2
|
||||||
|
|
||||||
|
cout = $FDED
|
||||||
|
prbyte = $FDDA
|
||||||
|
crout = $FD8E
|
||||||
|
rdkey = $FD0C
|
||||||
|
|
||||||
|
DEBUG = 0
|
||||||
|
|
||||||
; Decompress from pSrc to pDst, stop at pEnd. The source and dest can overlap, as long as the
|
; Decompress from pSrc to pDst, stop at pEnd. The source and dest can overlap, as long as the
|
||||||
; source block ends (at least) 2 bytes beyond the end of the dest block, e.g.
|
; source block ends (at least) 2 bytes beyond the end of the dest block, e.g.
|
||||||
; DDDDDDDDDDDDDDD
|
; DDDDDDDDDDDDDDD
|
||||||
@@ -43,8 +42,9 @@ decomp !zone {
|
|||||||
.lits asl bits ; get bit that tells us whether there's a literal string
|
.lits asl bits ; get bit that tells us whether there's a literal string
|
||||||
bne + ; ran out of bits in bit buffer?
|
bne + ; ran out of bits in bit buffer?
|
||||||
.lits2 jsr .getbts ; get more bits
|
.lits2 jsr .getbts ; get more bits
|
||||||
+ bcc .seq ; if bit was zero, no literals: go straight to sequence
|
+ bcc .endchk ; if bit was zero, no literals: go straight to sequence (after end check)
|
||||||
jsr .gamma ; Yes we have literals. Get the count.
|
jsr .gamma ; Yes we have literals. Get the count.
|
||||||
|
!if DEBUG { jsr .dbg1 }
|
||||||
tax
|
tax
|
||||||
cpx #255 ; special case: long literal marked by len=255; chk and save to carry
|
cpx #255 ; special case: long literal marked by len=255; chk and save to carry
|
||||||
- lda (pSrc),y
|
- lda (pSrc),y
|
||||||
@@ -62,7 +62,8 @@ decomp !zone {
|
|||||||
cmp pEnd
|
cmp pEnd
|
||||||
lda pDst+1
|
lda pDst+1
|
||||||
sbc pEnd+1
|
sbc pEnd+1
|
||||||
bcs .ret
|
;bcs .ret
|
||||||
|
bcs .chk
|
||||||
|
|
||||||
.seq lda (pSrc),y
|
.seq lda (pSrc),y
|
||||||
inc pSrc
|
inc pSrc
|
||||||
@@ -79,9 +80,9 @@ decomp !zone {
|
|||||||
sta tmp
|
sta tmp
|
||||||
jsr .gamma
|
jsr .gamma
|
||||||
lsr
|
lsr
|
||||||
rol tmp
|
ror tmp
|
||||||
lsr
|
lsr
|
||||||
rol tmp
|
ror tmp
|
||||||
sta tmp+1
|
sta tmp+1
|
||||||
.gotoff lda pDst
|
.gotoff lda pDst
|
||||||
clc ; effectively add 1 to offset.
|
clc ; effectively add 1 to offset.
|
||||||
@@ -97,6 +98,7 @@ decomp !zone {
|
|||||||
adc #1 ; A>=1 + sec + 1 => final len 3 or more
|
adc #1 ; A>=1 + sec + 1 => final len 3 or more
|
||||||
tax
|
tax
|
||||||
.gotlen
|
.gotlen
|
||||||
|
!if DEBUG { jsr .dbg2 }
|
||||||
- lda (pTmp),y
|
- lda (pTmp),y
|
||||||
sta (pDst),y
|
sta (pDst),y
|
||||||
iny
|
iny
|
||||||
@@ -109,7 +111,7 @@ decomp !zone {
|
|||||||
ldy #0 ; back to 0 as expected by lits section
|
ldy #0 ; back to 0 as expected by lits section
|
||||||
bcc .lits
|
bcc .lits
|
||||||
inc pDst+1
|
inc pDst+1
|
||||||
bcs .lits ; always taken
|
jmp .lits
|
||||||
|
|
||||||
; Read an Elias Gamma value into A. Destroys X. Sets carry.
|
; Read an Elias Gamma value into A. Destroys X. Sets carry.
|
||||||
.gamma lda #1
|
.gamma lda #1
|
||||||
@@ -134,4 +136,42 @@ decomp !zone {
|
|||||||
sta bits
|
sta bits
|
||||||
txa
|
txa
|
||||||
.ret rts
|
.ret rts
|
||||||
|
|
||||||
|
.chk ora pDst
|
||||||
|
eor pEnd
|
||||||
|
beq .ret
|
||||||
|
brk
|
||||||
|
|
||||||
|
!if DEBUG {
|
||||||
|
.dbg1 pha
|
||||||
|
lda #'L'|$80
|
||||||
|
jsr cout
|
||||||
|
pla
|
||||||
|
pha
|
||||||
|
.dbgEnd jsr prbyte
|
||||||
|
jsr crout
|
||||||
|
;- bit $C000
|
||||||
|
; bpl -
|
||||||
|
; bit $C010
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
|
||||||
|
.dbg2 pha
|
||||||
|
lda #'S'|$80
|
||||||
|
jsr cout
|
||||||
|
txa
|
||||||
|
jsr prbyte
|
||||||
|
lda #' '|$80
|
||||||
|
jsr cout
|
||||||
|
lda tmp
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
pha
|
||||||
|
lda tmp+1
|
||||||
|
adc #0
|
||||||
|
jsr prbyte
|
||||||
|
pla
|
||||||
|
jmp .dbgEnd
|
||||||
|
}
|
||||||
|
|
||||||
} ; end of zone
|
} ; end of zone
|
||||||
|
151
Platform/Apple/virtual/src/core/loader.s
Normal file
151
Platform/Apple/virtual/src/core/loader.s
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
;****************************************************************************************
|
||||||
|
; Copyright (C) 2017 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1
|
||||||
|
; (the "License"); you may not use this file except in compliance with the License.
|
||||||
|
; You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-1.1>.
|
||||||
|
; Unless required by applicable law or agreed to in writing, software distributed under
|
||||||
|
; the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
||||||
|
; ANY KIND, either express or implied. See the License for the specific language
|
||||||
|
; governing permissions and limitations under the License.
|
||||||
|
;****************************************************************************************
|
||||||
|
|
||||||
|
;@com.wudsn.ide.asm.hardware=APPLE2
|
||||||
|
; LegendOS bootstrapping loader
|
||||||
|
; -----------------------------
|
||||||
|
|
||||||
|
; Use hi-bit ASCII for Apple II
|
||||||
|
!convtab "../include/hiBitAscii.ct"
|
||||||
|
|
||||||
|
; Handy global defs
|
||||||
|
!source "../include/global.i"
|
||||||
|
|
||||||
|
DEBUG = 0
|
||||||
|
|
||||||
|
* = $2000
|
||||||
|
|
||||||
|
tmp = $2 ; len 2
|
||||||
|
pTmp = $4 ; len 2
|
||||||
|
bits = $6 ; len 1
|
||||||
|
|
||||||
|
pSrc = $C ; len 2
|
||||||
|
pDst = $E ; len 2
|
||||||
|
pEnd = $10 ; len 2
|
||||||
|
|
||||||
|
pData = $80 ; len 2
|
||||||
|
pRun = $82 ; len 2
|
||||||
|
|
||||||
|
decomp = $DF00
|
||||||
|
|
||||||
|
init ; Init pointer to blocks we're going to move/decompress
|
||||||
|
lda #<dataStart
|
||||||
|
sta pData
|
||||||
|
lda #>dataStart
|
||||||
|
sta pData+1
|
||||||
|
; temporary: copy ROM so we can debug decompressor
|
||||||
|
bit setLcWr ; read from ROM, write to LC ram
|
||||||
|
bit setLcWr
|
||||||
|
ldy #0
|
||||||
|
sty pSrc
|
||||||
|
ldx #$f8
|
||||||
|
-- stx pSrc+1
|
||||||
|
- lda (pSrc),y
|
||||||
|
sta (pSrc),y
|
||||||
|
iny
|
||||||
|
bne -
|
||||||
|
inx
|
||||||
|
bne --
|
||||||
|
; First is the decompressor itself (special: just copy one page)
|
||||||
|
jsr getBlk
|
||||||
|
bit setLcRW+lcBank1 ; switch in target bank
|
||||||
|
bit setLcRW+lcBank1
|
||||||
|
- lda (pSrc),y
|
||||||
|
.st sta decomp,y
|
||||||
|
iny
|
||||||
|
bne -
|
||||||
|
; Next comes ProRWTS
|
||||||
|
jsr runBlk
|
||||||
|
; Then PLASMA
|
||||||
|
jsr runBlk
|
||||||
|
; And finally the memory mgr (fall through)
|
||||||
|
runBlk jsr getBlk ; get block size and calc pointers
|
||||||
|
!if DEBUG {
|
||||||
|
lda #1 ; turn on printer
|
||||||
|
jsr $FE95
|
||||||
|
jsr debug
|
||||||
|
}
|
||||||
|
bit setLcRW+lcBank1
|
||||||
|
jsr decomp ; decompress the code
|
||||||
|
!if DEBUG {
|
||||||
|
lda #"R"
|
||||||
|
jsr ROM_cout
|
||||||
|
jsr ROM_crout
|
||||||
|
}
|
||||||
|
jmp $4000 ; and run it so it'll relocate itself
|
||||||
|
|
||||||
|
getByte ldy #0
|
||||||
|
lda (pData),y
|
||||||
|
inc pData
|
||||||
|
bne +
|
||||||
|
inc pData+1
|
||||||
|
+ rts
|
||||||
|
|
||||||
|
getWord jsr getByte
|
||||||
|
pha
|
||||||
|
jsr getByte
|
||||||
|
tax
|
||||||
|
pla
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
|
||||||
|
getBlk ; Get uncompressed len from the block header,
|
||||||
|
; and calculate dest end (based on start of $4000)
|
||||||
|
jsr getWord
|
||||||
|
sta pEnd
|
||||||
|
txa
|
||||||
|
adc #$40
|
||||||
|
sta pEnd+1
|
||||||
|
|
||||||
|
; Get compressed len
|
||||||
|
jsr getWord
|
||||||
|
pha ; save lo byte of len
|
||||||
|
|
||||||
|
; We're now looking at start of compressed data. Record that pointer.
|
||||||
|
lda pData
|
||||||
|
sta pSrc
|
||||||
|
lda pData+1
|
||||||
|
sta pSrc+1
|
||||||
|
|
||||||
|
; We always decompress to $4000
|
||||||
|
sty pDst ; Y already zero
|
||||||
|
lda #$40
|
||||||
|
sta pDst+1
|
||||||
|
|
||||||
|
; Add compressed length to get to start of next block
|
||||||
|
pla ; get len back
|
||||||
|
adc pData
|
||||||
|
sta pData
|
||||||
|
txa
|
||||||
|
adc pData+1
|
||||||
|
sta pData+1
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
!if DEBUG {
|
||||||
|
debug jsr ROM_crout
|
||||||
|
lda #"B"
|
||||||
|
jsr ROM_cout
|
||||||
|
lda pSrc+1
|
||||||
|
ldx pSrc
|
||||||
|
jsr .pr
|
||||||
|
lda pDst+1
|
||||||
|
ldx pDst
|
||||||
|
jsr .pr
|
||||||
|
lda pEnd+1
|
||||||
|
ldx pEnd
|
||||||
|
jsr ROM_prntax
|
||||||
|
jmp ROM_crout
|
||||||
|
.pr jsr ROM_prntax
|
||||||
|
lda #" "
|
||||||
|
jmp ROM_cout
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStart = *
|
@@ -14,7 +14,7 @@
|
|||||||
;
|
;
|
||||||
; See detailed description in mem.i
|
; See detailed description in mem.i
|
||||||
|
|
||||||
* = $2000 ; PLASMA loader loads us initially at $2000
|
* = $4000 ; PLASMA loader loads us initially at $2000
|
||||||
|
|
||||||
; Use hi-bit ASCII for Apple II
|
; Use hi-bit ASCII for Apple II
|
||||||
!convtab "../include/hiBitAscii.ct"
|
!convtab "../include/hiBitAscii.ct"
|
||||||
|
Reference in New Issue
Block a user