1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-01-09 13:33:26 +00:00

LZ4 unpack library and sample lz4cat

This commit is contained in:
David Schmenk 2018-04-19 13:41:14 -07:00
parent 6cf47da936
commit 912a4526fe
6 changed files with 215 additions and 167 deletions

3
src/inc/lz4.plh Normal file
View File

@ -0,0 +1,3 @@
import lz4
predef lz4Unpack(seq, seqend, buff, buffend)
end

91
src/libsrc/lz4.pla Normal file
View File

@ -0,0 +1,91 @@
include "inc/cmdsys.plh"
asm incs
!SOURCE "vmsrc/plvmzp.inc"
end
//
// Always forward copy memory - important for overlapping match sequences
//
asm bcpy(dst, src, len)#0
INX
INX
INX
LDA ESTKL-3,X
ORA ESTKH-3,X
BEQ CPYEX
LDA ESTKL-1,X
STA DSTL
LDA ESTKH-1,X
STA DSTH
LDA ESTKL-2,X
STA SRCL
LDA ESTKH-2,X
STA SRCH
LDY ESTKL-3,X
BEQ CPYLP
INC ESTKH-3,X
LDY #$00
CPYLP LDA (SRC),Y
STA (DST),Y
INY
BNE +
INC DSTH
INC SRCH
+ DEC ESTKL-3,X
BNE CPYLP
DEC ESTKH-3,X
BNE CPYLP
CPYEX RTS
end
//
// Unpack LZ4 sequence into buffer, return unpacked length
//
export def lz4Unpack(seq, seqend, buff, buffend)
word data, len, match, i
byte token
data = buff
while isult(seq, seqend)
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
if isuge(data + len, buffend); return 0; fin
bcpy(data, seq, len)
data = data + len
seq = seq + len
fin
len = token & $0F
if len or isult(seq, seqend)
//
// Match sequence
//
match = data - *seq
seq = seq + 2
len = len + 4
if len == 19 // $0F + 4
while ^seq == 255
len = len + 255
seq++
loop
len = len + ^seq
seq++
fin
if isuge(data + len, buffend); return 0; fin
bcpy(data, match, len)
data = data + len
fin
loop
return data - buff
end
done

View File

@ -36,7 +36,8 @@ SNDSEQ = rel/apple/SNDSEQ\#FE1000
PLAYSEQ = rel/apple/PLAYSEQ\#FE1000
SANITY = rel/SANITY\#FE1000
RPNCALC = rel/RPNCALC\#FE1000
LZ4DECOMP = rel/LZ4DECOMP\#FE1000
LZ4 = rel/LZ4\#FE1000
LZ4CAT = rel/LZ4CAT\#FE1000
UTHERNET2 = rel/apple/UTHERNET2\#FE1000
UTHERNET = rel/apple/UTHERNET\#FE1000
ETHERIP = rel/ETHERIP\#FE1000
@ -82,7 +83,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) $(LZ4DECOMP) $(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) $(LZ4) $(LZ4CAT) $(RPNCALC) $(SNDSEQ) $(PLAYSEQ)
-rm vmsrc/plvmzp.inc
c64: $(PLVMZP_C64) $(PLASM) $(PLVM) $(PLVMC64)
@ -256,9 +257,13 @@ $(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
$(LZ4): libsrc/lz4.pla $(PLVM02) $(PLASM)
./$(PLASM) -AMOW < libsrc/lz4.pla > libsrc/lz4.a
acme --setpc 4094 -o $(LZ4) libsrc/lz4.a
$(LZ4CAT): samplesrc/lz4cat.pla inc/lz4.plh $(PLVM02) $(PLASM)
./$(PLASM) -AMOW < samplesrc/lz4cat.pla > samplesrc/lz4cat.a
acme --setpc 4094 -o $(LZ4CAT) samplesrc/lz4cat.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

View File

@ -33,6 +33,7 @@ cp rel/FPU#FE1000 prodos/sys/FPU.REL
cp rel/SANE#FE1000 prodos/sys/SANE.REL
cp ../sysfiles/FP6502.CODE#060000 prodos/sys/FP6502.CODE.BIN
cp ../sysfiles/ELEMS.CODE#060000 prodos/sys/ELEMS.CODE.BIN
cp rel/LZ4#FE1000 prodos/sys/LZ4.REL
rm -rf prodos/sos
mkdir prodos/sos
@ -47,7 +48,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/LZ4CAT#FE1000 prodos/demos/LZ4CAT.REL
cp rel/ROD#FE1000 prodos/demos/ROD.REL
mkdir prodos/demos/rogue
@ -99,6 +100,7 @@ cp samplesrc/rogue.pla prodos/bld/ROGUE.PLA.TXT
cp samplesrc/rogue.map.pla prodos/bld/ROGUE.MAP.PLA.TXT
cp samplesrc/rogue.combat.pla prodos/bld/ROGUE.COMBAT.PLA.TXT
cp samplesrc/gfxdemo.pla prodos/bld/GFXDEMO.PLA.TXT
cp samplesrc/lz4cat.pla prodos/bld/LZ4CAT.PLA.TXT
mkdir prodos/bld/inc
cp inc/args.plh prodos/bld/inc/ARGS.PLH.TXT
@ -120,4 +122,5 @@ cp inc/sndseq.plh prodos/bld/inc/SNDSEQ.PLH.TXT
cp inc/spiport.plh prodos/bld/inc/SPIPORT.PLH.TXT
cp inc/testlib.plh prodos/bld/inc/TESTLIB.PLH.TXT
cp inc/grafix.plh prodos/bld/inc/GRAFIX.PLH.TXT
cp inc/lz4.plh prodos/bld/inc/LZ4.PLH.TXT
cp vmsrc/apple/plvmzp.inc prodos/bld/inc/PLVMZP.INC.TXT

View File

@ -1,161 +0,0 @@
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

107
src/samplesrc/lz4cat.pla Normal file
View File

@ -0,0 +1,107 @@
include "inc/cmdsys.plh"
include "inc/args.plh"
include "inc/fileio.plh"
include "inc/lz4.plh"
struc t_header
word magic[2]
byte FLG
byte BD
end
word arg
byte ref
def lz4ReadBlock(flags)#2
word size[2], block, data, len
len = fileio:read(ref, @size, 4)
if len <> 4 or size[0] == 0 or size[1] & $7FFF
return NULL, 0
fin
block = heapalloc(size[0])
if block
len = fileio:read(ref, block, size[0])
if len <> size[0]
heaprelease(block)
return NULL, 0
fin
else
return NULL, 0
fin
if size[1] & $8000
//
// Uncompressed block
//
data = block
else
//
// Decompress block
//
len = heapavail - 256 // Allocate almost entire heap to decompress into
data = heapalloc(len)
if data
len = lz4Unpack(block, block + size[0], data, data + len)
memcpy(block, data, len)
data = block
else
len = 0
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)
if len
while len
putc(^data <> $0A ?? ^data :: $0D)
data++
len--
loop
heaprelease(data)
fin
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