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:
parent
6cf47da936
commit
912a4526fe
3
src/inc/lz4.plh
Normal file
3
src/inc/lz4.plh
Normal file
@ -0,0 +1,3 @@
|
||||
import lz4
|
||||
predef lz4Unpack(seq, seqend, buff, buffend)
|
||||
end
|
91
src/libsrc/lz4.pla
Normal file
91
src/libsrc/lz4.pla
Normal 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
|
15
src/makefile
15
src/makefile
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
107
src/samplesrc/lz4cat.pla
Normal 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
|
Loading…
x
Reference in New Issue
Block a user