option casemap:none 
.486p 
.model flat,stdcall 


include pce_protos.inc


.data

db "compression engine",0


.code 

DllEntry proc hInstDLL:DWORD, reason:DWORD, reserved1:DWORD 
    	xor	eax,eax
        inc	eax
        ret 
DllEntry Endp 


PCELZSS_Decompress proc stdcall src:DWORD, dest:DWORD
	pushad
	xor ebx,ebx								;ebx=ctrl_count
	mov esi,src
	movzx edx,byte ptr [esi]				;edx=ctrl
	inc esi
	mov edi,dest
NextByte:
	bt edx,7
	jc IsCodeWord
	movsb
	jmp Next
IsCodeWord:
	xor eax,eax
	lodsb
	shl eax,8
	lodsb								
	mov ecx,eax								;eax=codeword
	shr ecx,4								;ecx=phrase_index
	jecxz Finished
	push esi
	mov esi,edi
	sub esi,ecx
	and eax,0Fh
	inc eax
	inc eax
	mov ecx,eax
	rep movsb
	pop esi
Next:
	shl edx,1
	inc ebx
	cmp bl,8
	jb NextByte
	movzx edx,byte ptr [esi]				;edx=ctrl
	inc esi
	xor ebx,ebx
	jmp NextByte	
Finished:	
	mov eax,edi
	sub eax,[dest]
	mov dword ptr [esp+28],eax 
	popad
	ret
PCELZSS_Decompress endp


SearchForPhrase proc stdcall string:DWORD, src:DWORD, max_len:DWORD, best_lenptr:DWORD
	pushad
	mov esi,[string]
	mov edi,esi
	mov bl,byte ptr [esi]
	xor edx,edx				;edx=best string
	mov eax,[best_lenptr]
	mov dword ptr [eax],1
	dec esi
NextByte:
	cmp esi,[src]
	jb Finished
	cmp byte ptr [esi], bl
	jnz NotHere
	push esi
	push edi
	inc esi
	inc edi
	mov ecx,max_len
	mov eax,ecx
	repe cmpsb
	sub eax,ecx
	pop edi
	pop esi
	mov ecx,[best_lenptr]
	cmp eax,[ecx]
	jbe NotHere
	mov [ecx],eax
	mov edx,esi
NotHere:
	dec esi
	jmp NextByte	
Finished:
	mov [esp+28],edx	
	popad
	ret
SearchForPhrase endp 


PCELZSS_Compress proc stdcall src:DWORD, dest:DWORD, len:DWORD
	local src_end:DWORD
	local dest_end:DWORD
	local phrase_ptr:DWORD
	local lazy_ptr:DWORD
	local ctrl_ptr:DWORD
	local phrase_len:DWORD
	local lazy_len:DWORD
	local temp:DWORD
	pushad
	mov eax,[src]
	add eax,[len]
	mov [src_end],eax
	mov eax,[dest]
	add eax,[len]
	sub eax,3
	mov [dest_end],eax
	xor eax,eax
	mov [phrase_ptr],eax
	cdq								;edx=ctrl
	xor ebx,ebx						;ebx=ctrl_count
	mov esi,[src]
	mov edi,[dest]
	mov [ctrl_ptr],edi
	inc edi
NextByte:
	cmp esi,[src_end]
	jge Finished
	cmp edi,[dest_end]
	jge Finished
	inc ebx
	cmp ebx,9
	jnz StillBitsInCode
	mov eax,[ctrl_ptr]
	mov byte ptr [eax],dl
	mov [ctrl_ptr],edi
	inc edi
	xor edx,edx
	mov ebx,1
StillBitsInCode:
	mov ecx,[src_end]
	sub ecx,esi
	cmp ecx,15+2
	jbe LenGood
	mov ecx,15+2						;ecx=max_len
LenGood:
	mov eax,esi
	sub eax,4095
	cmp eax,[src]
	jae WindowGood
	mov eax,[src]
WindowGood:	
	mov [temp],eax
	cmp [phrase_ptr],0
	jnz TestLazy
	invoke SearchForPhrase,esi,[temp],ecx,addr phrase_len
	mov [phrase_ptr],eax
TestLazy:	
	cmp ecx,2
	jb CantTestLazy
	inc esi
	inc [temp]
	invoke SearchForPhrase,esi,[temp],ecx,addr lazy_len
	dec ecx
	mov [lazy_ptr],eax
	dec esi
CantTestLazy:	
	shl edx,1
	cmp [phrase_ptr],0
	jz code_literal
	jecxz code_literal
	cmp [lazy_ptr],0
	jz code_word
	mov eax,[lazy_len]
	cmp eax,[phrase_len]
	jbe code_word
code_literal:	
	push [lazy_ptr]
	pop [phrase_ptr]
	push [lazy_len]
	pop [phrase_len]
	movsb
	jmp NextByte
code_word:	
	or edx,1
	mov eax,esi
	sub eax,[phrase_ptr]
	shl eax,4
	mov ecx,[phrase_len]
	dec ecx
	dec ecx
	and ecx,0Fh
	or eax,ecx
	push eax
	shr eax,8
	stosb
	pop eax
	stosb
	add esi,[phrase_len]
	mov [phrase_ptr],0
	jmp NextByte
Finished:
	inc ebx
	shl edx,1
	or edx,1
TryNextBits:
	cmp ebx,8
	jae NoMoreBits
	shl edx,1
	inc ebx
	jmp TryNextBits	
NoMoreBits:
	mov eax,[ctrl_ptr]
	mov byte ptr [eax],dl
	xor eax,eax
	stosw
	sub edi,[dest]
	mov [esp+28],edi
	popad
	ret
PCELZSS_Compress endp







END DllEntry
END