From 845239c2cf2f665fe2fecd2ffd3179181e53ac8e Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Fri, 6 Jan 2017 17:49:51 -0800 Subject: [PATCH] Got decompression working, yay\! --- .../src/org/badvision/A2PackPartitions.groovy | 4 +- Platform/Apple/virtual/src/core/decomp.s | 8 +- Platform/Apple/virtual/src/core/loader.s | 8 +- Platform/Apple/virtual/src/core/mem.s | 130 ++++++++++++++---- Platform/Apple/virtual/src/include/mem.i | 2 +- 5 files changed, 109 insertions(+), 43 deletions(-) diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy index 271e8e7b..ec4e3fb9 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy @@ -1249,10 +1249,10 @@ class A2PackPartitions } // If we saved at least 10 bytes, take the compressed version. - if (false && (uncompressedLen - compressedLen) >= 10) { + if ((uncompressedLen - compressedLen) >= 10) { if (debugCompression) println String.format(" Compress. rawLen=\$%x compLen=\$%x", uncompressedLen, compressedLen) - compressionSavings += (uncompressedLen - compressedLen) - 2 + compressionSavings += (uncompressedLen - compressedLen) - 2 // -2 for storing compressed len return [data:compressedData, len:compressedLen, compressed:true, uncompressedLen:uncompressedLen] } diff --git a/Platform/Apple/virtual/src/core/decomp.s b/Platform/Apple/virtual/src/core/decomp.s index e73d36c3..0e7759f0 100644 --- a/Platform/Apple/virtual/src/core/decomp.s +++ b/Platform/Apple/virtual/src/core/decomp.s @@ -15,11 +15,11 @@ * = $DF00 tmp = $2 ; len 2 -pTmp = $4 ; len 2 -bits = $6 ; len 1 +pTmp = $6 ; len 2 ; not at $4, to preserve memmgr's pTmp +bits = $8 ; len 1 -pSrc = $C ; len 2 -pDst = $E ; len 2 +pDst = $C ; len 2 ; opposite order from memmgr, +pSrc = $E ; len 2 ; so it can avoid swapping pEnd = $10 ; len 2 cout = $FDED diff --git a/Platform/Apple/virtual/src/core/loader.s b/Platform/Apple/virtual/src/core/loader.s index 219f5a19..b26902df 100644 --- a/Platform/Apple/virtual/src/core/loader.s +++ b/Platform/Apple/virtual/src/core/loader.s @@ -22,12 +22,8 @@ DEBUG = 0 * = $2000 -tmp = $2 ; len 2 -pTmp = $4 ; len 2 -bits = $6 ; len 1 - -pSrc = $C ; len 2 -pDst = $E ; len 2 +pDst = $C ; len 2 ; opposite order from memmgr, +pSrc = $E ; len 2 ; so it can avoid swapping pEnd = $10 ; len 2 pData = $80 ; len 2 diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index 53710138..ca8a9b07 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -27,8 +27,8 @@ ; Constants MAX_SEGS = 96 -DEBUG = 1 -SANITY_CHECK = 1 ; also prints out request data +DEBUG = 0 +SANITY_CHECK = 0 ; also prints out request data ; Zero page temporary variables tmp = $2 ; len 2 @@ -37,10 +37,10 @@ reqLen = $6 ; len 2 resType = $8 ; len 1 resNum = $9 ; len 1 isAuxCmd = $A ; len 1 -isCompressed = $B ; len 1 +unused____0B = $B ; len 1 pSrc = $C ; len 2 pDst = $E ; len 2 -ucLen = $10 ; len 2 +pEnd = $10 ; len 2 ; Mapping of ProRWTS register names to mem mgr registers: ; "status" -> tmp+1 @@ -97,9 +97,9 @@ relocate: cpx #$40 ; skip our own unrelocated code $4000.4FFF bne + ldx #$60 -+ cpx #$C0 ; skip IO space $C000.CFFF ++ cpx #$C0 ; skip IO space $C000.CFFF, our future home $D000.DEFF, and decomp $DF00.DFFF bne + - ldx #$D0 + ldx #$E0 + cpx #$F6 ; skip ProRWTS $F600.FEFF, and ROM vecs $FF00.FFFF bne .clr1 @@ -207,11 +207,11 @@ init: !zone ; 0: main $0000 -> 4, active + locked ; 1: aux $0000 -> 2, active + locked ; 2: aux $0200 -> 3, inactive -; 3: aux $C000 -> 0, active + locked +; 3: aux $BFFD -> 0, active + locked ; 4: main $0xxx -> 5, inactive (xxx = end of mem mgr low mem portion) ; 5: main $4000 -> 6, active + locked ; 6: main $6000 -> 7, inactive -; 7: main $BF00 -> 8, active + locked +; 7: main $BFFD -> 8, active + locked ; 8: main $E000 -> 9, inactive ; 9: main $FFFA -> 0, active + locked ; First, the flags @@ -242,10 +242,9 @@ init: !zone ; Then the addresses lda #2 sta tSegAdrHi+2 - ldy #$C0 - sty tSegAdrHi+3 - dey - sty tSegAdrHi+7 + lda #$BF + sta tSegAdrHi+3 + sta tSegAdrHi+7 lda #lastLoMem @@ -258,6 +257,9 @@ init: !zone sta tSegAdrHi+8 lda #$FA sta tSegAdrLo+9 + lda #$FD + sta tSegAdrLo+3 + sta tSegAdrLo+7 lda #$FF sta tSegAdrHi+9 ; Finally, form a long list of the remaining unused segments. @@ -2072,8 +2074,8 @@ disk_queueLoad: !zone lda (pTmp),y ; and hi byte + stx reqLen ; save the uncompressed length sta reqLen+1 ; both bytes - !if DEBUG { +prStr : !text "uclen=",0 : +prWord reqLen : +crout } -; Load the bytecode of the main (first) bytecode module at the highest possible point + !if DEBUG { +prStr : !text "ucLen=",0 : +prWord reqLen : +crout } +; Load the bytecode of the gamelib (first) bytecode module at the highest possible point ; (to reduce fragmentation of the rest of aux mem) lda resType cmp #RES_TYPE_BYTECODE @@ -2081,11 +2083,12 @@ disk_queueLoad: !zone lda resNum cmp #1 bne + - lda #0 + ; Take $BFFD - size. Why $BFFD and not $C000? Because decomp temporarily overwrites 3-byte "unnderlap" after. + lda #$FD sec sbc reqLen sta targetAddr - lda #$C0 + lda #$BF sbc reqLen+1 sta targetAddr+1 + jsr shared_alloc ; reserve memory for this resource (main or aux as appropriate) @@ -2210,30 +2213,29 @@ disk_finishLoad: !zone ldy .ysave lda (pTmp),y ; grab resource length on disk sta reqLen ; save for reading - sta ucLen + sta pEnd iny lda (pTmp),y ; hi byte too - sta isCompressed ; save flag + php ; save hi bit (isCompressed) for later check and #$7F ; mask off the flag to get the real (on-disk) length sta reqLen+1 - bit isCompressed ; retrieve flag - bpl + ; if uncompressed, we also have the ucLen now - iny ; is compressed + iny ; if compressed, we also have the uncomp len avail next lda (pTmp),y ; fetch uncomp length - sta ucLen ; and save it + sta pEnd ; and save it iny lda (pTmp),y ; hi byte of uncomp len -+ sta ucLen+1 ; save uncomp len hi byte + sta pEnd+1 ; save uncomp len hi byte jsr scanForResource ; find the segment number allocated to this resource beq .addrErr ; it better have been allocated 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 + ldy tSegAdrHi,x ; hi byte too + sta pDst ; and save it for later + sty pDst+1 !if DEBUG { jsr .debug2 } - lda #cmdread + plp ; retrieve isCompressed flag + bmi .readAndDecomp ; if so, go do read/decompress thing + lda #cmdread ; else, just read. jsr readAndAdj - ;jsr lz4Decompress ; decompress (or copy if uncompressed) .resume ldy .ysave .next lda (pTmp),y ; lo byte of length clc @@ -2255,6 +2257,60 @@ disk_finishLoad: !zone + jmp .scan ; back for more .addrErr: jmp invalParam +.readAndDecomp: + ; Calculate end of uncompressed data, and start of compressed data. + ; We overlap the compressed and uncompressed as much as possible, e.g.: + ; DDDDDDDDDDDDDD + ; SSSSSSSSSsss ; sss is the 3-byte 'underlap' + sta pSrc + sty pSrc+1 + clc + adc pEnd + sta pEnd ; reuse pEnd for end ptr + tax + tya + adc pEnd+1 + sta pEnd+1 + tay + txa + adc #3 ; this is the max "underlap" required for decompressing overlapped buffers + bcc + + iny ++ sec + sbc reqLen ; then back up by the compressed size + sta pDst ; and load the compressed data there + tya + sbc reqLen+1 + sta pDst+1 + ; save the 3 byte underlap bytes because we're going to read over them + ldy #2 + ldx isAuxCmd + sta clrAuxRd,x ; from aux mem if appropriate +- lda (pEnd),y + pha + dey + bpl - + sta clrAuxRd + ; Now read the raw (compressed) data + lda #cmdread + jsr readAndAdj + !if DEBUG { jsr .debug3 } + ; Stuff was read to into pDst. Now that becomes the source. Decompressor is set up + ; to decompress *from* our pDst to our pSrc. Its labels are swapped. + ldx isAuxCmd + sta clrAuxRd,x ; switch to r/w aux mem if appropriate + sta clrAuxWr,x + jsr lx47Decomp ; remaining work is for the dedicated decompressor + ; restore the underlap bytes + ldy #0 +- pla + sta (pEnd),y + iny + cpy #3 + bne - + sta clrAuxRd + sta clrAuxWr + jmp .resume ; always taken .ysave: !byte 0 .nFixups: !byte 0 @@ -2281,6 +2337,15 @@ disk_finishLoad: !zone +prWord pDst +crout rts +.debug3:+prStr : !text "decomp ",0 + +prStr : !text "src=",0 + +prWord pDst + +prStr : !text "dst=",0 + +prWord pSrc + +prStr : !text "end=",0 + +prWord pEnd + +crout + rts } ; end DEBUG ;------------------------------------------------------------------------------ @@ -2821,8 +2886,13 @@ tSegAdrHi !fill MAX_SEGS tableEnd = * ; Be careful not to grow past the size of the LC bank -!if tableEnd > $DFFF { - !error "Memory manager grew too large." +!ifdef PASS2 { + !warn "mmgr spare: ", lx47Decomp - tableEnd + !if tableEnd >= lx47Decomp { + !error "Memory manager grew too large." + } +} else { ;PASS2 + !set PASS2=1 } } ; end of !pseudopc $D000 diff --git a/Platform/Apple/virtual/src/include/mem.i b/Platform/Apple/virtual/src/include/mem.i index b5df2553..369b95ff 100644 --- a/Platform/Apple/virtual/src/include/mem.i +++ b/Platform/Apple/virtual/src/include/mem.i @@ -71,7 +71,7 @@ ; 0000.01FF 6502 zero page and stack ; 0200.2xxx expander (if 3D map is running) ; 3000.9xxx (free) -; Axxx.BFFF gameloop PLASMA code +; Axxx.BFFF gameloop PLASMA code (loaded as high as possible) ; C000.CFFF I/O ; D000.DFFF bank 1: ProRWTS runtime (Note: D900.DFFF free) ; bank 2: part of expander