home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
A
/
ARC20.ARC
/
ARCLZW.INC
< prev
next >
Wrap
Text File
|
1989-11-10
|
6KB
|
202 lines
(* ARCLZW.INC TR 101189 *)
const hsize = 5003;
firstfree = 257;
clearcode = 256;
initbits = 9;
maxbits = 12;
maxmax = 4096; (* = 1 shl maxbits *)
check_gap = 10000.0;
type entry = record
case byte of
0 : (neucod:byte; lastcod:integer; buf:byte);
1 : (dum,lzwcod : integer);
end;
lzwtab = array[0..hsize] of entry;
var buf : array[0..maxbits] of byte;
tab : ^lzwtab;
scod,lzwlen : longword;
bytpos,codzahl : byte;
actbits,nextfree,maxcode : integer;
ratio,nextcheck : real;
(* Codebreite (9 bis 12 Bit) neu einstellen *)
procedure setbits(n:byte);
begin
actbits:=n;
if n=maxbits then maxcode:=maxmax else maxcode:=rmask[n];
bitpos:=0; bytpos:=0; codzahl:=0;
end;
(* Einzelnen 9/12-Bit-Code an LZW-Datei ausgeben *)
procedure putcode(var f:binfile; code:integer);
procedure boost(n:byte);
var i : byte;
begin
for i:=0 to pred(n) do fputc(f,buf[i]);
add_long_int(lzwlen,n);
bitpos:=0; bytpos:=0;
end;
procedure setbits_put(n:byte);
begin
if bytpos>0 then boost(actbits);
setbits(n);
end;
begin
if code>=0 then begin
inline($2A/CODE/$1E/$00/$3A/BITPOS/$B7/$28/$06/$47/$29/$CB/$13/$10/$FB/
$4F/$06/$00/$DD/$21/RMASK/$DD/$09/$DD/$09/$DD/$7E/$00/$ED/$4B/BYTPOS/
$06/$00/$DD/$21/BUF/$DD/$09/$DD/$A6/$00/$B5/$DD/$77/$00/$DD/$74/$01/
$2A/ACTBITS/$3A/BITPOS/$85/$D6/$08/$0C/$FE/$08/$38/$06/$D6/$08/$0C/
$DD/$73/$02/$32/BITPOS/$79/$32/BYTPOS);
if bytpos>=actbits then boost(actbits);
if code=clearcode then setbits_put(initbits)
else if nextfree>maxcode then setbits_put(succ(actbits));
end
else boost(bytpos+byte(bitpos>0));
end;
(* gesamte Datei komprimierend in Archiv uebernehmen *)
procedure crunch_lzw(var source,dest:binfile);
var inbytes : longword;
last,neu,i,disp : integer;
fnd : boolean;
procedure checkratio;
var rat : real;
begin
nextcheck:=nextcheck+check_gap;
rat:=long_to_real(inbytes)/long_to_real(lzwlen);
if ratio<rat then ratio:=rat else begin
ratio:=0.0;
fillchar(tab^,sizeof(lzwtab),$FF);
nextfree:=firstfree;
putcode(dest,clearcode);
end;
end;
begin
ratio:=0.0; nextcheck:=check_gap;
setbits(initbits);
nextfree:=firstfree;
new(tab); fillchar(tab^,sizeof(lzwtab),$FF);
fputc(dest,maxbits); lzwlen:=long_eins;
last:=getc_ncr(source); inbytes:=long_eins;
while not ncrend do begin
neu:=getc_ncr(source);
inc_long(inbytes);
inline($2A/NEU/$26/$00/$29/$29/$29/$29/$ED/$5B/LAST/$7C/$AA/$67/
$7D/$AB/$6F/$22/I/$B4/$21/$01/$00/$28/$09/$21/$8B/$13/$ED/$5B/I/
$ED/$52/$22/DISP/$2A/I/$29/$29/$ED/$5B/TAB/$19/$E5/$3A/NEU/$BE/$20/$2B/
$ED/$4B/LAST/$23/$79/$BE/$20/$22/$23/$7E/$E6/$0F/$B8/$20/$1B/$7E/
$23/$66/$CB/$3C/$1F/$CB/$3C/$1F/$CB/$3C/$1F/$CB/$3C/$1F/$6F/$22/LAST/
$E1/$3E/$01/$32/FND/$18/$24/$AF/$32/FND/$E1/$7E/$23/$A6/$23/$A6/
$23/$A6/$3C/$28/$15/$2A/I/$ED/$5B/DISP/$B7/$ED/$52/$30/$04/$11/$8B/$13/
$19/$22/I/$18/$A0);
if not fnd then begin
putcode(dest,last);
if nextfree<maxmax then begin
tab^[i].neucod:=neu;
tab^[i].lastcod:=last;
tab^[i].lzwcod:=tab^[i].lzwcod and $F + (nextfree shl 4);
nextfree:=succ(nextfree);
end
else if long_to_real(inbytes)>=nextcheck then checkratio;
last:=neu;
end;
end;
putcode(dest,last);
putcode(dest,-1);
dispose(tab);
end;
(* Einzelnen 9/12-Bit-Code aus LZW-Datei holen *)
function getcode(var f:binfile):integer;
begin
if codzahl=0 then begin
bytpos:=0; bitpos:=0;
while (siz.hi>=0) and (codzahl<actbits) do begin
buf[codzahl]:=crypt(getc_decsiz(f));
codzahl:=succ(codzahl);
end;
if codzahl<2 then begin getcode:=-1; exit; end;
codzahl:=(codzahl shl 3) div actbits;
end;
scod.b0:=buf[bytpos];
bytpos:=succ(bytpos);
scod.b1:=buf[bytpos];
scod.b2:=buf[succ(bytpos)];
shift_long(scod,-bitpos);
getcode:=scod.lo and rmask[actbits];
bitpos:=bitpos+actbits-8;
if bitpos>7 then begin bitpos:=bitpos-8; bytpos:=succ(bytpos); end;
codzahl:=pred(codzahl);
end;
(* komplette LZW-Datei dekomprimieren *)
procedure uncrunch_lzw(var source,dest:binfile);
var code,last,sp,c : integer;
procedure put_tab(x:byte);
begin
putc_ncr(dest,x);
if nextfree<maxmax then begin
tab^[nextfree].lastcod:=last;
tab^[nextfree].neucod:=x;
nextfree:=succ(nextfree);
end;
end;
begin
code:=crypt(getc_decsiz(source));
if code<>maxbits then begin
writeln('File packed with ',code,' bits, I can only handle ',maxbits);
halt; end;
setbits(initbits); nextfree:=firstfree;
last:=getcode(source); if last=-1 then exit;
new(tab);
putc_ncr(dest,last);
repeat
if nextfree>maxcode then setbits(succ(actbits));
code:=getcode(source);
if code>=0 then begin
if code=clearcode then begin
setbits(initbits);
nextfree:=firstfree;
end
else begin
if code<firstfree then put_tab(code) else begin
sp:=0;
if code<nextfree then c:=code else begin
tab^[sp].buf:=c; (* letzter Anfangscode! *)
sp:=succ(sp);
c:=last;
end;
while c>=firstfree do begin
tab^[sp].buf:=tab^[c].neucod;
c:=tab^[c].lastcod;
sp:=succ(sp);
end;
put_tab(c);
while sp>0 do begin
sp:=pred(sp);
putc_ncr(dest,tab^[sp].buf);
end;
end;
last:=code;
end;
end;
until code<0;
dispose(tab);
end;