/programs/other/kpack/kerpack_linux/Makefile |
---|
0,0 → 1,21 |
CFLAGS=-O3 |
all: kpack kerpack |
kpack: kpack64.o LZMAEncoder-kpack.o MatchFinder.o RangeCoder.o |
gcc -nostartfiles -o kpack kpack64.o LZMAEncoder-kpack.o MatchFinder.o RangeCoder.o |
kpack64.o: kpack64.asm |
fasm kpack64.asm kpack64.o |
kerpack: kerpack64.o LZMAEncoder-kerpack.o MatchFinder.o RangeCoder.o |
gcc -nostartfiles -o kerpack kerpack64.o LZMAEncoder-kerpack.o MatchFinder.o RangeCoder.o |
kerpack64.o: kerpack64.asm |
fasm kerpack64.asm kerpack64.o |
LZMAEncoder-kpack.o: lzma_c/LZMAEncoder.c lzma_c/LZMAEncoder.h lzma_c/MatchFinder.h lzma_c/lzma.h lzma_c/RangeCoder.h lzma_c/RangeCoderBit.h lzma_c/RangeCoderBitTree.h lzma_c/common.h |
gcc -c $(CFLAGS) -o LZMAEncoder-kpack.o lzma_c/LZMAEncoder.c |
LZMAEncoder-kerpack.o: lzma_c/LZMAEncoder.c lzma_c/LZMAEncoder.h lzma_c/MatchFinder.h lzma_c/lzma.h lzma_c/RangeCoder.h lzma_c/RangeCoderBit.h lzma_c/RangeCoderBitTree.h lzma_c/common.h |
gcc -c -DFOR_KERPACK $(CFLAGS) -o LZMAEncoder-kerpack.o lzma_c/LZMAEncoder.c |
MatchFinder.o: lzma_c/MatchFinder.c lzma_c/MatchFinder.h lzma_c/common.h |
gcc -c $(CFLAGS) -o MatchFinder.o lzma_c/MatchFinder.c |
RangeCoder.o: lzma_c/RangeCoder.c lzma_c/RangeCoder.h lzma_c/RangeCoderBit.h lzma_c/RangeCoderBitTree.h lzma_c/lzma.h lzma_c/common.h |
gcc -c $(CFLAGS) -o RangeCoder.o lzma_c/RangeCoder.c |
clean: |
rm *.o kpack kerpack |
/programs/other/kpack/kerpack_linux/calltrick2.asm |
---|
0,0 → 1,32 |
pop esi |
push esi |
loader_patch4: |
mov ecx, 0 ; will be patched: number of calltrick entries |
ctrloop: |
lodsb |
@@: |
cmp al, 0xF |
jnz .f |
lodsb |
cmp al, 80h |
jb @b |
cmp al, 90h |
jb @f |
.f: |
sub al, 0E8h |
cmp al, 1 |
ja ctrloop |
@@: |
cmp byte [esi], 0 ; will be patched: code in calltrick entries |
loader_patch5: |
jnz ctrloop |
lodsd |
; "bswap eax" is not supported on i386 |
; mov al,0/bswap eax = 4 bytes, following instructions = 9 bytes |
shr ax, 8 |
ror eax, 16 |
xchg al, ah |
sub eax, esi |
add eax, [esp] |
mov [esi-4], eax |
loop ctrloop |
/programs/other/kpack/kerpack_linux/kerpack64.asm |
---|
0,0 → 1,460 |
;freebsd = 1 ;uncomment for FreeBSD-specific changes |
format ELF64 |
public _start |
.data? fix section ".bss" writeable align 4 |
.data fix section ".data" writeable align 4 |
.const fix section ".const" align 4 |
.code fix section ".text" executable align 16 |
offset fix |
ptr fix |
struc label type { |
label . type } |
extrn lzma_compress |
extrn lzma_set_dict_size |
.data? |
infilename dq ? |
outfilename dq ? |
infile dq ? |
outfile dq ? |
inptr dq ? |
workmem dq ? |
insize dd ? |
outsize dd ? |
lzma_dictsize dd ? |
indelta dd ? |
strucstat rq 18 |
if defined freebsd |
st_atime_offset = 24 |
st_mtime_offset = 40 |
st_birthtime_offset = 104 |
st_size_offset = 72 |
else |
st_atime_offset = 72 |
st_mtime_offset = 88 |
;st_birthtime_offset not defined |
st_size_offset = 48 |
end if |
public environ |
environ dq ? |
public __progname |
__progname dq ? |
ct1 db 256 dup (?) |
ctn dd ? |
cti db ? |
.const |
usage_str db 'Written by diamond in 2006, 2007 specially for KolibriOS',13,10 |
db 'LZMA compression library is copyright (c) 1999-2005 by Igor Pavlov',13,10 |
db 13,10 |
db 'Usage: kerpack <infile> [<outfile>]',13,10 |
usage_len = $ - offset usage_str |
errload_str db 'Cannot load input file',13,10 |
errload_len = $ - offset errload_str |
outfileerr_str db 'Cannot save output file',13,10 |
outfileerr_len = $ - offset outfileerr_str |
nomem_str db 'No memory',13,10 |
nomem_len = $ - offset nomem_str |
too_big_str db 'failed, output is greater than input.',13,10 |
too_big_len = $ - too_big_str |
compressing_str db 'Compressing ... ' |
compressing_len = $ - compressing_str |
.data |
done_str db 'OK! Compression ratio: ' |
ratio dw '00' |
db '%',13,10,13,10 |
done_len = $ - done_str |
use_lzma = 1 |
use_no_calltrick = 0 |
use_calltrick1 = 40h |
use_calltrick2 = 80h |
method db 1 |
.code |
; Write string from [rsi] of rdx bytes. |
write_string: |
; 1. Align stack on 16 bytes. |
push rdi |
; 2. Set rdi to 1 = descriptor for stdout. |
xor edi, edi |
inc edi |
; 3. Do system call. |
call write |
; 4. Restore stack and return. |
pop rdi |
ret |
; Write string from [rsi] of rdx bytes and exit. Note that main code jumps (not calls) here, |
; so we should not align the stack. |
write_exit: |
; 1. Call prev func. |
call write_string |
; 2. Do system call for exit. |
; Note that this can be used as independent proc jumped (not called) to. |
doexit: |
xor edi, edi |
inc edi |
call exit |
; Main procedure. |
_start: |
; 1. Parse command line. |
; Linux: [rsp] = argc, rsp+8 = argv |
; FreeBSD: [rdi] = argc, rdi+8 = argv |
; 1a. Load argc and argv to registers, |
; skip first argument (which is always program name) |
if defined freebsd |
mov ecx, [rdi] ; ecx = argc |
add rdi, 16 ; rdi = &argv[1] |
else |
mov ecx, [rsp] ; ecx = argc |
lea rdi, [rsp+16] ; rdi = &argv[1] |
end if |
; 1b. Test for first filename parameter. If no, goto step 2. |
call get_file_name |
jz usage |
; 1c. We got input file name, save it. |
; Assume that output file name is the same; if no, we will rewrite it in step 1d. |
mov [infilename], rax |
mov [outfilename], rax |
; 1d. Test for second filename parameter. If yes, rewrite assumption in step 1c and check that there are no 3rd parameter. |
call get_file_name |
jz @f |
mov [outfilename], rax |
call get_file_name |
jnz usage |
@@: |
; 1e. Parsing is done, process to step 3. |
jmp short cont |
; 2. No arguments or too many arguments given; write message and exit. |
usage: |
push usage_len |
pop rdx |
mov rsi, offset usage_str |
jmp write_exit |
cont: |
; 4. Load the input file. |
; 4a. Do system call for stat - get file times and file size. |
mov rdi, [infilename] |
mov rsi, offset strucstat |
mov r13, rsi |
call stat |
; 4b. Test result; if not 0 (0 is OK), goto 4e. |
test rax, rax |
jnz short infileerr |
; 4c. Do system call for open. |
mov rdi, [infilename] |
mov rsi, offset open_mode |
call fopen |
; 4d. Test result; if not NULL, goto 4f. |
test rax, rax |
jnz short inopened |
infileerr: |
; 4e. Say error and abort. |
push errload_len |
pop rdx |
mov rsi, offset errload_str |
jmp write_exit |
inopened: |
mov r12, rax |
; 4f. Check that the size is nonzero and less than 4G. |
mov edi, [r13+st_size_offset] |
test edi, edi |
jz short infileerr |
cmp dword [r13+st_size_offset+4], 0 |
jnz short infileerr |
; 4g. Allocate memory for the input file. |
mov [insize], edi |
call malloc |
test rax, rax |
jz nomem |
mov [infile], rax |
; 4g. Read the input file to the allocated memory. |
mov rdi, rax |
push 1 |
pop rsi |
mov edx, [r13+st_size_offset] |
mov rcx, r12 |
call fread |
; 4h. Test result; must be equal to file size. |
cmp eax, [r13+st_size_offset] |
jnz infileerr |
; 4i. Close the input file. |
mov rdi, r12 |
call fclose |
; 5. Calculate maximum size of the output. |
mov edi, [insize] |
shr edi, 3 |
add edi, [insize] |
add edi, 400h ; should be enough for header |
mov r12d, edi |
; 6. Allocate memory for two copies of maximum output. |
; 6a. Do system call. |
call malloc |
; 6b. Test return value. If ok, goto 6d. |
test rax, rax |
jnz short outmemok |
; 6c. No memory; say error and exit. |
nomem: |
push nomem_len |
pop rdx |
mov rsi, offset nomem_str |
jmp write_exit |
; 6d. Remember allocated memory address. |
outmemok: |
mov [outfile], rax |
; 8. Determine and set lzma_dict_size. |
push 18h |
pop rdi |
call lzma_set_dict_size |
; 9. Allocate lzma_workmem. |
mov edi, (1 shl 18h) * 19 / 2 + 509000h |
call malloc |
test rax, rax |
jz nomem |
mov [workmem], rax |
; 10. Say another 'hi'. |
push compressing_len |
pop rdx |
mov rsi, offset compressing_str |
call write_string |
; 11. Do work. |
; find jump to 32-bit code |
mov rdi, [infile] |
dec rdi |
@@: |
inc rdi |
cmp dword [rdi], 0E88EE08Eh ; mov fs,ax/mov gs,ax |
jnz @b |
cmp dword [rdi+4], 00BCD08Eh ; mov ss,ax/mov esp,00xxxxxx |
jnz @b |
add rdi, 11 |
mov [inptr], rdi |
sub rdi, [infile] |
mov [indelta], edi |
mov eax, [insize] |
mov ebx, eax |
add eax, 0x10000 |
mov [loader_base+..loader_patch3+2], eax |
sub ebx, edi |
mov [insize], ebx |
call preprocess_calltrick2 |
mov al, [cti] |
mov [loader_base+loader_patch5-1], al |
mov eax, [ctn] |
mov [loader_base+loader_patch4+1], eax |
mov esi, [indelta] |
add rsi, [outfile] |
add rsi, loader_size - 5 |
mov rdi, [inptr] |
mov edx, [insize] |
mov rcx, [workmem] |
call lzma_compress |
mov edx, [indelta] |
add eax, loader_size-5 |
mov [loader_base+loader_patch1+6], eax |
add eax, edx |
mov [outsize], eax |
mov eax, edx |
add rax, [outfile] |
mov ecx, [rax + loader_size - 4] |
bswap ecx |
mov [loader_base+loader_patch2+4], ecx |
add edx, 0x10000 |
mov [loader_base+loader_patch1+1], edx |
mov rsi, [infile] |
mov rdi, [outfile] |
mov ecx, [indelta] |
rep movsb |
mov rsi, loader_base |
mov ecx, loader_size |
rep movsb |
mov eax, [outsize] |
cmp eax, [insize] |
jb short packed_ok |
push too_big_len |
pop rdx |
mov rsi, offset too_big_str |
jmp write_exit |
packed_ok: |
; 12. Main work is done. Free lzma_workmem. |
mov rdi, [workmem] |
call free |
; 13. Set header |
mov eax, [outsize] |
mov ecx, 100 |
mul ecx |
div [insize] |
mov cl, 10 |
div cl |
add ax, '00' |
mov [ratio], ax |
push done_len |
pop rdx |
mov rsi, offset done_str |
call write_string |
; 14. Save the output file. |
; 14a. Do system call for open. |
mov rdi, [outfilename] |
mov rsi, create_mode |
call fopen |
; 14b. Test for success; if yes, goto 14d. |
test rax, rax |
jnz short @f |
; 14c. Say error and exit. |
outerr: |
push outfileerr_len |
pop rdx |
mov rsi, offset outfileerr_str |
jmp write_exit |
; 14d. Do system call for write. |
@@: |
mov r12, rax |
mov rdi, [outfile] |
mov esi, [outsize] |
push 1 |
pop rdx |
mov rcx, r12 |
call fwrite |
test eax, eax |
jz short outerr |
; 14e. Close output file. |
mov rdi, r12 |
call fclose |
; 15. Exit. |
xor edi, edi |
call exit |
; Scan command line, skipping possible options, and return first non-option |
; ecx is number of arguments left, rdi points to first new argument (updated by func) |
; After the call: ZF set if no arguments left, otherwise rax points to the arg. |
get_file_name: |
; 1. Test whether there are still arguments. If no, goto 5; note ZF is set. |
dec ecx |
jz @@end |
; 2. Get the new arg, advance rdi (ecx was decreased in step 1). |
mov rax, [rdi] |
add rdi, 8 |
; 5. No arguments (ZF set) or normal argument (ZF cleared); return. |
@@end: |
ret |
pack_calltrick_fail: |
xor eax, eax |
xor ebx, ebx |
mov [ctn], eax |
ret |
preprocess_calltrick2: |
; restore input |
mov rsi, [infile] |
; input preprocessing |
push rax |
mov edi, [insize] |
add edi, edi |
call malloc |
pop rcx |
test rax, rax |
jz pack_calltrick_fail |
mov rdi, offset ct1 |
xchg rax, rbx |
xor eax, eax |
push rdi |
mov ecx, 256/4 |
rep stosd |
pop rdi |
mov ecx, [insize] |
mov rsi, [inptr] |
xchg eax, edx |
push rbx |
input_pre2: |
lodsb |
@@: |
cmp al, 0Fh |
jnz short ip1 |
dec ecx |
jz short input_pre_done2 |
lodsb |
cmp al, 80h |
jb short @b |
cmp al, 90h |
jb short @f |
ip1: |
sub al, 0E8h |
cmp al, 1 |
ja short input_pre_cont2 |
@@: |
cmp ecx, 5 |
jb short input_pre_done2 |
lodsd |
add eax, esi |
sub eax, dword ptr [inptr] |
cmp eax, [insize] |
jae short xxx2 |
cmp eax, 1000000h |
jae short xxx2 |
sub ecx, 4 |
bswap eax |
mov [rsi-4], eax |
inc edx |
mov [rbx], rsi |
add rbx, 8 |
jmp short input_pre_cont2 |
xxx2: sub rsi, 4 |
movzx eax, byte ptr [rsi] |
mov byte ptr [rax+rdi], 1 |
input_pre_cont2: |
loop input_pre2 |
input_pre_done2: |
mov [ctn], edx |
pop rdx |
xor eax, eax |
mov ecx, 256 |
repnz scasb |
jnz pack_calltrick_fail |
not cl |
mov [cti], cl |
@@: |
cmp rbx, rdx |
jz @f |
sub rbx, 8 |
mov rax, [rbx] |
mov [rax-4], cl |
jmp @b |
@@: |
push rax |
mov rdi, rbx |
call free |
pop rax |
ret |
extrn exit |
extrn fopen |
extrn fread |
extrn fwrite |
extrn fclose |
extrn fseek |
extrn ftell |
extrn malloc |
extrn free |
extrn write |
extrn utimes |
extrn stat |
open_mode db "rb",0 |
create_mode db "wb",0 |
.data |
loader_base: |
use32 |
org 0 |
include 'loader_lzma.asm' |
/programs/other/kpack/kerpack_linux/kpack64.asm |
---|
0,0 → 1,657 |
; kpack = Kolibri Packer |
; Written by diamond in 2006 specially for KolibriOS |
; Uses LZMA compression library by Igor Pavlov |
; (for more information on LZMA and 7-Zip visit http://www.7-zip.org) |
; (plain-C packer and ASM unpacker are ported by diamond) |
;freebsd = 1 ;uncomment for FreeBSD-specific changes |
format ELF64 |
public _start |
.data? fix section ".bss" writeable align 4 |
.data fix section ".data" writeable align 4 |
.const fix section ".const" align 4 |
.code fix section ".text" executable align 16 |
offset fix |
ptr fix |
struc label type { |
label . type } |
extrn lzma_compress |
extrn lzma_set_dict_size |
.data? |
infilename dq ? |
outfilename dq ? |
infile dq ? |
outfile1 dq ? |
outfile2 dq ? |
outfile dq ? |
outfilebest dq ? |
workmem dq ? |
insize dd ? |
outsize dd ? |
lzma_dictsize dd ? |
dd ? |
strucstat rq 18 |
if defined freebsd |
st_atime_offset = 24 |
st_mtime_offset = 40 |
st_birthtime_offset = 104 |
st_size_offset = 72 |
else |
st_atime_offset = 72 |
st_mtime_offset = 88 |
;st_birthtime_offset not defined |
st_size_offset = 48 |
end if |
timeval rq 2*2 |
public environ |
environ dq ? |
public __progname |
__progname dq ? |
ct1 db 256 dup (?) |
ctn dd ? |
cti db ? |
.const |
info_str db 'KPack - Kolibri Packer, version 0.11',13,10 |
db 'Uses LZMA v4.32 compression library',13,10,13,10 |
info_len = $ - offset info_str |
usage_str db 'Written by diamond in 2006, 2007 specially for KolibriOS',13,10 |
db 'LZMA compression library is copyright (c) 1999-2005 by Igor Pavlov',13,10 |
db 13,10 |
db 'Usage: kpack [--nologo] <infile> [<outfile>]',13,10 |
usage_len = $ - offset usage_str |
errload_str db 'Cannot load input file',13,10 |
errload_len = $ - offset errload_str |
outfileerr_str db 'Cannot save output file',13,10 |
outfileerr_len = $ - offset outfileerr_str |
nomem_str db 'No memory',13,10 |
nomem_len = $ - offset nomem_str |
too_big_str db 'failed, output is greater than input.',13,10 |
too_big_len = $ - too_big_str |
compressing_str db 'Compressing ... ' |
compressing_len = $ - compressing_str |
.data |
bNoLogo db 0 |
done_str db 'OK! Compression ratio: ' |
ratio dw '00' |
db '%',13,10,13,10 |
done_len = $ - done_str |
use_lzma = 1 |
use_no_calltrick = 0 |
use_calltrick1 = 40h |
use_calltrick2 = 80h |
method db 1 |
.code |
; Write string from [rsi] of rdx bytes. |
write_string: |
; 1. Align stack on 16 bytes. |
push rdi |
; 2. Set rdi to 1 = descriptor for stdout. |
xor edi, edi |
inc edi |
; 3. Do system call. |
call write |
; 4. Restore stack and return. |
pop rdi |
ret |
; Write string from [rsi] of rdx bytes and exit. Note that main code jumps (not calls) here, |
; so we should not align the stack. |
write_exit: |
; 1. Call prev func. |
call write_string |
; 2. Do system call for exit. |
; Note that this can be used as independent proc jumped (not called) to. |
doexit: |
xor edi, edi |
call exit |
; Main procedure. |
_start: |
; 1. Parse command line. |
; Linux: [rsp] = argc, rsp+8 = argv |
; FreeBSD: [rdi] = argc, rdi+8 = argv |
; 1a. Load argc and argv to registers, |
; skip first argument (which is always program name) |
if defined freebsd |
mov ecx, [rdi] ; ecx = argc |
add rdi, 16 ; rdi = &argv[1] |
else |
mov ecx, [rsp] ; ecx = argc |
lea rdi, [rsp+16] ; rdi = &argv[1] |
end if |
; 1b. Test for first filename parameter. If no, goto step 2. |
call get_file_name |
jz usage |
; 1c. We got input file name, save it. |
; Assume that output file name is the same; if no, we will rewrite it in step 1d. |
mov [infilename], rax |
mov [outfilename], rax |
; 1d. Test for second filename parameter. If yes, rewrite assumption in step 1c and check that there are no 3rd parameter. |
call get_file_name |
jz @f |
mov [outfilename], rax |
call get_file_name |
jnz usage |
@@: |
; 1e. Parsing is done, process to step 3. |
jmp short cont |
; 2. No arguments or too many arguments given; write message and exit. |
usage: |
cmp [bNoLogo], 0 |
jnz doexit |
push info_len + usage_len |
pop rdx |
mov rsi, offset info_str;usage_str |
jmp write_exit |
; 3. Say hello unless disabled with --nologo. |
cont: |
cmp [bNoLogo], 0 |
jnz @f |
push info_len |
pop rdx |
mov rsi, info_str |
call write_string |
@@: |
; 4. Load the input file. |
; 4a. Do system call for stat - get file times and file size. |
mov rdi, [infilename] |
mov rsi, offset strucstat |
mov r13, rsi |
call stat |
; 4b. Test result; if not 0 (0 is OK), goto 4e. |
test rax, rax |
jnz short infileerr |
; 4c. Do system call for open. |
mov rdi, [infilename] |
mov rsi, offset open_mode |
call fopen |
; 4d. Test result; if not NULL, goto 4f. |
test rax, rax |
jnz short inopened |
infileerr: |
; 4e. Say error and abort. |
push errload_len |
pop rdx |
mov rsi, offset errload_str |
jmp write_exit |
inopened: |
mov r12, rax |
; 4f. Check that the size is nonzero and less than 4G. |
mov edi, [r13+st_size_offset] |
test edi, edi |
jz short infileerr |
cmp dword [r13+st_size_offset+4], 0 |
jnz short infileerr |
; 4g. Allocate memory for the input file. |
mov [insize], edi |
call malloc |
test rax, rax |
jz nomem |
mov [infile], rax |
; 4g. Read the input file to the allocated memory. |
mov rdi, rax |
push 1 |
pop rsi |
mov edx, [r13+st_size_offset] |
mov rcx, r12 |
call fread |
; 4h. Test result; must be equal to file size. |
cmp eax, [r13+st_size_offset] |
jnz infileerr |
; 4i. Close the input file. |
mov rdi, r12 |
call fclose |
; 5. Calculate maximum size of the output. |
mov edi, [insize] |
shr edi, 3 |
add edi, [insize] |
add edi, 400h ; should be enough for header |
mov r12d, edi |
; 6. Allocate memory for two copies of maximum output. |
; 6a. Do system call. |
add edi, edi |
call malloc |
; 6b. Test return value. If ok, goto 6d. |
test rax, rax |
jnz short outmemok |
; 6c. No memory; say error and exit. |
nomem: |
push nomem_len |
pop rdx |
mov rsi, offset nomem_str |
jmp write_exit |
; 6d. Remember allocated memory address. |
outmemok: |
mov [outfile], rax |
mov [outfile1], rax |
mov [outfilebest], rax |
add rax, r12 |
mov [outfile2], rax |
sub rax, r12 |
; 7. Initialize KPCK header. |
mov dword ptr [rax], 'KPCK' |
mov ecx, [insize] |
mov dword ptr [rax+4], ecx |
; 8. Determine and set lzma_dict_size. |
dec ecx |
bsr eax, ecx |
inc eax |
cmp eax, 28 |
jb short @f |
mov eax, 28 |
@@: |
push rax |
mov edi, eax |
call lzma_set_dict_size |
pop rcx |
mov edi, 1 |
shl edi, cl |
mov [lzma_dictsize], edi |
; 9. Allocate lzma_workmem. |
imul edi, 19 |
shr edi, 1 |
add edi, 509000h |
call malloc |
test rax, rax |
jz nomem |
mov [workmem], rax |
; 10. Say another 'hi'. |
push compressing_len |
pop rdx |
mov rsi, offset compressing_str |
call write_string |
; 11. Do work. |
mov rax, [outfile2] |
mov [outfile], rax |
xchg rax, rdi |
mov rsi, [outfile1] |
movsd |
movsd |
call pack_lzma |
mov [outsize], eax |
mov rax, [outfile] |
mov [outfilebest], rax |
mov [method], use_lzma |
call preprocess_calltrick |
test eax, eax |
jz short noct1 |
call set_outfile |
call pack_lzma |
add eax, 5 |
cmp eax, [outsize] |
jae short @f |
mov [outsize], eax |
mov rax, [outfile] |
mov [outfilebest], rax |
mov [method], use_lzma or use_calltrick1 |
@@: |
noct1: |
call set_outfile |
push qword ptr [ctn] |
push qword ptr [cti] |
call preprocess_calltrick2 |
test eax, eax |
jz noct2 |
call set_outfile |
call pack_lzma |
add eax, 5 |
cmp eax, [outsize] |
jae short @f |
mov [outsize], eax |
mov rax, [outfile] |
mov [outfilebest], rax |
mov [method], use_lzma or use_calltrick2 |
pop rcx |
pop rcx |
push qword ptr [ctn] |
push qword ptr [cti] |
@@: |
noct2: |
pop rax |
mov [cti], al |
pop rax |
mov [ctn], eax |
add [outsize], 12 |
mov eax, [outsize] |
cmp eax, [insize] |
jb short packed_ok |
push too_big_len |
pop rdx |
mov rsi, offset too_big_str |
jmp write_exit |
packed_ok: |
; 12. Main work is done. Free lzma_workmem. |
mov rdi, [workmem] |
call free |
; 13. Set header |
movzx eax, [method] |
mov rdi, [outfilebest] |
mov [rdi+8], eax |
test al, use_calltrick1 or use_calltrick2 |
jz short @f |
mov ecx, [outsize] |
add rcx, rdi |
mov eax, [ctn] |
mov [rcx-5], eax |
mov al, [cti] |
mov [rcx-1], al |
@@: |
mov eax, [outsize] |
mov ecx, 100 |
mul ecx |
div [insize] |
mov cl, 10 |
div cl |
add ax, '00' |
mov [ratio], ax |
push done_len |
pop rdx |
cmp [bNoLogo], 0 |
jz @f |
sub dl, 2 |
@@: |
mov rsi, offset done_str |
call write_string |
; 14. Save the output file. |
; 14a. Do system call for open. |
mov rdi, [outfilename] |
mov rsi, create_mode |
call fopen |
; 14b. Test for success; if yes, goto 14d. |
test rax, rax |
jnz short @f |
; 14c. Say error and exit. |
outerr: |
push outfileerr_len |
pop rdx |
mov rsi, offset outfileerr_str |
jmp write_exit |
; 14d. Do system call for write. |
@@: |
mov r12, rax |
mov rdi, [outfilebest] |
mov esi, [outsize] |
push 1 |
pop rdx |
mov rcx, r12 |
call fwrite |
test eax, eax |
jz short outerr |
; 14e. Close output file. |
mov rdi, r12 |
call fclose |
; 14f. Set output file time from the input file. |
; Do two system calls, one for birth time, one for modification time. |
mov rdi, [outfilename] |
mov rsi, timeval |
mov rax, [r13+st_atime_offset] |
mov [rsi], rax |
mov rax, [r13+st_atime_offset+8] |
mov [rsi+8], rax |
if defined st_birthtime_offset |
mov rax, [r13+st_birthtime_offset] |
mov [rsi+16], rax |
mov rax, [r13+st_birthtime_offset+8] |
mov [rsi+24], rax |
call utimes |
mov rdi, [outfilename] |
mov rsi, timeval |
end if |
mov rax, [r13+st_mtime_offset] |
mov [rsi+16], rax |
mov rax, [r13+st_mtime_offset+8] |
mov [rsi+24], rax |
call utimes |
; 15. Exit. |
xor edi, edi |
call exit |
; Scan command line, skipping possible options, and return first non-option |
; ecx is number of arguments left, rdi points to first new argument (updated by func) |
; After the call: ZF set if no arguments left, otherwise rax points to the arg. |
get_file_name: |
; 1. Test whether there are still arguments. If no, goto 5; note ZF is set. |
dec ecx |
jz @@end |
; 2. Get the new arg, advance rdi (ecx was decreased in step 1). |
mov rax, [rdi] |
add rdi, 8 |
; 3. Test for --nologo option. If no, goto 5; note ZF is cleared. |
cmp dword [rax], '--no' |
jnz @@end |
cmp dword [rax+4], 'logo' |
jnz @@end |
; 4. Remember that --nologo was given and continue from the beginning. |
mov [bNoLogo], 1 |
jmp get_file_name |
; 5. No arguments (ZF set) or normal argument (ZF cleared); return. |
@@end: |
ret |
set_outfile: |
mov rax, [outfilebest] |
xor rax, [outfile1] |
xor rax, [outfile2] |
mov [outfile], rax |
ret |
pack_calltrick_fail: |
xor eax, eax |
xor ebx, ebx |
mov [ctn], eax |
ret |
preprocess_calltrick: |
; input preprocessing |
push rax |
mov edi, [insize] |
add edi, edi |
call malloc |
pop rcx |
test rax, rax |
jz pack_calltrick_fail |
push rax |
xor eax, eax |
mov rdi, offset ct1 |
mov ecx, 256/4 |
push rdi |
rep stosd |
pop rdi |
mov ecx, [insize] |
mov rsi, [infile] |
xchg eax, edx |
pop rax |
xchg rax, rbx |
push rbx |
input_pre: |
lodsb |
sub al, 0E8h |
cmp al, 1 |
ja short input_pre_cont |
cmp ecx, 5 |
jb short input_pre_done |
lodsd |
add eax, esi |
sub eax, dword ptr [infile] |
cmp eax, [insize] |
jae short xxx |
cmp eax, 1000000h |
jae short xxx |
sub ecx, 4 |
bswap eax |
mov [rsi-4], eax |
inc edx |
mov [rbx], rsi |
add rbx, 8 |
jmp short input_pre_cont |
xxx: sub rsi, 4 |
movzx eax, byte ptr [rsi] |
mov byte ptr [rax+rdi], 1 |
input_pre_cont: |
loop input_pre |
input_pre_done: |
mov [ctn], edx |
pop rdx |
xor eax, eax |
mov ecx, 256 |
repnz scasb |
jnz pack_calltrick_fail |
not cl |
mov [cti], cl |
@@: |
cmp rbx, rdx |
jz @f |
sub rbx, 8 |
mov rax, [rbx] |
mov [rax-4], cl |
jmp @b |
@@: |
push rax |
mov rdi, rbx |
call free |
pop rax |
ret |
pack_lzma: |
push rcx |
mov rdi, [infile] |
mov rsi, [outfile] |
add rsi, 11 |
mov edx, [insize] |
mov rcx, [workmem] |
call lzma_compress |
pop rcx |
mov rcx, [outfile] |
mov edx, [rcx+12] |
bswap edx |
mov [rcx+12], edx |
dec eax |
ret |
preprocess_calltrick2: |
; restore input |
mov rsi, [infile] |
mov ecx, [ctn] |
jecxz pc2l2 |
pc2l1: |
lodsb |
sub al, 0E8h |
cmp al, 1 |
ja short pc2l1 |
mov al, [cti] |
cmp [rsi], al |
jnz short pc2l1 |
lodsd |
mov al, 0 |
bswap eax |
sub eax, esi |
add eax, dword ptr [infile] |
mov [rsi-4], eax |
loop pc2l1 |
pc2l2: |
; input preprocessing |
push rax |
mov edi, [insize] |
add edi, edi |
call malloc |
pop rcx |
test rax, rax |
jz pack_calltrick_fail |
mov rdi, offset ct1 |
xchg rax, rbx |
xor eax, eax |
push rdi |
mov ecx, 256/4 |
rep stosd |
pop rdi |
mov ecx, [insize] |
mov rsi, [infile] |
xchg eax, edx |
push rbx |
input_pre2: |
lodsb |
@@: |
cmp al, 0Fh |
jnz short ip1 |
dec ecx |
jz short input_pre_done2 |
lodsb |
cmp al, 80h |
jb short @b |
cmp al, 90h |
jb short @f |
ip1: |
sub al, 0E8h |
cmp al, 1 |
ja short input_pre_cont2 |
@@: |
cmp ecx, 5 |
jb short input_pre_done2 |
lodsd |
add eax, esi |
sub eax, dword ptr [infile] |
cmp eax, [insize] |
jae short xxx2 |
cmp eax, 1000000h |
jae short xxx2 |
sub ecx, 4 |
bswap eax |
mov [rsi-4], eax |
inc edx |
mov [rbx], rsi |
add rbx, 8 |
jmp short input_pre_cont2 |
xxx2: sub rsi, 4 |
movzx eax, byte ptr [rsi] |
mov byte ptr [rax+rdi], 1 |
input_pre_cont2: |
loop input_pre2 |
input_pre_done2: |
mov [ctn], edx |
pop rdx |
xor eax, eax |
mov ecx, 256 |
repnz scasb |
jnz pack_calltrick_fail |
not cl |
mov [cti], cl |
@@: |
cmp rbx, rdx |
jz @f |
sub rbx, 8 |
mov rax, [rbx] |
mov [rax-4], cl |
jmp @b |
@@: |
push rax |
mov rdi, rbx |
call free |
pop rax |
ret |
extrn exit |
extrn fopen |
extrn fread |
extrn fwrite |
extrn fclose |
extrn fseek |
extrn ftell |
extrn malloc |
extrn free |
extrn write |
extrn utimes |
extrn stat |
open_mode db "rb",0 |
create_mode db "wb",0 |
/programs/other/kpack/kerpack_linux/loader_lzma.asm |
---|
0,0 → 1,404 |
loader_start: |
; start address; this code will be injected after the init code |
; (some commands below "B32" in the kernel) |
mov edi, 0x280000 |
lea ebx, [edi+loader_size1+16] |
lea edx, [ebx+4] |
loader_patch1: |
mov esi, 0 ; will be patched: start address to copy |
mov ecx, 0 ; will be patched: size of data to copy |
push esi |
rep movsb |
jmp edx |
loader_size1 = $ - loader_start |
loader_patch2: |
dd 0x280000 + loader_size |
dd 0 ; will be patched: start value for code |
; (LZMA-specific) |
dd -1 |
dd _RangeDecoderBitDecode_edx - loader_start + 0x280000 |
dd _RangeDecoderBitDecode - loader_start + 0x280000 |
RangeDecoderBitDecode equ dword [ebx] |
RangeDecoderBitDecode_edx equ dword [ebx-4] |
code_ equ ebx-12 |
range equ ebx-8 |
rep1 equ ebx-28 |
rep2 equ ebx-24 |
rep3 equ ebx-20 |
inptr_ldr equ ebx-16 |
pb equ 0 ; pos state bits |
lp equ 0 ; literal pos state bits |
lc equ 3 ; literal context bits |
posStateMask equ ((1 shl pb)-1) |
literalPosMask equ ((1 shl lp)-1) |
kNumPosBitsMax = 4 |
kNumPosStatesMax = (1 shl kNumPosBitsMax) |
kLenNumLowBits = 3 |
kLenNumLowSymbols = (1 shl kLenNumLowBits) |
kLenNumMidBits = 3 |
kLenNumMidSymbols = (1 shl kLenNumMidBits) |
kLenNumHighBits = 8 |
kLenNumHighSymbols = (1 shl kLenNumHighBits) |
LenChoice = 0 |
LenChoice2 = 1 |
LenLow = 2 |
LenMid = (LenLow + (kNumPosStatesMax shl kLenNumLowBits)) |
LenHigh = (LenMid + (kNumPosStatesMax shl kLenNumMidBits)) |
kNumLenProbs = (LenHigh + kLenNumHighSymbols) |
kNumStates = 12 |
kNumLitStates = 7 |
kStartPosModelIndex = 4 |
kEndPosModelIndex = 14 |
kNumFullDistances = (1 shl (kEndPosModelIndex/2)) |
kNumPosSlotBits = 6 |
kNumLenToPosStates = 4 |
kNumAlignBits = 4 |
kAlignTableSize = (1 shl kNumAlignBits) |
kMatchMinLen = 2 |
IsMatch = 0 |
IsRep = 0xC0 ; (IsMatch + (kNumStates shl kNumPosBitsMax)) |
IsRepG0 = 0xCC ; (IsRep + kNumStates) |
IsRepG1 = 0xD8 ; (IsRepG0 + kNumStates) |
IsRepG2 = 0xE4 ; (IsRepG1 + kNumStates) |
IsRep0Long = 0xF0 ; (IsRepG2 + kNumStates) |
PosSlot = 0x1B0 ; (IsRep0Long + (kNumStates shl kNumPosBitsMax)) |
SpecPos = 0x2B0 ; (PosSlot + (kNumLenToPosStates shl kNumPosSlotBits)) |
Align_ = 0x322 ; (SpecPos + kNumFullDistances - kEndPosModelIndex) |
Lencoder = 0x332 ; (Align_ + kAlignTableSize) |
RepLencoder = 0x534 ; (Lencoder + kNumLenProbs) |
Literal = 0x736 ; (RepLencoder + kNumLenProbs) |
LZMA_BASE_SIZE = 1846 ; must be ==Literal |
LZMA_LIT_SIZE = 768 |
kNumTopBits = 24 |
kTopValue = (1 shl kNumTopBits) |
kNumBitModelTotalBits = 11 |
kBitModelTotal = (1 shl kNumBitModelTotalBits) |
kNumMoveBits = 5 |
uninit_base = 2C0000h |
p = uninit_base |
unpacker: |
xor ebp, ebp |
xor eax, eax |
dec eax |
lea edi, [rep1] |
stosd |
stosd |
stosd |
xchg eax, esi |
; mov ecx, Literal + (LZMA_LIT_SIZE shl (lc+lp)) |
mov ch, (Literal + (LZMA_LIT_SIZE shl (lc+lp)) + 0xFF) shr 8 |
mov eax, kBitModelTotal/2 |
mov edi, p |
rep stosd |
pop edi |
push edi |
.main_loop: |
..loader_patch3: |
cmp edi, dword 0 ; will be patched: end of data to unpack |
jae .main_loop_done |
if posStateMask |
mov edx, edi |
and edx, posStateMask |
else |
xor edx, edx |
end if |
push eax ; al = previous byte |
lea eax, [ebp + ((p+IsMatch*4) shr (kNumPosBitsMax+2))] |
shl eax, kNumPosBitsMax+2 |
if posStateMask |
call RangeDecoderBitDecode_edx |
else |
call RangeDecoderBitDecode |
end if |
pop eax |
jc .1 |
movzx eax, al |
if literalPosMask |
mov ah, dl |
and ah, literalPosMask |
end if |
if ((LZMA_LIT_SIZE*4) and ((1 shl (8-lc)) - 1)) <> 0 |
shr eax, 8-lc |
imul eax, LZMA_LIT_SIZE*4 |
else |
and al, not ((1 shl (8-lc)) - 1) |
imul eax, (LZMA_LIT_SIZE*4) shr (8-lc) |
end if |
add eax, p+Literal*4 |
mov dl, 1 |
cmp ebp, kNumLitStates |
jb .literal |
mov cl, [edi + esi] |
.lx0: |
add cl, cl |
adc dh, 1 |
call RangeDecoderBitDecode_edx |
adc dl, dl |
jc .lx1 |
xor dh, dl |
test dh, 1 |
mov dh, 0 |
jnz .lx0 |
.literal: |
@@: |
call RangeDecoderBitDecode_edx |
adc dl, dl |
jnc @b |
.lx1: |
mov eax, ebp |
cmp al, 4 |
jb @f |
cmp al, 10 |
mov al, 3 |
jb @f |
mov al, 6 |
@@: sub ebp, eax |
xchg eax, edx |
.stosb_main_loop: |
stosb |
jmp .main_loop |
.1: |
lea eax, [p + IsRep*4 + ebp*4] |
call RangeDecoderBitDecode |
jnc .10 |
add eax, (IsRepG0 - IsRep)*4 ;lea eax, [p + IsRepG0*4 + ebp*4] |
call RangeDecoderBitDecode |
jc .111 |
mov eax, ebp |
shl eax, kNumPosBitsMax+2 |
add eax, p + IsRep0Long*4 |
call RangeDecoderBitDecode_edx |
jc .1101 |
cmp ebp, 7 |
sbb ebp, ebp |
lea ebp, [ebp+ebp+11] |
mov al, [edi + esi] |
jmp .stosb_main_loop |
.111: |
add eax, (IsRepG1 - IsRepG0) * 4 ;lea eax, [p + IsRepG1*4 + ebp*4] |
call RangeDecoderBitDecode |
xchg esi, [rep1] |
jnc @f |
add eax, (IsRepG2 - IsRepG1) * 4 ;lea eax, [p + IsRepG2*4 + ebp*4] |
call RangeDecoderBitDecode |
xchg esi, [rep2] |
jnc @f |
xchg esi, [rep3] |
@@: |
.1101: |
mov eax, p + RepLencoder*4 |
call LzmaLenDecode |
push 8 |
jmp .rmu |
.10: |
xchg esi, [rep1] |
xchg esi, [rep2] |
mov [rep3], esi |
mov eax, p + Lencoder*4 |
call LzmaLenDecode |
push kNumLenToPosStates-1 |
pop edx |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
push ecx |
push kNumPosSlotBits |
pop ecx |
mov eax, p+PosSlot*4 |
shl edx, cl |
call RangeDecoderBitTreeDecode |
mov esi, ecx |
cmp ecx, kStartPosModelIndex |
jb .l6 |
mov edx, ecx |
xor eax, eax |
shr ecx, 1 |
adc al, 2 |
dec ecx |
shl eax, cl |
mov esi, eax |
sub eax, edx |
lea eax, [p + (SpecPos - 1)*4 + eax*4] |
cmp edx, kEndPosModelIndex |
jb .l59 |
; call RangeDecoderDecodeDirectBits |
;RangeDecoderDecodeDirectBits: |
xor eax, eax |
.l: |
shr dword [range], 1 |
add eax, eax |
mov edx, [code_] |
sub edx, [range] |
jb @f |
mov [code_], edx |
add al, 1 shl kNumAlignBits |
@@: |
call update_decoder |
dec ecx |
cmp ecx, kNumAlignBits |
jnz .l |
; ret |
add esi, eax |
mov eax, p+Align_*4 |
.l59: |
; call RangeDecoderReverseBitTreeDecode_addesi |
;_RangeDecoderReverseBitTreeDecode_addesi: |
; in: eax->probs,ecx=numLevels |
; out: esi+=length; destroys edx |
push edi |
xor edx, edx |
inc edx |
mov edi, edx |
@@: |
call RangeDecoderBitDecode_edx |
jnc .591 |
add esi, edi |
stc |
.591: |
adc edx, edx |
add edi, edi |
loop @b |
pop edi |
; ret |
.l6: |
pop ecx |
not esi |
push 7 |
.rmu: |
cmp ebp, 7 |
pop ebp |
jb @f |
add ebp, 3 |
@@: |
.repmovsb: |
inc ecx |
push esi |
add esi, edi |
rep movsb |
lodsb |
pop esi |
jmp .stosb_main_loop |
.main_loop_done: |
include 'calltrick2.asm' |
ret |
_RangeDecoderBitDecode: |
; in: eax->prob |
; out: CF=bit |
push edx |
mov edx, [range] |
shr edx, kNumBitModelTotalBits |
imul edx, [eax] |
cmp [code_], edx |
jae .ae |
mov [range], edx |
mov edx, kBitModelTotal |
sub edx, [eax] |
shr edx, kNumMoveBits |
add [eax], edx |
.n: |
pushfd |
call update_decoder |
popfd |
pop edx |
ret |
.ae: |
sub [range], edx |
sub [code_], edx |
mov edx, [eax] |
shr edx, kNumMoveBits |
sub [eax], edx |
stc |
jmp .n |
update_decoder: |
cmp byte [range+3], 0 ;cmp dword [range], kTopValue |
jnz @f ;jae @f |
shl dword [range], 8 |
shl dword [code_], 8 |
push eax |
mov eax, [inptr_ldr] |
mov al, [eax] |
inc dword [inptr_ldr] |
mov byte [code_], al |
pop eax |
@@: ret |
_RangeDecoderBitDecode_edx: |
push eax |
lea eax, [eax+edx*4] |
call RangeDecoderBitDecode |
pop eax |
ret |
LzmaLenDecode: |
; in: eax->prob, edx=posState |
; out: ecx=len |
; LenChoice==0 |
; add eax, LenChoice*4 |
if kLenNumMidBits <> kLenNumLowBits |
error in optimization |
end if |
mov cl, kLenNumMidBits |
call RangeDecoderBitDecode |
jnc .0 |
add eax, (LenChoice2-LenChoice)*4 |
call RangeDecoderBitDecode |
jc @f |
if (kLenNumMidBits <> 3) | (LenMid-LenChoice2 > 0x7F + kLenNumMidBits) |
shl edx, cl |
add edx, LenMid-LenChoice2 |
else |
lea edx, [ecx + edx*8 - kLenNumMidBits + LenMid-LenChoice2] |
end if |
push kLenNumLowSymbols |
jmp RangeDecoderBitTreeDecode.1 |
@@: |
mov edx, LenHigh-LenChoice2 |
mov cl, kLenNumHighBits |
push kLenNumLowSymbols + kLenNumMidSymbols |
jmp RangeDecoderBitTreeDecode.1 |
.0: |
shl edx, cl |
if LenLow = 2 |
inc edx |
inc edx |
else |
add edx, LenLow |
end if |
RangeDecoderBitTreeDecode: |
; in: eax+edx*4->probs,ecx=numLevels |
; out: ecx=length; destroys edx |
push 0 |
.1: |
lea eax, [eax+edx*4] |
xor edx, edx |
inc edx |
push ecx |
@@: |
call RangeDecoderBitDecode_edx |
adc edx, edx |
loop @b |
pop ecx |
btc edx, ecx |
pop ecx |
add ecx, edx |
ret |
loader_size = $ - loader_start |
/programs/other/kpack/kerpack_linux/lzma_c/LZMAEncoder.c |
---|
0,0 → 1,1078 |
#include "LZMAEncoder.h" |
#include "MatchFinder.h" |
const byte kLiteralNextStates[kNumStates] = {0,0,0,0,1,2,3,4,5,6,4,5}; |
const byte kMatchNextStates[kNumStates] = {7,7,7,7,7,7,7,10,10,10,10,10}; |
const byte kRepNextStates[kNumStates] = {8,8,8,8,8,8,8,11,11,11,11,11}; |
const byte kShortRepNextStates[kNumStates] = {9,9,9,9,9,9,9,11,11,11,11,11}; |
static CState _state; |
static byte _previousByte; |
static unsigned _repDistances[kNumRepDistances]; |
static COptimal _optimum[kNumOpts]; |
static CMyBitEncoder _isMatch[kNumStates][kNumPosStatesEncodingMax]; |
static CMyBitEncoder _isRep[kNumStates]; |
static CMyBitEncoder _isRepG0[kNumStates]; |
static CMyBitEncoder _isRepG1[kNumStates]; |
static CMyBitEncoder _isRepG2[kNumStates]; |
static CMyBitEncoder _isRep0Long[kNumStates][kNumPosStatesEncodingMax]; |
static NRangeCoder_CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; |
static CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; |
static NRangeCoder_CBitTreeEncoder _posAlignEncoder; |
static NLength_CPriceTableEncoder _lenEncoder; |
static NLength_CPriceTableEncoder _repMatchLenEncoder; |
static CLiteralEncoder _literalEncoder; |
static unsigned _matchDistances[kMatchMaxLen+1]; |
static unsigned _numFastBytes; |
static unsigned _longestMatchLength; |
static unsigned _additionalOffset; |
static unsigned _optimumEndIndex; |
static unsigned _optimumCurrentIndex; |
static bool _longestMatchWasFound; |
static unsigned _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; |
static unsigned _distancesPrices[kNumLenToPosStates][kNumFullDistances]; |
static unsigned _alignPrices[kAlignTableSize]; |
static unsigned _alignPriceCount; |
static unsigned _distTableSize; |
static unsigned _posStateBits; |
static unsigned _posStateMask; |
static unsigned _numLiteralPosStateBits; |
static unsigned _numLiteralContextBits; |
static unsigned _dictionarySize; |
static uint64 lastPosSlotFillingPos; |
static uint64 nowPos64; |
static bool _finished; |
static bool _writeEndMark; |
static byte g_FastPos[1024]; |
// must be called before work |
static void FastPosInit(void) |
{ |
int c = 2; |
int slotFast; |
unsigned j,k; |
g_FastPos[0] = 0; |
g_FastPos[1] = 1; |
for (slotFast = 2; slotFast < 20; slotFast++) |
{ |
k = (1 << ((slotFast >> 1) - 1)); |
for (j=0;j<k;j++) g_FastPos[c++] = slotFast; |
} |
} |
static unsigned GetPosSlot(unsigned pos) |
{ |
if (pos < (1<<10)) |
return g_FastPos[pos]; |
if (pos < (1<<19)) |
return g_FastPos[pos>>9]+18; |
return g_FastPos[pos>>18]+36; |
} |
static unsigned GetPosSlot2(unsigned pos) |
{ |
if (pos < (1<<16)) |
return g_FastPos[pos>>6]+12; |
if (pos < (1<<25)) |
return g_FastPos[pos>>15]+30; |
return g_FastPos[pos>>24]+48; |
} |
unsigned pack_length; |
unsigned pack_pos; |
const byte* curin; |
byte* curout; |
static void NLength_CEncoder_Init(NLength_CEncoder*e, unsigned numPosStates) |
{ |
unsigned posState; |
CMyBitEncoder_Init(e->_choice); |
CMyBitEncoder_Init(e->_choice2); |
for (posState=0;posState<numPosStates;posState++) |
{ |
CBitTreeEncoder_Init(&e->_lowCoder[posState],kNumLowBits); |
CBitTreeEncoder_Init(&e->_midCoder[posState],kNumMidBits); |
} |
CBitTreeEncoder_Init(&e->_highCoder,kNumHighBits); |
} |
static void NLength_CEncoder_Encode(NLength_CEncoder*e, unsigned symbol, unsigned posState) |
{ |
if (symbol < kNumLowSymbols) |
{ |
CMyBitEncoder_Encode(&e->_choice,0); |
CBitTreeEncoder_Encode(&e->_lowCoder[posState],symbol); |
} |
else |
{ |
CMyBitEncoder_Encode(&e->_choice,1); |
if (symbol < kNumLowSymbols + kNumMidSymbols) |
{ |
CMyBitEncoder_Encode(&e->_choice2,0); |
CBitTreeEncoder_Encode(&e->_midCoder[posState],symbol-kNumLowSymbols); |
} |
else |
{ |
CMyBitEncoder_Encode(&e->_choice2,1); |
CBitTreeEncoder_Encode(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); |
} |
} |
} |
static unsigned NLength_CEncoder_GetPrice(NLength_CEncoder*e, unsigned symbol, unsigned posState) |
{ |
unsigned price; |
if (symbol < kNumLowSymbols) |
return CMyBitEncoder_GetPrice0(&e->_choice) + |
CBitTreeEncoder_GetPrice(&e->_lowCoder[posState],symbol); |
price = CMyBitEncoder_GetPrice1(&e->_choice); |
if (symbol < kNumLowSymbols + kNumMidSymbols) |
{ |
price += CMyBitEncoder_GetPrice0(&e->_choice2); |
price += CBitTreeEncoder_GetPrice(&e->_midCoder[posState],symbol-kNumLowSymbols); |
} |
else |
{ |
price += CMyBitEncoder_GetPrice1(&e->_choice2); |
price += CBitTreeEncoder_GetPrice(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); |
} |
return price; |
} |
static void CPriceTableEncoder_SetTableSize(NLength_CPriceTableEncoder*pte,unsigned tableSize) |
{pte->_tableSize = tableSize;} |
static unsigned CPriceTableEncoder_GetPrice(NLength_CPriceTableEncoder*pte,unsigned symbol,unsigned posState) |
{return pte->_prices[symbol][posState];} |
static void CPriceTableEncoder_UpdateTable(NLength_CPriceTableEncoder*pte,unsigned posState) |
{ |
unsigned len; |
for (len=0;len<pte->_tableSize;len++) |
pte->_prices[len][posState] = NLength_CEncoder_GetPrice(&pte->base,len,posState); |
pte->_counters[posState] = pte->_tableSize; |
} |
static void CPriceTableEncoder_UpdateTables(NLength_CPriceTableEncoder*pte,unsigned numPosStates) |
{ |
unsigned posState; |
for (posState=0;posState<numPosStates;posState++) |
CPriceTableEncoder_UpdateTable(pte,posState); |
} |
static void CPriceTableEncoder_Encode(NLength_CPriceTableEncoder*pte, unsigned symbol, unsigned posState) |
{ |
NLength_CEncoder_Encode(&pte->base,symbol,posState); |
if (--pte->_counters[posState] == 0) |
CPriceTableEncoder_UpdateTable(pte,posState); |
} |
static void CBaseState_Init(void) |
{ |
unsigned i; |
CState_Init(_state); |
_previousByte = 0; |
for (i=0;i<kNumRepDistances;i++) |
_repDistances[i] = 0; |
} |
static void CLiteralEncoder2_Init(CLiteralEncoder2 le) |
{ |
int i; |
for (i=0;i<0x300;i++) |
CMyBitEncoder_Init(le[i]); |
} |
static void CLiteralEncoder2_Encode(CLiteralEncoder2 le, byte symbol) |
{ |
unsigned context = 1; |
int i; |
unsigned bit; |
for (i=8;i--;) |
{ |
bit = (symbol >> i) & 1; |
CMyBitEncoder_Encode(&le[context],bit); |
context = (context << 1) | bit; |
} |
} |
static void CLiteralEncoder2_EncodeMatched(CLiteralEncoder2 le, byte matchByte, byte symbol) |
{ |
unsigned context = 1; |
int i; |
unsigned bit,matchBit; |
for (i=8;i--;) |
{ |
bit = (symbol >> i) & 1; |
matchBit = (matchByte >> i) & 1; |
CMyBitEncoder_Encode(&le[0x100 + (matchBit<<8) + context],bit); |
context = (context << 1) | bit; |
if (matchBit != bit) |
{ |
while (i--) |
{ |
bit = (symbol >> i) & 1; |
CMyBitEncoder_Encode(&le[context],bit); |
context = (context << 1) | bit; |
} |
break; |
} |
} |
} |
static unsigned CLiteralEncoder2_GetPrice(CLiteralEncoder2 le, bool matchMode, byte matchByte, byte symbol) |
{ |
unsigned price = 0; |
unsigned context = 1; |
unsigned bit,matchBit; |
int i = 8; |
if (matchMode) |
{ |
do |
{ |
i--; |
matchBit = (matchByte >> i) & 1; |
bit = (symbol >> i) & 1; |
price += CMyBitEncoder_GetPrice(&le[0x100 + (matchBit<<8) + context],bit); |
context = (context << 1) | bit; |
if (matchBit != bit) |
break; |
} while (i); |
} |
while (i--) |
{ |
bit = (symbol >> i) & 1; |
price += CMyBitEncoder_GetPrice(&le[context],bit); |
context = (context << 1) | bit; |
} |
return price; |
} |
static void WriteEndMarker(unsigned posState) |
{ |
unsigned posSlot; |
if (!_writeEndMark) |
return; |
CMyBitEncoder_Encode(&_isMatch[_state][posState],1); |
CMyBitEncoder_Encode(&_isRep[_state],0); |
CState_UpdateMatch(_state); |
CPriceTableEncoder_Encode(&_lenEncoder,0,posState); |
posSlot = (1<<kNumPosSlotBits) - 1; |
CBitTreeEncoder_Encode(&_posSlotEncoder[GetLenToPosState(kMatchMinLen)],posSlot); |
RangeEncoder_EncodeDirectBits(((1<<30)-1)>>kNumAlignBits,30-kNumAlignBits); |
CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,((1<<30)-1) & kAlignMask); |
} |
static void CEncoder_Flush(void) |
{ |
WriteEndMarker((unsigned)nowPos64 & _posStateMask); |
RangeEncoder_FlushData(); |
} |
static void CLiteralEncoder_Create(CLiteralEncoder*le, byte** memory, int numPosBits, int numPrevBits) |
{ |
unsigned numStates; |
le->_coders = (CLiteralEncoder2*)*memory; |
numStates = 1 << (numPosBits+numPrevBits); |
*memory = (byte*)(le->_coders + numStates); |
le->_numPosBits = numPosBits; |
le->_posMask = (1<<numPosBits) - 1; |
le->_numPrevBits = numPrevBits; |
} |
static void CLiteralEncoder_Init(CLiteralEncoder*le) |
{ |
unsigned numStates,i; |
numStates = 1 << (le->_numPosBits + le->_numPrevBits); |
for (i=0;i<numStates;i++) |
CLiteralEncoder2_Init(le->_coders[i]); |
} |
static unsigned CLiteralEncoder_GetState(CLiteralEncoder*le,unsigned pos,byte prevByte) |
{return ((pos&le->_posMask)<<le->_numPrevBits)+(prevByte>>(8-le->_numPrevBits));} |
static CLiteralEncoder2* CLiteralEncoder_GetSubCoder(CLiteralEncoder*le,unsigned pos,byte prevByte) |
{return &le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)];} |
static unsigned CLiteralEncoder_GetPrice(CLiteralEncoder*le,unsigned pos,byte prevByte, |
bool matchMode, byte matchByte, byte symbol) |
{ |
return CLiteralEncoder2_GetPrice(le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)], |
matchMode, matchByte, symbol); |
} |
static void CEncoder_Create(void*workmem) |
{ |
byte* workpos = (byte*)workmem; |
/* align on dword boundary */ |
unsigned a; |
a = (unsigned)workpos & 3; |
if (a) workpos += 4-a; |
/* sizeof(CLiteralEncoder2) * (1<<(numPosBits+numPrevBits)) for literal encoders */ |
/* = 0xC00 * 8 = 0x6000 with current settings */ |
CLiteralEncoder_Create(&_literalEncoder,&workpos,_numLiteralPosStateBits,_numLiteralContextBits); |
/* (dictsize+0x1223)*1.5+256 for LZ input window */ |
/* (0x140400 + (dictsize+1)*2) * 4 for match finder hash */ |
MatchFinder_Create(_dictionarySize,kNumOpts,_numFastBytes, |
kMatchMaxLen*2+1-_numFastBytes,&workpos); |
/* total 0x508C3C + dictsize*9.5 */ |
/* plus max 6 bytes for alignment */ |
} |
static void CEncoder_Init(void) |
{ |
int i; |
unsigned j; |
CBaseState_Init(); |
RangeEncoder_Init(); |
for (i=0;i<kNumStates;i++) |
{ |
for (j=0;j<=_posStateMask;j++) |
{ |
CMyBitEncoder_Init(_isMatch[i][j]); |
CMyBitEncoder_Init(_isRep0Long[i][j]); |
} |
CMyBitEncoder_Init(_isRep[i]); |
CMyBitEncoder_Init(_isRepG0[i]); |
CMyBitEncoder_Init(_isRepG1[i]); |
CMyBitEncoder_Init(_isRepG2[i]); |
} |
CLiteralEncoder_Init(&_literalEncoder); |
for (i=0;i<kNumLenToPosStates;i++) |
CBitTreeEncoder_Init(_posSlotEncoder+i,kNumPosSlotBits); |
for (i=0;i<kNumFullDistances-kEndPosModelIndex;i++) |
CMyBitEncoder_Init(_posEncoders[i]); |
CPriceTableEncoder_Init(_lenEncoder, 1<<_posStateBits); |
CPriceTableEncoder_Init(_repMatchLenEncoder,1<<_posStateBits); |
CBitTreeEncoder_Init(&_posAlignEncoder,kNumAlignBits); |
_longestMatchWasFound = false; |
_optimumEndIndex = 0; |
_optimumCurrentIndex = 0; |
_additionalOffset = 0; |
} |
static void MovePos(unsigned num) |
{ |
for (;num--;) |
{ |
DummyLongestMatch(); |
MatchFinder_MovePos(); |
_additionalOffset++; |
} |
} |
static unsigned Backward(unsigned* backRes, unsigned cur) |
{ |
unsigned posMem,backMem; |
unsigned posPrev,backCur; |
_optimumEndIndex = cur; |
posMem = _optimum[cur].PosPrev; |
backMem = _optimum[cur].BackPrev; |
do |
{ |
if (_optimum[cur].Prev1IsChar) |
{ |
COptimal_MakeAsChar(&_optimum[posMem]); |
_optimum[posMem].PosPrev = posMem-1; |
if (_optimum[cur].Prev2) |
{ |
_optimum[posMem-1].Prev1IsChar = false; |
_optimum[posMem-1].PosPrev = _optimum[cur].PosPrev2; |
_optimum[posMem-1].BackPrev = _optimum[cur].BackPrev2; |
} |
} |
posPrev = posMem; |
backCur = backMem; |
backMem = _optimum[posPrev].BackPrev; |
posMem = _optimum[posPrev].PosPrev; |
_optimum[posPrev].BackPrev = backCur; |
_optimum[posPrev].PosPrev = cur; |
cur = posPrev; |
} while (cur); |
*backRes = _optimum[0].BackPrev; |
_optimumCurrentIndex = _optimum[0].PosPrev; |
return _optimumCurrentIndex; |
} |
static unsigned ReadMatchDistances(void) |
{ |
unsigned res; |
res = GetLongestMatch(_matchDistances); |
if (res == _numFastBytes) |
res += GetMatchLen(res,_matchDistances[res],kMatchMaxLen-res); |
_additionalOffset++; |
MatchFinder_MovePos(); |
return res; |
} |
static void FillPosSlotPrices(void) |
{ |
unsigned lenToPosState,posSlot; |
for (lenToPosState=0;lenToPosState<kNumLenToPosStates;lenToPosState++) |
{ |
for (posSlot=0;posSlot<kEndPosModelIndex && posSlot<_distTableSize;posSlot++) |
_posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot); |
for (;posSlot<_distTableSize;posSlot++) |
_posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot) + |
(((posSlot>>1)-1-kNumAlignBits)<<kNumBitPriceShiftBits); |
} |
} |
static void FillDistancesPrices(void) |
{ |
unsigned lenToPosState,i; |
unsigned posSlot,footerBits,base; |
for (lenToPosState=0;lenToPosState<kNumLenToPosStates;lenToPosState++) |
{ |
for (i=0;i<kStartPosModelIndex;i++) |
_distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; |
for (;i<kNumFullDistances;i++) |
{ |
posSlot = GetPosSlot(i); |
footerBits = ((posSlot>>1)-1); |
base = (2|(posSlot&1))<<footerBits; |
_distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + |
ReverseBitTreeGetPrice(_posEncoders+base-posSlot-1,footerBits,i-base); |
} |
} |
} |
static void FillAlignPrices(void) |
{ |
unsigned i; |
for (i=0;i<kAlignTableSize;i++) |
_alignPrices[i] = CBitTreeEncoder_ReverseGetPrice(&_posAlignEncoder,i); |
_alignPriceCount = kAlignTableSize; |
} |
static unsigned GetRepLen1Price(CState state, unsigned posState) |
{ |
return CMyBitEncoder_GetPrice0(&_isRepG0[state]) + |
CMyBitEncoder_GetPrice0(&_isRep0Long[state][posState]); |
} |
static unsigned GetRepPrice(unsigned repIndex, unsigned len, CState state, unsigned posState) |
{ |
unsigned price; |
price = CPriceTableEncoder_GetPrice(&_repMatchLenEncoder,len-kMatchMinLen,posState); |
if (!repIndex) |
{ |
price += CMyBitEncoder_GetPrice0(&_isRepG0[state]); |
price += CMyBitEncoder_GetPrice1(&_isRep0Long[state][posState]); |
} |
else |
{ |
price += CMyBitEncoder_GetPrice1(&_isRepG0[state]); |
if (repIndex == 1) |
price += CMyBitEncoder_GetPrice0(&_isRepG1[state]); |
else |
{ |
price += CMyBitEncoder_GetPrice1(&_isRepG1[state]); |
price += CMyBitEncoder_GetPrice(&_isRepG2[state],repIndex-2); |
} |
} |
return price; |
} |
static unsigned GetPosLenPrice(unsigned pos, unsigned len, unsigned posState) |
{ |
unsigned price,lenToPosState; |
if (len==2 && pos>=0x80) |
return kIfinityPrice; |
lenToPosState = GetLenToPosState(len); |
if (pos < kNumFullDistances) |
price = _distancesPrices[lenToPosState][pos]; |
else |
price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + |
_alignPrices[pos & kAlignMask]; |
return price + CPriceTableEncoder_GetPrice(&_lenEncoder,len-kMatchMinLen,posState); |
} |
static void GetOptimum(unsigned position,unsigned*backRes,unsigned*lenRes) |
{ |
int lenMain,lenEnd; |
COptimal* opt,*prevOpt; |
int reps[kNumRepDistances]; |
int repLens[kNumRepDistances]; |
int repIndex,repMaxIndex; |
int i,len,repLen,lenTest,newLen,lenTestTemp,lenTest2; |
int posState,posStateNext; |
byte currentByte,matchByte; |
unsigned matchPrice,repMatchPrice,shortRepPrice,normalMatchPrice,curAndLenPrice,curPrice,curAnd1Price,curAndLenCharPrice; |
unsigned nextMatchPrice,nextRepMatchPrice; |
int cur,posPrev,pos; |
CState state,state2; |
const byte* data; |
bool nextIsChar; |
int numAvailableBytesFull,numAvailableBytes; |
int backOffset,offset; |
int limit; |
if (_optimumEndIndex != _optimumCurrentIndex) |
{ |
opt = &_optimum[_optimumCurrentIndex]; |
*lenRes = opt->PosPrev - _optimumCurrentIndex; |
*backRes = opt->BackPrev; |
_optimumCurrentIndex = opt->PosPrev; |
return; |
} |
_optimumCurrentIndex = _optimumEndIndex = 0; |
if (!_longestMatchWasFound) |
lenMain = ReadMatchDistances(); |
else |
{ |
lenMain = _longestMatchLength; |
_longestMatchWasFound = false; |
} |
for (i=0;i<kNumRepDistances;i++) |
{ |
reps[i] = _repDistances[i]; |
repLens[i] = GetMatchLen(0-1,reps[i],kMatchMaxLen); |
if (i==0 || repLens[i] > repLens[repMaxIndex]) |
repMaxIndex = i; |
} |
if (repLens[repMaxIndex] >= _numFastBytes) |
{ |
*backRes = repMaxIndex; |
*lenRes = repLens[repMaxIndex]; |
MovePos(*lenRes-1); |
return; |
} |
if (lenMain >= _numFastBytes) |
{ |
*backRes = _matchDistances[_numFastBytes]+kNumRepDistances; |
*lenRes = lenMain; |
MovePos(lenMain-1); |
return; |
} |
currentByte = GetIndexByte(0-1); |
_optimum[0].State = _state; |
matchByte = GetIndexByte(0-_repDistances[0]-2); |
posState = position & _posStateMask; |
_optimum[1].Price = CMyBitEncoder_GetPrice0(&_isMatch[_state][posState]) + |
CLiteralEncoder_GetPrice(&_literalEncoder,position,_previousByte, |
(bool)!CState_IsCharState(_state),matchByte,currentByte); |
COptimal_MakeAsChar(&_optimum[1]); |
_optimum[1].PosPrev = 0; |
for (i=0;i<kNumRepDistances;i++) |
_optimum[0].Backs[i] = reps[i]; |
matchPrice = CMyBitEncoder_GetPrice1(&_isMatch[_state][posState]); |
repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[_state]); |
if (matchByte == currentByte) |
{ |
shortRepPrice = repMatchPrice + GetRepLen1Price(_state,posState); |
if (shortRepPrice < _optimum[1].Price) |
{ |
_optimum[1].Price = shortRepPrice; |
COptimal_MakeAsShortRep(&_optimum[1]); |
} |
} |
if (lenMain < 2) |
{ |
*backRes = _optimum[1].BackPrev; |
*lenRes = 1; |
return; |
} |
normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[_state]); |
if (lenMain <= repLens[repMaxIndex]) |
lenMain = 0; |
for (len=2;len<=lenMain;len++) |
{ |
_optimum[len].PosPrev = 0; |
_optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; |
_optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len],len,posState); |
_optimum[len].Prev1IsChar = false; |
} |
if (lenMain < repLens[repMaxIndex]) |
lenMain = repLens[repMaxIndex]; |
for (;len<=lenMain;len++) |
_optimum[len].Price = kIfinityPrice; |
for (i=0;i<kNumRepDistances;i++) |
{ |
repLen = repLens[i]; |
for (lenTest=2;lenTest<=repLen;lenTest++) |
{ |
curAndLenPrice = repMatchPrice + GetRepPrice(i,lenTest,_state,posState); |
opt = &_optimum[lenTest]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = 0; |
opt->BackPrev = i; |
opt->Prev1IsChar = false; |
} |
} |
} |
cur=0; |
lenEnd = lenMain; |
while (1) |
{ |
cur++; |
if (cur==lenEnd) |
{ |
*lenRes = Backward(backRes,cur); |
return; |
} |
position++; |
opt = &_optimum[cur]; |
posPrev = opt->PosPrev; |
if (opt->Prev1IsChar) |
{ |
posPrev--; |
if (opt->Prev2) |
{ |
state = _optimum[opt->PosPrev2].State; |
if (opt->BackPrev2 < kNumRepDistances) |
CState_UpdateRep(state); |
else |
CState_UpdateMatch(state); |
} |
else |
state = _optimum[posPrev].State; |
CState_UpdateChar(state); |
} |
else |
state = _optimum[posPrev].State; |
if (posPrev == cur-1) |
{ |
if (COptimal_IsShortRep(opt)) |
CState_UpdateShortRep(state); |
else |
CState_UpdateChar(state); |
} |
else |
{ |
if (opt->Prev1IsChar && opt->Prev2) |
{ |
posPrev = opt->PosPrev2; |
pos = opt->BackPrev2; |
CState_UpdateRep(state); |
} |
else |
{ |
pos = opt->BackPrev; |
if (pos < kNumRepDistances) |
CState_UpdateRep(state); |
else |
CState_UpdateMatch(state); |
} |
prevOpt = &_optimum[posPrev]; |
if (pos < kNumRepDistances) |
{ |
reps[0] = prevOpt->Backs[pos]; |
for (i=1;i<=pos;i++) |
reps[i] = prevOpt->Backs[i-1]; |
for (;i<kNumRepDistances;i++) |
reps[i] = prevOpt->Backs[i]; |
} |
else |
{ |
reps[0] = pos-kNumRepDistances; |
for (i=1;i<kNumRepDistances;i++) |
reps[i] = prevOpt->Backs[i-1]; |
} |
} |
opt->State = state; |
for (i=0;i<kNumRepDistances;i++) |
opt->Backs[i] = reps[i]; |
newLen = ReadMatchDistances(); |
if (newLen >= _numFastBytes) |
{ |
_longestMatchLength = newLen; |
_longestMatchWasFound = true; |
*lenRes = Backward(backRes,cur); |
return; |
} |
curPrice = opt->Price; |
data = GetPointerToCurrentPos()-1; |
currentByte = *data; |
matchByte = data[-1-reps[0]]; |
posState = position & _posStateMask; |
curAnd1Price = curPrice + CMyBitEncoder_GetPrice0(&_isMatch[state][posState]) + |
CLiteralEncoder_GetPrice(&_literalEncoder,position,data[-1],(bool)!CState_IsCharState(state),matchByte,currentByte); |
opt = &_optimum[cur+1]; |
nextIsChar = false; |
if (curAnd1Price < opt->Price) |
{ |
opt->Price = curAnd1Price; |
opt->PosPrev = cur; |
COptimal_MakeAsChar(opt); |
nextIsChar = true; |
} |
matchPrice = curPrice + CMyBitEncoder_GetPrice1(&_isMatch[state][posState]); |
repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[state]); |
if (matchByte == currentByte && !(opt->PosPrev<cur && !opt->BackPrev)) |
{ |
shortRepPrice = repMatchPrice + GetRepLen1Price(state,posState); |
if (shortRepPrice <= opt->Price) |
{ |
opt->Price = shortRepPrice; |
opt->PosPrev = cur; |
COptimal_MakeAsShortRep(opt); |
} |
} |
numAvailableBytesFull = GetNumAvailableBytes()+1; |
if (numAvailableBytesFull > kNumOpts-1-cur) |
numAvailableBytesFull = kNumOpts-1-cur; |
numAvailableBytes = numAvailableBytesFull; |
if (numAvailableBytes < 2) |
continue; |
if (numAvailableBytes > _numFastBytes) |
numAvailableBytes = _numFastBytes; |
if (numAvailableBytes >= 3 && !nextIsChar) |
{ |
// try Literal + rep0 |
int temp; |
backOffset = reps[0]+1; |
for (temp=1;temp<numAvailableBytes;temp++) |
if (data[temp]!=data[temp-backOffset]) |
break; |
lenTest = temp-1; |
if (lenTest>=2) |
{ |
int posStateNext; |
unsigned nextRepMatchPrice; |
state2 = state; |
CState_UpdateChar(state2); |
posStateNext = (position+1) & _posStateMask; |
nextRepMatchPrice = curAnd1Price + |
CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]) + |
CMyBitEncoder_GetPrice1(&_isRep[state2]); |
while (lenEnd < cur+1+lenTest) |
_optimum[++lenEnd].Price = kIfinityPrice; |
curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest,state2,posStateNext); |
opt = &_optimum[cur+1+lenTest]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = cur+1; |
opt->BackPrev = 0; |
opt->Prev1IsChar = true; |
opt->Prev2 = false; |
} |
} |
} |
for (repIndex=0;repIndex<kNumRepDistances;repIndex++) |
{ |
backOffset = reps[repIndex]+1; |
if (data[0] != data[0-backOffset] || |
data[1] != data[1-backOffset]) |
continue; |
for (lenTest=2;lenTest<numAvailableBytes;lenTest++) |
if (data[lenTest]!=data[lenTest-backOffset]) |
break; |
lenTestTemp = lenTest; |
do |
{ |
while (lenEnd < cur+lenTest) |
_optimum[++lenEnd].Price = kIfinityPrice; |
curAndLenPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState); |
opt = &_optimum[cur+lenTest]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = cur; |
opt->BackPrev = repIndex; |
opt->Prev1IsChar = false; |
} |
} while (--lenTest>=2); |
lenTest = lenTestTemp; |
lenTest2 = lenTest+1; |
limit = lenTest2 + _numFastBytes; |
if (limit > numAvailableBytesFull) |
limit = numAvailableBytesFull; |
for (;lenTest2<limit;lenTest2++) |
if (data[lenTest2] != data[lenTest2-backOffset]) |
break; |
lenTest2 -= lenTest+1; |
if (lenTest2 >= 2) |
{ |
unsigned nextMatchPrice,nextRepMatchPrice; |
int offset; |
state2 = state; |
CState_UpdateRep(state2); |
posStateNext = (position+lenTest)&_posStateMask; |
curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState) + |
CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + |
CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); |
CState_UpdateChar(state2); |
posStateNext = (position+lenTest+1)&_posStateMask; |
nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); |
nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); |
offset = lenTest+1+lenTest2; |
while (lenEnd<cur+offset) |
_optimum[++lenEnd].Price = kIfinityPrice; |
curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext); |
opt = &_optimum[cur+offset]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = cur+lenTest+1; |
opt->BackPrev = 0; |
opt->Prev1IsChar = true; |
opt->Prev2 = true; |
opt->PosPrev2 = cur; |
opt->BackPrev2 = repIndex; |
} |
} |
} |
if (newLen > numAvailableBytes) |
newLen = numAvailableBytes; |
if (newLen >= 2) |
{ |
if (newLen==2 && _matchDistances[2] >= 0x80) |
continue; |
normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[state]); |
while (lenEnd < cur+newLen) |
_optimum[++lenEnd].Price = kIfinityPrice; |
for (lenTest=newLen;lenTest>=2;lenTest--) |
{ |
backOffset = _matchDistances[lenTest]; |
curAndLenPrice = normalMatchPrice + GetPosLenPrice(backOffset,lenTest,posState); |
opt = &_optimum[cur+lenTest]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = cur; |
opt->BackPrev = backOffset+kNumRepDistances; |
opt->Prev1IsChar = false; |
} |
if (lenTest==newLen || backOffset!=_matchDistances[lenTest+1]) |
{ |
// Try Match + Literal + Rep0 |
backOffset++; |
lenTest2 = lenTest+1; |
limit = lenTest2+_numFastBytes; |
if (limit > numAvailableBytesFull) |
limit = numAvailableBytesFull; |
for (;lenTest2<limit;lenTest2++) |
if (data[lenTest2]!=data[lenTest2-backOffset]) |
break; |
lenTest2 -= lenTest+1; |
if (lenTest2 >= 2) |
{ |
state2 = state; |
CState_UpdateMatch(state2); |
posStateNext = (position+lenTest)&_posStateMask; |
curAndLenCharPrice = curAndLenPrice + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + |
CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); |
CState_UpdateChar(state2); |
posStateNext = (position+lenTest+1)&_posStateMask; |
nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); |
nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); |
offset = lenTest+1+lenTest2; |
while (lenEnd<cur+offset) |
_optimum[++lenEnd].Price = kIfinityPrice; |
curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext); |
opt = &_optimum[cur+offset]; |
if (curAndLenPrice < opt->Price) |
{ |
opt->Price = curAndLenPrice; |
opt->PosPrev = cur+lenTest+1; |
opt->BackPrev = 0; |
opt->Prev1IsChar = true; |
opt->Prev2 = true; |
opt->PosPrev2 = cur; |
opt->BackPrev2 = backOffset - 1 + kNumRepDistances; |
} |
} |
} |
} |
} |
} |
} |
static bool CodeOneBlock(void) |
{ |
unsigned posState; |
byte curByte,matchByte; |
unsigned pos,len,distance,i; |
unsigned posSlot,lenToPosState; |
CLiteralEncoder2* subCoder; |
uint64 progressPosValuePrev; |
if (_finished) |
return false; |
_finished = true; |
progressPosValuePrev = nowPos64; |
if (nowPos64 == 0) |
{ |
if (GetNumAvailableBytes() == 0) |
{ |
CEncoder_Flush(); |
return false; |
} |
ReadMatchDistances(); |
posState = (unsigned)nowPos64 & _posStateMask; |
CMyBitEncoder_Encode(&_isMatch[_state][posState],0); |
CState_UpdateChar(_state); |
curByte = GetIndexByte(0 - _additionalOffset); |
CLiteralEncoder2_Encode( |
*CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,_previousByte), |
curByte); |
_previousByte = curByte; |
_additionalOffset--; |
nowPos64++; |
} |
if (GetNumAvailableBytes() == 0) |
{ |
CEncoder_Flush(); |
return false; |
} |
for (;;) |
{ |
posState = (unsigned)nowPos64 & _posStateMask; |
GetOptimum((unsigned)nowPos64,&pos,&len); |
if (len==1 && pos==0xFFFFFFFF) |
{ |
CMyBitEncoder_Encode(&_isMatch[_state][posState],0); |
curByte = GetIndexByte(0-_additionalOffset); |
subCoder = CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64, |
_previousByte); |
if (!CState_IsCharState(_state)) |
{ |
matchByte = GetIndexByte(0-_repDistances[0]-1-_additionalOffset); |
CLiteralEncoder2_EncodeMatched(*subCoder,matchByte,curByte); |
} |
else |
CLiteralEncoder2_Encode(*subCoder,curByte); |
CState_UpdateChar(_state); |
_previousByte = curByte; |
} |
else |
{ |
CMyBitEncoder_Encode(&_isMatch[_state][posState],1); |
if (pos < kNumRepDistances) |
{ |
CMyBitEncoder_Encode(&_isRep[_state],1); |
if (pos==0) |
{ |
CMyBitEncoder_Encode(&_isRepG0[_state],0); |
CMyBitEncoder_Encode(&_isRep0Long[_state][posState], |
(len==1) ? 0 : 1); |
} |
else |
{ |
CMyBitEncoder_Encode(&_isRepG0[_state],1); |
if (pos==1) |
CMyBitEncoder_Encode(&_isRepG1[_state],0); |
else |
{ |
CMyBitEncoder_Encode(&_isRepG1[_state],1); |
CMyBitEncoder_Encode(&_isRepG2[_state],pos-2); |
} |
} |
if (len==1) |
CState_UpdateShortRep(_state); |
else |
{ |
CPriceTableEncoder_Encode(&_repMatchLenEncoder,len-kMatchMinLen,posState); |
CState_UpdateRep(_state); |
} |
distance = _repDistances[pos]; |
if (pos) |
{ |
for (i=pos;i;i--) |
_repDistances[i] = _repDistances[i-1]; |
_repDistances[0] = distance; |
} |
} |
else |
{ |
CMyBitEncoder_Encode(&_isRep[_state],0); |
CState_UpdateMatch(_state); |
CPriceTableEncoder_Encode(&_lenEncoder,len-kMatchMinLen,posState); |
pos -= kNumRepDistances; |
posSlot = GetPosSlot(pos); |
lenToPosState = GetLenToPosState(len); |
CBitTreeEncoder_Encode(&_posSlotEncoder[lenToPosState],posSlot); |
if (posSlot >= kStartPosModelIndex) |
{ |
unsigned footerBits; |
unsigned base,posReduced; |
footerBits = (posSlot>>1)-1; |
base = (2 | (posSlot&1)) << footerBits; |
posReduced = pos-base; |
if (posSlot < kEndPosModelIndex) |
ReverseBitTreeEncode(_posEncoders+base-posSlot-1, |
footerBits,posReduced); |
else |
{ |
RangeEncoder_EncodeDirectBits(posReduced>>kNumAlignBits,footerBits-kNumAlignBits); |
CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,posReduced&kAlignMask); |
if (--_alignPriceCount == 0) |
FillAlignPrices(); |
} |
} |
distance = pos; |
for (i=kNumRepDistances-1;i;i--) |
_repDistances[i] = _repDistances[i-1]; |
_repDistances[0] = distance; |
} |
_previousByte = GetIndexByte(len-1-_additionalOffset); |
} |
_additionalOffset -= len; |
nowPos64 += len; |
if (nowPos64 - lastPosSlotFillingPos >= (1<<9)) |
{ |
FillPosSlotPrices(); |
FillDistancesPrices(); |
lastPosSlotFillingPos = nowPos64; |
} |
if (!_additionalOffset) |
{ |
if (GetNumAvailableBytes() == 0) |
{ |
CEncoder_Flush(); |
return false; |
} |
if (nowPos64 - progressPosValuePrev >= (1<<12)) |
{ |
_finished = false; |
return true; |
} |
} |
} |
} |
extern void __stdcall lzma_set_dict_size( |
unsigned logdictsize) |
{ |
_dictionarySize = 1 << logdictsize; |
_distTableSize = logdictsize*2; |
} |
extern unsigned __stdcall lzma_compress( |
const void* source, |
void* destination, |
unsigned length, |
void* workmem) |
{ |
FastPosInit(); |
//memset(&encoder,0,sizeof(encoder)); |
//memset(&rangeEncoder,0,sizeof(rangeEncoder)); |
// CEncoder::CEncoder, CEncoder::SetCoderProperties |
_numFastBytes = 128; |
#ifdef FOR_KERPACK |
_posStateBits = 0; |
_posStateMask = 0; |
#else |
_posStateBits = 2; |
_posStateMask = 3; |
#endif |
_numLiteralContextBits = 3; |
_numLiteralPosStateBits = 0; |
_writeEndMark = false; |
// CEncoder::Code - ïîåõàëè! |
_finished = false; |
CEncoder_Create(workmem); |
CEncoder_Init(); |
FillPosSlotPrices(); |
FillDistancesPrices(); |
FillAlignPrices(); |
CPriceTableEncoder_SetTableSize(&_lenEncoder,_numFastBytes+1-kMatchMinLen); |
CPriceTableEncoder_UpdateTables(&_lenEncoder,1<<_posStateBits); |
CPriceTableEncoder_SetTableSize(&_repMatchLenEncoder,_numFastBytes+1-kMatchMinLen); |
CPriceTableEncoder_UpdateTables(&_repMatchLenEncoder,1<<_posStateBits); |
lastPosSlotFillingPos = 0; |
nowPos64 = 0; |
pack_length = length; |
pack_pos = 0; |
curin = (const byte*)source; |
curout = (byte*)destination; |
MatchFinder_Init(); |
while (CodeOneBlock()) ; |
return curout - (byte*)destination; |
} |
/programs/other/kpack/kerpack_linux/lzma_c/LZMAEncoder.h |
---|
0,0 → 1,53 |
#ifndef _LZMA_ENCODER_H |
#define _LZMA_ENCODER_H |
#include "lzma.h" |
#include "RangeCoderBitTree.h" |
typedef struct |
{ |
CState State; |
bool Prev1IsChar; |
bool Prev2; |
unsigned PosPrev2; |
unsigned BackPrev2; |
unsigned Price; |
unsigned PosPrev; |
unsigned BackPrev; |
unsigned Backs[kNumRepDistances]; |
} COptimal; |
#define COptimal_MakeAsChar(a) (a)->BackPrev=(unsigned)-1,(a)->Prev1IsChar=false |
#define COptimal_MakeAsShortRep(a) (a)->BackPrev=0,(a)->Prev1IsChar=false |
#define COptimal_IsShortRep(a) ((a)->BackPrev==0) |
#define kIfinityPrice 0xFFFFFFF |
#define kNumOpts (1<<12) |
typedef CMyBitEncoder CLiteralEncoder2[0x300]; |
typedef struct |
{ |
CLiteralEncoder2* _coders; |
int _numPrevBits; |
int _numPosBits; |
unsigned _posMask; |
} CLiteralEncoder; |
typedef struct |
{ |
CMyBitEncoder _choice; |
CMyBitEncoder _choice2; |
NRangeCoder_CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; |
NRangeCoder_CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; |
NRangeCoder_CBitTreeEncoder _highCoder; |
} NLength_CEncoder; |
typedef struct |
{ |
NLength_CEncoder base; |
unsigned _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; |
unsigned _tableSize; |
unsigned _counters[kNumPosStatesEncodingMax]; |
} NLength_CPriceTableEncoder; |
#define CPriceTableEncoder_Init(a,b) NLength_CEncoder_Init(&a.base,b) |
#endif |
/programs/other/kpack/kerpack_linux/lzma_c/MatchFinder.c |
---|
0,0 → 1,422 |
#include "MatchFinder.h" |
/* memcpy must be inlined - we do not want to use RTL */ |
#include <memory.h> |
/*#pragma function(memcpy) |
void* __cdecl memcpy(void* _Dst, const void* _Src, size_t _Size) |
{ |
unsigned long i; |
for (i = 0; i < _Size; i++) |
((char*)_Dst)[i] = ((char*)_Src)[i]; |
return _Dst; |
}*/ |
//#pragma intrinsic(memcpy) |
#define kMaxValForNormalize (((unsigned)1<<31)-1) |
/* settings for bt4: |
defined HASH_ARRAY_2 |
defined HASH_ARRAY_3 |
*/ |
//#define kHash2Size 0x400 |
#define kNumHashDirectBytes 0 |
#define kNumHashBytes 3 |
//#define kHash3Size 0x40000 |
#define kHash2Size 0x10000 |
#define kHashSize 0x100000 |
#define kHashSizeSum (kHashSize+kHash2Size) |
#define kHash2Offset kHashSize |
static unsigned _cyclicBufferPos; |
static unsigned _cyclicBufferSize; |
static unsigned _matchMaxLen; |
static unsigned* _hash; |
static unsigned _cutValue; |
#ifdef GENERIC_INPUT |
static byte* _bufferBase; |
static unsigned _posLimit; |
static bool _streamEndWasReached; |
static byte* _pointerToLastSafePosition; |
static byte* _buffer; |
static unsigned _blockSize; |
static unsigned _pos; |
static unsigned _keepSizeBefore; |
static unsigned _keepSizeAfter; |
static unsigned _keepSizeReserv; |
static unsigned _streamPos; |
#else |
#define _buffer curin |
#define _pos pack_pos |
#define _streamPos pack_length |
#endif |
#ifdef GENERIC_INPUT |
/* LZ Window */ |
static void LZInWindow_Create(unsigned keepSizeBefore,unsigned keepSizeAfter,unsigned keepSizeReserv,byte**mem) |
{ |
_keepSizeBefore = keepSizeBefore; |
_keepSizeAfter = keepSizeAfter; |
_keepSizeReserv = keepSizeReserv; |
_blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; |
_bufferBase = *mem; |
_blockSize = (_blockSize + 3) & ~3; |
*mem += _blockSize; |
_pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; |
} |
static void ReadBlock(void) |
{ |
if (_streamEndWasReached) |
return; |
for (;;) |
{ |
unsigned size; |
size = (unsigned)(_bufferBase-_buffer) + _blockSize - _streamPos; |
if (!size) return; |
if (size > pack_length - pack_pos) |
size = pack_length - pack_pos; |
memcpy(_buffer+_streamPos,curin,size); |
curin += size; |
pack_pos += size; |
if (size == 0) |
{ |
byte* pointerToPosition; |
_posLimit = _streamPos; |
pointerToPosition = _buffer + _posLimit; |
if (pointerToPosition > _pointerToLastSafePosition) |
_posLimit = _pointerToLastSafePosition - _buffer; |
_streamEndWasReached = true; |
return; |
} |
_streamPos += size; |
if (_streamPos >= _pos + _keepSizeAfter) |
{ |
_posLimit = _streamPos - _keepSizeAfter; |
return; |
} |
} |
} |
static void LZInWindow_Init(void) |
{ |
_buffer = _bufferBase; |
_pos = 0; |
_streamPos = 0; |
_streamEndWasReached = false; |
ReadBlock(); |
} |
#else |
#define LZInWindow_Create(a,b,c,d) /* nothing */ |
#define LZInWindow_Init() _buffer--, _pos++, _streamPos++ |
#endif |
const byte* GetPointerToCurrentPos(void) {return _buffer+_pos;} |
#ifdef GENERIC_INPUT |
static void MoveBlock(void) |
{ |
unsigned offset,numBytes; |
offset = _buffer-_bufferBase+_pos-_keepSizeBefore; |
numBytes = _buffer-_bufferBase+_streamPos-offset; |
// copying backwards: safe to use memcpy instead of memmove |
memcpy(_bufferBase,_bufferBase+offset,numBytes); |
_buffer -= offset; |
} |
static void LZInWindow_MovePos(void) |
{ |
_pos++; |
if (_pos > _posLimit) |
{ |
const byte* pointerToPosition = _buffer+_pos; |
if (pointerToPosition > _pointerToLastSafePosition) |
MoveBlock(); |
ReadBlock(); |
} |
} |
#else |
#define LZInWindow_MovePos() _pos++ |
#endif |
byte GetIndexByte(int index) {return _buffer[_pos+index];} |
unsigned GetMatchLen(int index,unsigned distance,unsigned limit) |
{ |
const byte* pby; |
unsigned i; |
#ifdef GENERIC_INPUT |
if (_streamEndWasReached) |
if ((_pos+index)+limit > _streamPos) |
limit = _streamPos - (_pos+index); |
#else |
unsigned limit2 = pack_length - (pack_pos + index); |
if (limit > limit2) |
limit = limit2; |
#endif |
distance++; |
pby = _buffer + _pos + index; |
for (i=0;i<limit && pby[i]==pby[(int)(i-distance)];i++) ; |
return i; |
} |
unsigned GetNumAvailableBytes(void) {return _streamPos-_pos;} |
#ifdef GENERIC_INPUT |
void ReduceOffsets(int subValue) |
{ |
_buffer += subValue; |
_posLimit -= subValue; |
_pos -= subValue; |
_streamPos -= subValue; |
} |
#else |
#define ReduceOffsets(a) /* nothing */ |
#endif |
/* Binary tree Match Finder */ |
static unsigned crc_table[256]; |
void MatchFinder_Create(unsigned historySize,unsigned keepAddBufferBefore,unsigned matchMaxLen,unsigned keepAddBufferAfter,byte**mem) |
{ |
unsigned sizeReserv; |
sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter)/2+256; |
LZInWindow_Create(historySize+keepAddBufferBefore,matchMaxLen+keepAddBufferAfter,sizeReserv,mem); |
_matchMaxLen = matchMaxLen; |
_cyclicBufferSize = historySize+1; |
_hash = (unsigned*)*mem; |
*mem += (kHashSizeSum + _cyclicBufferSize*2) * sizeof(unsigned); |
_cutValue = 0xFF; |
} |
void MatchFinder_Init(void) |
{ |
unsigned i,j,r; |
LZInWindow_Init(); |
for (i=0;i<kHashSizeSum;i++) |
_hash[i] = 0; |
_cyclicBufferPos = 0; |
ReduceOffsets(-1); |
for (i=0;i<256;i++) |
{ |
r = i; |
for (j=0;j<8;j++) |
{ |
if (r & 1) |
r = (r>>1) ^ 0xEDB88320; |
else |
r >>= 1; |
} |
crc_table[i] = r; |
} |
} |
static unsigned Hash(const byte* ptr, unsigned* hash2Value) |
{ |
unsigned temp; |
temp = crc_table[ptr[0]] ^ ptr[1]; |
*hash2Value = *(word*)ptr; //ptr[0] + ((unsigned)ptr[1] << 8); |
return (temp ^ ((unsigned)ptr[2]<<8)) & (kHashSize - 1); |
} |
unsigned GetLongestMatch(unsigned* distances) |
{ |
unsigned lenLimit,maxLen=0; |
unsigned matchMinPos; |
const byte* cur; |
unsigned hash2Value,hashValue; |
unsigned curMatch,curMatch2; |
unsigned *son,*ptr0,*ptr1; |
unsigned len0,len1,count; |
if (_pos + _matchMaxLen <= _streamPos) |
lenLimit = _matchMaxLen; |
else |
{ |
lenLimit = _streamPos - _pos; |
if (lenLimit < kNumHashBytes) |
return 0; |
} |
matchMinPos = (_pos>_cyclicBufferSize) ? (_pos-_cyclicBufferSize) : 0; |
cur = _buffer+_pos; |
hashValue = Hash(cur,&hash2Value); |
curMatch = _hash[hashValue]; |
curMatch2 = _hash[kHash2Offset + hash2Value]; |
_hash[kHash2Offset + hash2Value] = _pos; |
distances[2] = 0xFFFFFFFF; |
if (curMatch2 > matchMinPos) |
//if (_buffer[curMatch2] == cur[0]) |
{ |
distances[2] = _pos - curMatch2 - 1; |
maxLen = 2; |
} |
_hash[hashValue] = _pos; |
son = _hash + kHashSizeSum; |
ptr0 = son + (_cyclicBufferPos << 1) + 1; |
ptr1 = son + (_cyclicBufferPos << 1); |
distances[kNumHashBytes] = 0xFFFFFFFF; |
len0 = len1 = kNumHashDirectBytes; |
count = _cutValue; |
for (;;) |
{ |
const byte* pb; |
unsigned len,delta; |
unsigned cyclicPos; |
unsigned* pair; |
if (curMatch <= matchMinPos || count--==0) |
{ |
*ptr0 = *ptr1 = 0; |
break; |
} |
pb = _buffer+curMatch; |
len = (len0<len1) ? len0 : len1; |
do |
if (pb[len] != cur[len]) break; |
while (++len != lenLimit); |
delta = _pos - curMatch; |
while (maxLen < len) |
distances[++maxLen] = delta-1; |
cyclicPos = (delta <= _cyclicBufferPos) ? |
(_cyclicBufferPos - delta) : |
(_cyclicBufferPos - delta + _cyclicBufferSize); |
pair = son + (cyclicPos<<1); |
if (len != lenLimit) |
{ |
if (pb[len] < cur[len]) |
{ |
*ptr1 = curMatch; |
ptr1 = pair+1; |
curMatch = *ptr1; |
len1 = len; |
} |
else |
{ |
*ptr0 = curMatch; |
ptr0 = pair; |
curMatch = *ptr0; |
len0 = len; |
} |
} |
else |
{ |
*ptr1 = pair[0]; |
*ptr0 = pair[1]; |
break; |
} |
} |
/*if (distances[4] < distances[3]) |
distances[3] = distances[4]; |
if (distances[3] < distances[2]) |
distances[2] = distances[3];*/ |
return maxLen; |
} |
void DummyLongestMatch(void) |
{ |
unsigned lenLimit; |
unsigned matchMinPos; |
const byte* cur; |
unsigned hash2Value,hashValue; |
unsigned curMatch; |
unsigned* son,*ptr0,*ptr1; |
unsigned len0,len1,count; |
if (_pos + _matchMaxLen <= _streamPos) |
lenLimit = _matchMaxLen; |
else |
{ |
lenLimit = _streamPos - _pos; |
if (lenLimit < kNumHashBytes) |
return; |
} |
matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; |
cur = _buffer+_pos; |
hashValue = Hash(cur,&hash2Value); |
_hash[kHash2Offset + hash2Value] = _pos; |
curMatch = _hash[hashValue]; |
_hash[hashValue] = _pos; |
son = _hash+kHashSizeSum; |
ptr0 = son + (_cyclicBufferPos << 1) + 1; |
ptr1 = son + (_cyclicBufferPos << 1); |
len0 = len1 = kNumHashDirectBytes; |
count = _cutValue; |
for (;;) |
{ |
const byte* pb; |
unsigned len; |
unsigned delta,cyclicPos; |
unsigned* pair; |
if (curMatch <= matchMinPos || count--==0) |
break; |
pb = _buffer+curMatch; |
len = (len0<len1) ? len0 : len1; |
do |
if (pb[len] != cur[len]) break; |
while (++len != lenLimit); |
delta = _pos - curMatch; |
cyclicPos = (delta <= _cyclicBufferPos) ? |
(_cyclicBufferPos - delta) : |
(_cyclicBufferPos - delta + _cyclicBufferSize); |
pair = son + (cyclicPos << 1); |
if (len != lenLimit) |
{ |
if (pb[len] < cur[len]) |
{ |
*ptr1 = curMatch; |
ptr1 = pair+1; |
curMatch = *ptr1; |
len1 = len; |
} |
else |
{ |
*ptr0 = curMatch; |
ptr0 = pair; |
curMatch = *ptr0; |
len0 = len; |
} |
} |
else |
{ |
*ptr1 = pair[0]; |
*ptr0 = pair[1]; |
return; |
} |
} |
*ptr0 = *ptr1 = 0; |
} |
#ifdef GENERIC_INPUT |
// for memory input size is always less than kMaxValForNormalize |
static void Normalize(void) |
{ |
unsigned subValue; |
unsigned* items; |
unsigned i,numItems; |
subValue = _pos - _cyclicBufferSize; |
items = _hash; |
numItems = (kHashSizeSum + _cyclicBufferSize*2); |
for (i=0;i<numItems;i++) |
{ |
unsigned value; |
value = items[i]; |
if (value <= subValue) |
value = 0; |
else |
value -= subValue; |
items[i] = value; |
} |
ReduceOffsets(subValue); |
} |
#endif |
void MatchFinder_MovePos(void) |
{ |
if (++_cyclicBufferPos == _cyclicBufferSize) |
_cyclicBufferPos = 0; |
LZInWindow_MovePos(); |
#ifdef GENERIC_INPUT |
if (_pos == kMaxValForNormalize) |
Normalize(); |
#endif |
} |
/programs/other/kpack/kerpack_linux/lzma_c/MatchFinder.h |
---|
0,0 → 1,13 |
#include "common.h" |
extern const byte* GetPointerToCurrentPos(void); |
extern byte GetIndexByte(int index); |
extern unsigned GetMatchLen(int index,unsigned distance,unsigned limit); |
extern unsigned GetNumAvailableBytes(void); |
extern void ReduceOffsets(int subValue); |
extern void MatchFinder_Init(void); |
extern void MatchFinder_Create(unsigned historySize,unsigned keepAddBufferBefore,unsigned matchMaxLen,unsigned keepAddBufferAfter,byte**mem); |
extern unsigned GetLongestMatch(unsigned*distances); |
extern void DummyLongestMatch(void); |
extern void MatchFinder_MovePos(void); |
/programs/other/kpack/kerpack_linux/lzma_c/RangeCoder.c |
---|
0,0 → 1,191 |
#include "RangeCoderBitTree.h" |
#include "lzma.h" |
static unsigned _cacheSize; |
static byte _cache; |
static uint64 low; |
static unsigned range; |
static unsigned PriceTable[kBitModelTotal >> kNumMoveReducingBits]; |
void RangeEncoder_Init(void) |
{ |
int i; |
unsigned start,end,j; |
low = 0; |
range = 0xFFFFFFFF; |
_cacheSize = 1; |
_cache = 0; |
/* init price table */ |
#define kNumBits (kNumBitModelTotalBits - kNumMoveReducingBits) |
for (i=kNumBits;i--;) |
{ |
start = 1 << (kNumBits - i - 1); |
end = 1 << (kNumBits - i); |
for (j=start;j<end;j++) |
PriceTable[j] = (i<<kNumBitPriceShiftBits) + |
(((end-j)<<kNumBitPriceShiftBits) >> (kNumBits - i - 1)); |
} |
#undef kNumBits |
} |
void RangeEncoder_ShiftLow(void) |
{ |
if ((unsigned)low < 0xFF000000U || (int)(low>>32)) |
{ |
byte temp = _cache; |
do |
{ |
*curout++ = (byte)(temp + (byte)(low>>32)); |
temp = 0xFF; |
} while (--_cacheSize); |
_cache = (byte)((unsigned)low>>24); |
} |
_cacheSize++; |
low = (unsigned)low << 8; |
} |
void RangeEncoder_FlushData(void) |
{ |
int i; |
for (i=0;i<5;i++) |
RangeEncoder_ShiftLow(); |
} |
void RangeEncoder_EncodeDirectBits(unsigned value,int numTotalBits) |
{ |
int i; |
for (i=numTotalBits;i--;) |
{ |
range >>= 1; |
if (((value >> i) & 1) == 1) |
low += range; |
if (range < kTopValue) |
{ |
range <<= 8; |
RangeEncoder_ShiftLow(); |
} |
} |
} |
void CMyBitEncoder_Encode(CMyBitEncoder* e,unsigned symbol) |
{ |
unsigned newBound; |
newBound = (range >> kNumBitModelTotalBits) * *e; |
if (symbol == 0) |
{ |
range = newBound; |
*e += (kBitModelTotal - *e) >> kNumMoveBits; |
} |
else |
{ |
low += newBound; |
range -= newBound; |
*e -= *e >> kNumMoveBits; |
} |
if (range < kTopValue) |
{ |
range <<= 8; |
RangeEncoder_ShiftLow(); |
} |
} |
unsigned CMyBitEncoder_GetPrice(CMyBitEncoder* e, unsigned symbol) |
{ |
return PriceTable[(((*e-symbol)^((-(int)symbol))) & (kBitModelTotal-1)) >> kNumMoveReducingBits]; |
} |
unsigned CMyBitEncoder_GetPrice0(CMyBitEncoder* e) |
{ |
return PriceTable[*e >> kNumMoveReducingBits]; |
} |
unsigned CMyBitEncoder_GetPrice1(CMyBitEncoder* e) |
{ |
return PriceTable[(kBitModelTotal - *e) >> kNumMoveReducingBits]; |
} |
void CBitTreeEncoder_Init(NRangeCoder_CBitTreeEncoder*e,int numBitLevels) |
{ |
unsigned i; |
e->numBitLevels = numBitLevels; |
for (i=1;i<((unsigned)1<<numBitLevels);i++) |
CMyBitEncoder_Init(e->Models[i]); |
} |
void CBitTreeEncoder_Encode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) |
{ |
unsigned modelIndex = 1; |
int bitIndex; |
unsigned bit; |
for (bitIndex = e->numBitLevels; bitIndex--;) |
{ |
bit = (symbol >> bitIndex) & 1; |
CMyBitEncoder_Encode(&e->Models[modelIndex],bit); |
modelIndex = (modelIndex << 1) | bit; |
} |
} |
void CBitTreeEncoder_ReverseEncode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) |
{ |
unsigned modelIndex = 1; |
int i; |
unsigned bit; |
for (i=0;i<e->numBitLevels;i++) |
{ |
bit = symbol & 1; |
CMyBitEncoder_Encode(&e->Models[modelIndex],bit); |
modelIndex = (modelIndex << 1) | bit; |
symbol >>= 1; |
} |
} |
unsigned CBitTreeEncoder_GetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) |
{ |
unsigned price = 0; |
symbol |= (1 << e->numBitLevels); |
while (symbol != 1) |
{ |
price += CMyBitEncoder_GetPrice(&e->Models[symbol>>1],symbol&1); |
symbol >>= 1; |
} |
return price; |
} |
unsigned CBitTreeEncoder_ReverseGetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) |
{ |
unsigned price=0; |
unsigned modelIndex=1; |
int i; |
unsigned bit; |
for (i=e->numBitLevels;i;i--) |
{ |
bit = symbol&1; |
symbol >>= 1; |
price += CMyBitEncoder_GetPrice(&e->Models[modelIndex],bit); |
modelIndex = (modelIndex<<1)|bit; |
} |
return price; |
} |
unsigned ReverseBitTreeGetPrice(CMyBitEncoder*Models,unsigned NumBitLevels,unsigned symbol) |
{ |
unsigned price=0; |
unsigned modelIndex=1; |
unsigned bit; |
int i; |
for (i=NumBitLevels;i;i--) |
{ |
bit = symbol & 1; |
symbol >>= 1; |
price += CMyBitEncoder_GetPrice(Models+modelIndex,bit); |
modelIndex = (modelIndex<<1)|bit; |
} |
return price; |
} |
void ReverseBitTreeEncode(CMyBitEncoder*Models,int NumBitLevels,unsigned symbol) |
{ |
unsigned modelIndex = 1; |
int i; |
unsigned bit; |
for (i=0;i<NumBitLevels;i++) |
{ |
bit = symbol & 1; |
CMyBitEncoder_Encode(Models+modelIndex,bit); |
modelIndex = (modelIndex<<1)|bit; |
symbol >>= 1; |
} |
} |
/programs/other/kpack/kerpack_linux/lzma_c/RangeCoder.h |
---|
0,0 → 1,7 |
#include "common.h" |
#define kNumTopBits 24 |
#define kTopValue (1<<kNumTopBits) |
extern void RangeEncoder_Init(void); |
extern void RangeEncoder_FlushData(void); |
extern void RangeEncoder_ShiftLow(void); |
extern void RangeEncoder_EncodeDirectBits(unsigned value,int numTotalBits); |
/programs/other/kpack/kerpack_linux/lzma_c/RangeCoderBit.h |
---|
0,0 → 1,18 |
#include "RangeCoder.h" |
#define kNumBitModelTotalBits 11 |
#define kBitModelTotal (1<<kNumBitModelTotalBits) |
#define kNumMoveReducingBits 2 |
#define kNumBitPriceShiftBits 6 |
#define kBitPrice (1<<kNumBitPriceShiftBits) |
typedef unsigned NRangeCoder_CBitModel; |
typedef NRangeCoder_CBitModel CMyBitEncoder; |
extern void CMyBitEncoder_Encode(CMyBitEncoder* e,unsigned symbol); |
extern unsigned CMyBitEncoder_GetPrice(CMyBitEncoder* e, unsigned symbol); |
extern unsigned CMyBitEncoder_GetPrice0(CMyBitEncoder* e); |
extern unsigned CMyBitEncoder_GetPrice1(CMyBitEncoder* e); |
#define CMyBitEncoder_Init(a) a=kBitModelTotal/2 |
/programs/other/kpack/kerpack_linux/lzma_c/RangeCoderBitTree.h |
---|
0,0 → 1,15 |
#include "RangeCoderBit.h" |
typedef struct |
{ |
CMyBitEncoder Models[1<<8]; |
int numBitLevels; |
} NRangeCoder_CBitTreeEncoder; |
extern void CBitTreeEncoder_Init(NRangeCoder_CBitTreeEncoder*e,int numBitLevels); |
extern void CBitTreeEncoder_Encode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol); |
extern void CBitTreeEncoder_ReverseEncode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol); |
extern unsigned CBitTreeEncoder_GetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol); |
extern unsigned CBitTreeEncoder_ReverseGetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol); |
extern unsigned ReverseBitTreeGetPrice(CMyBitEncoder*Models,unsigned NumBitLevels,unsigned symbol); |
extern void ReverseBitTreeEncode(CMyBitEncoder*Models,int NumBitLevels,unsigned symbol); |
/programs/other/kpack/kerpack_linux/lzma_c/common.h |
---|
0,0 → 1,22 |
#ifndef _COMMON_H |
#define _COMMON_H |
typedef unsigned char byte; |
typedef unsigned short word; |
// conditional compiling, mike.dld |
#ifdef WIN32 |
typedef unsigned __int64 uint64; |
#else |
typedef unsigned long long uint64; |
#define __stdcall __attribute__((stdcall)) |
#endif |
typedef byte bool; |
#define true 1 |
#define false 0 |
extern unsigned pack_length; |
extern unsigned pack_pos; |
extern const byte* curin; |
extern byte* curout; |
#endif |
/programs/other/kpack/kerpack_linux/lzma_c/lzma.h |
---|
0,0 → 1,52 |
#include "common.h" |
#define kNumRepDistances 4 |
#define kNumStates 12 |
extern const byte kLiteralNextStates[kNumStates]; |
extern const byte kMatchNextStates[kNumStates]; |
extern const byte kRepNextStates[kNumStates]; |
extern const byte kShortRepNextStates[kNumStates]; |
typedef byte CState; |
#define CState_Init(a) a=0 |
#define CState_UpdateChar(a) a=kLiteralNextStates[a] |
#define CState_UpdateMatch(a) a=kMatchNextStates[a] |
#define CState_UpdateRep(a) a=kRepNextStates[a] |
#define CState_UpdateShortRep(a) a=kShortRepNextStates[a] |
#define CState_IsCharState(a) (a<7) |
#define kNumPosSlotBits 6 |
#define kDicLogSizeMin 0 |
#define kDicLogSizeMax 32 |
#define kDistTableSizeMax (kDicLogSizeMax*2) |
#define kNumLenToPosStates 4 |
#define GetLenToPosState(len) ((len<kNumLenToPosStates+2)?len-2:kNumLenToPosStates-1) |
#define kNumPosStatesBitsMax 4 |
#define kNumPosStatesMax (1<<kNumPosStatesBitsMax) |
#define kNumPosStatesBitsEncodingMax 4 |
#define kNumPosStatesEncodingMax (1 << kNumPosStatesBitsEncodingMax) |
#define kNumLowBits 3 |
#define kNumMidBits 3 |
#define kNumHighBits 8 |
#define kNumLowSymbols (1<<kNumLowBits) |
#define kNumMidSymbols (1<<kNumMidBits) |
#define kNumSymbolsTotal (kNumLowSymbols + kNumMidSymbols + (1<<kNumHighBits)) |
#define kMatchMinLen 2 |
#define kMatchMaxLen (kMatchMinLen + kNumSymbolsTotal - 1) |
#define kNumAlignBits 4 |
#define kAlignTableSize (1<<kNumAlignBits) |
#define kAlignMask (kAlignTableSize-1) |
#define kStartPosModelIndex 4 |
#define kEndPosModelIndex 14 |
#define kNumPosModels (kEndPosModelIndex-kStartPosModelIndex) |
#define kNumFullDistances (1<<(kEndPosModelIndex/2)) |
#define kNumLitPosStatesBitsEncodingMax 4 |
#define kNumLitContextBitsMax 8 |
#define kNumMoveBits 5 |
/programs/other/kpack/kerpack_linux/lzma_c/lzmapack.dsp |
---|
0,0 → 1,132 |
# Microsoft Developer Studio Project File - Name="lzmapack" - Package Owner=<4> |
# Microsoft Developer Studio Generated Build File, Format Version 6.00 |
# ** DO NOT EDIT ** |
# TARGTYPE "Win32 (x86) Static Library" 0x0104 |
CFG=lzmapack - Win32 Debug |
!MESSAGE This is not a valid makefile. To build this project using NMAKE, |
!MESSAGE use the Export Makefile command and run |
!MESSAGE |
!MESSAGE NMAKE /f "lzmapack.mak". |
!MESSAGE |
!MESSAGE You can specify a configuration when running NMAKE |
!MESSAGE by defining the macro CFG on the command line. For example: |
!MESSAGE |
!MESSAGE NMAKE /f "lzmapack.mak" CFG="lzmapack - Win32 Debug" |
!MESSAGE |
!MESSAGE Possible choices for configuration are: |
!MESSAGE |
!MESSAGE "lzmapack - Win32 Release" (based on "Win32 (x86) Static Library") |
!MESSAGE "lzmapack - Win32 Debug" (based on "Win32 (x86) Static Library") |
!MESSAGE |
# Begin Project |
# PROP AllowPerConfigDependencies 0 |
# PROP Scc_ProjName "" |
# PROP Scc_LocalPath "" |
CPP=cl.exe |
RSC=rc.exe |
!IF "$(CFG)" == "lzmapack - Win32 Release" |
# PROP BASE Use_MFC 0 |
# PROP BASE Use_Debug_Libraries 0 |
# PROP BASE Output_Dir "Release" |
# PROP BASE Intermediate_Dir "Release" |
# PROP BASE Target_Dir "" |
# PROP Use_MFC 0 |
# PROP Use_Debug_Libraries 0 |
# PROP Output_Dir "" |
# PROP Intermediate_Dir "Release" |
# PROP Target_Dir "" |
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c |
# ADD CPP /nologo /W3 /GX /O1 /Ob1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /Zl /FD /c |
# ADD BASE RSC /l 0x419 /d "NDEBUG" |
# ADD RSC /l 0x419 /d "NDEBUG" |
BSC32=bscmake.exe |
# ADD BASE BSC32 /nologo |
# ADD BSC32 /nologo |
LIB32=link.exe -lib |
# ADD BASE LIB32 /nologo |
# ADD LIB32 /nologo |
!ELSEIF "$(CFG)" == "lzmapack - Win32 Debug" |
# PROP BASE Use_MFC 0 |
# PROP BASE Use_Debug_Libraries 1 |
# PROP BASE Output_Dir "Debug" |
# PROP BASE Intermediate_Dir "Debug" |
# PROP BASE Target_Dir "" |
# PROP Use_MFC 0 |
# PROP Use_Debug_Libraries 1 |
# PROP Output_Dir "" |
# PROP Intermediate_Dir "Debug" |
# PROP Target_Dir "" |
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c |
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c |
# ADD BASE RSC /l 0x419 /d "_DEBUG" |
# ADD RSC /l 0x419 /d "_DEBUG" |
BSC32=bscmake.exe |
# ADD BASE BSC32 /nologo |
# ADD BSC32 /nologo |
LIB32=link.exe -lib |
# ADD BASE LIB32 /nologo |
# ADD LIB32 /nologo |
!ENDIF |
# Begin Target |
# Name "lzmapack - Win32 Release" |
# Name "lzmapack - Win32 Debug" |
# Begin Group "Source Files" |
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" |
# Begin Source File |
SOURCE=.\LZMAEncoder.c |
# End Source File |
# Begin Source File |
SOURCE=.\MatchFinder.c |
# End Source File |
# Begin Source File |
SOURCE=.\RangeCoder.c |
# End Source File |
# End Group |
# Begin Group "Header Files" |
# PROP Default_Filter "h;hpp;hxx;hm;inl" |
# Begin Source File |
SOURCE=.\common.h |
# End Source File |
# Begin Source File |
SOURCE=.\lzma.h |
# End Source File |
# Begin Source File |
SOURCE=.\LZMAEncoder.h |
# End Source File |
# Begin Source File |
SOURCE=.\MatchFinder.h |
# End Source File |
# Begin Source File |
SOURCE=.\RangeCoder.h |
# End Source File |
# Begin Source File |
SOURCE=.\RangeCoderBit.h |
# End Source File |
# Begin Source File |
SOURCE=.\RangeCoderBitTree.h |
# End Source File |
# End Group |
# End Target |
# End Project |
/programs/other/kpack/kerpack_linux/lzma_c/lzmapack.dsw |
---|
0,0 → 1,44 |
Microsoft Developer Studio Workspace File, Format Version 6.00 |
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! |
############################################################################### |
Project: "lzmapack"=.\lzmapack.dsp - Package Owner=<4> |
Package=<5> |
{{{ |
}}} |
Package=<4> |
{{{ |
}}} |
############################################################################### |
Project: "lzmatest"=.\lzmatest\lzmatest.dsp - Package Owner=<4> |
Package=<5> |
{{{ |
}}} |
Package=<4> |
{{{ |
Begin Project Dependency |
Project_Dep_Name lzmapack |
End Project Dependency |
}}} |
############################################################################### |
Global: |
Package=<5> |
{{{ |
}}} |
Package=<3> |
{{{ |
}}} |
############################################################################### |
/programs/other/kpack/kerpack_linux/lzma_c/lzmatest/lzmatest.dsp |
---|
0,0 → 1,102 |
# Microsoft Developer Studio Project File - Name="lzmatest" - Package Owner=<4> |
# Microsoft Developer Studio Generated Build File, Format Version 6.00 |
# ** DO NOT EDIT ** |
# TARGTYPE "Win32 (x86) Console Application" 0x0103 |
CFG=lzmatest - Win32 Debug |
!MESSAGE This is not a valid makefile. To build this project using NMAKE, |
!MESSAGE use the Export Makefile command and run |
!MESSAGE |
!MESSAGE NMAKE /f "lzmatest.mak". |
!MESSAGE |
!MESSAGE You can specify a configuration when running NMAKE |
!MESSAGE by defining the macro CFG on the command line. For example: |
!MESSAGE |
!MESSAGE NMAKE /f "lzmatest.mak" CFG="lzmatest - Win32 Debug" |
!MESSAGE |
!MESSAGE Possible choices for configuration are: |
!MESSAGE |
!MESSAGE "lzmatest - Win32 Release" (based on "Win32 (x86) Console Application") |
!MESSAGE "lzmatest - Win32 Debug" (based on "Win32 (x86) Console Application") |
!MESSAGE |
# Begin Project |
# PROP AllowPerConfigDependencies 0 |
# PROP Scc_ProjName "" |
# PROP Scc_LocalPath "" |
CPP=cl.exe |
RSC=rc.exe |
!IF "$(CFG)" == "lzmatest - Win32 Release" |
# PROP BASE Use_MFC 0 |
# PROP BASE Use_Debug_Libraries 0 |
# PROP BASE Output_Dir "Release" |
# PROP BASE Intermediate_Dir "Release" |
# PROP BASE Target_Dir "" |
# PROP Use_MFC 0 |
# PROP Use_Debug_Libraries 0 |
# PROP Output_Dir "Release" |
# PROP Intermediate_Dir "Release" |
# PROP Ignore_Export_Lib 0 |
# PROP Target_Dir "" |
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c |
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c |
# ADD BASE RSC /l 0x419 /d "NDEBUG" |
# ADD RSC /l 0x419 /d "NDEBUG" |
BSC32=bscmake.exe |
# ADD BASE BSC32 /nologo |
# ADD BSC32 /nologo |
LINK32=link.exe |
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 |
# ADD LINK32 kernel32.lib ..\lzmapack.lib /nologo /subsystem:console /machine:I386 |
!ELSEIF "$(CFG)" == "lzmatest - Win32 Debug" |
# PROP BASE Use_MFC 0 |
# PROP BASE Use_Debug_Libraries 1 |
# PROP BASE Output_Dir "Debug" |
# PROP BASE Intermediate_Dir "Debug" |
# PROP BASE Target_Dir "" |
# PROP Use_MFC 0 |
# PROP Use_Debug_Libraries 1 |
# PROP Output_Dir "Debug" |
# PROP Intermediate_Dir "Debug" |
# PROP Ignore_Export_Lib 0 |
# PROP Target_Dir "" |
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c |
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c |
# ADD BASE RSC /l 0x419 /d "_DEBUG" |
# ADD RSC /l 0x419 /d "_DEBUG" |
BSC32=bscmake.exe |
# ADD BASE BSC32 /nologo |
# ADD BSC32 /nologo |
LINK32=link.exe |
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept |
# ADD LINK32 kernel32.lib ..\lzmapack.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept |
!ENDIF |
# Begin Target |
# Name "lzmatest - Win32 Release" |
# Name "lzmatest - Win32 Debug" |
# Begin Group "Source Files" |
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" |
# Begin Source File |
SOURCE=.\main.cpp |
# End Source File |
# End Group |
# Begin Group "Header Files" |
# PROP Default_Filter "h;hpp;hxx;hm;inl" |
# End Group |
# Begin Group "Resource Files" |
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" |
# End Group |
# End Target |
# End Project |
/programs/other/kpack/kerpack_linux/lzma_c/lzmatest/main.cpp |
---|
0,0 → 1,31 |
#include <stdio.h> |
#include <windows.h> |
extern "C" __stdcall lzma_set_dict_size(unsigned logdictsize); |
extern "C" __stdcall lzma_compress( |
const void* source, |
void* destination, |
unsigned length, |
void* workmem); |
int main() |
{ |
FILE* f; |
f = fopen("test.in","rb"); |
fseek(f,0,SEEK_END); |
unsigned inlen = ftell(f); |
fseek(f,0,SEEK_SET); |
void* in = VirtualAlloc(NULL,inlen,MEM_COMMIT,PAGE_READWRITE); |
void* out = VirtualAlloc(NULL,inlen,MEM_COMMIT,PAGE_READWRITE); |
fread(in,1,inlen,f); |
fclose(f); |
unsigned logdictsize,dictsize; |
for (logdictsize=0,dictsize=1;dictsize<inlen && logdictsize<=28;logdictsize++,dictsize<<=1) ; |
lzma_set_dict_size(logdictsize); |
void* work = VirtualAlloc(NULL,dictsize*19/2+0x509000,MEM_COMMIT,PAGE_READWRITE); |
unsigned outlen = lzma_compress(in,out,inlen,work); |
printf("%d -> %d\n",inlen,outlen); |
f = fopen("test.out","wb"); |
fwrite(out,1,outlen,f); |
fclose(f); |
return 0; |
} |
/programs/other/kpack/kerpack_linux/lzma_c/readme.txt |
---|
0,0 → 1,44 |
 ýòîì êàòàëîãå íàõîäèòñÿ óïðîùåííàÿ ïåðåïèñàííàÿ íà C ìíîþ, diamond'îì, âåðñèÿ |
LZMA-óïàêîâùèêà. Îðèãèíàëüíûé LZMA SDK 4.32 ÿâëÿåòñÿ copyright (c) 1999-2005 |
Igor Pavlov, ìîæåò áûòü ïîëó÷åí íà ñòðàíèöå http://www.7-zip.org/sdk.html, |
ñîäåðæèò, â ÷àñòíîñòè, âåðñèè èñõîäíîãî êîäà íà C++,C# è Java äëÿ óïàêîâêè è |
ðàñïàêîâêè, êîä LZMA-ðàñïàêîâêè íà ANSI-C, îïèñàíèå ôîðìàòà 7z. |
Ýòà âåðñèÿ íå ÿâëÿåòñÿ áåçîïàñíîé â ìíîãîïîòî÷íîé ñðåäå, ïîääåðæèâàåò òîëüêî |
bt4 match-finder, íåêîòîðûå ïàðàìåòðû óïàêîâêè çàôèêñèðîâàíû (âïðî÷åì, ýòî ïðè |
íåîáõîäèìîñòè ëåãêî ìîäèôèöèðîâàòü), ïîääåðæèâàåòñÿ òîëüêî ñæàòèå äàííûõ â |
îïåðàòèâíîé ïàìÿòè. (Ýòèõ îãðàíè÷åíèé íåò â îðèãèíàëüíîì LZMA |
SDK.) Ýòà âåðñèÿ íå îáÿçàíà êîìïèëèðîâàòüñÿ ëþáûì êîìïèëÿòîðîì, èáî ÿ èñïîëüçóþ |
òîëüêî VC++, õîòÿ åäèíñòâåííîå èçâåñòíîå ìíå îòêëîíåíèå îò ANSI C ñîñòîèò â |
èñïîëüçîâàíèè VC-ñïåöèôè÷íîé äèðåêòèâû #pragma intrinsic(memcpy), íåîáõîäèìîé, |
÷òîáû memcpy áûëà âñòðîåíà ïðÿìî â êîä - â ðåçóëüòàòå áèáëèîòåêà íå ññûëàåòñÿ |
íè íà îäíó èç ôóíêöèé C run-time library. (Ìíå ýòî íåîáõîäèìî, ïîñêîëüêó |
áèáëèîòåêà èñïîëüçóåòñÿ â àññåìáëåðíîé ïðîãðàììå MtApPack, íå èñïîëüçóþùåé |
RTL è ê òîìó æå ñóùåñòâóþùåé è äëÿ Windows, è äëÿ Kolibri.) |
Ýòà áèáëèîòåêà, êàê è îðèãèíàëüíûé LZMA SDK, ìîæåò áûòü èñïîëüçîâàíà â äðóãèõ |
ïðîãðàììàõ â ñîîòâåòñòâèè ñ îäíîé èç ëèöåíçèé (íà âàø âûáîð) GNU LGPL èëè |
GNU CPL. (Îðèãèíàëüíûé SDK òàêæå äîïóñêàåò èñïîëüçîâàíèå îðèãèíàëüíîé |
áèáëèîòåêè áåç îãðàíè÷åíèé ïðè óñëîâèè èñïîëüçîâàíèÿ îáúåêòíûõ ôàéëîâ áåç |
ìîäèôèêàöèè êîäà, íà äàííóþ âåðñèþ ýòî íå ðàñïðîñòðàíÿåòñÿ.) |
Ýêñïîðòèðóþòñÿ äâå ôóíêöèè: â C++-ñòèëå îáúÿâëåíèå âûãëÿäèò òàê: |
extern "C" __stdcall void lzma_set_dict_size(unsigned logdictsize); |
extern "C" __stdcall unsigned lzma_compress( |
const void* source, |
void* destination, |
unsigned length, |
void* workmem); |
Ïåðåä óïàêîâêîé òðåáóåòñÿ óñòàíîâèòü ðàçìåð ñëîâàðÿ ïåðâîé èç ýòèõ ôóíêöèé, |
ïðèíèìàþùåé ëîãàðèôì ïî îñíîâàíèþ 2 ýòîãî çíà÷åíèÿ |
(ò.å. dictsize == (1<<logdictsize)). Ìàêñèìàëüíûé ðàçìåð áóôåðà ðàâåí 256Mb, |
òàê ÷òî ïàðàìåòð logdictsize íå äîëæåí ïðåâîñõîäèòü 28. Åñëè ðàçìåð áóôåðà |
áîëüøå ðàçìåðà âõîäíûõ äàííûõ, òî ðåçóëüòàò íå çàâèñèò îò ðàçìåðà áóôåðà, |
ò.å. äëÿ äàííûõ ðàçìåðîì 12345 áàéò ðåçóëüòàòû ñæàòèÿ ñ áóôåðîì íà 16384 áàéò è |
íà 1 ìåãàáàéò îäèíàêîâû. |
Óïàêîâêà ïðîèçâîäèòñÿ âûçîâîì âòîðîé èç ýòèõ ôóíêöèé. source - óêàçàòåëü íà |
âõîäíûå äàííûå, destination - óêàçàòåëü íà áóôåð äëÿ óïàêîâàííûõ äàííûõ, |
length - äëèíà âõîäíûõ äàííûõ, workmem - óêàçàòåëü íà âðåìåííóþ ïàìÿòü, |
èñïîëüçóåìóþ óïàêîâùèêîì; äîëæíî áûòü âûäåëåíî íå ìåíåå 0x509000+dictsize*19/2 |
áàéò. Äëÿ óïàêîâàííûõ äàííûõ â õóäøåì ñëó÷àå äîñòàòî÷íî 0x10 + length*9/8 áàéò. |
/programs/other/kpack/trunk/Tupfile.lua |
---|
0,0 → 1,2 |
if tup.getconfig("NO_FASM") ~= "" then return end |
tup.rule("kpack.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "kpack") |