From 6cf47da936371c28ee0a231a2c8444b85394968d Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 19 Apr 2018 06:59:39 -0700 Subject: [PATCH] LZ4 decompressor --- src/makefile | 7 +- src/mkrel | 1 + src/samplesrc/lz4.pla | 161 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/samplesrc/lz4.pla diff --git a/src/makefile b/src/makefile index af1fb6f..985ce19 100755 --- a/src/makefile +++ b/src/makefile @@ -36,6 +36,7 @@ SNDSEQ = rel/apple/SNDSEQ\#FE1000 PLAYSEQ = rel/apple/PLAYSEQ\#FE1000 SANITY = rel/SANITY\#FE1000 RPNCALC = rel/RPNCALC\#FE1000 +LZ4DECOMP = rel/LZ4DECOMP\#FE1000 UTHERNET2 = rel/apple/UTHERNET2\#FE1000 UTHERNET = rel/apple/UTHERNET\#FE1000 ETHERIP = rel/ETHERIP\#FE1000 @@ -81,7 +82,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(DGR) $(DGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) +apple: $(PLVMZP_APL) $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVMJIT) $(PLVM802) $(PLVM03) $(CMD) $(CMDJIT) $(JIT) $(JIT16) $(JITUNE) $(SOSCMD) $(PLASMAPLASM) $(CODEOPT) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(FIBERTEST) $(LONGJMP) $(ED) $(MON) $(SOS) $(ROD) $(SIEVE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(GRAFIX) $(GFXDEMO) $(DGR) $(DGRTEST) $(FILEIO_APL) $(CONIO_APL) $(JOYBUZZ) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) $(FATPUT) $(FATWDSK) $(FATRDSK) $(SANE) $(FPSTR) $(FPU) $(SANITY) $(LZ4DECOMP) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ) -rm vmsrc/plvmzp.inc c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64) @@ -255,6 +256,10 @@ $(SANITY): samplesrc/sanity.pla $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/sanity.pla > samplesrc/sanity.a acme --setpc 4094 -o $(SANITY) samplesrc/sanity.a +$(LZ4DECOMP): samplesrc/lz4.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AMOW < samplesrc/lz4.pla > samplesrc/lz4.a + acme --setpc 4094 -o $(LZ4DECOMP) samplesrc/lz4.a + $(RPNCALC): samplesrc/rpncalc.pla libsrc/fpu.pla inc/fpu.plh libsrc/fpstr.pla inc/fpstr.plh inc/conio.plh $(PLVM02) $(PLASM) ./$(PLASM) -AMOW < samplesrc/rpncalc.pla > samplesrc/rpncalc.a acme --setpc 4094 -o $(RPNCALC) samplesrc/rpncalc.a diff --git a/src/mkrel b/src/mkrel index 1155e03..8702feb 100755 --- a/src/mkrel +++ b/src/mkrel @@ -47,6 +47,7 @@ rm -rf prodos/demos mkdir prodos/demos cp rel/apple/DGRTEST#FE1000 prodos/demos/DGRTEST.REL cp rel/RPNCALC#FE1000 prodos/demos/RPNCALC.REL +cp rel/LZ4DECOMP#FE1000 prodos/demos/LZ4DECOMP.REL cp rel/ROD#FE1000 prodos/demos/ROD.REL mkdir prodos/demos/rogue diff --git a/src/samplesrc/lz4.pla b/src/samplesrc/lz4.pla new file mode 100644 index 0000000..aebc459 --- /dev/null +++ b/src/samplesrc/lz4.pla @@ -0,0 +1,161 @@ +include "inc/cmdsys.plh" +include "inc/args.plh" +include "inc/fileio.plh" + +struc t_header + word magic[2] + byte FLG + byte BD +end +word arg +byte ref + +def dump(addr, len)#0 + while len + putc(^addr == $0A ?? $0D :: ^addr) + addr++ + len-- + loop +end +def lz4Decomp(seq, seqend)#2 + word buff, data, len, offset, fill + byte token + + buff = heapalloc(heapavail - 256) + data = buff + if not buff + return NULL, 0 + fin + while seq < seqend + //puts("LZ4 sequence @ $"); puth(seq); putln + token = ^seq + seq++ + len = token >> 4 + if len + // + // Literal sequence + // + if len == 15 + while ^seq == 255 + len = len + 255 + seq++ + loop + len = len + ^seq + seq++ + fin + //puts("Literals @ $"); puth(seq); puts(", len $"); puth(len); putln; getc + dump(seq, len) + memcpy(data, seq, len) + data = data + len + seq = seq + len + fin + // + // Match sequence + // + offset = *seq + seq = seq + 2 + len = (token & $0F) + 4 + if len == 19 // $0F + 4 + while ^seq == 255 + len = len + 255 + seq++ + loop + len = len + ^seq + seq++ + fin + //puts("Match offset $"); puth(offset); puts(" @ $"); puth(data - offset); puts(", len $"); puth(len); putln; getc + while len > offset + memcpy(data, data - offset, offset) + dump(data, offset) + data = data + offset + len = len - offset + loop + memcpy(data, data - offset, len) + dump(data, len) + data = data + len + loop + return buff, data - buff +end + +def lz4ReadBlock(flags)#2 + word size[2], block, data, len + + fileio:read(ref, @size, 4) + if size[1] & $7FFF + return NULL, 0 + fin + block = heapalloc(size[0]) + if block + fileio:read(ref, block, size[0]) + else + return NULL, 0 + fin + if size[1] & $8000 + // + // Uncompressed block + // + data = block + //puts("Uncompressed data @ $"); puth(data); putln + else + // + // Decompress block + // + //puts("Compressed block @ $"); puth(block); putln + data, len = lz4Decomp(block, block + size[0]) + //puts("Uncompressed data @ $"); puth(data); putln + if data + memcpy(block, data, len) + data = block + fin + heaprelease(block + len) + fin + if flags & $10 // Block Checksum + fileio:read(ref, @size, 4) + fin + return data, len +end + +def lz4ReadFrame#0 + word data, len + byte header[t_header], opt + + fileio:read(ref, @header, t_header) + if header:magic[1] <> $184D or header:magic[0] <> $2204 + puts("Not LZ4 file.\n") + return + fin + if header.FLG & $C0 <> $40 + puts("Wrong LZ4 version.\n") + return + fin + if header.BD & $70 <> $40 + puts("Not 64K block size.\n") + return + fin + opt = 1 + if header.FLG & $08 // Content Size + opt = opt + 8 + fin + if header.FLG & $01 // Dictionary ID + opt = opt + 4 + fin + fileio:read(ref, heapmark, opt) // Read rest of header and throw away + repeat + data, len = lz4ReadBlock(header.FLG) + until not data + if header.FLG & $04 // Content Checksun + fileio:read(ref, heapmark, 4) + fin +end +arg = argNext(argFirst) +if ^arg + ref = fileio:open(arg) + if ref + lz4ReadFrame + fileio:close(ref) + else + puts("File not found.\n") + fin +fin + +done