mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
100 lines
3.1 KiB
Lua
100 lines
3.1 KiB
Lua
compression {
|
|
|
|
sub decode_rle(uword @zp compressed, uword @zp target, uword maxsize) -> uword {
|
|
cx16.r0 = target ; original target
|
|
cx16.r1 = target+maxsize ; decompression limit
|
|
|
|
while target<cx16.r1 {
|
|
cx16.r2L = @(compressed)
|
|
if_neg {
|
|
if cx16.r2L==128
|
|
break
|
|
; replicate the next byte -n+1 times
|
|
compressed++
|
|
cx16.r3L = @(compressed)
|
|
repeat 2+(cx16.r2L^255) {
|
|
@(target) = cx16.r3L
|
|
target++
|
|
}
|
|
compressed++
|
|
} else {
|
|
; copy the next n+1 bytes
|
|
compressed++
|
|
repeat cx16.r2L+1 {
|
|
@(target) = @(compressed)
|
|
compressed++
|
|
target++
|
|
}
|
|
}
|
|
}
|
|
return target-cx16.r0
|
|
}
|
|
|
|
sub encode_rle(uword data, uword size, uword target, bool is_last_block) -> uword {
|
|
; -- Compress the given data block using ByteRun1 aka PackBits RLE encoding.
|
|
; Returns the size of the compressed RLE data. Worst case result storage size needed = (size + (size+126) / 127) + 1.
|
|
; is_last_block = usually true, but you can set it to false if you want to concatenate multiple
|
|
; compressed blocks (for instance if the source data is >64Kb)
|
|
; This routine is not optimized for speed but for readability and ease of use.
|
|
uword idx = 0
|
|
uword literals_start_idx = 0
|
|
ubyte literals_length = 0
|
|
uword orig_target = target
|
|
|
|
sub next_same_span() {
|
|
; returns length in cx16.r1L, and the byte value in cx16.r1H
|
|
cx16.r1H = data[idx]
|
|
cx16.r1L = 0
|
|
while data[idx]==cx16.r1H and cx16.r1L<128 and idx<size {
|
|
idx++
|
|
cx16.r1L++
|
|
}
|
|
}
|
|
|
|
sub output_literals() {
|
|
@(target) = literals_length-1
|
|
target++
|
|
uword dataptr = data + literals_start_idx
|
|
ubyte i
|
|
for i in 0 to literals_length-1 {
|
|
@(target) = @(dataptr)
|
|
target++
|
|
dataptr++
|
|
}
|
|
literals_length = 0
|
|
}
|
|
|
|
while idx<size {
|
|
next_same_span() ; count in r1L, value in r1H
|
|
if cx16.r1L>1 {
|
|
; a replicate run
|
|
if literals_length>0
|
|
output_literals()
|
|
@(target) = (cx16.r1L^255)+2 ; 257-cx16.r1L
|
|
target++
|
|
@(target) = cx16.r1H
|
|
target++
|
|
}
|
|
else {
|
|
; add more to the literals run
|
|
if literals_length==128
|
|
output_literals()
|
|
if literals_length==0
|
|
literals_start_idx = idx-1
|
|
literals_length++
|
|
}
|
|
}
|
|
|
|
if literals_length>0
|
|
output_literals()
|
|
|
|
if is_last_block {
|
|
@(target) = 128
|
|
target ++
|
|
}
|
|
|
|
return target-orig_target
|
|
}
|
|
|
|
}
|