Making slow progress integrating ProRWTS with mem mgr.

This commit is contained in:
Martin Haye 2017-01-04 13:15:39 -08:00
parent 8ff169d1e6
commit dd061c37c3
8 changed files with 2130 additions and 2830 deletions

View File

@ -17,7 +17,6 @@ package org.badvision
import java.nio.ByteBuffer
import java.nio.channels.Channels
import net.jpountz.lz4.LZ4Factory
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.zip.GZIPInputStream
@ -78,7 +77,7 @@ class A2PackPartitions
def globalScripts = [:]
def lastSysModule
def compressor = LZ4Factory.fastestInstance().highCompressor()
def compressor = new Lx47Algorithm()
def ADD_COMP_CHECKSUMS = false
@ -1225,137 +1224,6 @@ class A2PackPartitions
static int lx47Total = 0
static int lx47Savings = 0
// 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.
//
def testLx47(inData, inLen, lz4Len)
{
def lx47 = new Lx47Algorithm()
def inputData = new byte[inLen]
System.arraycopy(inData, 0, inputData, 0, inLen)
def outputData = lx47.compress(inputData)
def savings = lz4Len - outputData.length
if (savings >= 8) {
//def uncomp = new byte[inLen]
//lx47.decompress(outputData, 0, uncomp, 0, inLen)
//assert uncomp == inputData
// Verify the stream comes out right with overlapped decompression
def underlap = 2
def buf = new byte[inLen+underlap]
def initialOffset = inLen - outputData.length + underlap;
System.arraycopy(outputData, 0, buf, initialOffset, outputData.length)
lx47.decompress(buf, initialOffset, buf, 0, inLen)
def uncomp = Arrays.copyOfRange(buf, 0, inLen)
assert uncomp == inputData
uncompTotal += inLen
lx47Savings += savings
lz4Total += lz4Len
lx47Total += outputData.length
println String.format("lz47 usize=%d savings=%d utot=%d lz4tot=%d lx47tot=%d total_savings=%d",
inLen, savings, uncompTotal, lz4Total, lx47Total, lx47Savings)
}
else {
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
// as one byte instead of two. In our data, that's about 1/3 of the offsets.
//
def recompress(data, inLen, uncompData, uncompLen)
{
def outLen = 0
def sp = 0
def dp = 0
def cksum = 0
while (true)
{
assert dp <= sp
// First comes the token: 4 bits literal len, 4 bits match len
def token = data[dp++] = (data[sp++] & 0xFF)
def matchLen = token & 0xF
def literalLen = token >> 4
// The literal length might get extended
if (literalLen == 15) {
while (true) {
token = data[dp++] = (data[sp++] & 0xFF)
literalLen += token
if (token != 0xFF)
break
}
}
if (debugCompression)
println String.format("Literal: ptr=\$%x, len=\$%x.", sp, literalLen)
// Copy the literal bytes
outLen += literalLen
for ( ; literalLen > 0; --literalLen) {
cksum ^= data[sp]
data[dp++] = data[sp++]
}
// The last block has only literals, and no match
if (sp == inLen)
break
// Grab the offset
token = data[sp++] & 0xFF
def offset = token | ((data[sp++] & 0xFF) << 8)
// Re-encode the offset using 1 byte if possible
assert offset < 32768
if (offset < 128)
data[dp++] = offset
else {
data[dp++] = (offset & 0x7F) | 0x80
data[dp++] = (offset >> 7) & 0xFF
}
// If checksums are enabled, output the checksum so far
if (offset < 128 && ADD_COMP_CHECKSUMS) {
if (debugCompression)
println String.format(" [chksum=\$%x]", cksum & 0xFF)
data[dp++] = (byte) cksum
}
// The match length might get extended
if (matchLen == 15) {
while (true) {
token = data[dp++] = (data[sp++] & 0xFF)
matchLen += token
if (token != 0xFF)
break
}
}
matchLen += 4 // min match length is 4
if (debugCompression)
println String.format("Match: offset=\$%x, len=\$%x.", offset, matchLen)
// We do nothing with the match bytes except add them to the checksum
(0..<matchLen).each {
cksum ^= uncompData[outLen]
++outLen
}
}
// If checksums are enabled, output the final checksum
if (ADD_COMP_CHECKSUMS) {
if (debugCompression)
println String.format("Final cksum: \$%x", cksum & 0xFF)
data[dp++] = (byte) cksum
}
assert outLen == uncompLen
return dp
}
def compressionSavings = 0
def compress(buf)
@ -1364,30 +1232,25 @@ class A2PackPartitions
def uncompressedLen = buf.position()
def uncompressedData = unwrapByteBuffer(buf)
// Now compress it with LZ4
// Now compress it with LX47
assert uncompressedLen < 327678 : "data block too big"
assert uncompressedLen > 0
def maxCompressedLen = compressor.maxCompressedLength(uncompressedLen)
def compressedData = new byte[maxCompressedLen]
def compressedLen = compressor.compress(uncompressedData, 0, uncompressedLen,
compressedData, 0, maxCompressedLen)
def compressedData = compressor.compress(uncompressedData)
def compressedLen = compressedData.length
assert compressedLen > 0
// Then recompress to LZ4M (pretty much always smaller)
def recompressedLen = recompress(compressedData, compressedLen, uncompressedData, uncompressedLen)
//testLx47(uncompressedData, uncompressedLen, recompressedLen)
// If we saved at least 20 bytes, take the compressed version.
if ((uncompressedLen - recompressedLen) >= 20) {
// If we saved at least 10 bytes, take the compressed version.
println "TODO: Put back compression"
if (false && (uncompressedLen - compressedLen) >= 10) {
if (debugCompression)
println String.format(" Compress. rawLen=\$%x compLen=\$%x", uncompressedLen, recompressedLen)
compressionSavings += (uncompressedLen - recompressedLen) - 2 - (ADD_COMP_CHECKSUMS ? 1 : 0)
return [data:compressedData, len:recompressedLen,
println String.format(" Compress. rawLen=\$%x compLen=\$%x", uncompressedLen, compressedLen)
compressionSavings += (uncompressedLen - compressedLen) - 2 - (ADD_COMP_CHECKSUMS ? 1 : 0)
return [data:compressedData, len:compressedLen,
compressed:true, uncompressedLen:uncompressedLen]
}
else {
if (debugCompression)
println String.format(" No compress. rawLen=\$%x compLen=\$%x", uncompressedLen, recompressedLen)
println String.format(" No compress. rawLen=\$%x compLen=\$%x", uncompressedLen, compressedLen)
return [data:uncompressedData, len:uncompressedLen, compressed:false]
}
}
@ -1470,8 +1333,7 @@ class A2PackPartitions
def prevUserDir = System.getProperty("user.dir")
def result
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())
if (inFile) {
@ -1625,14 +1487,13 @@ class A2PackPartitions
{
if (binaryStubsOnly)
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
new File(inDir + "build").mkdirs()
println "Created dir ${new File(inDir + "build")}"
def outBuf = ByteBuffer.allocate(50000)
def compressor = new Lx47Algorithm()
["loader", "decomp", "PRORWTS", "PLVM02", "mem"].each { name ->
def code
if (name == "PRORWTS")
@ -1649,7 +1510,6 @@ class A2PackPartitions
}
code = sysCode[name].buf
}
println "Processing $name."
def compressed = (name ==~ /loader|decomp/) ?
code : wrapByteArray(compressor.compress(unwrapByteBuffer(code)))
if (name != "loader") {
@ -1663,7 +1523,7 @@ class A2PackPartitions
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))

View File

@ -19,7 +19,7 @@ public class Lx47Algorithm
void addDebug(String format, Object... arguments) {
String str = String.format(format, arguments);
System.out.println("Gen: " + str);
//System.out.println("Gen: " + str);
debugs.add(str);
}
@ -419,7 +419,7 @@ public class Lx47Algorithm
chkDebug("EOF");
}
public byte[] compress(byte[] input_data) {
if (false) {
input_data = "hellohelloabchello".getBytes();

File diff suppressed because it is too large Load Diff

View File

@ -41,22 +41,11 @@ init ; Init pointer to blocks we're going to move/decompress
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)
bit setLcWr+lcBank1 ; read from ROM, write to LC ram
bit setLcWr+lcBank1
jsr getBlk
bit setLcRW+lcBank1 ; switch in target bank
bit setLcRW+lcBank1
- lda (pSrc),y
.st sta decomp,y
iny
@ -74,6 +63,7 @@ runBlk jsr getBlk ; get block size and calc pointers
}
bit setLcRW+lcBank1
jsr decomp ; decompress the code
bit setLcWr+lcBank1
!if DEBUG {
lda #"R"
jsr ROM_cout

View File

@ -27,10 +27,8 @@
; Constants
MAX_SEGS = 96
DO_COMP_CHECKSUMS = 0 ; during compression debugging
DEBUG_DECOMP = 0
DEBUG = 0
SANITY_CHECK = 0 ; also prints out request data
DEBUG = 1
SANITY_CHECK = 1 ; also prints out request data
; Zero page temporary variables
tmp = $2 ; len 2
@ -43,10 +41,29 @@ isCompressed = $B ; len 1
pSrc = $C ; len 2
pDst = $E ; len 2
ucLen = $10 ; len 2
checksum = $12 ; len 1
plasmaNextOp = $F0 ; PLASMA's dispatch loop
plasmaXTbl = $D300 ; op table for auXiliary code execution
; Mapping of ProRWTS register names to mem mgr registers:
; "status" -> tmp+1
; "auxreq" -> isAuxCmd
; "reqcmd" -> tmp
; "sizelo"+hi -> reqLen
; "ldrlo"+hi -> pDst
; "namlo"+hi -> pSrc
lx47Decomp = $DF00
; ProRWTS constants
cmdseek = 0
cmdread = 1
cmdwrite = 2
; ProRWTS locations
reseek_0 = $18 ; to reset seek ptr, zero out these 3 locs
reseek_1 = $1B
reseek_2 = $1C
proRWTS = $F600
opendir = proRWTS
rdwrpart = opendir+3
; Memory buffers
fileBuf = $4000 ; len $400
@ -63,21 +80,10 @@ gcHash_link = $5300
gcHash_dstLo = $5400
gcHash_dstHi = $5500
; Other equates
prodosMemMap = $BF58
;------------------------------------------------------------------------------
!macro callMLI cmd, parms {
lda #cmd
ldx #<parms
ldy #>parms
jsr _callMLI
}
;------------------------------------------------------------------------------
; Relocate all the pieces to their correct locations and perform patching.
relocate:
; put something interesting on the screen :)
; Put something interesting on the screen :)
jsr ROM_home
ldy #0
- lda .welcomeText,y
@ -85,24 +91,27 @@ relocate:
jsr ROM_cout
iny
bne -
jmp +
.welcomeText: !text "Welcome to LegendOS.",$8D,0
+
; special: clear most of the lower 48k
; special: clear most of the lower 48k and the ProDOS bank of the LC
+ bit setLcRW+lcBank1
bit setLcRW+lcBank1
ldy #0
tya
ldx #8
.clr1 stx .clrst1+2
stx .clrst2+2
ldy #0
tya
.clrst1 sta $800,y
.clrst2 sta $880,y
iny
bpl .clrst1
inx
cpx #$20
cpx #$40 ; skip our own unrelocated code $4000.4FFF
bne +
ldx #$40
+ cpx #$BF
ldx #$50
+ cpx #$C0 ; skip IO space $C000.CFFF
bne +
ldx #$D0
+ cpx #$F6 ; skip ProRWTS $F600.FEFF, and ROM vecs $FF00.FFFF
bne .clr1
; first our lo memory piece goes to $800
@ -116,9 +125,6 @@ relocate:
inc .lost+2
dex
bne .lold
; set up to copy the ProDOS code from main memory to aux
bit setLcRW+lcBank1 ; only copy bank 1, because bank 2 is PLASMA runtime
bit setLcRW+lcBank1 ; write to it
; verify that aux mem exists
inx
stx $D000
@ -134,50 +140,8 @@ relocate:
cpx $D000
beq .gotaux
.noaux jsr inlineFatal : !text "AuxMemReq",0
.gotaux ldx #$D0
.pglup stx .ld+2
stx .st+2
sei
.bylup sta clrAuxZP ; get byte from main LC
.ld lda $D000,y
sta setAuxZP ; temporarily turn on aux LC
.st sta $D000,y
iny
bne .bylup
inx ; all pages until we hit $00
bne .pglup
cli
sta clrAuxZP ; ...back to main LC
; patch into the main ProDOS MLI entry point
ldx #$4C ; jmp
stx $BFBB
lda #<enterProDOS1
sta $BFBC
lda #>enterProDOS1
sta $BFBD
; patch into the interrupt handler
stx $BFEB
lda #<enterProDOS2
sta $BFEC
lda #>enterProDOS2
sta $BFED
; patch into the shared MLI/IRQ exit routine
stx $BFA0
lda #<exitProDOS
sta $BFA1
lda #>exitProDOS
sta $BFA2
; now blow away the main RAM LC area as a check
ldx #$D0
tya
.clrlup stx .st2+2
.st2 sta $D000,Y
iny
bne .st2
inx
bne .clrlup
; Copy the vectors
ldx #6
; Copy the 6502 ROM vectors
.gotaux ldx #5
bit setLcWr+lcBank1 ; read from ROM, write to LC RAM
- lda $FFFA,x
sta $FFFA,x
@ -192,7 +156,7 @@ relocate:
sta $FFFE
lda #>brkHandler
sta $FFFF
; Place the bulk of the memory manager code into the newly cleared LC
; Place the bulk of the memory manager code into the LC
ldx #>hiMemBegin
.cpmm stx .ld4+2
.ld4 lda hiMemBegin,y
@ -217,30 +181,12 @@ init: !zone
lda #$B
sta $c0ab
+ ; END OF KLUDGE
; grab the prefix of the current drive
lda #<prodosPrefix
sta getPfxAddr
lda #>prodosPrefix
sta getPfxAddr+1
+callMLI MLI_GET_PREFIX, getPfxParams
bcc +
jmp prodosError
+ lda prodosPrefix
and #$F ; strip off drive/slot, keep string len
sta prodosPrefix
; switch in mem mgr
bit setLcRW+lcBank1
bit setLcRW+lcBank1
; close all files
lda #0
jsr closeFile
; clear ProDOS mem map so it lets us load stuff anywhere we want
ldx #$18
lda #0
.clr: sta prodosMemMap-1,x
dex
bne .clr
; clear the segment tables
lda #0
tax
- sta tSegLink,x
sta tSegAdrLo,x
sta tSegAdrHi,x
@ -252,7 +198,7 @@ init: !zone
; clear other pointers
sta targetAddr+1
sta scanStart
sta partFileRef
sta partFileOpen
sta curPartition
lda #<diskLoader
sta nextLdVec+1
@ -477,64 +423,6 @@ fatalError: !zone
jsr ROM_bell
.hang: jmp .hang ; loop forever
;------------------------------------------------------------------------------
; Normal entry point for ProDOS MLI calls. This patches the code at $BFBB.
enterProDOS1: !zone
pla ; saved A reg
sta .ld2+1
pla ; lo byte of ret addr
sta .ld1+1
pla ; hi byte of ret addr
sta setAuxZP ; switch to aux stack/ZP/LC
pha ; hi byte of ret addr
.ld1 lda #11 ; self-modified earlier
pha ; lo byte of ret addr
.ld2 lda #11 ; saved A reg
pha
lda $E000 ; this is what the original code at $BFBB did
jmp $BFBE ; jump back in where ProDOS enter left off
;------------------------------------------------------------------------------
; Entry point for ProDOS interrupt handler. This patches the code at $BFEB.
enterProDOS2: !zone
pla ; saved P reg
sta .ld2+1
pla ; ret addr lo
sta .ld1+1
pla ; ret addr hi
sta setAuxZP ; switch to aux stack/ZP/LC
pha
.ld1 lda #11 ; self-modified earlier
pha
.ld2 lda #11 ; ditto
pha
bit $C08B ; this is what the original code at $BFEB did
jmp $BFEE ; back to where ProDOS left off
;------------------------------------------------------------------------------
; Shared exit point for ProDOS MLI and IRQ handlers. This patches the code
; at $BFA0.
exitProDOS: !zone
; pop data from AUX stack
pla ; saved A reg
sta .ld3+1
pla ; P-reg for RTI
sta .ld2+1
pla ; hi byte of ret addr
sta .ld1+1
pla ; lo byte of ret addr
; push data to MAIN stack
sta clrAuxZP ; back to main stack/ZP/LC
pha ; lo byte of ret addr
.ld1 lda #11 ; self-modified earlier
pha ; hi byte of ret addr
.ld2 lda #11 ; ditto
pha ; P-reg for RTI
.ld3 lda #11 ; self-modified earlier (the saved A reg)
; Note! We leave LC bank 1 enabled, since that's where the memory
; manager lives, and it's the only code that calls ProDOS.
rti ; RTI pops P-reg and *exact* return addr (not adding 1)
;------------------------------------------------------------------------------
; BRK and IRQ handler: switch to ROM, call default handler, switch back
brkHandler:
@ -790,44 +678,8 @@ __internalErr: !zone {
; Space (in main RAM) for saving the state of the LC bank switch
savedLCBnk2State !byte 0
; Call MLI from main memory rather than LC, since it lives in aux LC.
_callMLI: sta .cmd
stx .params
sty .params+1
jsr mli
.cmd !byte 0
.params !word 0
rts
; Our ProDOS param blocks can't be in LC ram
openParams: !byte 3 ; param count
!word filename ; pointer to file name
!word fileBuf ; pointer to buffer
openFileRef: !byte 0 ; returned file number
; ProDOS prefix of the boot disk
prodosPrefix: !fill 16
; Buffer for forming the full filename
filename: !fill 28 ; 16 for prefix plus 11 for "/GAME.PART.1"
readParams: !byte 4 ; param count
readFileRef: !byte 0 ; file ref to read
readAddr: !word 0
readLen: !word 0
readGot: !word 0
setMarkParams: !byte 2 ; param count
setMarkFileRef: !byte 0 ; file reference to set mark in
setMarkPos: !byte 0 ; mark position (3 byte integer)
!byte 0
!byte 0
closeParams: !byte 1 ; param count
closeFileRef: !byte 0 ; file ref to close
getPfxParams: !byte 1 ; param count
getPfxAddr: !word 0 ; pointer to buffer
filename: !fill 12 ; 1 for len plus 11 for "GAME.PART.1"
;------------------------------------------------------------------------------
; Heap management routines
@ -1101,12 +953,10 @@ gc2_sweep: !zone
rts
closePartFile: !zone
lda partFileRef ; close the partition file
lda partFileOpen ; check if open
beq .done
!if DEBUG { +prStr : !text "ClosePart.",0 }
jsr closeFile
lda #0 ; zero out...
sta partFileRef ; ... the file reference so we know it's no longer open
dec partFileOpen
.done rts
heapCollect: !zone
@ -1233,10 +1083,11 @@ scanStart: !byte 0, 1 ; main, aux
segNum: !byte 0
nextLdVec: jmp diskLoader
curPartition: !byte 0
partFileRef: !byte 0
partFileOpen: !byte 0
curMarkPos: !fill 3
setMarkPos: !fill 3
nSegsQueued: !byte 0
bufferDigest: !fill 4
multiDiskMode: !byte 0 ; hardcoded to YES for now
diskActState: !byte 0
;------------------------------------------------------------------------------
@ -2071,27 +1922,9 @@ calcBufferDigest: !zone
;------------------------------------------------------------------------------
openPartition: !zone
!if DEBUG { +prStr : !text "OpenPart ",0 : +prByte curPartition : +crout }
; complete the partition file name, changing "1" to "2" if we're in multi-disk mode
; and opening partition 2.
.mkname ldx #1
; complete the partition file name, changing "1" to "2" if opening partition 2.
.mkname ldx #0
ldy #1
- lda prodosPrefix,x
sta filename,y
cmp #$31 ; "1"
bne +
lda multiDiskMode
beq + ; don't change if single-disk mode
lda curPartition
cmp #2
bcc +
lda #$32 ; "2"
sta filename,y
+ cpx prodosPrefix ; done with full length of prefix?
beq +
inx
iny
bne - ; always taken
+ ldx #0
- lda .fileStr,x
beq +++
cmp #$31 ; "1"
@ -2108,39 +1941,41 @@ openPartition: !zone
+++ dey
sty filename ; total length
; open the file
.open +callMLI MLI_OPEN, openParams
bcc .opened
cmp #$46 ; file not found?
bne +
lda #1 ; enter into
sta multiDiskMode ; multi-disk mode
bne .mkname ; and retry
+ cmp #$45 ; volume not found?
beq .insert ; ask user to insert the disk
jmp prodosError ; no, misc error - print it and die
; grab the file number, since we're going to keep it open
.opened lda openFileRef
sta partFileRef
sta readFileRef
; Read the first two bytes, which tells us how long the header is.
.open lda #<filename
sta pSrc
lda #>filename
sta pSrc+1
lda #<headerBuf
sta readAddr
sta pDst
lda #>headerBuf
sta readAddr+1
lda #2
sta readLen
sta pDst+1
lda #2 ; read 2 bytes (which will tell us how long the header is)
sta reqLen
lda #0
sta readLen+1
jsr readToMain
lda headerBuf ; grab header size
sta readLen ; set to read that much. Will actually get 2 extra bytes,
; but that's no biggie.
sta reqLen+1
lda #0 ; cmdread, for drive 1
sta tmp
jsr opendir
lda tmp+1 ; get status
bne .insert ; zero=ok, 1=err
jsr disk_reseek ; by opening, we did an implicit seek
lda #2 ; and we read 2 bytes
sta curMarkPos
; read the full header
.opened lda headerBuf ; grab header size
sec
sbc #2 ; minus size of the size
sta reqLen ; set to read that much.
lda headerBuf+1 ; hi byte too
sta readLen+1
lda #2 ; read just after the 2-byte length
sta readAddr
jmp readToMain ; finish by reading the rest of the header
sbc #0
sta reqLen+1
lda #<headerBuf
sta pDst
lda #>headerBuf
sta pDst+1
jmp disk_read
; ask user to insert the disk
; TODO: handle dual drive configuration
.insert +safeHome
+prStr : !text "Insert disk ",0
bit $c051
@ -2152,34 +1987,15 @@ openPartition: !zone
+safeHome
bit $c050
jmp .open ; try again
.fileStr !raw "/GAME.PART.1",0 ; 'raw' chars to get lo-bit ascii that ProDOS likes.
.fileStr !raw "GAME.PART.1",0 ; 'raw' chars to get lo-bit ascii that ProDOS likes.
;------------------------------------------------------------------------------
sequenceError: !zone
jsr inlineFatal : !text "BadSeq", 0
;------------------------------------------------------------------------------
prodosError: !zone
pha
lsr
lsr
lsr
lsr
jsr .digit
sta .num
pla
jsr .digit
sta .num+1
jsr inlineFatal
.msg: !text "ProDOSErr $"
.num: !text "xx"
!byte 0
.digit: and #$F
ora #$B0
cmp #$BA
bcc +
adc #6
+ rts
diskError: !zone
jsr inlineFatal : !text "DskErr", 0
;------------------------------------------------------------------------------
disk_startLoad: !zone
@ -2188,7 +2004,7 @@ disk_startLoad: !zone
cpx curPartition ; switching partition?
stx curPartition ; (and store the new part num in any case)
bne .new ; if different, close the old one
lda partFileRef
lda partFileOpen
beq .done ; if nothing already open, we're okay with that.
jsr calcBufferDigest ; same partition - check that buffers are still intact
beq .done ; if correct partition file already open, we're done.
@ -2211,7 +2027,7 @@ disk_queueLoad: !zone
lda #$FF
jsr showDiskActivity ; graphical marker that disk activity happening
inc nSegsQueued ; record the fact that we're queuing a seg
lda partFileRef ; check if we've opened the file yet
lda partFileOpen ; check if we've opened the file yet
bne + ; yes, don't re-open
jsr openPartition ; open the partition file
+ jsr startHeaderScan ; start scanning the partition header
@ -2285,20 +2101,85 @@ disk_queueLoad: !zone
jsr adjYpTmp ; keep it small
+ jmp .scan ; go for more
;------------------------------------------------------------------------------
disk_reseek: !zone
lda #0
sta reseek_0 ; rewind the ProRWTS seek pointer
sta reseek_1
sta reseek_2
sta curMarkPos
sta curMarkPos+1
sta curMarkPos+2
rts
;------------------------------------------------------------------------------
disk_seek: !zone
lda #cmdseek
sta tmp
lda setMarkPos
sec
sbc curMarkPos
sta reqLen
lda setMarkPos+1
sbc curMarkPos+1
sta reqLen+1
lda setMarkPos+2
sbc curMarkPos+2
bmi .back
bne .far
jmp rdwrpart
.back jsr disk_reseek
jmp disk_seek
.far lda #$FF
sta reqLen
sta reqLen+1
jsr rdwrpart
lda #$FF
tax
jsr adjMark
jmp disk_seek
;------------------------------------------------------------------------------
adjMark: !zone
clc
adc curMarkPos
sta curMarkPos
txa
adc curMarkPos+1
sta curMarkPos+1
bcc +
inc curMarkPos+2
+ rts
;------------------------------------------------------------------------------
disk_read: !zone
lda #cmdread
sta tmp
lda reqLen
pha
lda reqLen+1
pha
jsr rdwrpart
pla
tax
pla
jsr adjMark
+ lda tmp+1
bne .err
rts
.err jmp diskError
;------------------------------------------------------------------------------
disk_finishLoad: !zone
lda nSegsQueued ; see if we actually queued anything
beq .done ; if nothing queued, we're done
lda partFileRef
sta setMarkFileRef ; copy the file ref number to our MLI param blocks
sta readFileRef
lda headerBuf ; grab # header bytes
sta setMarkPos ; set to start reading at first non-header byte in file
lda headerBuf+1 ; hi byte too
lda headerBuf ; grab # header bytes
sta setMarkPos ; set to start reading at first non-header byte in file
lda headerBuf+1 ; hi byte too
sta setMarkPos+1
lda #0
sta setMarkPos+2
sta .nFixups
sta .nFixups ; might as well clear fixup count while we're at it
jsr startHeaderScan ; start scanning the partition header
.scan: lda (pTmp),y ; get resource type byte
bne .notdone ; zero = end of header
@ -2353,13 +2234,12 @@ disk_finishLoad: !zone
+ sta ucLen+1 ; save uncomp len hi byte
jsr scanForResource ; find the segment number allocated to this resource
beq .addrErr ; it better have been allocated
jsr disk_seek ; move the file pointer to the current block
lda tSegAdrLo,x ; grab the address
sta pDst ; and save it to the dest point for copy or decompress
lda tSegAdrHi,x ; hi byte too
sta pDst+1
!if DEBUG { jsr .debug2 }
+callMLI MLI_SET_MARK, setMarkParams ; move the file pointer to the current block
bcs .prodosErr
!if DEBUG >= 3 { +prStr : !text "Deco.",0 }
jsr lz4Decompress ; decompress (or copy if uncompressed)
!if DEBUG >= 3 { +prStr : !text "Done.",0 }
@ -2382,8 +2262,6 @@ disk_finishLoad: !zone
bpl + ; if Y index is is small, no need to adjust
jsr adjYpTmp ; adjust pTmp and Y to make it small again
+ jmp .scan ; back for more
.prodosErr:
jmp prodosError
.addrErr:
jmp invalParam
@ -2426,323 +2304,10 @@ adjYpTmp: !zone
inc pTmp+1 ; go to next page
+ rts
;------------------------------------------------------------------------------
closeFile: !zone
sta closeFileRef
+callMLI MLI_CLOSE, closeParams
bcs .prodosErr
rts
.prodosErr:
jmp prodosError
;------------------------------------------------------------------------------
readToMain: !zone
+callMLI MLI_READ, readParams
bcs .err
rts
.err: jmp prodosError
;------------------------------------------------------------------------------
readToBuf: !zone
; Read as much data as we can, up to min(compLen, bufferSize) into the diskBuf.
lda #0
sta readAddr ; buffer addr always on even page boundary
sta pSrc
lda #>diskBuf ; we're reading into a buffer in main mem
sta readAddr+1
sta pSrc+1 ; restart src pointer at start of buffer
.nextGroup:
ldx reqLen
lda reqLen+1 ; see how many pages we want
cmp #>DISK_BUF_SIZE ; less than our max?
bcc + ; yes, read exact amount
lda #>DISK_BUF_SIZE ; no, limit to size of buffer
ldx #0
+ stx readLen
sta readLen+1 ; save number of pages
jsr readToMain ; now read
lda reqLen ; decrement reqLen by the amount we read
sec
sbc readLen
sta reqLen
lda reqLen+1 ; all 16 bits of reqLen
sbc readLen+1
sta reqLen+1
ldy #0 ; index for reading first byte
rts ; all done
;------------------------------------------------------------------------------
lz4Decompress: !zone
; Input: pSrc - pointer to source data
; pDst - pointer to destination buffer
; ucLen - length of *destination* data (16-bit)
; isCompressed - if hi bit set, decompress; if not, just copy.
; All inputs are destroyed by the process.
!macro LOAD_YSRC {
lda (pSrc),y ; load byte
iny ; inc low byte of ptr
bne + ; non-zero, done
jsr nextSrcPage ; zero, need to go to next page
+
}
!if DEBUG_DECOMP { jsr .debug1 }
jsr readToBuf ; read first pages into buffer
ldx #<clrAuxWr ; start by assuming write to main mem
ldy #<clrAuxRd ; and read from main mem
lda isAuxCmd ; if we're decompressing to aux...
beq + ; no? keep those values
inx ; yes, write to aux mem
iny ; and read from aux mem
+ stx .auxWr1+1 ; set all the write switches for aux/main
stx .auxWr3+1
stx .auxWr2+1
sty .auxRd1+1 ; and the read switches too
+ ldx pDst ; calculate the end of the dest buffer
txa ; also put low byte of ptr in X (where we'll use it constantly)
clc
adc ucLen ; add in the uncompressed length
sta .endChk1+1 ; that's what we'll need to check to see if we're done
lda ucLen+1 ; grab, but don't add, hi byte of dest length
adc #0 ; no, we don't add pDst+1 - see endChk2
sta .endChk2+1 ; this is essentially a count of dest page bumps
lda pDst+1 ; grab the hi byte of dest pointer
sta .dstStore1+2 ; self-modify our storage routines
sta .dstStore2+2
ldy pSrc ; Y will always track the hi byte of the source ptr
lda #0 ; so zero out the low byte of the ptr itself
sta pSrc
!if DO_COMP_CHECKSUMS {
sta checksum
}
bit isCompressed ; check compression flag
bpl .goLit ; not compressed? Treat as a single literal sequence.
sta ucLen+1 ; ucLen+1 always needs to be zero
; Grab the next token in the compressed data
.getToken:
+LOAD_YSRC ; load next source byte
pha ; save the token byte. We use half now, and half later
lsr ; shift to get the hi 4 bits...
lsr
lsr ; ...into the lo 4 bits
lsr
beq .endChk1 ; if ucLen=0, there is no literal data.
cmp #$F ; ucLen=15 is a special marker
bcc + ; not special, go copy the literals
jsr .longLen ; special marker: extend the length
+ sta ucLen ; record resulting length (lo byte)
.goLit:
!if DEBUG_DECOMP { jsr .debug2 }
+
.auxWr1 sta setAuxWr ; this gets self-modified depending on if target is in main or aux mem
.litCopy: ; loop to copy the literals
+LOAD_YSRC ; grab a literal source byte
.dstStore1:
sta $1100,x ; hi-byte gets self-modified to point to dest page
!if DO_COMP_CHECKSUMS {
eor checksum
sta checksum
}
inx ; inc low byte of ptr
bne + ; non-zero, done
jsr .nextDstPage ; zero, need to go to next page
+ dec ucLen ; count bytes
bne + ; low count = 0?
lda ucLen+1 ; hi count = 0?
beq .endChk ; both zero - end of loop
+ lda ucLen ; did low byte wrap around?
cmp #$FF
bne .litCopy ; no, go again
dec ucLen+1 ; yes, decrement hi byte
jmp .litCopy ; and go again
.endChk sta clrAuxWr ; back to writing main mem
.endChk1:
cpx #11 ; end check - self-modified earlier
bcc .decodeMatch ; if less, keep going
.endChk2:
lda #0 ; have we finished all pages? - self modified and decremented
bmi .endBad ; negative? that's very bad (because we never have blocks >= 32Kbytes)
bne .decodeMatch ; non-zero? keep going.
bit isCompressed
bpl + ; if not compressed, no extra work at end
pla ; toss unused match length
!if DO_COMP_CHECKSUMS { jsr .verifyCksum }
+ rts ; all done!
.endBad +internalErr 'O' ; barf out
; Now that we've finished with the literals, decode the match section
.decodeMatch:
+LOAD_YSRC ; grab first byte of match offset
sta tmp ; save for later
cmp #0
bmi .far ; if hi bit is set, there will be a second byte
!if DO_COMP_CHECKSUMS { jsr .verifyCksum }
lda #0 ; otherwise, second byte is assumed to be zero
beq .doInv ; always taken
.far: +LOAD_YSRC ; grab second byte of offset
asl tmp ; toss the unused hi bit of the lo byte
lsr ; shift out lo bit of the hi byte
ror tmp ; to fill in the hi bit of the lo byte
.doInv: sta tmp+1 ; got the hi byte of the offset now
lda #0 ; calculate zero minus the offset, to obtain ptr diff
sec
sbc tmp
sta .srcLoad+1 ; that's how much less to read from
lda .dstStore2+2 ; same with hi byte of offset
sbc tmp+1
sta .srcLoad+2 ; to hi byte of offsetted pointer
!if DEBUG_DECOMP { jsr .debug3 }
.getMatchLen:
pla ; recover the token byte
and #$F ; mask to get just the match length
clc
adc #4 ; adjust: min match is 4 bytes
cmp #$13 ; was it the special value $0F? ($F + 4 = $13)
bne + ; if not, no need to extend length
jsr .longLen ; need to extend the length
+ sty tmp ; save index to source pointer, so we can use Y...
!if DEBUG_DECOMP { sta ucLen : jsr .debug4 }
tay ; ...to count bytes
bne +
dec ucLen+1 ; special case for len being an exact multiple of 256
+
sei ; prevent interrupts while we access aux mem
.auxWr2 sta setAuxWr ; self-modified earlier, based on isAuxCmd
.auxRd1 sta setAuxRd ; self-modified based on isAuxCmd
.srcLoad:
lda $1100,x ; self-modified earlier for offsetted source
.dstStore2:
sta $1100,x ; self-modified earlier for dest buffer
!if DO_COMP_CHECKSUMS {
eor checksum
sta checksum
}
inx ; inc to next src/dst byte
bne + ; non-zero, skip page bump
jsr .nextDstPage ; do the bump
+ dey ; count bytes -- first page yet?
bne .srcLoad ; loop for more
dec ucLen+1 ; count pages
bpl .srcLoad ; loop for more. NOTE: this would fail if we had blocks >= 32K
sta clrAuxRd ; back to reading main mem, for mem mgr code
sta clrAuxWr ; back to writing main mem
cli
inc ucLen+1 ; to make it zero for the next match decode
+ ldy tmp ; restore index to source pointer
jmp .getToken ; go on to the next token in the compressed stream
; Subroutine called when length token = $F, to extend the length by additional bytes
.longLen:
- sta ucLen ; save what we got so far
+LOAD_YSRC ; get another byte
cmp #$FF ; check for special there-is-more marker byte
php ; save result of that
clc
adc ucLen ; add $FF to ucLen
bcc + ; no carry, only lo byte has changed
inc ucLen+1 ; increment hi byte of ucLen
+ plp ; retrieve comparison status from earlier
beq - ; if it was $FF, go back for more len bytes
rts
!if DO_COMP_CHECKSUMS {
.verifyCksum:
+LOAD_YSRC
!if DEBUG_DECOMP {
+prStr : !text "cksum exp=",0
pha
jsr prbyte
+prStr : !text " got=",0
+prByte checksum
+crout
pla
}
cmp checksum ; get computed checksum
beq + ; should be zero, because compressor stores checksum byte as part of stream
+internalErr 'C' ; checksum doesn't match -- abort!
+ rts
}
nextSrcPage:
pha ; save byte that was loaded
inc pSrc+1 ; go to next page
lda pSrc+1 ; check the resulting page num
cmp #>diskBufEnd ; did we reach end of buffer?
bne + ; if not, we're done
sta clrAuxWr ; buffer is in main mem
txa
pha
jsr readToBuf ; read more pages
pla
tax
.auxWr3 sta setAuxWr ; go back to writing aux mem (self-modified for aux or main)
+ pla ; restore loaded byte
rts
.nextDstPage:
inc .srcLoad+2 ; inc offset pointer for match copies
inc .dstStore1+2 ; inc pointers for dest stores
inc .dstStore2+2
dec .endChk2+1 ; decrement total page counter
rts
!if DEBUG_DECOMP {
.debug1 +prStr : !text "Decompressing: isComp=",0
+prByte isCompressed
+prStr : !text "isAux=",0
+prByte isAuxCmd
+prStr : !text "compLen=",0
+prWord reqLen
+prStr : !text "uncompLen=",0
+prWord ucLen
+crout
rts
.debug2 +prStr : !text "Lit ptr=",0
tya
clc
adc pSrc
sta .dbgTmp
lda pSrc+1
adc #0
sta .dbgTmp+1
+prWord .dbgTmp
+prStr : !text "len=",0
+prWord ucLen
+crout
rts
.debug3 +prStr : !text "Match src=",0
txa ; calculate src address with X (not Y!) as offset
clc
adc .srcLoad+1
sta .dbgTmp
lda .srcLoad+2
adc #0
sta .dbgTmp+1
+prWord .dbgTmp
+prStr : !text "dst=",0
txa ; calculate dest address with X as offset
clc
adc .dstStore2+1
sta tmp
lda .dstStore2+2
adc #0
sta tmp+1
+prWord tmp
+prStr : !text "offset=",0
lda tmp ; now calculate the difference
sec
sbc .dbgTmp
sta .dbgTmp
lda tmp+1
sbc .dbgTmp+1
sta .dbgTmp+1
+prWord .dbgTmp ; and print it
rts
.debug4 +prStr : !text "len=",0
+prWord ucLen
+crout
rts
.dbgTmp !word 0
}
; TODO: replace with LX47
brk
;------------------------------------------------------------------------------
; Apply fixups to all modules that were loaded this round, and free the fixup
@ -3068,10 +2633,10 @@ advSingleAnim:
iny ; now y=2, index number of frames
lda (tmp),y
adc #$FF ; minus one to get last frame (carry clear from prev add)
sta checksum+1 ; save it for later reference
sta .maxFrame ; save it for later reference
iny ; now y=3, index current frame number
lda (tmp),y
sta checksum ; save it for comparison later
sta .curFrame ; save it for comparison later
!if DEBUG = 2 { jsr .dbgB1 }
.chkr ldy #0
@ -3089,8 +2654,8 @@ advSingleAnim:
.chkfs iny ; index of current dir
cmp #3 ; is it a forward+stop anim?
bne .chkfb
lda checksum ; compare cur frame
eor checksum+1 ; to (nFrames-1)
lda .curFrame ; compare cur frame
eor .maxFrame ; to (nFrames-1)
bne .adv ; if not there yet, advance.
rts ; we're at last frame; nothing left to do.
@ -3107,12 +2672,12 @@ advSingleAnim:
jsr .fwbk ; advance the frame number in that direction
.doptch ldy #3 ; index current frame
lda (tmp),y
cmp checksum ; compare to what it was
cmp .curFrame ; compare to what it was
bne + ; if not equal, we have work to do
rts ; no change, all done.
+ inc .ret2+1 ; advance count of number of things we actually changed
pha
lda checksum
lda .curFrame
jsr applyPatch ; un-patch old frame
pla
jmp applyPatch ; apply patch for the new frame
@ -3123,7 +2688,7 @@ advSingleAnim:
dey ; index of number of frames
cmp #0
bpl + ; can only be negative if dir=-1 and we wrapped around
lda checksum+1 ; go to (previously saved) last frame number
lda .maxFrame ; go to (previously saved) last frame number
+ cmp (tmp),y ; are we at the limit of number of frames?
bne +
lda #0 ; back to start
@ -3132,6 +2697,9 @@ advSingleAnim:
!if DEBUG = 2 { jsr .dbgB2 }
rts
.curFrame !byte 0
.maxFrame !byte 0
!if DEBUG = 2 {
.dbgin sta clrAuxRd
sta clrAuxWr
@ -3146,8 +2714,8 @@ advSingleAnim:
+prStr : !text "single ",0
+prWord pTmp
+prWord tmp
+prByte checksum
+prByte checksum+1
+prByte .curFrame
+prByte .maxFrame
jmp .dbgout
.dbgB2 jsr .dbgin
+prStr : !text "fwbk ",0

View File

@ -28,31 +28,6 @@ a2h = $3F
inbuf = $200
resetVec = $3F2
; PRODOS
mli = $BF00
MLI_QUIT = $65
MLI_GET_TIME = $82
MLI_CREATE = $C0
MLI_DESTROY = $C1
MLI_RENAME = $C2
MLI_SET_FILE_INFO=$C3
MLI_GET_FILE_INFO=$C4
MLI_ONLINE = $C5
MLI_SET_PREFIX = $C6
MLI_GET_PREFIX = $C7
MLI_OPEN = $C8
MLI_NEWLINE = $C9
MLI_READ = $CA
MLI_WRITE = $CB
MLI_CLOSE = $CC
MLI_FLUSH = $CD
MLI_SET_MARK = $CE
MLI_GET_MARK = $CF
MLI_SET_EOF = $D0
MLI_GET_EOF = $D1
MLI_SET_BUF = $D2
MLI_GET_BUF = $D3
; I/O soft switches
kbd = $C000
clrAuxRd = $C002
@ -62,21 +37,21 @@ setAuxWr = $C005
clrAuxZP = $C008
setAuxZP = $C009
kbdStrobe = $C010
rdLCBnk2 = $C011 ;reading from LC bank $Dx 2
rdLCRam = $C012 ;reading from LC RAM
rdRamRd = $C013 ;reading from aux/alt 48K
rdRamWr = $C014 ;writing to aux/alt 48K
rdCXRom = $C015 ;using internal Slot ROM
rdAuxZP = $C016 ;using Slot zero page, stack, & LC
rdC3Rom = $C017 ;using external (Slot) C3 ROM
rd80Col = $C018 ;80STORE is On- using 80-column memory mapping
rdVblBar = $C019 ;not VBL (VBL signal low)
rdText = $C01A ;using text mode
rdMixed = $C01B ;using mixed mode
rdPage2 = $C01C ;using text/graphics page2
rdHires = $C01D ;using Hi-res graphics mode
rdAltCh = $C01E ;using alternate character set
rd80Vid = $C01F ;using 80-column display mode
rdLCBnk2 = $C011 ;reading from LC bank $Dx 2
rdLCRam = $C012 ;reading from LC RAM
rdRamRd = $C013 ;reading from aux/alt 48K
rdRamWr = $C014 ;writing to aux/alt 48K
rdCXRom = $C015 ;using internal Slot ROM
rdAuxZP = $C016 ;using Slot zero page, stack, & LC
rdC3Rom = $C017 ;using external (Slot) C3 ROM
rd80Col = $C018 ;80STORE is On- using 80-column memory mapping
rdVblBar = $C019 ;not VBL (VBL signal low)
rdText = $C01A ;using text mode
rdMixed = $C01B ;using mixed mode
rdPage2 = $C01C ;using text/graphics page2
rdHires = $C01D ;using Hi-res graphics mode
rdAltCh = $C01E ;using alternate character set
rd80Vid = $C01F ;using 80-column display mode
clrText = $C050
setText = $C051

View File

@ -15,30 +15,6 @@ include "diskops.plh"
include "gen_modules.plh"
include "gen_players.plh"
// ProDOS MLI constants
const MLI_QUIT = $65
const MLI_GET_TIME = $82
const MLI_CREATE = $C0
const MLI_DESTROY = $C1
const MLI_RENAME = $C2
const MLI_SET_FILE_INFO = $C3
const MLI_GET_FILE_INFO = $C4
const MLI_ONLINE = $C5
const MLI_SET_PREFIX = $C6
const MLI_GET_PREFIX = $C7
const MLI_OPEN = $C8
const MLI_NEWLINE = $C9
const MLI_READ = $CA
const MLI_WRITE = $CB
const MLI_CLOSE = $CC
const MLI_FLUSH = $CD
const MLI_SET_MARK = $CE
const MLI_GET_MARK = $CF
const MLI_SET_EOF = $D0
const MLI_GET_EOF = $D1
const MLI_SET_BUF = $D2
const MLI_GET_BUF = $D3
// This pointer is the root of all heap-tracked (and garbage collected) objects.
// See playtype.plh for definitions of all the datastructures and how they interconnect.
word global
@ -50,36 +26,6 @@ word[] funcTbl = @_saveGame, @_loadGame, @_newOrLoadGame
byte[] game1_filename = "GAME.1.SAVE"
// ProDOS command tables
byte open_params = 3 // parameter count
word open_filename
word open_buffer
byte open_fileref
byte create_params = 7 // parameter count
word create_filename
byte create_accessbits
byte create_filetype
word create_auxtype
byte create_storagetype
word create_date
word create_time
byte write_params = 4 // parameter count
byte write_fileref
word write_addr
word write_length
word write_actual
byte read_params = 4 // parameter count
byte read_fileref
word read_addr
word read_length
word read_actual
byte close_params = 1 // parameter count
byte close_fileref
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions used by assembly code
asm __defs
@ -127,40 +73,6 @@ asm copyHeap // params: dir (0=LCtoMain, 1=MainToLC)
rts
end
///////////////////////////////////////////////////////////////////////////////////////////////////
asm mliStub
; call MLI directly. Caller is expected to modify the command and param vectors
; before calling.
+asmPlasm 0 ; bytes 0-4
jsr mli ; bytes 5-7
!byte 0 ; byte 8
!word 0 ; bytes 9-10
bcs +
lda #0
+ bit setLcRW+lcBank2 ; Our crazy aux ProDOS stub doesn't preserve the LC bank; put PLASMA back.
rts
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def callMLI(cmd, p_params)
byte err
//printf2("callMLI: cmd=$%x p_params=$%x\n", cmd, p_params)
mliStub.8 = cmd
mliStub:9 = p_params
err = mliStub()
return err
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def guaranteeMLI(cmd, p_params)
byte err
err = callMLI(cmd, p_params)
if err > 0
printf1("\nErr $%x\n", err)
fatal("ProDOS error")
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def _saveGame()
@ -172,48 +84,48 @@ def _saveGame()
copyHeap(0) // LC to low mem
// Open the file if it already exists...
open_filename = @game1_filename
open_buffer = $5C00
if callMLI(MLI_OPEN, @open_params) > 0
create_filename = open_filename
create_accessbits = $C3 // full access
create_filetype = $F1 // user type 1
create_auxtype = 0
create_storagetype = 1
create_date = 0
create_time = 0
guaranteeMLI(MLI_CREATE, @create_params)
guaranteeMLI(MLI_OPEN, @open_params)
fin
//open_filename = @game1_filename
//open_buffer = $5C00
//if callMLI(MLI_OPEN, @open_params) > 0
//create_filename = open_filename
//create_accessbits = $C3 // full access
//create_filetype = $F1 // user type 1
//create_auxtype = 0
//create_storagetype = 1
//create_date = 0
//create_time = 0
//guaranteeMLI(MLI_CREATE, @create_params)
//guaranteeMLI(MLI_OPEN, @open_params)
//fin
// Write the game data to it
write_fileref = open_fileref
write_addr = $5000
write_length = HEAP_SIZE
guaranteeMLI(MLI_WRITE, @write_params)
//write_fileref = open_fileref
//write_addr = $5000
//write_length = HEAP_SIZE
//guaranteeMLI(MLI_WRITE, @write_params)
// All done.
close_fileref = open_fileref
guaranteeMLI(MLI_CLOSE, @close_params)
//close_fileref = open_fileref
//guaranteeMLI(MLI_CLOSE, @close_params)
end
def loadInternal()
word p_loaded
// Open the file. If that fails, return FALSE (instead of halting)
open_filename = @game1_filename
open_buffer = $5C00
if callMLI(MLI_OPEN, @open_params) > 0; return FALSE; fin
//open_filename = @game1_filename
//open_buffer = $5C00
//if callMLI(MLI_OPEN, @open_params) > 0; return FALSE; fin
// Read the game data from it
read_fileref = open_fileref
read_addr = $5000
read_length = HEAP_SIZE
guaranteeMLI(MLI_READ, @read_params)
//read_fileref = open_fileref
//read_addr = $5000
//read_length = HEAP_SIZE
//guaranteeMLI(MLI_READ, @read_params)
// All done with the file
close_fileref = open_fileref
guaranteeMLI(MLI_CLOSE, @close_params)
//close_fileref = open_fileref
//guaranteeMLI(MLI_CLOSE, @close_params)
// Copy the heap up, and init it with the correct size.
p_loaded = $5000
@ -255,12 +167,7 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
def gameExists()
open_filename = @game1_filename
open_buffer = $5000
if callMLI(MLI_OPEN, @open_params) > 0; return FALSE; fin
close_fileref = open_fileref
guaranteeMLI(MLI_CLOSE, @close_params)
return TRUE
return FALSE // FIXME
end
///////////////////////////////////////////////////////////////////////////////////////////////////