From dd061c37c35d3d84b5c8d8a0dda380e6166216e5 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Wed, 4 Jan 2017 13:15:39 -0800 Subject: [PATCH] Making slow progress integrating ProRWTS with mem mgr. --- .../src/org/badvision/A2PackPartitions.groovy | 168 +- .../src/org/badvision/Lx47Algorithm.java | 4 +- Platform/Apple/tools/ProRWTS/PRORWTS2#4000 | Bin 1608 -> 1608 bytes Platform/Apple/tools/ProRWTS/PRORWTS2.S | 3790 ++++++++--------- Platform/Apple/virtual/src/core/loader.s | 16 +- Platform/Apple/virtual/src/core/mem.s | 776 +--- Platform/Apple/virtual/src/include/global.i | 55 +- Platform/Apple/virtual/src/plasma/diskops.pla | 151 +- 8 files changed, 2130 insertions(+), 2830 deletions(-) diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy index ece59c8b..88931fad 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy @@ -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.. 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)) diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/Lx47Algorithm.java b/Platform/Apple/tools/PackPartitions/src/org/badvision/Lx47Algorithm.java index c9f8e418..aa5ae65b 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/Lx47Algorithm.java +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/Lx47Algorithm.java @@ -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(); diff --git a/Platform/Apple/tools/ProRWTS/PRORWTS2#4000 b/Platform/Apple/tools/ProRWTS/PRORWTS2#4000 index bbf0a7083f3c4f7a4b85aadb303137908407ffc2..4121a8bece8fa97bce76725a42ed7d4240247217 100644 GIT binary patch delta 676 zcmZwEOK1~87zgm#-K3-sp+YN>790wZHWsSjp$3e9}A=pPUVtPsn%AwSx;mX{Eg9P1h z_O#dBcdAk-Jpug$_3-C6*?EqcB1nD+s8<@XN6$zU8?*Le=L2T;gsuu_pHviXKA>3hp%+iJNbG(jBGqF9 zf~&3HEBW9a$@o9j4JUj|)H)>8qEHzM0UyT3;a0>6zQfM~08qEhIqath6GN`SKY~bRG$jbQh65h8z zL8lz>I*Vdc5w;HtQw(0S16fkU={j3o*UV&bC9bV6Xob4n|KgqowLiOStp!li@xk!g zf#TRaEZl0`M{!4A*OA~OlJn4}AVph_;YpTwljCVtpm2^PUg~c#mZ@yX)zqZM<91hi zJTn0w{G&>LtFngb9QjMtd!%YMRYx1Dy=c+d-E00wmKFeW!6-qmoDWaX`H&ozE~`c9 Q(pa(hesfpZ+1<+h0%AX1LjV8( delta 676 zcmZwEUr19?90%}o@7-kT0t1bOLI+`?OR%5^A!oz3MaznGUh*OFrHCNtDSFEX?_~`K zlM|s2!ewlOD{XAh%N~?#Cf)U5XGHiIM679$=bT;V{6p(58ASE)JLi0V=ikFex9j#y zJIC#y4({x^a=3YVK`ZN}w$D=>;Dv(6&x4T{J274bu!*LfMoF%!7Rj#~=stJJz8ig; z=8cqKz&?sn-06NIjrBw=Dv(B%lUe^#1Q>eO9|5~PQNcWt6cgi;SN6q&#Fo4b`v|&a z?QE?$?j1?K#2EAt)X87ysz^Tb0dI_pSBup!IUx_P03!!>ZSW#R5BN|EvEe31;^)c- zf)4opZjyhA_Z30%KtNs6pgB4RLzqmNi~J|NZ%*jCaQ@kj!p#gT#*FXPb1e{l7zjwU zaIau%>2XPJxJiG14AOK*8-?4i>&wZqR2}4+dTea zeuB*}*mX@`0tgsl-mS?qG&Fp`7On}Ot-Ar>1RCK&G zkl9i!tJ}Fd_4_Dd>25z3d_vMr+7P5@%`y;V(RXQ{rUVM7N%Xb;9%H#GAIeAZpvL1? zTVgah1|R*SN`I@ey6QCfOVxF(T5hNg)m6LDoVBB?{2y7G1Iz|P1ii67K1FAIvR}HY S7Njd9g~G?x4JE&^mi`58?^_xG diff --git a/Platform/Apple/tools/ProRWTS/PRORWTS2.S b/Platform/Apple/tools/ProRWTS/PRORWTS2.S index e21beb32..b3edcb6e 100755 --- a/Platform/Apple/tools/ProRWTS/PRORWTS2.S +++ b/Platform/Apple/tools/ProRWTS/PRORWTS2.S @@ -1,1895 +1,1895 @@ -;extended open/read/write binary file in ProDOS filesystem, with random access -;copyright (c) Peter Ferrie 2013-16 -;license:BSD-3-Clause - -!cpu 6502 -*=$4000 - -;place no code before init label below. - - ;user-defined options - verbose_info = 1 ;set to 1 to enable display of memory usage - enable_floppy = 1 ;set to 1 to enable floppy drive support - poll_drive = 1 ;set to 1 to check if disk is in drive - override_adr = 1 ;set to 1 to require an explicit load address - aligned_read = 0 ;set to 1 if all reads can be a multiple of block size - enable_write = 1 ;set to 1 to enable write support - ;file must exist already and its size cannot be altered - ;writes occur in multiples of block size (256 bytes for floppy, 512 bytes for HDD) - enable_seek = 1 ;set to 1 to enable seek support - allow_multi = 1 ;set to 1 to allow multiple floppies - check_chksum = 1 ;set to 1 to enforce checksum verification for floppies - allow_subdir = 0 ;set to 1 to allow opening subdirectories to access files - might_exist = 1 ;set to 1 if file is not known to always exist already - ;makes use of status to indicate success or failure - allow_aux = 1 ;set to 1 to allow read/write directly to/from aux memory - ;requires load_high to be set for arbitrary memory access - ;else driver must be running from same memory target - ;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 - ;but limits file size to 64k-2 bytes. - 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 - lc_bank = 1 ;load into specified bank (1 or 2) if load_banked=1 - - ;user-defined driver load address -!if load_banked = 1 { - !if load_high = 1 { - !ifdef PASS2 { - } else { ;PASS2 - reloc = $fb00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch - } ;PASS2 - } else { ;load_high - reloc = $ef00 ;page-aligned, but otherwise wherever you want - } ;load_high -} else { ;load_banked - !if load_high = 1 { - !ifdef PASS2 { - } else { ;PASS2 - reloc = $bf00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch - } ;PASS2 - } else { ;load_high - reloc = $1000 ;page-aligned, but otherwise wherever you want - } ;load_high -} ;load_banked - - ;zpage usage, arbitrary selection except for the "ProDOS constant" ones - ;feel free to move them around - -!if (might_exist + poll_drive) > 0 { - status = $50 ;returns non-zero on error -} ;might_exist or poll_drive -!if allow_aux = 1 { - auxreq = $51 ;set to 1 to read/write aux memory, else main memory is used -} ;allow_aux - sizelo = $52 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking - sizehi = $53 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking - reqcmd = $54 ;set (read/write/seek) if enable_write=1 or enable_seek=1 - ;if allow_multi=1, bit 7 selects floppy drive in current slot (clear=drive 1, set=drive 2) during open call - ;bit 7 must be clear for read/write/seek on opened file - ldrlo = $55 ;set to load address if override_adr=1 - ldrhi = $56 ;set to load address if override_adr=1 - namlo = $57 ;name of file to access - namhi = $58 ;name of file to access - -!if enable_floppy = 1 { - tmpsec = $3c ;(internal) sector number read from disk - reqsec = $3d ;(internal) requested sector number - curtrk = $40 ;(internal) track number read from disk -} ;enable_floppy - - command = $42 ;ProDOS constant - unit = $43 ;ProDOS constant - adrlo = $44 ;ProDOS constant - adrhi = $45 ;ProDOS constant - bloklo = $46 ;ProDOS constant - blokhi = $47 ;ProDOS constant - - entries = $f8 ;(internal) total number of entries in directory -!if bounds_check = 1 { - bleftlo = $f9 ;(internal) bytes left in file - blefthi = $fa ;(internal) bytes left in file -} ;bounds_check - blkofflo = $fb ;(internal) offset within cache block - blkoffhi = $fc ;(internal) offset within cache block -!if enable_floppy = 1 { - step = $fd ;(internal) state for stepper motor - tmptrk = $fe ;(internal) temporary copy of current track - phase = $ff ;(internal) current phase for seek -} ;enable_floppy - - ;constants - cmdseek = 0 ;requires enable_seek=1 - cmdread = 1 ;requires enable_write=1 - cmdwrite = 2 ;requires enable_write=1 - SETKBD = $fe89 - SETVID = $fe93 - DEVNUM = $bf30 - PHASEOFF = $c080 - MOTOROFF = $c088 - MOTORON = $c089 - DRV0EN = $c08a - Q6L = $c08c - Q6H = $c08d - Q7L = $c08e - Q7H = $c08f - MLI = $bf00 - NAME_LENGTH = $4 ;ProDOS constant - MASK_SAPLING = $20 ;ProDOS constant - MASK_TREE = $30 ;ProDOS constant - MASK_SUBDIR = $d0 ;ProDOS constant - MASK_ALL = $f0 ;ProDOS constant - KEY_POINTER = $11 ;ProDOS constant - EOF_LO = $15 ;ProDOS constant - EOF_HI = $16 ;ProDOS constant - AUX_TYPE = $1f ;ProDOS constant - ENTRY_SIZE = $27 ;ProDOS constant - NEXT_BLOCK_LO = $2 ;ProDOS constant - NEXT_BLOCK_HI = $3 ;ProDOS constant - SAPLING = $20 ;ProDOS constant - FILE_COUNT = $25 ;ProDOS constant - ROMIN = $c081 - LCBANK2 = $c089 - CLRAUXRD = $c002 - CLRAUXWR = $c004 - -init jsr SETVID - jsr SETKBD - lda DEVNUM - sta x80_parms + 1 - sta unrunit + 1 - and #$70 -!if (enable_floppy + enable_write) > 1 { - sta unrslot1 + 1 - sta unrslot2 + 1 - sta unrslot3 + 1 - sta unrslot4 + 1 -} ;enable_floppy and enable_write - pha -!if enable_floppy = 1 { - ora #(readbuff + NAME_LENGTH) - sta blokhi -inextent ldy #0 - lda (bloklo), y - pha - and #MASK_SUBDIR - - ;watch for subdirectory entries - - cmp #MASK_SUBDIR - bne + - - lda (bloklo), y - and #$0f - tax - iny --- lda (bloklo), y - cmp (namlo), y - beq ifoundname - - ;match failed, move to next directory in this block, if possible - -- -+ pla - clc - lda bloklo - adc #ENTRY_SIZE - sta bloklo - bcc + - - ;there can be only one page crossed, so we can increment instead of adc - - inc blokhi -+ cmp #<(readbuff + $1ff) ;4 + ($27 * $0d) - lda blokhi - sbc #>(readbuff + $1ff) - bcc inextent - - ;read next directory block when we reach the end of this block - - lda readbuff + NEXT_BLOCK_LO - ldx readbuff + NEXT_BLOCK_HI - bcs + - -ifoundname iny - dex - bne -- - - ;parse path until last directory is seen - - lda (namlo), y - cmp #'/' - bne - - tya - eor #$ff - adc sizelo - sta sizelo - clc - tya - adc namlo - sta namlo - pla - and #$20 ;Volume Directory Header XOR subdirectory - bne ++ - - ;cache block number of current directory - ;as starting position for subsequent searches - - ldy #(KEY_POINTER + 1) - lda (bloklo), y - tax - dey - lda (bloklo), y -!if enable_floppy = 1 { - sta unrblocklo + 1 - stx unrblockhi + 1 -} ;enable_floppy - sta unrhddblocklo + 1 - stx unrhddblockhi + 1 -+ sta x80_parms + 4 - stx x80_parms + 5 -++ lda sizelo - bne readblock - - ;unit to slot for SmartPort interface - -+++ pla - lsr - lsr - lsr - tax - lsr - ora #$c0 - ldy $bf11, x - cpy #$c8 ;max slot+1 - bcs set_slot - tya -set_slot sta slot + 2 - sta unrentry + 2 -!if enable_floppy = 1 { - ldx #>unrelocdsk - ldy #unrelochdd - ldy #((codeend - rdwrpart) + $ff) - ldy #0 -- lda (bloklo), y -reladr sta reloc, y - iny - bne - - inc blokhi - inc reladr + 2 - dex - bne - - plp - bne ++ - - ;build 6-and-2 denibbilisation table - - ldx #$16 --- stx bloklo - txa - asl - bit bloklo - beq + - ora bloklo - eor #$ff - and #$7e -- bcs + - lsr - bne - - tya - sta nibtbl - $16, x - !if enable_write = 1 { - ;and 6-and-2 nibbilisation table if writing - - txa - ora #$80 - sta xlattbl, y - } ;enable_write - iny -+ inx - bpl -- -++ rts -} else { ;enable_floppy -slot lda $cfff - sta unrentry + 1 - !if load_banked = 1 { - !if lc_bank = 1 { - lda LCBANK2 - lda LCBANK2 - } else { ;lc_bank - lda ROMIN - lda ROMIN - } ;lc_bank - } ;load_banked - ldy #0 -- lda unrelochdd, y - sta reloc, y - - ;hack to avoid address overflow when load_high and load_banked - ;and code is less than two pages long (e.g. aligned_read, no write) - - !ifdef PASS2 { - !if >(hddcodeend - reloc) > 1 { - !set hack=$100 - } ;hddcodeend - } else { ;PASS2 - !set hack=0 - } ;PASS2 - sta reloc + hack, y - iny - bne - - rts -} ;enable_floppy - -c7_parms !byte 1 - !word $200 - -x80_parms !byte 3, $d1 - !word readbuff, 2 - -!if enable_floppy = 1 { -unrelocdsk -!pseudopc reloc { -!if override_adr = 1 { - ;only available when load address is specified - -rdwrpart jmp rdwrfile -} ;override_adr - ;read volume directory key block - ;self-modified by init code - -opendir -unrblocklo = unrelocdsk + (* - reloc) - ldx #2 -unrblockhi = unrelocdsk + (* - reloc) - lda #0 - jsr readdirsel - - ;include volume directory header in count - -readdir - !if might_exist = 1 { - ldx dirbuf + FILE_COUNT ;assuming only 256 files per subdirectory - inx - stx entries - } ;might_exist - -firstent lda #<(dirbuf + NAME_LENGTH) - sta bloklo - lda #>(dirbuf + NAME_LENGTH) - sta blokhi - -nextent ldy #0 - !if might_exist = 1 { - sty status - } ;might_exist - lda (bloklo), y - !if (might_exist + allow_subdir) > 0 { - and #MASK_ALL - - !if might_exist = 1 { - ;skip deleted entries without counting - - beq ++ - } ;might_exist - - !if allow_subdir = 1 { - ;subdirectory entries are seedlings - ;but we need to distinguish between them later - - cmp #MASK_SUBDIR - beq savetype - } ;allow_subdir - } ;might_exist or allow_subdir - - ;watch for seedling and saplings only - - cmp #MASK_TREE - bcs + - - ;remember type - -savetype - !if allow_subdir = 1 { - asl - asl - } else { ;allow_subdir - cmp #MASK_SAPLING - } ;allow_subdir - php - - ;match name lengths before attempting to match names - - lda (bloklo), y - and #$0f - tax - inx - !byte $2c ;mask lda, y on first pass -- lda (bloklo), y - cmp (namlo), y - beq foundname - - ;match failed, check if any directory entries remain - - plp -+ - !if might_exist = 1 { - dec entries - bne ++ - } ;might_exist - !if (might_exist + poll_drive) > 0 { -nodisk -unrdrvoff1=unrelocdsk+(*-reloc) - lda MOTOROFF - inc status - rts - } ;might_exist or poll_drive - - ;move to next directory in this block, if possible - -++ clc - lda bloklo - adc #ENTRY_SIZE - sta bloklo - bcc + - - ;there can be only one page crossed, so we can increment instead of adc - - inc blokhi -+ cmp #<(dirbuf + $1ff) ;4 + ($27 * $0d) - lda blokhi - sbc #>(dirbuf + $1ff) - bcc nextent - - ;read next directory block when we reach the end of this block - - ldx dirbuf + NEXT_BLOCK_LO - lda dirbuf + NEXT_BLOCK_HI - jsr readdirsec - bne firstent - -foundname iny - dex - bne - - stx entries - stx blkofflo - stx blkoffhi - - !if enable_write = 1 { - ldy reqcmd - cpy #cmdwrite ;control carry instead of zero - bne + - - ;round requested size up to nearest block if writing - - !if aligned_read = 0 { - php - } ;aligned_read - lda sizelo - ldx sizehi - jsr round - sta sizehi - !if aligned_read = 0 { - plp - } ;aligned_read -+ - } ;enable_write - - !if bounds_check = 1 { - ;cache EOF (file size, loaded backwards) - - ldy #EOF_HI - lda (bloklo), y - !if (enable_write + aligned_read) > 0 { - tax - } else { ;enable_write or aligned_read - sta blefthi - } ;enable_write or aligned_read - dey ;EOF_LO - lda (bloklo), y - !if (enable_write + aligned_read) > 0 { - - ;round file size up to nearest sector if writing without aligned reads - ;or nearest block if using aligned reads - - !if aligned_read = 0 { - bcc + - } ;aligned_read - - jsr round - tax - lda #0 - !if aligned_read = 0 { - sta sizelo - } ;aligned_read -+ stx blefthi - } ;enable_write or aligned_read - !if aligned_read = 0 { - sta bleftlo - } ;aligned_read - } else { ;bounds_check - !if enable_write = 1 { - !if aligned_read = 0 { - bcc + - lda #0 - sta sizelo -+ - } ;aligned_read - } ;enable_write - } ;bounds_check - ;cache AUX_TYPE (load offset for binary files) - - !if override_adr = 0 { - !if allow_subdir = 1 { - pla - tax - } else { ;allow_subdir - plp - } ;allow_subdir - ldy #AUX_TYPE - lda (bloklo), y - pha - iny - lda (bloklo), y - pha - !if allow_subdir = 1 { - txa - pha - } ;allow_subdir - } ;override_adr - - ;cache KEY_POINTER - - ldy #KEY_POINTER - lda (bloklo), y - tax - sta dirbuf - iny - lda (bloklo), y - sta dirbuf + 256 - - ;read index block in case of sapling - - !if allow_subdir = 1 { - plp - bpl rdwrfile - php - jsr readdirsec - plp - } else { ;allow_subdir - !if override_adr = 1 { - plp - } ;override_adr - bcc rdwrfile - jsr readdirsec - } ;allow_subdir - - ;restore load offset - -rdwrfile - !if override_adr = 1 { - ldx ldrhi - lda ldrlo - } else { ;override_adr - pla - tax - pla - } ;override_adr - - !if allow_subdir = 1 { - ;check file type and fake size and load address for subdirectories - - bcc + - ldy #2 - sty sizehi - ldx #>dirbuf - lda # 0 { - ldy reqcmd - ;cpy #cmdseek - beq + - } ;enable_write or enable_seek - - !if allow_aux = 1 { - ldx auxreq - jsr setaux - } ;allow_aux - !if (enable_write + enable_seek) > 0 { - dey ;cpy #cmdread - !if enable_write = 1 { - bne rdwrloop - } ;enable_write - } ;enable_write or enable_seek -+ - lda blkofflo - tax - ora blkoffhi - beq rdwrloop - lda sizehi - pha - lda sizelo - pha - lda adrhi - sta blokhi - lda adrlo - sta bloklo - stx adrlo - lda #>encbuf - clc - adc blkoffhi - sta adrhi - - !if bounds_check = 1 { - ;determine bytes left in block - - !if (enable_write + enable_seek) > 0 { - tya - } else { ;enable_write or enable_seek - lda #0 - } ;enable_write or enable_seek - sec - sbc blkofflo - tay - lda #2 - sbc blkoffhi - tax - - ;set requested size to min(bytes left, requested size) - - cpy sizelo - sbc sizehi - bcs + - sty sizelo - stx sizehi -+ - } ;bounds_check - - lda sizehi - jsr copycache - lda ldrlo - adc sizelo - sta ldrlo - lda ldrhi - adc sizehi - sta ldrhi - sec - pla - sbc sizelo - sta sizelo - pla - sbc sizehi - sta sizehi - ora sizelo - bne rdwrfile - beq rdwrdone - } else { ;aligned_read - !if bounds_check = 1 { - lda blefthi - cmp sizehi - bcs + - sta sizehi -+ - } ;bounds_check - !if allow_aux = 1 { - ldx auxreq - jsr setaux - } ;allow_aux - } ;aligned_read - -rdwrloop - !if (enable_write + enable_seek) > 0 { - ldx reqcmd - } ;enable_write or enable_seek - !if aligned_read = 0 { - - ;set read/write size to min(length, $200) - - lda sizehi - cmp #2 - bcs + - pha - lda #2 - sta sizehi - - ;redirect read to private buffer for partial copy - - lda adrhi - pha - lda adrlo - pha - lda #>encbuf - sta adrhi - lda #0 - sta adrlo - !if (enable_write + enable_seek) > 0 { - ldx #cmdread - } ;enable_write or enable_seek -+ - } ;aligned_read - - ;fetch data block and read/write it - - ldy entries - inc entries - !if enable_seek = 1 { - txa ;cpx #cmdseek, but that would require php at top - beq + - } ;enable_seek - stx command - ldx dirbuf, y - lda dirbuf + 256, y - !if aligned_read = 0 { - php - } ;aligned_read - jsr seekrdwr - !if aligned_read = 0 { - plp -+ bcc + - } ;aligned_read - !if bounds_check = 1 { - dec blefthi - dec blefthi - } ;bounds_check -+ dec sizehi - dec sizehi - bne rdwrloop - -unrdrvoff2 = unrelocdsk + (* - reloc) - lda MOTOROFF - !if aligned_read = 0 { - bcc + - lda sizelo - bne rdwrloop - } ;aligned_read -rdwrdone - !if allow_aux = 1 { - ldx #0 -setaux sta CLRAUXRD, x - sta CLRAUXWR, x - } ;allow_aux - rts - - !if aligned_read = 0 { - ;cache partial block offset - -+ pla - sta bloklo - pla - sta blokhi - pla - sta sizehi - dec adrhi - dec adrhi -copycache - !if enable_seek = 1 { - ldy reqcmd - ;cpy #cmdseek - beq ++ - } ;enable_seek - tay - beq + - dey -- lda (adrlo), y - sta (bloklo), y - iny - bne - - inc blokhi - inc adrhi - bne + -- lda (adrlo), y - sta (bloklo), y - iny -+ cpy sizelo - bne - -++ - !if bounds_check = 1 { - lda bleftlo - sec - sbc sizelo - sta bleftlo - lda blefthi - sbc sizehi - sta blefthi - } ;bounds_check - clc - lda blkofflo - adc sizelo - sta blkofflo - lda blkoffhi - adc sizehi - and #$fd - sta blkoffhi - bcc rdwrdone ;always - } ;aligned_read - - !if (enable_write + (bounds_check & aligned_read)) > 0 { -round clc - adc #$ff - txa - adc #1 - and #$fe - rts - } ;enable_write or (bounds_check and aligned_read) - - ;no tricks here, just the regular stuff - -seek sty step - asl phase - txa - asl -copy_cur tax - sta tmptrk - sec - sbc phase - beq +++ - bcs + - eor #$ff - inx - bcc ++ -+ sbc #1 - dex -++ cmp step - bcc + - lda step -+ cmp #8 - bcs + - tay - sec -+ txa - pha - ldx step1, y -+++ php - bne + ---- clc - lda tmptrk - ldx step2, y -+ stx tmpsec - and #3 - rol - tax - lsr -unrseek = unrelocdsk + (* - reloc) - lda PHASEOFF, x --- ldx #$13 -- dex - bne - - dec tmpsec - bne -- - bcs --- - plp - beq seekret - pla - inc step - bne copy_cur - -step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c -step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c - -readadr -- jsr readd5aa - cmp #$96 - bne - - ldy #3 -- sta curtrk - jsr readnib - rol - sta tmpsec - jsr readnib - and tmpsec - dey - bne - -seekret rts - -readd5aa --- jsr readnib -- cmp #$d5 - bne -- - jsr readnib - cmp #$aa - bne - - tay ;we need Y=#$AA later - -readnib -unrread1 = unrelocdsk + (* - reloc) -- lda Q6L - bpl - - rts - -readdirsel ldy #0 - sty adrlo - - !if allow_multi = 1 { - asl reqcmd - bcc seldrive - iny -seldrive lsr reqcmd -unrdrvsel = unrelocdsk + (* - reloc) - cmp DRV0EN, y - } ;allow_multi - !if poll_drive = 1 { - sty status -unrdrvon1 = unrelocdsk + (* - reloc) - ldy MOTORON -unrread2 = unrelocdsk + (* - reloc) -- ldy Q6L - bpl - -unrread3 = unrelocdsk + (* - reloc) -- cpy Q6L - bne readdirsec - inc status - bne - - pla - pla - jmp nodisk - } ;poll_drive - -readdirsec ldy #cmdread - sty command - ldy #>dirbuf - sty adrhi - - ;convert block number to track/sector - -seekrdwr -unrdrvon2 = unrelocdsk + (* - reloc) - ldy MOTORON - lsr - txa - ror - lsr - lsr - sta phase - txa - and #3 - php - asl - plp - rol - sta reqsec - jsr readadr - - ;if track does not match, then seek - - ldx curtrk - cpx phase - beq checksec - jsr seek - - ;force sector mismatch - - lda #$ff - - ;match or read/write sector - -checksec jsr cmpsec - inc reqsec - inc reqsec - - ;force sector mismatch - -cmpsecrd lda #$ff - -cmpsec - !if enable_write = 1 { - ldy command - cpy #cmdwrite ;we need Y=2 below - beq encsec - } ;enable_write -cmpsec2 cmp reqsec - beq readdata - jsr readadr - beq cmpsec2 - - ;read sector data - -readdata jsr readd5aa - eor #$ad ;zero A if match -;; bne * ;lock if read failure -unrread4 = unrelocdsk + (* - reloc) -- ldx Q6L - bpl - - eor nibtbl - $96, x - sta bit2tbl - $aa, y - iny - bne - -unrread5 = unrelocdsk + (* - reloc) -- ldx Q6L - bpl - - eor nibtbl - $96, x - sta (adrlo), y ;the real address - iny - !if check_chksum = 1 { - bne - -unrread6 = unrelocdsk + (* - reloc) -- ldx Q6L - bpl - - eor nibtbl - $96, x - bne cmpsecrd - } ;check_chksum --- ldx #$a9 -- inx - beq -- - lda (adrlo), y - lsr bit2tbl - $aa, x - rol - lsr bit2tbl - $aa, x - rol - sta (adrlo), y - iny - bne - -readret inc adrhi - rts - - !if enable_write = 1 { -encsec --- ldx #$aa -- dey - lda (adrlo), y - lsr - rol bit2tbl - $aa, x - lsr - rol bit2tbl - $aa, x - sta encbuf, y - lda bit2tbl - $aa, x - and #$3f - sta bit2tbl - $aa, x - inx - bne - - tya - bne -- - -cmpsecwr jsr readadr - cmp reqsec - bne cmpsecwr - - ;skip tail #$DE #$AA #$EB some #$FFs ... - - ldy #$24 -- dey - bpl - - - ;write sector data - -unrslot1 = unrelocdsk + (* - reloc) - ldx #$d1 - lda Q6H, x ;prime drive - lda Q7L, x ;required by Unidisk - tya - sta Q7H, x - ora Q6L, x - - ;40 cycles - - ldy #4 ;2 cycles - cmp $ea ;3 cycles - cmp ($ea, x) ;6 cycles -- jsr writenib1 ;(29 cycles) - - ;+6 cycles - dey ;2 cycles - bne - ;3 cycles if taken, 2 if not - - ;36 cycles - ;+10 cycles - ldy #(prolog_e - prolog) - ;2 cycles - cmp $ea ;3 cycles -- lda prolog - 1, y ;4 cycles - jsr writenib3 ;(17 cycles) - - ;32 cycles if branch taken - ;+6 cycles - dey ;2 cycles - bne - ;3 cycles if taken, 2 if not - - ;36 cycles on first pass - ;+10 cycles - tya ;2 cycles - ldy #$56 ;2 cycles -- eor bit2tbl - 1, y ;5 cycles - tax ;2 cycles - lda xlattbl, x ;4 cycles -unrslot2 = unrelocdsk + (* - reloc) - ldx #$d1 ;2 cycles - sta Q6H, x ;5 cycles - lda Q6L, x ;4 cycles - - ;32 cycles if branch taken - - lda bit2tbl - 1, y ;5 cycles - dey ;2 cycles - bne - ;3 cycles if taken, 2 if not - - ;32 cycles - ;+9 cycles - clc ;2 cycles --- eor encbuf, y ;4 cycles -- tax ;2 cycles - lda xlattbl, x ;4 cycles -unrslot3 = unrelocdsk + (* - reloc) - ldx #$d1 ;2 cycles - sta Q6H, x ;5 cycles - lda Q6L, x ;4 cycles - bcs + ;3 cycles if taken, 2 if not - - ;32 cycles if branch taken - - lda encbuf, y ;4 cycles - iny ;2 cycles - bne -- ;3 cycles if taken, 2 if not - - ;32 cycles - ;+10 cycles - sec ;2 cycles - bcs - ;3 cycles - - ;32 cycles - ;+3 cycles -+ ldy #(epilog_e - epilog) - ;2 cycles - cmp ($ea, x) ;6 cycles -- lda epilog - 1, y ;4 cycles - jsr writenib3 ;(17 cycles) - - ;32 cycles if branch taken - ;+6 cycles - dey ;2 cycles - bne - ;3 cycles if branch taken, 2 if not - - lda Q7L, x - lda Q6L, x ;flush final value - inc adrhi - rts - -writenib1 cmp ($ea, x) ;6 cycles -writenib2 cmp ($ea, x) ;6 cycles -writenib3 -unrslot4=unrelocdsk+(*-reloc) - ldx #$d1 ;2 cycles -writenib4 sta Q6H, x ;5 cycles - ora Q6L, x ;4 cycles - rts ;6 cycles - -prolog !byte $ad, $aa, $d5 -prolog_e -epilog !byte $ff, $eb, $aa, $de -epilog_e - } ;enable_write -codeend -bit2tbl = (* + 255) & -256 -nibtbl = bit2tbl + 86 - !if enable_write = 1 { -xlattbl = nibtbl + 106 -dataend = xlattbl + 64 - } else { ;enable_write -dataend = nibtbl + 106 - } ;enable_write -} ;enable_floppy -} ;reloc - -unrelochdd -!pseudopc reloc { -!if override_adr = 1 { -hddrdwrpart jmp hddrdwrfile -} ;override_adr - ;read volume directory key block - ;self-modified by init code - -hddopendir -unrhddblocklo = unrelochdd + (* - reloc) - ldx #2 -unrhddblockhi = unrelochdd + (* - reloc) - lda #0 - jsr hddreaddirsel - -!if enable_floppy = 1 { - !if (* - hddopendir) < (readdir - opendir) { - ;essential padding to match offset with floppy version - !fill (readdir - opendir) - (* - hddopendir), $ea - } -} ;enable_floppy - - ;include volume directory header in count - -hddreaddir - !if might_exist = 1 { - ldx hdddirbuf + FILE_COUNT - inx - stx entries - } ;might_exist - -hddfirstent lda #<(hdddirbuf + NAME_LENGTH) - sta bloklo - lda #>(hdddirbuf + NAME_LENGTH) - sta blokhi - -hddnextent ldy #0 - !if might_exist = 1 { - sty status - } ;might_exist - lda (bloklo), y - !if (might_exist + allow_subdir) > 0 { - and #MASK_ALL - - !if might_exist = 1 { - ;skip deleted entries without counting - - beq ++ - } ;might_exist - - !if allow_subdir = 1 { - ;subdirectory entries are seedlings - ;but we need to distinguish between them later - - cmp #MASK_SUBDIR - beq hddsavetype - } ;allow_subdir - } ;might_exist or allow_subdir - - ;watch for seedling and saplings only - - cmp #MASK_TREE - bcs + - - ;remember type - -hddsavetype - !if allow_subdir = 1 { - asl - asl - } else { ;allow_subdir - cmp #MASK_SAPLING - } ;allow_subdir - php - - ;match name lengths before attempting to match names - - lda (bloklo), y - and #$0f - tax - inx - !byte $2c ;mask lda, y on first pass -- lda (bloklo), y - cmp (namlo), y - beq hddfoundname - - ;match failed, check if any directory entries remain - - plp -+ - !if might_exist = 1 { - dec entries - bne ++ - inc status - rts - } ;might_exist - - ;move to next directory in this block, if possible - -++ clc - lda bloklo - adc #ENTRY_SIZE - sta bloklo - bcc + - - ;there can be only one page crossed, so we can increment instead of adc - - inc blokhi -+ cmp #<(hdddirbuf + $1ff) ;4 + ($27 * $0d) - lda blokhi - sbc #>(hdddirbuf + $1ff) - bcc hddnextent - - ;read next directory block when we reach the end of this block - - ldx hdddirbuf + NEXT_BLOCK_LO - lda hdddirbuf + NEXT_BLOCK_HI - jsr hddreaddirsec - bcc hddfirstent - -hddfoundname iny - dex - bne - - stx entries - stx blkofflo - stx blkoffhi - - !if enable_write = 1 { - ldy reqcmd - cpy #cmdwrite ;control carry instead of zero - bne + - - ;round requested size up to nearest block if writing - - !if aligned_read = 0 { - php - } ;aligned_read - lda sizelo - ldx sizehi - jsr hddround - sta sizehi - !if aligned_read = 0 { - plp - } ;aligned_read -+ - } ;enable_write - - !if bounds_check = 1 { - ;cache EOF (file size, loaded backwards) - - ldy #EOF_HI - lda (bloklo), y - !if (enable_write + aligned_read) > 0 { - tax - } else { ;enable_write or aligned_read - sta blefthi - } ;enable_write or aligned_read - dey ;EOF_LO - lda (bloklo), y - !if (enable_write + aligned_read) > 0 { - - ;round file size up to nearest block if writing without aligned reads - ;or always if using aligned reads - - !if aligned_read = 0 { - bcc + - } ;aligned_read - - jsr hddround - tax - lda #0 - !if aligned_read = 0 { - sta sizelo - } ;aligned_read -+ stx blefthi - } ;enable_write or aligned_read - !if aligned_read = 0 { - sta bleftlo - } ;aligned_read - } else { ;bounds_check - !if enable_write = 1 { - !if aligned_read = 0 { - bcc + - lda #0 - sta sizelo -+ - } ;aligned_read - } ;enable_write - } ;bounds_check - ;cache AUX_TYPE (load offset for binary files) - - !if override_adr = 0 { - !if allow_subdir = 1 { - pla - tax - } else { ;allow_subdir - plp - } ;allow_subdir - ldy #AUX_TYPE - lda (bloklo), y - pha - iny - lda (bloklo), y - pha - !if allow_subdir = 1 { - txa - pha - } ;allow_subdir - } ;override_adr - - ;cache KEY_POINTER - - ldy #KEY_POINTER - lda (bloklo), y - tax - sta hdddirbuf - iny - lda (bloklo), y - sta hdddirbuf + 256 - - ;read index block in case of sapling - - !if allow_subdir = 1 { - plp - bpl hddrdwrfile - php - jsr hddreaddirsec - plp - } else { ;allow_subdir - !if override_adr = 1 { - plp - } ;override_adr - bcc hddrdwrfile - jsr hddreaddirsec - } ;allow_subdir - - ;restore load offset - -hddrdwrfile - !if override_adr = 1 { - ldx ldrhi - lda ldrlo - } else { ;override_adr - pla - tax - pla - } ;override_adr - - !if allow_subdir = 1 { - ;check file type and fake size and load address for subdirectories - - bcc + - ldy #2 - sty sizehi - ldx #>hdddirbuf - lda # 0 { - ldy reqcmd - ;cpy #cmdseek - beq + - } ;enable_write or enable_seek - - !if allow_aux = 1 { - ldx auxreq - jsr hddsetaux - } ;allow_aux - !if (enable_write + enable_seek) > 0 { - dey ;cpy #cmdread - !if enable_write = 1 { - bne hddrdwrloop - } ;enable_write - } ;enable_write or enable_seek -+ - lda blkofflo - tax - ora blkoffhi - beq hddrdwrloop - lda sizehi - pha - lda sizelo - pha - lda adrhi - sta blokhi - lda adrlo - sta bloklo - stx adrlo - lda #>hddencbuf - clc - adc blkoffhi - sta adrhi - - !if bounds_check = 1 { - ;determine bytes left in block - - !if (enable_write + enable_seek) > 0 { - tya - } else { ;enable_write or enable_seek - lda #0 - } ;enable_write or enable_seek - sec - sbc blkofflo - tay - lda #2 - sbc blkoffhi - tax - - ;set requested size to min(bytes left, requested size) - - cpy sizelo - sbc sizehi - bcs + - sty sizelo - stx sizehi -+ - } ;bounds_check - - lda sizehi - jsr hddcopycache - lda ldrlo - adc sizelo - sta ldrlo - lda ldrhi - adc sizehi - sta ldrhi - sec - pla - sbc sizelo - sta sizelo - pla - sbc sizehi - sta sizehi - ora sizelo - bne hddrdwrfile - beq hddrdwrdone - } else { ;aligned_read - !if bounds_check = 1 { - lda blefthi - cmp sizehi - bcs + - sta sizehi -+ - } ;bounds_check - !if allow_aux = 1 { - ldx auxreq - jsr setaux - } ;allow_aux - } ;aligned_read - -hddrdwrloop - !if (enable_write + enable_seek) > 0 { - ldx reqcmd - } ;enable_write or enable_seek - !if aligned_read = 0 { - - ;set read/write size to min(length, $200) - - lda sizehi - cmp #2 - bcs + - pha - lda #2 - sta sizehi - - ;redirect read to private buffer for partial copy - - lda adrhi - pha - lda adrlo - pha - lda #>hddencbuf - sta adrhi - lda #0 - sta adrlo - !if (enable_write + enable_seek) > 0 { - ldx #cmdread - } ;enable_write or enable_seek -+ - } ;aligned_read - - ;fetch data block and read/write it - - ldy entries - inc entries - !if enable_seek = 1 { - txa ;cpx #cmdseek, but that would require php at top - beq + - } ;enable_seek - stx command - ldx hdddirbuf, y - lda hdddirbuf + 256, y - !if aligned_read = 0 { - php - } ;aligned_read - jsr hddseekrdwr - !if aligned_read = 0 { - plp -+ bcc + - } ;aligned_read - inc adrhi - inc adrhi - !if bounds_check = 1 { - dec blefthi - dec blefthi - } ;bounds_check -+ dec sizehi - dec sizehi - bne hddrdwrloop - !if aligned_read=0 { - bcc + - lda sizelo - bne hddrdwrloop - } ;aligned_read -hddrdwrdone - !if allow_aux = 1 { - ldx #0 -hddsetaux sta CLRAUXRD, x - sta CLRAUXWR, x - } ;allow_aux - rts - - !if aligned_read = 0 { - ;cache partial block offset - -+ pla - sta bloklo - pla - sta blokhi - pla - sta sizehi - dec adrhi - dec adrhi -hddcopycache - !if enable_seek = 1 { - ldy reqcmd - ;cpy #cmdseek - beq ++ - } ;enable_seek - tay - beq + - dey -- lda (adrlo), y - sta (bloklo), y - iny - bne - - inc blokhi - inc adrhi - bne + -- lda (adrlo), y - sta (bloklo), y - iny -+ cpy sizelo - bne - -++ - !if bounds_check = 1 { - lda bleftlo - sec - sbc sizelo - sta bleftlo - lda blefthi - sbc sizehi - sta blefthi - } ;bounds_check - clc - lda blkofflo - adc sizelo - sta blkofflo - lda blkoffhi - adc sizehi - and #$fd - sta blkoffhi - bcc hddrdwrdone - } ;aligned_read - - !if (enable_write + (bounds_check & aligned_read)) > 0 { -hddround clc - adc #$ff - txa - adc #1 - and #$fe - rts - } ;enable_write or (bounds_check and aligned_read) - -hddreaddirsel ldy #0 - sty adrlo - !if might_exist = 1 { - sty status - } ;might_exist - - !if allow_multi = 1 { - asl reqcmd - lsr reqcmd - } ;allow_multi - -hddreaddirsec ldy #cmdread - sty command - ldy #>hdddirbuf - sty adrhi - -hddseekrdwr stx bloklo - sta blokhi - -unrunit=unrelochdd+(*-reloc) - lda #$d1 - sta unit - -unrentry=unrelochdd+(*-reloc) - jmp $d1d1 -hddcodeend -hdddataend -} ;reloc - -;[music] you can't touch this [music] -;math magic to determine ideal loading address, and information dump -!ifdef PASS2 { -} else { ;PASS2 - !set PASS2=1 - !if enable_floppy = 1 { - !if reloc < $c000 { - !if ((dataend + $ff) & -256) > $c000 { - !serious "initial reloc too high, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) - } ;dataend - !if load_high = 1 { - !if ((dataend + $ff) & -256) != $c000 { - !warn "initial reloc too low, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) - } ;dataend - dirbuf=reloc - $200 - encbuf=dirbuf - $200 - } else { ;load_high - !pseudopc ((dataend + $ff) & -256) { - dirbuf = * - } - encbuf=dirbuf + $200 - } ;load_high - } else { ;reloc - !if ((dataend + $ff) & -256) < reloc { - !serious "initial reloc too high, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff - } ;dataend - !if load_high = 1 { - !if (((dataend + $ff) & -256) & $ffff) != 0 { - !warn "initial reloc too low, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff - } ;dataend - dirbuf=reloc - $200 - encbuf=dirbuf - $200 - } else { ;load_high - !pseudopc ((dataend + $ff) & -256) { - dirbuf = * - } - encbuf=dirbuf + $200 - } ;load_high - } ;reloc - !if verbose_info = 1 { - !warn "floppy code: ", reloc, "-", codeend - 1 - !warn "floppy data: ", bit2tbl, "-", dataend - 1 - !warn "floppy dirbuf: ", dirbuf, "-", dirbuf + $1ff - !warn "floppy encbuf: ", encbuf, "-", encbuf + $1ff - !warn "floppy driver start: ", unrelocdsk - init - } ;verbose_info - } ;enable_floppy - !if reloc < $c000 { - !if ((hdddataend + $ff) & -256) > $c000 { - !serious "initial reloc too high, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) - } ;hdddataend - !if load_high = 1 { - !if ((hdddataend + $ff) & -256) != $c000 { - !warn "initial reloc too low, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) - } ;hdddataend - hdddirbuf = reloc - $200 - !if aligned_read = 0 { - hddencbuf = hdddirbuf - $200 - } ;aligned_read - } else { ;load_high - !pseudopc ((hdddataend + $ff) & -256) { - hdddirbuf = * - } - !if aligned_read = 0 { - hddencbuf = hdddirbuf + $200 - } ;aligned_read - } ;load_high - } else { ;reloc - !if ((hdddataend + $ff) & -256) < reloc { - !serious "initial reloc too high, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff - } ;hdddataend - !if load_high = 1 { - !if enable_floppy = 0 { - !if (((hdddataend + $ff) & -256) & $ffff) != 0 { - !warn "initial reloc too low, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff - } ;hdddataend - } ;enable_floppy - hdddirbuf = reloc - $200 - !if aligned_read = 0 { - hddencbuf = hdddirbuf - $200 - } ;aligned_read - } else { ;load_high - !pseudopc ((hdddataend + $ff) & -256) { - hdddirbuf = * - } - !if aligned_read = 0 { - hddencbuf = hdddirbuf + $200 - } ;aligned_read - } ;load_high - } ;reloc - !if verbose_info = 1 { - !warn "hdd code: ", reloc, "-", hddcodeend - 1 - !warn "hdd dirbuf: ", hdddirbuf, "-", hdddirbuf + $1ff - !if aligned_read = 0 { - !warn "hdd encbuf: ", hddencbuf, "-", hddencbuf + $1ff - } ;aligned_read - !warn "hdd driver start: ", unrelochdd - init - } ;verbose_info -} ;PASS2 - -readbuff -!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE +;extended open/read/write binary file in ProDOS filesystem, with random access +;copyright (c) Peter Ferrie 2013-16 +;license:BSD-3-Clause + +!cpu 6502 +*=$4000 + +;place no code before init label below. + + ;user-defined options + verbose_info = 1 ;set to 1 to enable display of memory usage + enable_floppy = 1 ;set to 1 to enable floppy drive support + poll_drive = 1 ;set to 1 to check if disk is in drive + override_adr = 1 ;set to 1 to require an explicit load address + aligned_read = 0 ;set to 1 if all reads can be a multiple of block size + enable_write = 1 ;set to 1 to enable write support + ;file must exist already and its size cannot be altered + ;writes occur in multiples of block size (256 bytes for floppy, 512 bytes for HDD) + enable_seek = 1 ;set to 1 to enable seek support + allow_multi = 1 ;set to 1 to allow multiple floppies + check_chksum = 1 ;set to 1 to enforce checksum verification for floppies + allow_subdir = 0 ;set to 1 to allow opening subdirectories to access files + might_exist = 1 ;set to 1 if file is not known to always exist already + ;makes use of status to indicate success or failure + allow_aux = 1 ;set to 1 to allow read/write directly to/from aux memory + ;requires load_high to be set for arbitrary memory access + ;else driver must be running from same memory target + ;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 + ;but limits file size to 64k-2 bytes. + 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 + lc_bank = 1 ;load into specified bank (1 or 2) if load_banked=1 + + ;user-defined driver load address +!if load_banked = 1 { + !if load_high = 1 { + !ifdef PASS2 { + } else { ;PASS2 + reloc = $fb00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch + } ;PASS2 + } else { ;load_high + reloc = $f600 ;page-aligned, but otherwise wherever you want + } ;load_high +} else { ;load_banked + !if load_high = 1 { + !ifdef PASS2 { + } else { ;PASS2 + reloc = $bf00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch + } ;PASS2 + } else { ;load_high + reloc = $1000 ;page-aligned, but otherwise wherever you want + } ;load_high +} ;load_banked + + ;zpage usage, arbitrary selection except for the "ProDOS constant" ones + ;feel free to move them around + +!if (might_exist + poll_drive) > 0 { + status = $3 ;returns non-zero on error +} ;might_exist or poll_drive +!if allow_aux = 1 { + auxreq = $a ;set to 1 to read/write aux memory, else main memory is used +} ;allow_aux + sizelo = $6 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking + sizehi = $7 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking + reqcmd = $2 ;set (read/write/seek) if enable_write=1 or enable_seek=1 + ;if allow_multi=1, bit 7 selects floppy drive in current slot (clear=drive 1, set=drive 2) during open call + ;bit 7 must be clear for read/write/seek on opened file + ldrlo = $E ;set to load address if override_adr=1 + ldrhi = $F ;set to load address if override_adr=1 + namlo = $C ;name of file to access + namhi = $D ;name of file to access + +!if enable_floppy = 1 { + tmpsec = $10 ;(internal) sector number read from disk + reqsec = $11 ;(internal) requested sector number + curtrk = $12 ;(internal) track number read from disk +} ;enable_floppy + + command = $42 ;ProDOS constant + unit = $43 ;ProDOS constant + adrlo = $44 ;ProDOS constant + adrhi = $45 ;ProDOS constant + bloklo = $46 ;ProDOS constant + blokhi = $47 ;ProDOS constant + + entries = $18 ;(internal) total number of entries in directory +!if bounds_check = 1 { + bleftlo = $19 ;(internal) bytes left in file + blefthi = $1a ;(internal) bytes left in file +} ;bounds_check + blkofflo = $1b ;(internal) offset within cache block + blkoffhi = $1c ;(internal) offset within cache block +!if enable_floppy = 1 { + step = $1d ;(internal) state for stepper motor + tmptrk = $1e ;(internal) temporary copy of current track + phase = $1f ;(internal) current phase for seek +} ;enable_floppy + + ;constants + cmdseek = 0 ;requires enable_seek=1 + cmdread = 1 ;requires enable_write=1 + cmdwrite = 2 ;requires enable_write=1 + SETKBD = $fe89 + SETVID = $fe93 + DEVNUM = $bf30 + PHASEOFF = $c080 + MOTOROFF = $c088 + MOTORON = $c089 + DRV0EN = $c08a + Q6L = $c08c + Q6H = $c08d + Q7L = $c08e + Q7H = $c08f + MLI = $bf00 + NAME_LENGTH = $4 ;ProDOS constant + MASK_SAPLING = $20 ;ProDOS constant + MASK_TREE = $30 ;ProDOS constant + MASK_SUBDIR = $d0 ;ProDOS constant + MASK_ALL = $f0 ;ProDOS constant + KEY_POINTER = $11 ;ProDOS constant + EOF_LO = $15 ;ProDOS constant + EOF_HI = $16 ;ProDOS constant + AUX_TYPE = $1f ;ProDOS constant + ENTRY_SIZE = $27 ;ProDOS constant + NEXT_BLOCK_LO = $2 ;ProDOS constant + NEXT_BLOCK_HI = $3 ;ProDOS constant + SAPLING = $20 ;ProDOS constant + FILE_COUNT = $25 ;ProDOS constant + ROMIN = $c081 + LCBANK2 = $c089 + CLRAUXRD = $c002 + CLRAUXWR = $c004 + +init jsr SETVID + jsr SETKBD + lda DEVNUM + sta x80_parms + 1 + sta unrunit + 1 + and #$70 +!if (enable_floppy + enable_write) > 1 { + sta unrslot1 + 1 + sta unrslot2 + 1 + sta unrslot3 + 1 + sta unrslot4 + 1 +} ;enable_floppy and enable_write + pha +!if enable_floppy = 1 { + ora #(readbuff + NAME_LENGTH) + sta blokhi +inextent ldy #0 + lda (bloklo), y + pha + and #MASK_SUBDIR + + ;watch for subdirectory entries + + cmp #MASK_SUBDIR + bne + + + lda (bloklo), y + and #$0f + tax + iny +-- lda (bloklo), y + cmp (namlo), y + beq ifoundname + + ;match failed, move to next directory in this block, if possible + +- ++ pla + clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcc + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi ++ cmp #<(readbuff + $1ff) ;4 + ($27 * $0d) + lda blokhi + sbc #>(readbuff + $1ff) + bcc inextent + + ;read next directory block when we reach the end of this block + + lda readbuff + NEXT_BLOCK_LO + ldx readbuff + NEXT_BLOCK_HI + bcs + + +ifoundname iny + dex + bne -- + + ;parse path until last directory is seen + + lda (namlo), y + cmp #'/' + bne - + tya + eor #$ff + adc sizelo + sta sizelo + clc + tya + adc namlo + sta namlo + pla + and #$20 ;Volume Directory Header XOR subdirectory + bne ++ + + ;cache block number of current directory + ;as starting position for subsequent searches + + ldy #(KEY_POINTER + 1) + lda (bloklo), y + tax + dey + lda (bloklo), y +!if enable_floppy = 1 { + sta unrblocklo + 1 + stx unrblockhi + 1 +} ;enable_floppy + sta unrhddblocklo + 1 + stx unrhddblockhi + 1 ++ sta x80_parms + 4 + stx x80_parms + 5 +++ lda sizelo + bne readblock + + ;unit to slot for SmartPort interface + ++++ pla + lsr + lsr + lsr + tax + lsr + ora #$c0 + ldy $bf11, x + cpy #$c8 ;max slot+1 + bcs set_slot + tya +set_slot sta slot + 2 + sta unrentry + 2 +!if enable_floppy = 1 { + ldx #>unrelocdsk + ldy #unrelochdd + ldy #((codeend - rdwrpart) + $ff) + ldy #0 +- lda (bloklo), y +reladr sta reloc, y + iny + bne - + inc blokhi + inc reladr + 2 + dex + bne - + plp + bne ++ + + ;build 6-and-2 denibbilisation table + + ldx #$16 +-- stx bloklo + txa + asl + bit bloklo + beq + + ora bloklo + eor #$ff + and #$7e +- bcs + + lsr + bne - + tya + sta nibtbl - $16, x + !if enable_write = 1 { + ;and 6-and-2 nibbilisation table if writing + + txa + ora #$80 + sta xlattbl, y + } ;enable_write + iny ++ inx + bpl -- +++ rts +} else { ;enable_floppy +slot lda $cfff + sta unrentry + 1 + !if load_banked = 1 { + !if lc_bank = 1 { + lda LCBANK2 + lda LCBANK2 + } else { ;lc_bank + lda ROMIN + lda ROMIN + } ;lc_bank + } ;load_banked + ldy #0 +- lda unrelochdd, y + sta reloc, y + + ;hack to avoid address overflow when load_high and load_banked + ;and code is less than two pages long (e.g. aligned_read, no write) + + !ifdef PASS2 { + !if >(hddcodeend - reloc) > 1 { + !set hack=$100 + } ;hddcodeend + } else { ;PASS2 + !set hack=0 + } ;PASS2 + sta reloc + hack, y + iny + bne - + rts +} ;enable_floppy + +c7_parms !byte 1 + !word $200 + +x80_parms !byte 3, $d1 + !word readbuff, 2 + +!if enable_floppy = 1 { +unrelocdsk +!pseudopc reloc { +!if override_adr = 1 { + ;only available when load address is specified + +rdwrpart jmp rdwrfile +} ;override_adr + ;read volume directory key block + ;self-modified by init code + +opendir +unrblocklo = unrelocdsk + (* - reloc) + ldx #2 +unrblockhi = unrelocdsk + (* - reloc) + lda #0 + jsr readdirsel + + ;include volume directory header in count + +readdir + !if might_exist = 1 { + ldx dirbuf + FILE_COUNT ;assuming only 256 files per subdirectory + inx + stx entries + } ;might_exist + +firstent lda #<(dirbuf + NAME_LENGTH) + sta bloklo + lda #>(dirbuf + NAME_LENGTH) + sta blokhi + +nextent ldy #0 + !if might_exist = 1 { + sty status + } ;might_exist + lda (bloklo), y + !if (might_exist + allow_subdir) > 0 { + and #MASK_ALL + + !if might_exist = 1 { + ;skip deleted entries without counting + + beq ++ + } ;might_exist + + !if allow_subdir = 1 { + ;subdirectory entries are seedlings + ;but we need to distinguish between them later + + cmp #MASK_SUBDIR + beq savetype + } ;allow_subdir + } ;might_exist or allow_subdir + + ;watch for seedling and saplings only + + cmp #MASK_TREE + bcs + + + ;remember type + +savetype + !if allow_subdir = 1 { + asl + asl + } else { ;allow_subdir + cmp #MASK_SAPLING + } ;allow_subdir + php + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx + !byte $2c ;mask lda, y on first pass +- lda (bloklo), y + cmp (namlo), y + beq foundname + + ;match failed, check if any directory entries remain + + plp ++ + !if might_exist = 1 { + dec entries + bne ++ + } ;might_exist + !if (might_exist + poll_drive) > 0 { +nodisk +unrdrvoff1=unrelocdsk+(*-reloc) + lda MOTOROFF + inc status + rts + } ;might_exist or poll_drive + + ;move to next directory in this block, if possible + +++ clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcc + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi ++ cmp #<(dirbuf + $1ff) ;4 + ($27 * $0d) + lda blokhi + sbc #>(dirbuf + $1ff) + bcc nextent + + ;read next directory block when we reach the end of this block + + ldx dirbuf + NEXT_BLOCK_LO + lda dirbuf + NEXT_BLOCK_HI + jsr readdirsec + bne firstent + +foundname iny + dex + bne - + stx entries + stx blkofflo + stx blkoffhi + + !if enable_write = 1 { + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne + + + ;round requested size up to nearest block if writing + + !if aligned_read = 0 { + php + } ;aligned_read + lda sizelo + ldx sizehi + jsr round + sta sizehi + !if aligned_read = 0 { + plp + } ;aligned_read ++ + } ;enable_write + + !if bounds_check = 1 { + ;cache EOF (file size, loaded backwards) + + ldy #EOF_HI + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + tax + } else { ;enable_write or aligned_read + sta blefthi + } ;enable_write or aligned_read + dey ;EOF_LO + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + + ;round file size up to nearest sector if writing without aligned reads + ;or nearest block if using aligned reads + + !if aligned_read = 0 { + bcc + + } ;aligned_read + + jsr round + tax + lda #0 + !if aligned_read = 0 { + sta sizelo + } ;aligned_read ++ stx blefthi + } ;enable_write or aligned_read + !if aligned_read = 0 { + sta bleftlo + } ;aligned_read + } else { ;bounds_check + !if enable_write = 1 { + !if aligned_read = 0 { + bcc + + lda #0 + sta sizelo ++ + } ;aligned_read + } ;enable_write + } ;bounds_check + ;cache AUX_TYPE (load offset for binary files) + + !if override_adr = 0 { + !if allow_subdir = 1 { + pla + tax + } else { ;allow_subdir + plp + } ;allow_subdir + ldy #AUX_TYPE + lda (bloklo), y + pha + iny + lda (bloklo), y + pha + !if allow_subdir = 1 { + txa + pha + } ;allow_subdir + } ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + sta dirbuf + iny + lda (bloklo), y + sta dirbuf + 256 + + ;read index block in case of sapling + + !if allow_subdir = 1 { + plp + bpl rdwrfile + php + jsr readdirsec + plp + } else { ;allow_subdir + !if override_adr = 1 { + plp + } ;override_adr + bcc rdwrfile + jsr readdirsec + } ;allow_subdir + + ;restore load offset + +rdwrfile + !if override_adr = 1 { + ldx ldrhi + lda ldrlo + } else { ;override_adr + pla + tax + pla + } ;override_adr + + !if allow_subdir = 1 { + ;check file type and fake size and load address for subdirectories + + bcc + + ldy #2 + sty sizehi + ldx #>dirbuf + lda # 0 { + ldy reqcmd + ;cpy #cmdseek + beq + + } ;enable_write or enable_seek + + !if allow_aux = 1 { + ldx auxreq + jsr setaux + } ;allow_aux + !if (enable_write + enable_seek) > 0 { + dey ;cpy #cmdread + !if enable_write = 1 { + bne rdwrloop + } ;enable_write + } ;enable_write or enable_seek ++ + lda blkofflo + tax + ora blkoffhi + beq rdwrloop + lda sizehi + pha + lda sizelo + pha + lda adrhi + sta blokhi + lda adrlo + sta bloklo + stx adrlo + lda #>encbuf + clc + adc blkoffhi + sta adrhi + + !if bounds_check = 1 { + ;determine bytes left in block + + !if (enable_write + enable_seek) > 0 { + tya + } else { ;enable_write or enable_seek + lda #0 + } ;enable_write or enable_seek + sec + sbc blkofflo + tay + lda #2 + sbc blkoffhi + tax + + ;set requested size to min(bytes left, requested size) + + cpy sizelo + sbc sizehi + bcs + + sty sizelo + stx sizehi ++ + } ;bounds_check + + lda sizehi + jsr copycache + lda ldrlo + adc sizelo + sta ldrlo + lda ldrhi + adc sizehi + sta ldrhi + sec + pla + sbc sizelo + sta sizelo + pla + sbc sizehi + sta sizehi + ora sizelo + bne rdwrfile + beq rdwrdone + } else { ;aligned_read + !if bounds_check = 1 { + lda blefthi + cmp sizehi + bcs + + sta sizehi ++ + } ;bounds_check + !if allow_aux = 1 { + ldx auxreq + jsr setaux + } ;allow_aux + } ;aligned_read + +rdwrloop + !if (enable_write + enable_seek) > 0 { + ldx reqcmd + } ;enable_write or enable_seek + !if aligned_read = 0 { + + ;set read/write size to min(length, $200) + + lda sizehi + cmp #2 + bcs + + pha + lda #2 + sta sizehi + + ;redirect read to private buffer for partial copy + + lda adrhi + pha + lda adrlo + pha + lda #>encbuf + sta adrhi + lda #0 + sta adrlo + !if (enable_write + enable_seek) > 0 { + ldx #cmdread + } ;enable_write or enable_seek ++ + } ;aligned_read + + ;fetch data block and read/write it + + ldy entries + inc entries + !if enable_seek = 1 { + txa ;cpx #cmdseek, but that would require php at top + beq + + } ;enable_seek + stx command + ldx dirbuf, y + lda dirbuf + 256, y + !if aligned_read = 0 { + php + } ;aligned_read + jsr seekrdwr + !if aligned_read = 0 { + plp ++ bcc + + } ;aligned_read + !if bounds_check = 1 { + dec blefthi + dec blefthi + } ;bounds_check ++ dec sizehi + dec sizehi + bne rdwrloop + +unrdrvoff2 = unrelocdsk + (* - reloc) + lda MOTOROFF + !if aligned_read = 0 { + bcc + + lda sizelo + bne rdwrloop + } ;aligned_read +rdwrdone + !if allow_aux = 1 { + ldx #0 +setaux sta CLRAUXRD, x + sta CLRAUXWR, x + } ;allow_aux + rts + + !if aligned_read = 0 { + ;cache partial block offset + ++ pla + sta bloklo + pla + sta blokhi + pla + sta sizehi + dec adrhi + dec adrhi +copycache + !if enable_seek = 1 { + ldy reqcmd + ;cpy #cmdseek + beq ++ + } ;enable_seek + tay + beq + + dey +- lda (adrlo), y + sta (bloklo), y + iny + bne - + inc blokhi + inc adrhi + bne + +- lda (adrlo), y + sta (bloklo), y + iny ++ cpy sizelo + bne - +++ + !if bounds_check = 1 { + lda bleftlo + sec + sbc sizelo + sta bleftlo + lda blefthi + sbc sizehi + sta blefthi + } ;bounds_check + clc + lda blkofflo + adc sizelo + sta blkofflo + lda blkoffhi + adc sizehi + and #$fd + sta blkoffhi + bcc rdwrdone ;always + } ;aligned_read + + !if (enable_write + (bounds_check & aligned_read)) > 0 { +round clc + adc #$ff + txa + adc #1 + and #$fe + rts + } ;enable_write or (bounds_check and aligned_read) + + ;no tricks here, just the regular stuff + +seek sty step + asl phase + txa + asl +copy_cur tax + sta tmptrk + sec + sbc phase + beq +++ + bcs + + eor #$ff + inx + bcc ++ ++ sbc #1 + dex +++ cmp step + bcc + + lda step ++ cmp #8 + bcs + + tay + sec ++ txa + pha + ldx step1, y ++++ php + bne + +--- clc + lda tmptrk + ldx step2, y ++ stx tmpsec + and #3 + rol + tax + lsr +unrseek = unrelocdsk + (* - reloc) + lda PHASEOFF, x +-- ldx #$13 +- dex + bne - + dec tmpsec + bne -- + bcs --- + plp + beq seekret + pla + inc step + bne copy_cur + +step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c +step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c + +readadr +- jsr readd5aa + cmp #$96 + bne - + ldy #3 +- sta curtrk + jsr readnib + rol + sta tmpsec + jsr readnib + and tmpsec + dey + bne - +seekret rts + +readd5aa +-- jsr readnib +- cmp #$d5 + bne -- + jsr readnib + cmp #$aa + bne - + tay ;we need Y=#$AA later + +readnib +unrread1 = unrelocdsk + (* - reloc) +- lda Q6L + bpl - + rts + +readdirsel ldy #0 + sty adrlo + + !if allow_multi = 1 { + asl reqcmd + bcc seldrive + iny +seldrive lsr reqcmd +unrdrvsel = unrelocdsk + (* - reloc) + cmp DRV0EN, y + } ;allow_multi + !if poll_drive = 1 { + sty status +unrdrvon1 = unrelocdsk + (* - reloc) + ldy MOTORON +unrread2 = unrelocdsk + (* - reloc) +- ldy Q6L + bpl - +unrread3 = unrelocdsk + (* - reloc) +- cpy Q6L + bne readdirsec + inc status + bne - + pla + pla + jmp nodisk + } ;poll_drive + +readdirsec ldy #cmdread + sty command + ldy #>dirbuf + sty adrhi + + ;convert block number to track/sector + +seekrdwr +unrdrvon2 = unrelocdsk + (* - reloc) + ldy MOTORON + lsr + txa + ror + lsr + lsr + sta phase + txa + and #3 + php + asl + plp + rol + sta reqsec + jsr readadr + + ;if track does not match, then seek + + ldx curtrk + cpx phase + beq checksec + jsr seek + + ;force sector mismatch + + lda #$ff + + ;match or read/write sector + +checksec jsr cmpsec + inc reqsec + inc reqsec + + ;force sector mismatch + +cmpsecrd lda #$ff + +cmpsec + !if enable_write = 1 { + ldy command + cpy #cmdwrite ;we need Y=2 below + beq encsec + } ;enable_write +cmpsec2 cmp reqsec + beq readdata + jsr readadr + beq cmpsec2 + + ;read sector data + +readdata jsr readd5aa + eor #$ad ;zero A if match +;; bne * ;lock if read failure +unrread4 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + sta bit2tbl - $aa, y + iny + bne - +unrread5 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + sta (adrlo), y ;the real address + iny + !if check_chksum = 1 { + bne - +unrread6 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + bne cmpsecrd + } ;check_chksum +-- ldx #$a9 +- inx + beq -- + lda (adrlo), y + lsr bit2tbl - $aa, x + rol + lsr bit2tbl - $aa, x + rol + sta (adrlo), y + iny + bne - +readret inc adrhi + rts + + !if enable_write = 1 { +encsec +-- ldx #$aa +- dey + lda (adrlo), y + lsr + rol bit2tbl - $aa, x + lsr + rol bit2tbl - $aa, x + sta encbuf, y + lda bit2tbl - $aa, x + and #$3f + sta bit2tbl - $aa, x + inx + bne - + tya + bne -- + +cmpsecwr jsr readadr + cmp reqsec + bne cmpsecwr + + ;skip tail #$DE #$AA #$EB some #$FFs ... + + ldy #$24 +- dey + bpl - + + ;write sector data + +unrslot1 = unrelocdsk + (* - reloc) + ldx #$d1 + lda Q6H, x ;prime drive + lda Q7L, x ;required by Unidisk + tya + sta Q7H, x + ora Q6L, x + + ;40 cycles + + ldy #4 ;2 cycles + cmp $ea ;3 cycles + cmp ($ea, x) ;6 cycles +- jsr writenib1 ;(29 cycles) + + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles + ;+10 cycles + ldy #(prolog_e - prolog) + ;2 cycles + cmp $ea ;3 cycles +- lda prolog - 1, y ;4 cycles + jsr writenib3 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles on first pass + ;+10 cycles + tya ;2 cycles + ldy #$56 ;2 cycles +- eor bit2tbl - 1, y ;5 cycles + tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot2 = unrelocdsk + (* - reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + + ;32 cycles if branch taken + + lda bit2tbl - 1, y ;5 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;32 cycles + ;+9 cycles + clc ;2 cycles +-- eor encbuf, y ;4 cycles +- tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot3 = unrelocdsk + (* - reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + bcs + ;3 cycles if taken, 2 if not + + ;32 cycles if branch taken + + lda encbuf, y ;4 cycles + iny ;2 cycles + bne -- ;3 cycles if taken, 2 if not + + ;32 cycles + ;+10 cycles + sec ;2 cycles + bcs - ;3 cycles + + ;32 cycles + ;+3 cycles ++ ldy #(epilog_e - epilog) + ;2 cycles + cmp ($ea, x) ;6 cycles +- lda epilog - 1, y ;4 cycles + jsr writenib3 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if branch taken, 2 if not + + lda Q7L, x + lda Q6L, x ;flush final value + inc adrhi + rts + +writenib1 cmp ($ea, x) ;6 cycles +writenib2 cmp ($ea, x) ;6 cycles +writenib3 +unrslot4=unrelocdsk+(*-reloc) + ldx #$d1 ;2 cycles +writenib4 sta Q6H, x ;5 cycles + ora Q6L, x ;4 cycles + rts ;6 cycles + +prolog !byte $ad, $aa, $d5 +prolog_e +epilog !byte $ff, $eb, $aa, $de +epilog_e + } ;enable_write +codeend +bit2tbl = (* + 255) & -256 +nibtbl = bit2tbl + 86 + !if enable_write = 1 { +xlattbl = nibtbl + 106 +dataend = xlattbl + 64 + } else { ;enable_write +dataend = nibtbl + 106 + } ;enable_write +} ;enable_floppy +} ;reloc + +unrelochdd +!pseudopc reloc { +!if override_adr = 1 { +hddrdwrpart jmp hddrdwrfile +} ;override_adr + ;read volume directory key block + ;self-modified by init code + +hddopendir +unrhddblocklo = unrelochdd + (* - reloc) + ldx #2 +unrhddblockhi = unrelochdd + (* - reloc) + lda #0 + jsr hddreaddirsel + +!if enable_floppy = 1 { + !if (* - hddopendir) < (readdir - opendir) { + ;essential padding to match offset with floppy version + !fill (readdir - opendir) - (* - hddopendir), $ea + } +} ;enable_floppy + + ;include volume directory header in count + +hddreaddir + !if might_exist = 1 { + ldx hdddirbuf + FILE_COUNT + inx + stx entries + } ;might_exist + +hddfirstent lda #<(hdddirbuf + NAME_LENGTH) + sta bloklo + lda #>(hdddirbuf + NAME_LENGTH) + sta blokhi + +hddnextent ldy #0 + !if might_exist = 1 { + sty status + } ;might_exist + lda (bloklo), y + !if (might_exist + allow_subdir) > 0 { + and #MASK_ALL + + !if might_exist = 1 { + ;skip deleted entries without counting + + beq ++ + } ;might_exist + + !if allow_subdir = 1 { + ;subdirectory entries are seedlings + ;but we need to distinguish between them later + + cmp #MASK_SUBDIR + beq hddsavetype + } ;allow_subdir + } ;might_exist or allow_subdir + + ;watch for seedling and saplings only + + cmp #MASK_TREE + bcs + + + ;remember type + +hddsavetype + !if allow_subdir = 1 { + asl + asl + } else { ;allow_subdir + cmp #MASK_SAPLING + } ;allow_subdir + php + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx + !byte $2c ;mask lda, y on first pass +- lda (bloklo), y + cmp (namlo), y + beq hddfoundname + + ;match failed, check if any directory entries remain + + plp ++ + !if might_exist = 1 { + dec entries + bne ++ + inc status + rts + } ;might_exist + + ;move to next directory in this block, if possible + +++ clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcc + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi ++ cmp #<(hdddirbuf + $1ff) ;4 + ($27 * $0d) + lda blokhi + sbc #>(hdddirbuf + $1ff) + bcc hddnextent + + ;read next directory block when we reach the end of this block + + ldx hdddirbuf + NEXT_BLOCK_LO + lda hdddirbuf + NEXT_BLOCK_HI + jsr hddreaddirsec + bcc hddfirstent + +hddfoundname iny + dex + bne - + stx entries + stx blkofflo + stx blkoffhi + + !if enable_write = 1 { + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne + + + ;round requested size up to nearest block if writing + + !if aligned_read = 0 { + php + } ;aligned_read + lda sizelo + ldx sizehi + jsr hddround + sta sizehi + !if aligned_read = 0 { + plp + } ;aligned_read ++ + } ;enable_write + + !if bounds_check = 1 { + ;cache EOF (file size, loaded backwards) + + ldy #EOF_HI + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + tax + } else { ;enable_write or aligned_read + sta blefthi + } ;enable_write or aligned_read + dey ;EOF_LO + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + + ;round file size up to nearest block if writing without aligned reads + ;or always if using aligned reads + + !if aligned_read = 0 { + bcc + + } ;aligned_read + + jsr hddround + tax + lda #0 + !if aligned_read = 0 { + sta sizelo + } ;aligned_read ++ stx blefthi + } ;enable_write or aligned_read + !if aligned_read = 0 { + sta bleftlo + } ;aligned_read + } else { ;bounds_check + !if enable_write = 1 { + !if aligned_read = 0 { + bcc + + lda #0 + sta sizelo ++ + } ;aligned_read + } ;enable_write + } ;bounds_check + ;cache AUX_TYPE (load offset for binary files) + + !if override_adr = 0 { + !if allow_subdir = 1 { + pla + tax + } else { ;allow_subdir + plp + } ;allow_subdir + ldy #AUX_TYPE + lda (bloklo), y + pha + iny + lda (bloklo), y + pha + !if allow_subdir = 1 { + txa + pha + } ;allow_subdir + } ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + sta hdddirbuf + iny + lda (bloklo), y + sta hdddirbuf + 256 + + ;read index block in case of sapling + + !if allow_subdir = 1 { + plp + bpl hddrdwrfile + php + jsr hddreaddirsec + plp + } else { ;allow_subdir + !if override_adr = 1 { + plp + } ;override_adr + bcc hddrdwrfile + jsr hddreaddirsec + } ;allow_subdir + + ;restore load offset + +hddrdwrfile + !if override_adr = 1 { + ldx ldrhi + lda ldrlo + } else { ;override_adr + pla + tax + pla + } ;override_adr + + !if allow_subdir = 1 { + ;check file type and fake size and load address for subdirectories + + bcc + + ldy #2 + sty sizehi + ldx #>hdddirbuf + lda # 0 { + ldy reqcmd + ;cpy #cmdseek + beq + + } ;enable_write or enable_seek + + !if allow_aux = 1 { + ldx auxreq + jsr hddsetaux + } ;allow_aux + !if (enable_write + enable_seek) > 0 { + dey ;cpy #cmdread + !if enable_write = 1 { + bne hddrdwrloop + } ;enable_write + } ;enable_write or enable_seek ++ + lda blkofflo + tax + ora blkoffhi + beq hddrdwrloop + lda sizehi + pha + lda sizelo + pha + lda adrhi + sta blokhi + lda adrlo + sta bloklo + stx adrlo + lda #>hddencbuf + clc + adc blkoffhi + sta adrhi + + !if bounds_check = 1 { + ;determine bytes left in block + + !if (enable_write + enable_seek) > 0 { + tya + } else { ;enable_write or enable_seek + lda #0 + } ;enable_write or enable_seek + sec + sbc blkofflo + tay + lda #2 + sbc blkoffhi + tax + + ;set requested size to min(bytes left, requested size) + + cpy sizelo + sbc sizehi + bcs + + sty sizelo + stx sizehi ++ + } ;bounds_check + + lda sizehi + jsr hddcopycache + lda ldrlo + adc sizelo + sta ldrlo + lda ldrhi + adc sizehi + sta ldrhi + sec + pla + sbc sizelo + sta sizelo + pla + sbc sizehi + sta sizehi + ora sizelo + bne hddrdwrfile + beq hddrdwrdone + } else { ;aligned_read + !if bounds_check = 1 { + lda blefthi + cmp sizehi + bcs + + sta sizehi ++ + } ;bounds_check + !if allow_aux = 1 { + ldx auxreq + jsr setaux + } ;allow_aux + } ;aligned_read + +hddrdwrloop + !if (enable_write + enable_seek) > 0 { + ldx reqcmd + } ;enable_write or enable_seek + !if aligned_read = 0 { + + ;set read/write size to min(length, $200) + + lda sizehi + cmp #2 + bcs + + pha + lda #2 + sta sizehi + + ;redirect read to private buffer for partial copy + + lda adrhi + pha + lda adrlo + pha + lda #>hddencbuf + sta adrhi + lda #0 + sta adrlo + !if (enable_write + enable_seek) > 0 { + ldx #cmdread + } ;enable_write or enable_seek ++ + } ;aligned_read + + ;fetch data block and read/write it + + ldy entries + inc entries + !if enable_seek = 1 { + txa ;cpx #cmdseek, but that would require php at top + beq + + } ;enable_seek + stx command + ldx hdddirbuf, y + lda hdddirbuf + 256, y + !if aligned_read = 0 { + php + } ;aligned_read + jsr hddseekrdwr + !if aligned_read = 0 { + plp ++ bcc + + } ;aligned_read + inc adrhi + inc adrhi + !if bounds_check = 1 { + dec blefthi + dec blefthi + } ;bounds_check ++ dec sizehi + dec sizehi + bne hddrdwrloop + !if aligned_read=0 { + bcc + + lda sizelo + bne hddrdwrloop + } ;aligned_read +hddrdwrdone + !if allow_aux = 1 { + ldx #0 +hddsetaux sta CLRAUXRD, x + sta CLRAUXWR, x + } ;allow_aux + rts + + !if aligned_read = 0 { + ;cache partial block offset + ++ pla + sta bloklo + pla + sta blokhi + pla + sta sizehi + dec adrhi + dec adrhi +hddcopycache + !if enable_seek = 1 { + ldy reqcmd + ;cpy #cmdseek + beq ++ + } ;enable_seek + tay + beq + + dey +- lda (adrlo), y + sta (bloklo), y + iny + bne - + inc blokhi + inc adrhi + bne + +- lda (adrlo), y + sta (bloklo), y + iny ++ cpy sizelo + bne - +++ + !if bounds_check = 1 { + lda bleftlo + sec + sbc sizelo + sta bleftlo + lda blefthi + sbc sizehi + sta blefthi + } ;bounds_check + clc + lda blkofflo + adc sizelo + sta blkofflo + lda blkoffhi + adc sizehi + and #$fd + sta blkoffhi + bcc hddrdwrdone + } ;aligned_read + + !if (enable_write + (bounds_check & aligned_read)) > 0 { +hddround clc + adc #$ff + txa + adc #1 + and #$fe + rts + } ;enable_write or (bounds_check and aligned_read) + +hddreaddirsel ldy #0 + sty adrlo + !if might_exist = 1 { + sty status + } ;might_exist + + !if allow_multi = 1 { + asl reqcmd + lsr reqcmd + } ;allow_multi + +hddreaddirsec ldy #cmdread + sty command + ldy #>hdddirbuf + sty adrhi + +hddseekrdwr stx bloklo + sta blokhi + +unrunit=unrelochdd+(*-reloc) + lda #$d1 + sta unit + +unrentry=unrelochdd+(*-reloc) + jmp $d1d1 +hddcodeend +hdddataend +} ;reloc + +;[music] you can't touch this [music] +;math magic to determine ideal loading address, and information dump +!ifdef PASS2 { +} else { ;PASS2 + !set PASS2=1 + !if enable_floppy = 1 { + !if reloc < $c000 { + !if ((dataend + $ff) & -256) > $c000 { + !serious "initial reloc too high, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) + } ;dataend + !if load_high = 1 { + !if ((dataend + $ff) & -256) != $c000 { + !warn "initial reloc too low, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) + } ;dataend + dirbuf=reloc - $200 + encbuf=dirbuf - $200 + } else { ;load_high + !pseudopc ((dataend + $ff) & -256) { + dirbuf = * + } + encbuf=dirbuf + $200 + } ;load_high + } else { ;reloc + !if ((dataend + $ff) & -256) < reloc { + !serious "initial reloc too high, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff + } ;dataend + !if load_high = 1 { + !if (((dataend + $ff) & -256) & $ffff) != 0 { + !warn "initial reloc too low, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff + } ;dataend + dirbuf=reloc - $200 + encbuf=dirbuf - $200 + } else { ;load_high + !pseudopc ((dataend + $ff) & -256) { + dirbuf = * + } + encbuf=dirbuf + $200 + } ;load_high + } ;reloc + !if verbose_info = 1 { + !warn "floppy code: ", reloc, "-", codeend - 1 + !warn "floppy data: ", bit2tbl, "-", dataend - 1 + !warn "floppy dirbuf: ", dirbuf, "-", dirbuf + $1ff + !warn "floppy encbuf: ", encbuf, "-", encbuf + $1ff + !warn "floppy driver start: ", unrelocdsk - init + } ;verbose_info + } ;enable_floppy + !if reloc < $c000 { + !if ((hdddataend + $ff) & -256) > $c000 { + !serious "initial reloc too high, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) + } ;hdddataend + !if load_high = 1 { + !if ((hdddataend + $ff) & -256) != $c000 { + !warn "initial reloc too low, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) + } ;hdddataend + hdddirbuf = reloc - $200 + !if aligned_read = 0 { + hddencbuf = hdddirbuf - $200 + } ;aligned_read + } else { ;load_high + !pseudopc ((hdddataend + $ff) & -256) { + hdddirbuf = * + } + !if aligned_read = 0 { + hddencbuf = hdddirbuf + $200 + } ;aligned_read + } ;load_high + } else { ;reloc + !if ((hdddataend + $ff) & -256) < reloc { + !serious "initial reloc too high, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff + } ;hdddataend + !if load_high = 1 { + !if enable_floppy = 0 { + !if (((hdddataend + $ff) & -256) & $ffff) != 0 { + !warn "initial reloc too low, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff + } ;hdddataend + } ;enable_floppy + hdddirbuf = reloc - $200 + !if aligned_read = 0 { + hddencbuf = hdddirbuf - $200 + } ;aligned_read + } else { ;load_high + !pseudopc ((hdddataend + $ff) & -256) { + hdddirbuf = * + } + !if aligned_read = 0 { + hddencbuf = hdddirbuf + $200 + } ;aligned_read + } ;load_high + } ;reloc + !if verbose_info = 1 { + !warn "hdd code: ", reloc, "-", hddcodeend - 1 + !warn "hdd dirbuf: ", hdddirbuf, "-", hdddirbuf + $1ff + !if aligned_read = 0 { + !warn "hdd encbuf: ", hddencbuf, "-", hddencbuf + $1ff + } ;aligned_read + !warn "hdd driver start: ", unrelochdd - init + } ;verbose_info +} ;PASS2 + +readbuff +!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE diff --git a/Platform/Apple/virtual/src/core/loader.s b/Platform/Apple/virtual/src/core/loader.s index 7ab159ea..46a3bf47 100644 --- a/Platform/Apple/virtual/src/core/loader.s +++ b/Platform/Apple/virtual/src/core/loader.s @@ -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 diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index abd25272..be5d396c 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -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 - 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 $BFBD -; patch into the interrupt handler - stx $BFEB - lda #enterProDOS2 - sta $BFED -; patch into the shared MLI/IRQ exit routine - stx $BFA0 - 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+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 #filename + sta pSrc+1 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+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 #= 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 diff --git a/Platform/Apple/virtual/src/include/global.i b/Platform/Apple/virtual/src/include/global.i index 11a0a38b..5efd4461 100644 --- a/Platform/Apple/virtual/src/include/global.i +++ b/Platform/Apple/virtual/src/include/global.i @@ -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 diff --git a/Platform/Apple/virtual/src/plasma/diskops.pla b/Platform/Apple/virtual/src/plasma/diskops.pla index af149f16..686bec50 100644 --- a/Platform/Apple/virtual/src/plasma/diskops.pla +++ b/Platform/Apple/virtual/src/plasma/diskops.pla @@ -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 ///////////////////////////////////////////////////////////////////////////////////////////////////