9 Commits

Author SHA1 Message Date
a5406deb30 Merge pull request #2 from ped7g/z80_ped7g
Z80 ped7g - few more optimisations for current variant of packer
2022-09-16 00:26:55 +02:00
Peter Helcmanovsky (Ped)
9211544cb9 z80_unpacker: add resulting snapshot file to example 2022-09-15 18:37:06 +02:00
Peter Helcmanovsky (Ped)
3fa9e0fa12 z80_unpacker: optimisations: 0B, -13T in decode_bit (stays 177B) 2022-09-15 18:22:33 +02:00
Peter Helcmanovsky (Ped)
aa3fad4d80 z80_unpacker: optimisations: -3B and ~-24T in decode_bit = 177B 2022-09-15 18:22:32 +02:00
Peter Helcmanovsky (Ped)
6624940ed9 z80_unpacker: optimisations: -2B and -27T in decode_bit = 180B 2022-09-15 18:22:32 +02:00
Peter Helcmanovsky (Ped)
c3a9773e5c z80_unpacker: optimisations: -1B in unpack implementation = 182B 2022-09-15 18:22:31 +02:00
Peter Helcmanovsky (Ped)
a75a35efb2 z80_unpacker: probs context-size for offset/length numbers as EQU 2022-09-15 18:22:27 +02:00
540a91d1ba forgot to add back -l 9 2022-09-15 00:18:30 +02:00
e7aaf1491a add old-prob-update to compare script, add reverse option 2022-09-14 23:51:38 +02:00
5 changed files with 46 additions and 37 deletions

View File

@@ -2,7 +2,9 @@
configs = [
[:master, '-b'],
[:z80, '-b']
[:z80, '-b'],
[:z80, ['-b', '-r']],
['old-prob-update', '-b']
]
files = Dir[ARGV[0] + '/*'].select {|f| !(f =~ /\.txt$/) }
@@ -34,8 +36,8 @@ for config in configs
config_results = []
results << config_results
for file in files
if system('cargo', 'run', '--release', 'pack', '-l', '9', config[1], file, '/tmp/out.upk') &&
system('cargo', 'run', '--release', 'unpack', config[1], '/tmp/out.upk', '/tmp/out.bin') &&
if system(*['cargo', 'run', '--release', 'pack', '-l', '9', config[1], file, '/tmp/out.upk'].flatten) &&
system(*['cargo', 'run', '--release', 'unpack', config[1], '/tmp/out.upk', '/tmp/out.bin'].flatten) &&
File.read(file) == File.read('/tmp/out.bin')
size = File.size('/tmp/out.upk')
config_results << size

View File

@@ -10,12 +10,16 @@ fn main() -> Result<()> {
Some("pack") => {
let level = args.opt_value_from_str(["-l", "--level"])?.unwrap_or(2u8);
let use_bitstream = args.contains(["-b", "--bitstream"]);
let reverse = args.contains(["-r", "--reverse"]);
let infile = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let outfile = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let mut data = vec![];
File::open(infile)?.read_to_end(&mut data)?;
if reverse {
data.reverse();
}
let mut pb = pbr::ProgressBar::new(data.len() as u64);
pb.set_units(pbr::Units::Bytes);
@@ -39,14 +43,18 @@ fn main() -> Result<()> {
}
Some("unpack") => {
let use_bitstream = args.contains(["-b", "--bitstream"]);
let reverse = args.contains(["-r", "--reverse"]);
let infile = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let outfile = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let mut data = vec![];
File::open(infile)?.read_to_end(&mut data)?;
let packed_data = upkr::unpack(&data, use_bitstream);
File::create(outfile)?.write_all(&packed_data)?;
let mut unpacked_data = upkr::unpack(&data, use_bitstream);
if reverse {
unpacked_data.reverse();
}
File::create(outfile)?.write_all(&unpacked_data)?;
}
Some(other) => {
bail!("Unknown subcommand '{}'", other);

View File

@@ -1,4 +1,3 @@
*.bin
*.tap
*.sna
*.lst

Binary file not shown.

View File

@@ -12,12 +12,15 @@
;; upkr.unpack
;; IN: IX = packed data, DE' (shadow DE) = destination
;; OUT: IX = after packed data
;; modifies: all registers except IY, requires 14 bytes of stack space
;; modifies: all registers except IY, requires 10 bytes of stack space
;;
OPT push reset --syntax=abf
MODULE upkr
NUMBER_BITS EQU 16+15 ; context-bits per offset/length (16+15 for 16bit offsets/pointers)
; numbers (offsets/lengths) are encoded like: 1a1b1c1d1e0 = 0000'0000'001e'dbca
/*
u8* upkr_data_ptr;
u8 upkr_probs[1 + 255 + 1 + 2*32 + 2*32];
@@ -81,8 +84,8 @@ unpack:
; BC = probs (context_index 0), state HL = 0, A' = 0x80 (no source bits left in upkr_current_byte)
; ** main loop to decompress data
.decompress_data_reset_match:
ld d,0 ; prev_was_match = 0;
; D = prev_was_match = uninitialised, literal is expected first => will reset D to "false"
; values for false/true of prev_was_match are: false = high(probs), true = 1 + high(probs)
.decompress_data:
ld c,0
call decode_bit ; if(upkr_decode_bit(0))
@@ -99,21 +102,22 @@ unpack:
ld (de),a ; *write_ptr++ = byte;
inc de
exx
jr .decompress_data_reset_match
ld d,b ; prev_was_match = false
jr .decompress_data
; * copy chunk of already decompressed data (match)
.copy_chunk:
ld a,b
inc b ; context_index = 256
; if(prev_was_match || upkr_decode_bit(256)) {
; offset = upkr_decode_length(257) - 1;
; if (0 == offset) break;
; }
xor a
cp d ; CF = prev_was_match
call nc,decode_bit ; if not prev_was_match, then upkr_decode_bit(256)
jr nc,.keep_offset ; if neither, keep old offset
inc c
call decode_length
inc c ; context_index to first "number" set for offsets decoding (257)
call decode_number
dec de ; offset = upkr_decode_length(257) - 1;
ld a,d
or e
@@ -126,18 +130,18 @@ unpack:
; ++write_ptr;
; }
; prev_was_match = 1;
ld c,low(257+64) ; context_index = 257+64
call decode_length ; length = upkr_decode_length(257 + 64);
ld c,low(257 + NUMBER_BITS) ; context_index to second "number" set for lengths decoding
call decode_number ; length = upkr_decode_length(257 + 64);
push de
exx
ld h,d ; DE = write_ptr
ld l,e
.offset+*: ld bc,0
sbc hl,bc ; CF=0 from decode_length ; HL = write_ptr - offset
sbc hl,bc ; CF=0 from decode_number ; HL = write_ptr - offset
pop bc ; BC = length
ldir
exx
ld d,b ; prev_was_match = non-zero
ld d,b ; prev_was_match = true
djnz .decompress_data ; adjust context_index back to 0..255 range, go to main loop
/*
@@ -202,9 +206,8 @@ decode_bit:
cp l ; CF = bit = prob-1 < (upkr_state & 255) <=> prob <= (upkr_state & 255)
inc a
; ** adjust state
push af
push af
push hl
push bc
ld c,l ; C = (upkr_state & 255); (preserving the value)
push af
jr nc,.bit_is_0
neg ; A = -prob == (256-prob), CF=1 preserved
@@ -212,28 +215,23 @@ decode_bit:
ld d,0
ld e,a ; DE = state_scale ; prob || (256-prob)
ld l,d ; H:L = (upkr_state>>8) : 0
ld a,8 ; counter
ld b,8 ; counter
.mulLoop:
add hl,hl
jr nc,.mul0
add hl,de
.mul0:
dec a
jr nz,.mulLoop ; until HL = state_scale * (upkr_state>>8)
djnz .mulLoop ; until HL = state_scale * (upkr_state>>8), also BC becomes (upkr_state & 255)
add hl,bc ; HL = state_scale * (upkr_state >> 8) + (upkr_state & 255)
pop af
ld d,-16 ; D = -prob_offset (-16 0xF0 when bit = 0)
jr nc,.bit_is_0_2
dec d ; D = 0xFF (DE = -prob)
add hl,de ; HL += -prob
.bit_is_0_2: ; HL = state_offset + state_scale * (upkr_state >> 8)
pop de
ld d,0 ; DE = (upkr_state & 255)
add hl,de ; HL = state_offset + state_scale * (upkr_state >> 8) + (upkr_state & 255) ; new upkr_state
ld d,b ; D = -prob_offset (0 when bit = 1) (also does fix following ADD)
dec h
add hl,de ; HL += -prob (HL += (256 - prob) - 256)
.bit_is_0_2: ; HL = state_offset + state_scale * (upkr_state >> 8) + (upkr_state & 255) ; new upkr_state
; *** adjust probs[context_index]
pop af ; restore prob and bit
ld e,a
jr c,.bit_is_1
ld d,-16 ; 0xF0
.bit_is_1: ; D:E = -prob_offset:prob, A = prob
ld e,a ; D:E = -prob_offset:prob, A = prob
and $F8
rra
rra
@@ -242,8 +240,10 @@ decode_bit:
adc a,d ; A = -prob_offset + ((prob + 8) >> 4)
neg
add a,e ; A = prob_offset + prob - ((prob + 8) >> 4)
pop bc
ld (bc),a ; update probs[context_index]
pop af ; restore resulting CF = bit
add a,d ; bit=0: A = 23..249, D = 240 -> CF=1 || bit=1: D=0 -> CF=0
ccf ; resulting CF = bit restored
pop de
ret
@@ -258,7 +258,7 @@ int upkr_decode_length(int context_index) {
return length | (1 << bit_pos);
}
*/
decode_length:
decode_number:
; HL = upkr_state
; IX = upkr_data_ptr
; BC = probs+context_index
@@ -291,7 +291,7 @@ decode_length:
ENDIF
probs: EQU ($+255) & -$100 ; probs array aligned to 256
.real_c: EQU 1 + 255 + 1 + 2*32 + 2*32 ; real size of probs array
.real_c: EQU 1 + 255 + 1 + 2*NUMBER_BITS ; real size of probs array
.c: EQU (.real_c + 1) & -2 ; padding to even size (required by init code)
.e: EQU probs + .c