M .hgsubstate +1 -1
@@ 1,1 1,1 @@
-d30b04366fbd338ea986834315653980be450151 lib/neonlib
+8a43f418c682b8f87d70d518ce5484905361dad0 lib/neonlib
M src/Adler32Checker.asm +17 -55
@@ 2,15 2,6 @@
; Adler32 summer
;
Adler32Checker: MACRO
- this:
- Process:
- push ix
- ld ix,this
- Process_this: equ $ - 2
- call Adler32Checker_UpdateAdler32
- pop ix
- jp 0
- Process_oldHook: equ $ - 2
adler32:
dd 1
_size:
@@ 18,23 9,10 @@ Adler32Checker: MACRO
IF ZLIB_ADLER32
-; de = writer
; ix = this
; ix <- this
; Modifies: a
Adler32Checker_Construct:
- ld iyl,e
- ld iyh,d
- ld e,(iy + Writer.flusher)
- ld d,(iy + Writer.flusher + 1)
- ld (ix + Adler32Checker.Process_oldHook),e
- ld (ix + Adler32Checker.Process_oldHook + 1),d
- ld e,ixl
- ld d,ixh
- ld (iy + Writer.flusher),e
- ld (iy + Writer.flusher + 1),d
- ld (ix + Adler32Checker.Process_this),e
- ld (ix + Adler32Checker.Process_this + 1),d
xor a
ld (ix + Adler32Checker.adler32),1
ld (ix + Adler32Checker.adler32 + 1),a
@@ 42,37 20,26 @@ Adler32Checker_Construct:
ld (ix + Adler32Checker.adler32 + 3),a
ret
-; bc = byte count
-; de = buffer start
+; de = read address
+; hl = byte count
; ix = this
-; Modifies: none
Adler32Checker_UpdateAdler32:
- push af
- push bc
- push de
- push hl
- ex de,hl
+ ld a,l
+ or h
+ ret z
exx
- push bc
- push de
- push hl
ld e,(ix + Adler32Checker.adler32)
ld d,(ix + Adler32Checker.adler32 + 1)
ld c,(ix + Adler32Checker.adler32 + 2)
ld b,(ix + Adler32Checker.adler32 + 3)
+ exx
call Adler32Checker_CalculateAdler32
+ exx
ld (ix + Adler32Checker.adler32),e
ld (ix + Adler32Checker.adler32 + 1),d
ld (ix + Adler32Checker.adler32 + 2),c
ld (ix + Adler32Checker.adler32 + 3),b
- pop hl
- pop de
- pop bc
exx
- pop hl
- pop de
- pop bc
- pop af
ret
; bcde = expected adler32
@@ 92,22 59,18 @@ Adler32Checker_VerifyAdler32:
sub (ix + Adler32Checker.adler32 + 3)
ret
-; bc' = byte count
-; hl' = read address
-; bcde = current adler
+; de = read address
+; hl = byte count
+; bcde' = current adler32
; ix = this
-; bcde <- updated adler
-; Modifies: af, bc, de, hl, bc', hl'
+; bcde' <- updated adler32
Adler32Checker_CalculateAdler32: PROC
- exx
- ld a,c ; convert 16-bit counter bc to two 8-bit counters in b and c
- dec bc
- inc b
- ld c,b
- ld b,a
+ ld b,l ; convert 16-bit counter bc to two 8-bit counters in b and c
+ dec hl
+ inc h
Loop:
- ld a,(hl)
- inc hl
+ ld a,(de)
+ inc de
exx
ld l,a
ld h,0
@@ 119,9 82,8 @@ Loop:
ld b,h
exx
djnz Loop
- dec c
+ dec h
jp nz,Loop
- exx
ret
ENDP
M src/Application.asm +49 -77
@@ 2,6 2,8 @@
; Top-level application program class
;
Application: MACRO
+ outputFileHandle:
+ db 0FFH
outputSize:
dd 0
archiveFIB:
@@ 12,10 14,6 @@ Application: MACRO
CLI
fileReader:
FileReader
- fileWriter:
- FileWriter
- nullWriter:
- NullWriter
gzipArchive:
GzipArchive
_size:
@@ 25,7 23,6 @@ Application: MACRO
Application_Main:
call Application_CheckStack
- call WriterTest_Test
call CRC32CheckerTest_Test
call AlphabetTest_Test
@@ 74,26 71,6 @@ Application_GetFileReader:
ret
; ix = this
-; ix <- file writer
-; Modifies: f
-Application_GetFileWriter:
- push de
- ld de,Application.fileWriter
- add ix,de
- pop de
- ret
-
-; ix = this
-; ix <- null writer
-; Modifies: f
-Application_GetNullWriter:
- push de
- ld de,Application.nullWriter
- add ix,de
- pop de
- ret
-
-; ix = this
; ix <- gzip archive
; Modifies: f
Application_GetGzipArchive:
@@ 131,56 108,75 @@ Application_Inflate:
jp Application_InflateToFile
; ix = this
-Application_InflateToFile:
+Application_InflateToFile: PROC
call Application_FindNextFile
ret c
call Application_PrintInflating
- push ix
call Application_CreateFileReader
push de
call Application_ReadOutputSize
call Application_IsFast
cpl
+ pop hl
push ix
call Application_GetGzipArchive
+ ld bc,Application_decoders
+ ld de,WRITEBUFFER
call GzipArchive_Construct
- ex (sp),ix
+ pop ix
call Application_FindNewOutput
call Application_CreateFileWriter
call Application_PreAllocateOutput
+InflateLoop:
+ push ix
+ call Application_GetGzipArchive
+ call GzipArchive_Inflate
pop ix
- push de
- ld bc,Application_decoders
- call GzipArchive_Extract
- pop ix
- call FileWriter_Destruct
- pop ix
+ push af
+ push hl
+ call DOS_ConsoleStatus ; allow ctrl-c
+ pop hl
+ ld b,(ix + Application.outputFileHandle)
+ call DOS_WriteToFileHandle
+ call DOS_TerminateIfError
+ call DOS_ConsoleStatus ; allow ctrl-c
+ pop af
+ jr nz,InflateLoop
+ push ix
+ call Application_GetFileReader
call FileReader_Destruct
pop ix
+ ld b,(ix + Application.outputFileHandle)
+ call DOS_CloseFileHandle
+ call DOS_TerminateIfError
jr Application_InflateToFile
+ ENDP
; ix = this
-Application_InflateTest:
+Application_InflateTest: PROC
call Application_FindNextFile
ret c
call Application_PrintTesting
- push ix
call Application_CreateFileReader
push de
call Application_IsFast
cpl
+ pop hl
push ix
call Application_GetGzipArchive
+ ld bc,Application_decoders
+ ld de,WRITEBUFFER
call GzipArchive_Construct
- ex (sp),ix
- call Application_CreateNullWriter
+InflateLoop:
+ call GzipArchive_Inflate
+ jr nz,InflateLoop
pop ix
- ld bc,Application_decoders
- call GzipArchive_Extract
- pop ix
+ push ix
+ call Application_GetFileReader
call FileReader_Destruct
pop ix
jr Application_InflateTest
+ ENDP
; ix = this
Application_PrintWelcome:
@@ 333,36 329,19 @@ Application_CreateFileWriter:
ld hl,Application.outputFIB
add hl,de
ex de,hl
- ld hl,WRITEBUFFER
- ld bc,WRITEBUFFER_SIZE
- push ix
- call Application_GetFileWriter
- call FileWriter_Construct
- ld e,ixl
- ld d,ixh
- pop ix
- ret
-
-; ix = this
-; de <- null writer
-Application_CreateNullWriter:
- ld hl,WRITEBUFFER
- ld bc,WRITEBUFFER_SIZE
- push ix
- call Application_GetNullWriter
- call NullWriter_Construct
- ld e,ixl
- ld d,ixh
- pop ix
+ ld a,00000010B ; write only
+ ld b,0
+ call DOS_OpenFileHandle
+ call DOS_TerminateIfError
+ ld (ix + Application.outputFileHandle),b
ret
; de = file reader
; ix = this
-; Modifies: af, bc, hl, iy
+; Modifies: af, bc, de, hl, iy
Application_ReadOutputSize:
ld iyl,e
ld iyh,d
- push de
ld b,(iy + FileReader.fileHandle)
call DOS_GetFileHandlePointer
call DOS_TerminateIfError
@@ 387,21 366,15 @@ Application_ReadOutputSize:
pop de
ld b,(iy + FileReader.fileHandle)
call DOS_SetFileHandlePointer
- call DOS_TerminateIfError
- pop de
- ret
+ jp DOS_TerminateIfError
-; de = file writer
; ix = this
-; Modifies: af, bc, hl, iy
+; Modifies: af, bc, de, hl
Application_PreAllocateOutput:
- ld iyl,e
- ld iyh,d
ld a,(ix + Application.outputSize + 2)
or (ix + Application.outputSize + 3)
ret z ; don’t pre-allocate if < 64K
- push de
- ld b,(iy + FileWriter.fileHandle)
+ ld b,(ix + Application.outputFileHandle)
call DOS_GetFileHandlePointer
call DOS_TerminateIfError
push de
@@ 416,20 389,19 @@ Application_PreAllocateOutput:
ex de,hl
sbc hl,bc
ex de,hl
- ld b,(iy + FileWriter.fileHandle)
+ ld b,(ix + Application.outputFileHandle)
call DOS_SetFileHandlePointer
call DOS_TerminateIfError
ld de,0 ; don’t care which value we write
ld hl,1
- ld b,(iy + FileWriter.fileHandle)
+ ld b,(ix + Application.outputFileHandle)
call DOS_WriteToFileHandle
call DOS_TerminateIfError
pop hl
pop de
- ld b,(iy + FileWriter.fileHandle)
+ ld b,(ix + Application.outputFileHandle)
call DOS_SetFileHandlePointer
call DOS_TerminateIfError
- pop de
ret
; Check if the stack is well above the heap
M src/COM.asm +0 -4
@@ 39,11 39,7 @@ TPA_TOP:
INCLUDE "deflate/Branch.asm"
INCLUDE "deflate/HuffmanCodes.asm"
INCLUDE "Reader.asm"
- INCLUDE "Writer.asm"
- INCLUDE "WriterTest.asm"
INCLUDE "FileReader.asm"
- INCLUDE "FileWriter.asm"
- INCLUDE "NullWriter.asm"
INCLUDE "CRC32Checker.asm"
INCLUDE "CRC32CheckerTest.asm"
M src/CRC32Checker.asm +17 -55
@@ 2,15 2,6 @@
; CRC32 summer
;
CRC32Checker: MACRO
- this:
- Process:
- push ix
- ld ix,this
- Process_this: equ $ - 2
- call CRC32Checker_UpdateCRC32
- pop ix
- jp 0
- Process_oldHook: equ $ - 2
crc32:
dd 0FFFFFFFFH
_size:
@@ 18,22 9,9 @@ CRC32Checker: MACRO
IF GZIP_CRC32
-; de = writer
; ix = this
; ix <- this
CRC32Checker_Construct:
- ld iyl,e
- ld iyh,d
- ld e,(iy + Writer.flusher)
- ld d,(iy + Writer.flusher + 1)
- ld (ix + CRC32Checker.Process_oldHook),e
- ld (ix + CRC32Checker.Process_oldHook + 1),d
- ld e,ixl
- ld d,ixh
- ld (iy + Writer.flusher),e
- ld (iy + Writer.flusher + 1),d
- ld (ix + CRC32Checker.Process_this),e
- ld (ix + CRC32Checker.Process_this + 1),d
ld a,0FFH
ld (ix + CRC32Checker.crc32),a
ld (ix + CRC32Checker.crc32 + 1),a
@@ 41,37 19,26 @@ CRC32Checker_Construct:
ld (ix + CRC32Checker.crc32 + 3),a
ret
-; bc = byte count
-; de = buffer start
+; de = read address
+; hl = byte count
; ix = this
-; Modifies: none
CRC32Checker_UpdateCRC32:
- push af
- push bc
- push de
- push hl
- ex de,hl
+ ld a,l
+ or h
+ ret z
exx
- push bc
- push de
- push hl
ld e,(ix + CRC32Checker.crc32)
ld d,(ix + CRC32Checker.crc32 + 1)
ld c,(ix + CRC32Checker.crc32 + 2)
ld b,(ix + CRC32Checker.crc32 + 3)
+ exx
call CRC32Checker_CalculateCRC32
+ exx
ld (ix + CRC32Checker.crc32),e
ld (ix + CRC32Checker.crc32 + 1),d
ld (ix + CRC32Checker.crc32 + 2),c
ld (ix + CRC32Checker.crc32 + 3),b
- pop hl
- pop de
- pop bc
exx
- pop hl
- pop de
- pop bc
- pop af
ret
; bcde = expected crc32
@@ 93,22 60,18 @@ CRC32Checker_VerifyCRC32:
adc a,(ix + CRC32Checker.crc32 + 3)
ret
-; bc' = byte count
-; hl' = read address
-; bcde = current crc
+; de = read address
+; hl = byte count
+; bcde' = current crc32
; ix = this
-; bcde <- updated crc
-; Modifies: af, bc, de, hl, bc', hl'
+; bcde' <- updated crc32
CRC32Checker_CalculateCRC32: PROC
- exx
- ld a,c ; convert 16-bit counter bc to two 8-bit counters in b and c
- dec bc
- inc b
- ld c,b
- ld b,a
+ ld b,l ; convert 16-bit counter bc to two 8-bit counters in b and c
+ dec hl
+ inc h
Loop:
- ld a,(hl)
- inc hl
+ ld a,(de)
+ inc de
exx
xor e
ld l,a
@@ 128,9 91,8 @@ Loop:
ld b,(hl)
exx
djnz Loop
- dec c
+ dec h
jp nz,Loop
- exx
ret
ENDP
M src/CRC32CheckerTest.asm +12 -18
@@ 10,13 10,6 @@ CRC32CheckerTest_Test:
IF GZIP_CRC32
CRC32CheckerTest_TestCRC32: PROC
- ld hl,WRITEBUFFER
- ld bc,256
- ld ix,CRC32CheckerTest_nullWriter
- call NullWriter_Construct
- ld e,ixl
- ld d,ixh
-
ld ix,CRC32CheckerTest_crc32Checker
call CRC32Checker_Construct
@@ 27,12 20,14 @@ CRC32CheckerTest_TestCRC32: PROC
call nz,System_ThrowException
ld b,58
- ld ix,CRC32CheckerTest_nullWriter
+ ld hl,WRITEBUFFER
Loop1:
- ld a,b
- call Writer_Write
+ ld (hl),b
+ inc hl
djnz Loop1
- call Writer_FinishBlock
+ ld hl,58
+ ld de,WRITEBUFFER
+ call CRC32Checker_UpdateCRC32
ld de,07364H
ld bc,0DAA8H
ld ix,CRC32CheckerTest_crc32Checker
@@ 40,12 35,14 @@ Loop1:
call nz,System_ThrowException
ld b,200
- ld ix,CRC32CheckerTest_nullWriter
+ ld hl,WRITEBUFFER
Loop2:
- ld a,b
- call Writer_Write
+ ld (hl),b
+ inc hl
djnz Loop2
- call Writer_FinishBlock
+ ld hl,200
+ ld de,WRITEBUFFER
+ call CRC32Checker_UpdateCRC32
ld de,04E96H
ld bc,02DA9H
ld ix,CRC32CheckerTest_crc32Checker
@@ 58,7 55,4 @@ Loop2:
CRC32CheckerTest_crc32Checker:
CRC32Checker
-CRC32CheckerTest_nullWriter:
- NullWriter
-
ENDIF
M src/GzipArchive.asm +87 -53
@@ 2,6 2,7 @@
; Gzip archive
;
GzipArchive_STATE_CHECKSUM_BIT: equ 0
+GzipArchive_STATE_FOOTER_BIT: equ 1
GzipArchive_SIGNATURE_1: equ 1FH
GzipArchive_SIGNATURE_2: equ 8BH
GzipArchive_DEFLATE_ID: equ 8
@@ 17,6 18,8 @@ GzipArchive: MACRO
db 0
reader:
dw 0
+ count:
+ dd 0
flags:
db 0
mtime:
@@ 41,7 44,9 @@ GzipArchive: MACRO
ENDM
; a = -1: CRC32 check enabled, 0: disabled
-; de = reader
+; bc = decoders buffer
+; de = write buffer (32K, 256-byte aligned)
+; hl = reader
; ix = this
; ix <- this
GzipArchive_Construct:
@@ 51,8 56,27 @@ GzipArchive_Construct:
xor a
ENDIF
ld (ix + GzipArchive.state),a
- ld (ix + GzipArchive.reader),e
- ld (ix + GzipArchive.reader + 1),d
+ ld (ix + GzipArchive.reader),l
+ ld (ix + GzipArchive.reader + 1),h
+ xor a
+ ld (ix + GzipArchive.count),a
+ ld (ix + GzipArchive.count + 1),a
+ ld (ix + GzipArchive.count + 2),a
+ ld (ix + GzipArchive.count + 3),a
+ push ix
+ push de
+ ld de,GzipArchive.inflate
+ add ix,de
+ pop de
+ call Inflate_Construct
+ pop ix
+ IF GZIP_CRC32
+ push ix
+ ld bc,GzipArchive.crc32Checker
+ add ix,bc
+ call CRC32Checker_Construct
+ pop ix
+ ENDIF
jp GzipArchive_ReadHeader
; ix = this
@@ 66,16 90,6 @@ GzipArchive_GetReaderIY:
ret
; ix = this
-; ix <- Inflate implementation
-; Modifies: f
-GzipArchive_GetInflate:
- push de
- ld de,GzipArchive.inflate
- add ix,de
- pop de
- ret
-
-; ix = this
GzipArchive_ReadHeader: PROC
call GzipArchive_GetReaderIY
call Reader_Read_IY
@@ 147,59 161,84 @@ GzipArchive_ReadFooter:
ld (ix + GzipArchive.isize + 3),d
ret
-; bc = decoders buffer
-; de = writer (min 32K)
; ix = this
-GzipArchive_Extract:
- IF GZIP_CRC32
- push bc
- bit GzipArchive_STATE_CHECKSUM_BIT,(ix + GzipArchive.state)
- call nz,GzipArchive_CreateCRC32Checker
- pop bc
- ENDIF
- call GzipArchive_CreateInflate
- call GzipArchive_Inflate
+; a <- >0: more data, 0: final data
+; f <- nz: more data, z: final data
+; de <- buffer address
+; hl <- byte count
+GzipArchive_Inflate: PROC
+ push ix
+ ld de,GzipArchive.inflate
+ add ix,de
+ call Inflate_Inflate
+ pop ix
+ call GzipArchive_Update
+ ret nz
+ bit GzipArchive_STATE_FOOTER_BIT,(ix + GzipArchive.state)
+ call z,Footer
+ and a
+ ret
+Footer:
+ set GzipArchive_STATE_FOOTER_BIT,(ix + GzipArchive.state)
+ ex af,af'
+ exx
call GzipArchive_ReadFooter
call GzipArchive_Verify
+ exx
+ ex af,af'
+ ret
+ ENDP
+
+; de = buffer address
+; hl = byte count
+; ix = this
+GzipArchive_Update:
+ push af
+ call GzipArchive_UpdateCount
+ IF GZIP_CRC32
+ bit GzipArchive_STATE_CHECKSUM_BIT,(ix + GzipArchive.state)
+ call nz,GzipArchive_UpdateCRC32
+ ENDIF
+ pop af
ret
-; bc = decoders buffer
-; de = writer (min 32K)
+; de = buffer address
+; hl = byte count
; ix = this
-GzipArchive_CreateInflate:
- ld l,(ix + GzipArchive.reader)
- ld h,(ix + GzipArchive.reader + 1)
- push ix
- call GzipArchive_GetInflate
- call Inflate_Construct
- pop ix
+GzipArchive_UpdateCount:
+ push hl
+ ld c,(ix + GzipArchive.count)
+ ld b,(ix + GzipArchive.count + 1)
+ add hl,bc
+ ld (ix + GzipArchive.count),l
+ ld (ix + GzipArchive.count + 1),h
+ pop hl
+ ret nc
+ inc (ix + GzipArchive.count + 2)
+ ret nz
+ inc (ix + GzipArchive.count + 3)
ret
IF GZIP_CRC32
-; de = writer (min 32K)
+; hl = byte count
+; de = buffer address
; ix = this
-GzipArchive_CreateCRC32Checker:
+GzipArchive_UpdateCRC32:
push de
+ push hl
push ix
ld bc,GzipArchive.crc32Checker
add ix,bc
- call CRC32Checker_Construct
+ call CRC32Checker_UpdateCRC32
pop ix
+ pop hl
pop de
ret
ENDIF
; ix = this
-GzipArchive_Inflate:
- push ix
- call GzipArchive_GetInflate
- call Inflate_Inflate
- pop ix
- ret
-
-; ix = this
GzipArchive_Verify:
call GzipArchive_VerifyISIZE
ld hl,GzipArchive_isizeMismatchError
@@ 214,21 253,16 @@ GzipArchive_Verify:
; ix = this
; f <- nz: mismatch
GzipArchive_VerifyISIZE:
- push ix
- call GzipArchive_GetInflate
- call Inflate_GetWriter
- call Writer_GetCount
- pop ix
- ld a,e
+ ld a,(ix + GzipArchive.count)
cp (ix + GzipArchive.isize)
ret nz
- ld a,d
+ ld a,(ix + GzipArchive.count + 1)
cp (ix + GzipArchive.isize + 1)
ret nz
- ld a,c
+ ld a,(ix + GzipArchive.count + 2)
cp (ix + GzipArchive.isize + 2)
ret nz
- ld a,b
+ ld a,(ix + GzipArchive.count + 3)
cp (ix + GzipArchive.isize + 3)
ret
M src/ZlibArchive.asm +58 -44
@@ 2,6 2,7 @@
; Zlib archive
;
ZlibArchive_STATE_CHECKSUM_BIT: equ 0
+ZlibArchive_STATE_FOOTER_BIT: equ 1
ZlibArchive_DEFLATE_ID: equ 8
ZlibArchive_MAX_WINDOW: equ 7
@@ 30,7 31,9 @@ ZlibArchive: MACRO
ENDM
; a = -1: Adler32 check enabled, 0: disabled
-; de = reader
+; bc = decoders buffer
+; de = write buffer (32K, 256-byte aligned)
+; hl = reader
; ix = this
; ix <- this
ZlibArchive_Construct:
@@ 40,8 43,22 @@ ZlibArchive_Construct:
xor a
ENDIF
ld (ix + ZlibArchive.state),a
- ld (ix + ZlibArchive.reader),e
- ld (ix + ZlibArchive.reader + 1),d
+ ld (ix + ZlibArchive.reader),l
+ ld (ix + ZlibArchive.reader + 1),h
+ push ix
+ push de
+ ld de,ZlibArchive.inflate
+ add ix,de
+ pop de
+ call Inflate_Construct
+ pop ix
+ IF ZLIB_ADLER32
+ push ix
+ ld bc,ZlibArchive.adler32Checker
+ add ix,bc
+ call Adler32Checker_Construct
+ pop ix
+ ENDIF
jp ZlibArchive_ReadHeader
; ix = this
@@ 55,16 72,6 @@ ZlibArchive_GetReaderIY:
ret
; ix = this
-; ix <- Inflate implementation
-; Modifies: f
-ZlibArchive_GetInflate:
- push de
- ld de,ZlibArchive.inflate
- add ix,de
- pop de
- ret
-
-; ix = this
ZlibArchive_ReadHeader:
call ZlibArchive_GetReaderIY
call Reader_ReadWordBE_IY
@@ 130,59 137,66 @@ ZlibArchive_ReadFooter:
ENDIF
ret
-; bc = decoders buffer
-; de = writer (min 32K)
; ix = this
-ZlibArchive_Extract:
- IF ZLIB_ADLER32
- push bc
- bit ZlibArchive_STATE_CHECKSUM_BIT,(ix + ZlibArchive.state)
- call nz,ZlibArchive_CreateAdler32Checker
- pop bc
- ENDIF
- call ZlibArchive_CreateInflate
- call ZlibArchive_Inflate
+; a <- >0: more data, 0: final data
+; f <- nz: more data, z: final data
+; de <- buffer address
+; hl <- byte count
+ZlibArchive_Inflate: PROC
+ push ix
+ ld de,ZlibArchive.inflate
+ add ix,de
+ call Inflate_Inflate
+ pop ix
+ call ZlibArchive_Update
+ ret nz
+ bit ZlibArchive_STATE_FOOTER_BIT,(ix + ZlibArchive.state)
+ call z,Footer
+ and a
+ ret
+Footer:
+ set ZlibArchive_STATE_FOOTER_BIT,(ix + ZlibArchive.state)
+ ex af,af'
+ exx
call ZlibArchive_ReadFooter
call ZlibArchive_Verify
+ exx
+ ex af,af'
ret
+ ENDP
-; bc = decoders buffer
-; de = writer (min 32K)
+; de = buffer address
+; hl = byte count
; ix = this
-ZlibArchive_CreateInflate:
- ld l,(ix + ZlibArchive.reader)
- ld h,(ix + ZlibArchive.reader + 1)
- push ix
- call ZlibArchive_GetInflate
- call Inflate_Construct
- pop ix
+ZlibArchive_Update:
+ IF ZLIB_ADLER32
+ push af
+ bit ZlibArchive_STATE_CHECKSUM_BIT,(ix + ZlibArchive.state)
+ call nz,ZlibArchive_UpdateAdler32
+ pop af
+ ENDIF
ret
IF ZLIB_ADLER32
-; de = writer (min 32K)
+; de = buffer address
+; hl = byte count
; ix = this
-ZlibArchive_CreateAdler32Checker:
+ZlibArchive_UpdateAdler32:
push de
+ push hl
push ix
ld bc,ZlibArchive.adler32Checker
add ix,bc
- call Adler32Checker_Construct
+ call Adler32Checker_UpdateAdler32
pop ix
+ pop hl
pop de
ret
ENDIF
; ix = this
-ZlibArchive_Inflate:
- push ix
- call ZlibArchive_GetInflate
- call Inflate_Inflate
- pop ix
- ret
-
-; ix = this
ZlibArchive_Verify:
IF ZLIB_ADLER32
call ZlibArchive_VerifyAdler32
M src/deflate/Inflate.asm +268 -63
@@ 1,14 1,36 @@
;
; Inflate implementation
;
-Inflate_FINAL: equ 0
+Inflate_STATE_FINAL_BIT: equ 0
+Inflate_STATE_COPY_BIT: equ 1
+Inflate_STATE_COMPRESSED_BIT: equ 2
+Inflate_BUFFER_SIZE: equ 8000H
Inflate: MACRO
+ ; a = value
+ ; hl = literal/length decoder
+ ; ix = this
+ WriteLiteral:
+ ld (0),a
+ bufferPosition: equ $ - 2
+ inc (ix + Inflate.bufferPosition)
+ jr z,WriteLiteralCarry ; unlikely
+ jp hl
+ WriteLiteralCarry:
+ jp Inflate_WriteLiteralCarry
+ bufferStart:
+ db 0
+ bufferEnd:
+ db 0
+ bufferEndCopyMargin:
+ db 0
state:
db 0
- reader:
+ copyLength:
dw 0
- writer:
+ copySource:
+ dw 0
+ reader:
dw 0
decoders:
dw 0
@@ 18,21 40,25 @@ Inflate: MACRO
ENDM
; bc = decoders buffer
+; de = write buffer (32K, 256-byte aligned)
; hl = reader
-; de = writer (min 32K)
; ix = this
; ix <- this
Inflate_Construct:
- ld iyl,e ; check if write buffer is at least 32K
- ld iyh,d
- ld a,(iy + Writer.bufferSize + 1)
- cp 80H
- call c,System_ThrowException
+ ld a,e ; check if write buffer is 256-byte aligned
+ and a
+ call nz,System_ThrowException
+ ld (ix + Inflate.bufferStart),d
+ ld (ix + Inflate.bufferPosition),0
+ ld (ix + Inflate.bufferPosition + 1),d
+ ld a,d
+ add a,Inflate_BUFFER_SIZE >> 8
+ ld (ix + Inflate.bufferEnd),a
+ sub 3
+ ld (ix + Inflate.bufferEndCopyMargin),a
ld (ix + Inflate.state),0
ld (ix + Inflate.reader),l
ld (ix + Inflate.reader + 1),h
- ld (ix + Inflate.writer),e
- ld (ix + Inflate.writer + 1),d
ld (ix + Inflate.decoders),c
ld (ix + Inflate.decoders + 1),b
push ix
@@ 52,16 78,6 @@ Inflate_GetReaderIY:
ret
; ix = this
-; ix <- writer
-; Modifies: de
-Inflate_GetWriter:
- ld e,(ix + Inflate.writer)
- ld d,(ix + Inflate.writer + 1)
- ld ixl,e
- ld ixh,d
- ret
-
-; ix = this
; ix <- decoders buffer
; Modifies: de
Inflate_GetDecoders:
@@ 80,22 96,41 @@ Inflate_GetHuffmanCodes:
ret
; ix = this
+; a <- >0: more data, 0: final data
+; f <- nz: more data, z: final data
+; de <- buffer address
+; hl <- byte count
Inflate_Inflate:
call Inflate_GetReaderIY
- call Inflate_InflateLoop
- push ix
- call Inflate_GetWriter
- call Writer_FinishBlock
- pop ix
+ call Inflate_InflateResume
+ ld l,(ix + Inflate.bufferPosition)
+ ld h,(ix + Inflate.bufferPosition + 1)
+ ld e,0
+ ld d,(ix + Inflate.bufferStart)
+ ld (ix + Inflate.bufferPosition),e
+ ld (ix + Inflate.bufferPosition + 1),d
+ and a
+ sbc hl,de
+ ld a,(ix + Inflate.state)
+ xor 1 << Inflate_STATE_FINAL_BIT
ret
; ix = this
+Inflate_InflateResume:
+ bit Inflate_STATE_COMPRESSED_BIT,(ix + Inflate.state)
+ jp nz,Inflate_InflateCompressed
+ bit Inflate_STATE_COPY_BIT,(ix + Inflate.state)
+ jp nz,Inflate_InflateUncompressed.Resume
+ jp Inflate_InflateLoop
+
+; ix = this
Inflate_InflateLoop:
ld a,(ix + Inflate.state)
- and 1 << Inflate_FINAL
+ and 1 << Inflate_STATE_FINAL_BIT
+ ld (ix + Inflate.state),a
ret nz
call Reader_ReadBit_IY
- rla ; carry to Inflate_FINAL
+ rla ; carry to Inflate_STATE_FINAL_BIT
ld (ix + Inflate.state),a
ld b,2
call Reader_ReadBits_IY
@@ 108,7 143,8 @@ Inflate_InflateLoop:
; ix = this
; iy = reader
-Inflate_InflateUncompressed:
+Inflate_InflateUncompressed: PROC
+ set Inflate_STATE_COPY_BIT,(ix + Inflate.state)
call Reader_Align_IY
call Reader_ReadWord_IY
ld c,e
@@ 118,14 154,46 @@ Inflate_InflateUncompressed:
scf
adc hl,bc
jp nz,System_ThrowException ; invalid length
+ResumeLoop:
+ ld e,(ix + Inflate.bufferPosition)
+ ld d,(ix + Inflate.bufferPosition + 1)
+Loop:
ld a,c
or b
- ret z
- push ix
- call Inflate_GetWriter
- call Writer_CopyFromReader
- pop ix
- jp Inflate_InflateLoop
+ jp z,Inflate_InflateLoop
+ ld l,0
+ ld h,(ix + Inflate.bufferEnd)
+ sbc hl,de
+ jr c,Suspend
+ jr z,Suspend
+ push bc
+ sbc hl,bc
+ jr nc,NoSplit ; bc <= hl
+ add hl,bc
+ ld c,l
+ ld b,h
+NoSplit:
+ call Reader_ReadBlockDirect_IY
+ push bc
+ call System_FastLDIR
+ pop bc
+ pop hl
+ and a
+ sbc hl,bc
+ ld c,l
+ ld b,h
+ ld (ix + Inflate.bufferPosition),e
+ ld (ix + Inflate.bufferPosition + 1),d
+ jr Loop
+Suspend:
+ ld (ix + Inflate.copyLength),c
+ ld (ix + Inflate.copyLength + 1),b
+ ret
+Resume:
+ ld c,(ix + Inflate.copyLength)
+ ld b,(ix + Inflate.copyLength + 1)
+ jr ResumeLoop
+ ENDP
; ix = this
; iy = reader
@@ 152,54 220,67 @@ Inflate_InflateCompressed:
call Inflate_GetDecoders
call Decoders_GetDecoders
pop ix
- push ix
- ld c,(ix + Inflate.writer)
- ld b,(ix + Inflate.writer + 1)
- ld ixl,c
- ld ixh,b
call Reader_PrepareReadBitInline_IY
- call Inflate_DecodeLiteralLength
+ call Inflate_Decode
call Reader_FinishReadBitInline_IY
- pop ix
+ bit Inflate_STATE_COMPRESSED_BIT,(ix + Inflate.state)
+ ret nz
jp Inflate_InflateLoop
+Inflate_Decode: PROC
+ set Inflate_STATE_COMPRESSED_BIT,(ix + Inflate.state)
+ bit Inflate_STATE_COPY_BIT,(ix + Inflate.state)
+ jp nz,Inflate_CopySplitDestination.Resume
+ Inflate_DecodeLiteralLengthInline
+ ENDP
+
; c = inline bit reader state
; hl = literal/length decoder
; de = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_DecodeLiteralLengthInline: MACRO
jp hl
ENDM
-Inflate_DecodeLiteralLength:
- Inflate_DecodeLiteralLengthInline
-
; Literal/length alphabet symbols 0-255
; c = inline bit reader state
; hl = literal/length decoder
; de = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_WriteLiteral: REPT 256, ?value
ld a,?value
- Writer_WriteInline_JumpHL
+ jp ix
ENDM
+; c = inline bit reader state
+; hl = literal/length decoder
+; de = distance decoder
+; ix = this
+; iy = reader
+Inflate_WriteLiteralCarry:
+ inc (ix + Inflate.bufferPosition + 1)
+ ld a,(ix + Inflate.bufferPosition + 1)
+ cp (ix + Inflate.bufferEnd)
+ ret nc
+ jp hl
+
; Literal/length alphabet symbol 256
; c = inline bit reader state
; hl = literal/length decoder
; de = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_EndBlock:
+ res Inflate_STATE_COMPRESSED_BIT,(ix + Inflate.state)
ret
; Literal/length alphabet symbols 257-285
; c = inline bit reader state
; hl = literal/length decoder
; de = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_CopyLength.0:
exx
@@ 326,7 407,7 @@ Inflate_CopyLength.28:
; c' = inline bit reader state
; hl' = literal/length decoder
; de' = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_DecodeDistance_SetLength:
exx
@@ 338,7 419,7 @@ Inflate_DecodeDistance_SetLength:
; c' = inline bit reader state
; hl' = literal/length decoder
; de' = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_DecodeDistanceInline: MACRO
exx
@@ 351,7 432,7 @@ Inflate_DecodeDistanceInline: MACRO
; bc = length
; de = literal/length decoder
; hl = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_CopyDistance.0:
exx
@@ 511,13 592,13 @@ Inflate_CopyDistance.29:
; c' = inline bit reader state
; de' = literal/length decoder
; hl' = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_CopySmallDistance:
exx
ld l,a
ld h,-1
- Inflate_CopyInline
+ jp Inflate_Copy
; a = -distance MSB
; a' = ~-distance LSB
@@ 525,7 606,7 @@ Inflate_CopySmallDistance:
; c' = inline bit reader state
; de' = literal/length decoder
; hl' = distance decoder
-; ix = writer
+; ix = this
; iy = reader
Inflate_CopyLargeDistance:
exx
@@ 533,24 614,148 @@ Inflate_CopyLargeDistance:
ex af,af'
cpl
ld l,a
- Inflate_CopyInline
+ jp Inflate_Copy
; bc = length
; hl = -distance
; c' = inline bit reader state
; de' = literal/length decoder
; hl' = distance decoder
-; ix = writer
+; ix = this
; iy = reader
-Inflate_CopyInline: MACRO
- call Writer_Copy
+Inflate_Copy: PROC
+ ld e,(ix + Inflate.bufferPosition)
+ ld d,(ix + Inflate.bufferPosition + 1)
+ add hl,de
+ ld a,h
+ jr nc,WrapSource
+ cp (ix + Inflate.bufferStart)
+ jr c,WrapSource
+ ld a,(ix + Inflate.bufferEndCopyMargin)
+ cp d ; does the destination have a 512 byte margin without wrapping?
+ jr c,Inflate_CopySplitDestination
+Copy:
+ ldi
+ ldi
+ ldir
+Next:
+ ld (ix + Inflate.bufferPosition),e
+ ld (ix + Inflate.bufferPosition + 1),d
exx
ex de,hl
Inflate_DecodeLiteralLengthInline
- ENDM
+WrapSource:
+ add a,Inflate_BUFFER_SIZE >> 8
+ ld h,a
+ ld a,(ix + Inflate.bufferEndCopyMargin)
+ cp d ; does the destination have a 512 byte margin without wrapping?
+ jr c,Inflate_CopySplitDestination
+ cp h ; does the source have a 512 byte margin without wrapping?
+ jp nc,Copy
+ call Inflate_CopySplitSource
+ jp Next
+ ENDP
-Inflate_Copy:
- Inflate_CopyInline
+; bc = byte count
+; de = destination
+; hl = source
+; ix = this
+; bc <- 0
+; de <- updated destination
+; hl <- updated source
+; Modifies: af
+Inflate_CopySplitDestination: PROC
+ ex de,hl
+ add hl,bc
+ jr c,Split
+ ld a,h
+ cp (ix + Inflate.bufferEnd)
+ jr nc,Split
+ and a
+ sbc hl,bc
+ ex de,hl
+ call Inflate_CopySplitSource
+ jp Inflate_Copy.Next
+Split:
+ push hl
+ xor a
+ sbc hl,bc
+ sub l
+ ld c,a
+ ld a,(ix + Inflate.bufferEnd)
+ sbc a,h
+ ld b,a ; bc = buffer end - source start
+ ex de,hl
+ call Inflate_CopySplitSource
+ pop bc
+ ld a,b
+ sub (ix + Inflate.bufferEnd)
+ ld b,a ; bc = source end - buffer end
+ or c
+ jp z,SuspendLiteral
+Suspend:
+ set Inflate_STATE_COPY_BIT,(ix + Inflate.state)
+ ld (ix + Inflate.copyLength),c
+ ld (ix + Inflate.copyLength + 1),b
+ ld (ix + Inflate.copySource),l
+ ld (ix + Inflate.copySource + 1),h
+SuspendLiteral:
+ ld (ix + Inflate.bufferPosition),e
+ ld (ix + Inflate.bufferPosition + 1),d
+ exx
+ ex de,hl
+ ret
+Resume:
+ res Inflate_STATE_COPY_BIT,(ix + Inflate.state)
+ ex de,hl
+ exx
+ ld c,(ix + Inflate.copyLength)
+ ld b,(ix + Inflate.copyLength + 1)
+ ld e,(ix + Inflate.bufferPosition)
+ ld d,(ix + Inflate.bufferPosition + 1)
+ ld l,(ix + Inflate.copySource)
+ ld h,(ix + Inflate.copySource + 1)
+ jp Inflate_CopySplitDestination
+ ENDP
+
+; bc = byte count
+; de = destination
+; hl = source
+; ix = this
+; bc <- 0
+; de <- updated destination
+; hl <- updated source
+; Modifies: af
+Inflate_CopySplitSource: PROC
+ add hl,bc
+ jr c,Split
+ ld a,h
+ cp (ix + Inflate.bufferEnd)
+ jr nc,Split
+ and a
+ sbc hl,bc
+ ldir
+ ret
+Split:
+ push hl
+ xor a
+ sbc hl,bc
+ sub l
+ ld c,a
+ ld a,(ix + Inflate.bufferEnd)
+ sbc a,h
+ ld b,a ; bc = buffer end - source start
+ ldir
+ pop bc
+ ld h,(ix + Inflate.bufferStart)
+ ld a,b
+ sub (ix + Inflate.bufferEnd)
+ ld b,a ; bc = source end - buffer end
+ or c
+ ret z
+ ldir
+ ret
+ ENDP
;
Inflate_literalLengthSymbols: