home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / CHFLZ100.ZIP / LZSS16.PAS < prev    next >
Pascal/Delphi Source File  |  1996-09-05  |  42KB  |  1,155 lines

  1. {$G+}
  2.  
  3. Unit LZSS16;
  4. {
  5.    LZSSUNIT - Compress and uncompress unit using LZ77 algorithm for
  6.    Borland (Turbo) Pascal version 7.0.
  7.  
  8.    Assembler Programmer: Andy Tam, Pascal Conversion: Douglas Webb,
  9.    Unit Conversion and Dynamic Memory Allocation: Andrew Eigus.
  10.  
  11.    Written by Andrew Eigus (aka: Mr. Byte) of:
  12.    Fidonet: 2:5100/33,
  13.    Internet: aeigus@fgate.castle.riga.lv, aeigus@kristin.cclu.lv.
  14.  
  15.    Modified again by Chris Rankin: apart from a few minor tweaks to the
  16.    code, the only real change is the grouping together of TextBuf, Left,
  17.    Right and Mom into a (large!) record which is allocated in a single
  18.    segment on the Heap. This enables ES to be loaded ONCE at the beginning
  19.    of LZEncode and LZDecode, *drastically* reducing the number of segment
  20.    loads during a typical LZ call. This should enhance performance,
  21.    especially under DPMI and Windows.
  22.  
  23.  
  24.    Public Domain version 1.10, last changed on 15.07.96.
  25.    Target platforms: DOS, DPMI, Windows.
  26.  
  27. }
  28.  
  29. interface
  30.  
  31. {#Z+}
  32. { This unit is ready for use with Dj. Murdoch's ScanHelp utility which
  33.   will make a Borland .TPH file for it ????? }
  34. {#Z-}
  35.  
  36. type
  37.   TLZSSWord = word;
  38.  
  39. const Log2TLZSSWord = 1;
  40.  
  41. const
  42.   LZRWBufSize     = 32000{8192}; { Read buffer size }
  43.  
  44. {#Z+}
  45.   N           = 4096;  { Bigger N -> Better compression on big files only. }
  46.   F           = 18;
  47.   Threshold   = 2;
  48.   Nul         = N * SizeOf(TLZSSWord);
  49.   InBufPtr    : TLZSSWord = LZRWBufSize;
  50.   InBufSize   : TLZSSWord = LZRWBufSize;
  51.   OutBufPtr   : TLZSSWord = 0;
  52. {#Z-}
  53.  
  54. type
  55. {#X TWriteProc}{#X LZSquash}{#X LZUnsquash}
  56.  
  57.   TReadProc = function(var ReadBuf): TLZSSWord;
  58.   { This is declaration for custom read function. It should read
  59.     #LZRWBufSize# bytes from ReadBuf, returning the number of bytes
  60.     actually read. }
  61.  
  62. {#X TReadProc}{#X LZSquash}{#X LZUnsquash}
  63.   TWriteProc = function(var WriteBuf;
  64.                             Count: TLZSSWord): TLZSSWord;
  65.   { This is declaration for custom write function. It should write
  66.     Count bytes into WriteBuf, returning the number of actual bytes
  67.     written. }
  68.  
  69. {#Z+}
  70.   PLZRWBuffer = ^TLZRWBuffer;
  71.   TLZRWBuffer = array[0..LZRWBufSize - 1] of Byte; { file buffers }
  72.  
  73.   PLZTextBuf = ^TLZTextBuf;
  74.   TLZTextBuf = array[0..N + F - 2] of Byte;
  75.  
  76.   PLeftMomTree = ^TLeftMomTree;
  77.   TLeftMomTree = array[0..N] of TLZSSWord;
  78.   PRightTree = ^TRightTree;
  79.   TRightTree = array[0..N + 256] of TLZSSWord;
  80.  
  81.   PBinaryTree = ^TBinaryTree;
  82.   TBinaryTree = record
  83.                   TextBuf: TLZTextBuf;
  84.                   Left:    TLeftMomTree;
  85.                   Right:   TRightTree;
  86.                   Mom:     TLeftMomTree
  87.                 end;
  88. const
  89.   LZSSMemRequired = SizeOf(TLZRWBuffer)*2 + SizeOf(TBinaryTree);
  90. {#Z-}
  91.  
  92. function LZInit : boolean;
  93. { This function should be called before any other compression routines
  94.   from this unit - it allocates memory and initializes all internal
  95.   variables required by compression procedures. If allocation fails,
  96.   LZInit returns False, this means that there isn't enough memory for
  97.   compression or decompression process. It returns True if initialization
  98.   was successful. }
  99. {#X LZDone}{#X LZSquash}{#X LZUnsquash}
  100.  
  101. procedure LZSquash(ReadProc : TReadProc; WriteProc : TWriteProc);
  102. { This procedure is used for compression. ReadProc specifies custom
  103.   read function that reads data, and WriteProc specifies custom write
  104.   function that writes compressed data. }
  105. {#X LZUnsquash}{#X LZInit}{#X LZDone}
  106.  
  107. procedure LZUnSquash(ReadProc : TReadProc; WriteProc : TWriteProc);
  108. { This procedure is used for decompression. ReadProc specifies custom
  109.   read function that reads compressed data, and WriteProc specifies
  110.   custom write function that writes decompressed data. }
  111. {#X LZSquash}{#X LZInit}{#X LZDone}
  112.  
  113. procedure LZDone;
  114. { This procedure should be called after you finished compression or
  115.   decompression. It deallocates (frees) all memory allocated by LZInit.
  116.   Note: You should always call LZDone after you finished using compression
  117.   routines from this unit. }
  118. {#X LZInit}{#X LZSquash}{#X LZUnsquash}
  119.  
  120. procedure LZEncode;
  121. procedure LZDecode;
  122.  
  123. {#Z+}
  124. const BinaryTree: PBinaryTree = nil;
  125. const InBufP:     PLZRWBuffer = nil;
  126. const OutBufP:    PLZRWBuffer = nil;
  127.  
  128. const IsLZInitialized: boolean = false;
  129.  
  130. var
  131.   Height, MatchPos, MatchLen, LastLen: TLZSSWord;
  132.   CodeBuf : array[0..16] of Byte;
  133.   LZReadProc  : TReadProc;
  134.   LZWriteProc : TWriteProc;
  135. {#Z-}
  136.  
  137. implementation
  138.  
  139. type
  140.   PtrRec = record
  141.              Ofs, Seg: word
  142.            end;
  143.  
  144. Function LZSS_Read : TLZSSWord;    { Returns # of bytes read }
  145. Begin
  146.   LZSS_Read := LZReadProc(InBufP^);
  147. End; { LZSS_Read }
  148.  
  149. Function LZSS_Write : TLZSSWord;  { Returns # of bytes written }
  150. Begin
  151.   LZSS_Write := LZWriteProc(OutBufP^, OutBufPtr);
  152. End; { LZSS_Write }
  153.  
  154. Procedure GetC; assembler;
  155. Asm
  156. {
  157.   getc : return a character from the buffer
  158.           RETURN : AL = input char
  159.                    Carry set when EOF
  160. }
  161.               push    bx
  162.               mov     bx, inBufPtr
  163.               cmp     bx, inBufSize
  164.               jb      @getc1
  165.               push    cx
  166.               push    dx
  167.               push    di
  168.               push    si
  169.               push    es
  170.               call    LZSS_Read
  171.               pop     es
  172.               pop     si
  173.               pop     di
  174.               pop     dx
  175.               pop     cx
  176.               mov     inBufSize, ax
  177.               or      ax, ax
  178.               jnz     @NewBuf
  179.               stc                         { ; set carry to indicate EOF }
  180.               jmp     @Exit
  181.  
  182.   @NewBuf:    xor     bx, bx
  183.  
  184.   @getc1:     PUSH    DI
  185.               PUSH    ES
  186.               LES     DI,[InBufP]
  187.               MOV     AL,[ES:DI+BX]
  188.               POP     ES
  189.               POP     DI
  190.               inc     bx
  191.               mov     inBufPtr, bx
  192.               clc                         { ; clear the carry flag }
  193.  
  194.   @Exit:      pop bx
  195. End; { Getc }
  196.  
  197. Procedure PutC; assembler;
  198. {
  199.   putc : put a character into the output buffer
  200.              Entry : AL = output char
  201. }
  202. Asm
  203.               push    bx
  204.               mov     bx, outBufPtr
  205.               PUSH    DI
  206.               PUSH    ES
  207.               LES     DI,[OutBufP]
  208.               MOV     [ES:DI+BX],AL
  209.               POP     ES
  210.               POP     DI
  211.               inc     bx
  212.               cmp     bx, LZRWBufSize
  213.               jb      @putc1
  214.               mov     OutBufPtr,LZRWBufSize   { Just so the flush will work. }
  215.               push    cx
  216.               push    dx
  217.               push    di
  218.               push    si
  219.               push    es
  220.               call    LZSS_Write
  221.               pop     es
  222.               pop     si
  223.               pop     di
  224.               pop     dx
  225.               pop     cx
  226.               xor     bx, bx
  227.   @putc1:     mov     outBufPtr, bx
  228.               pop     bx
  229. End; { Putc }
  230.  
  231. Procedure InitTree; assembler;
  232. {
  233.   initTree : initialize all binary search trees.  There are 256 BST's, one
  234.              for all strings started with a particular character.  The
  235.              parent is tree K is the node N + K + 1 and it has only a
  236.              right child
  237. }
  238. Asm
  239.       cld
  240.       MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  241.       ADD     DI, OFFSET TBinaryTree.Mom
  242.       mov     cx, N+1
  243.       mov     ax, Nul
  244.       rep     stosw
  245. {                                                             }
  246. { Initialise last 256 elements to BinaryTree.Right to Nul ... }
  247. {                                                             }
  248.       add     di, OFFSET TBinaryTree.Right - OFFSET TBinaryTree.Mom
  249.       mov     ch, (256 shr 8)
  250.       rep     stosw
  251. End; { InitTree }
  252.  
  253. Procedure Splay; assembler;
  254. {
  255.   splay : use splay tree operations to move the node to the 'top' of
  256.            tree.  Note that it will not actual become the root of the tree
  257.            because the root of each tree is a special node.  Instead, it
  258.            will become the right child of this special node.
  259.  
  260.              ENTRY : di = the node to be rotated
  261. }
  262. Asm
  263.   @Splay1:
  264.               PUSH    BX
  265.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  266.               MOV     SI,[ES:BX+DI+OFFSET TBinaryTree.Mom]
  267.               POP     BX
  268. {              mov     si, [Offset Mom + di]}
  269.               cmp     si, Nul           { ; exit if its parent is a special node }
  270.               ja      @Splay4
  271.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  272.               MOV     BX,[ES:BX+SI+OFFSET TBinaryTree.Mom]
  273. {              mov     bx, [Offset Mom + si]}
  274.               cmp     bx, Nul           { ; check if its grandparent is special }
  275.               jbe     @Splay5           { ; if not then skip }
  276.               PUSH    BX
  277.               MOV     BX,PtrRec[BinaryTree].Ofs
  278.               CMP     DI,[ES:BX+SI+OFFSET TBinaryTree.Left]
  279.               POP     BX
  280. {              cmp     di, [Offset Left + si]} { ; is the current node is a left child ? }
  281.               jne     @Splay2
  282.               PUSH    BX
  283.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  284.               MOV     DX,[ES:BX+DI+OFFSET TBinaryTree.Right]
  285. {              mov     dx, [Offset Right + di]}    { ; perform a left zig operation }
  286.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Left],DX
  287. {              mov     [Offset Left + si], dx}
  288.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Right],SI
  289.               POP     BX
  290. {              mov     [Offset Right + di], si}
  291.               jmp     @Splay3
  292.   @Splay2:
  293.               PUSH    BX
  294.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  295.               MOV     DX,[ES:BX+DI+OFFSET TBinaryTree.Left]
  296. {              mov     dx, [Offset Left + di]}     { ; perform a right zig }
  297.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Right],DX
  298. {              mov     [Offset Right + si], dx}
  299.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Left],SI
  300.               POP     BX
  301. {              mov     [Offset Left + di], si}
  302.   @Splay3:
  303.               PUSH    SI
  304.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  305.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],DI
  306.               POP     SI
  307. {              mov     [Offset Right + bx], di}
  308.               xchg    bx, dx
  309.               PUSH    AX
  310.               MOV     AX,BX
  311.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  312.               ADD     BX,AX
  313.               MOV     [ES:BX+OFFSET TBinaryTree.Mom],SI
  314.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  315.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Mom],DI
  316.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Mom],DX
  317.               MOV     BX,AX
  318.               POP     AX
  319. {              mov     [Offset Mom + bx], si
  320.               mov     [Offset Mom + si], di
  321.               mov     [Offset Mom + di], dx}
  322.   @Splay4:    jmp     @end
  323.   @Splay5:
  324.               PUSH    DI
  325.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  326.               MOV     CX,[ES:DI+BX+OFFSET TBinaryTree.Mom]
  327.               POP     DI
  328. {              mov     cx, [Offset Mom + bx]}
  329.               PUSH    BX
  330.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  331.               CMP     DI,[ES:BX+SI+OFFSET TBinaryTree.Left]
  332.               POP     BX
  333. {              cmp     di, [Offset Left + si]}
  334.               jne     @Splay7
  335.               PUSH    DI
  336.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  337.               CMP     SI,[ES:DI+BX+OFFSET TBinaryTree.Left]
  338.               POP     DI
  339. {              cmp     si, [Offset Left + bx]}
  340.               jne     @Splay6
  341.               PUSH    AX
  342.               MOV     AX,DI
  343.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  344.               ADD     DI,SI
  345.               MOV     DX,[ES:DI+OFFSET TBinaryTree.Right]
  346. {              mov     dx, [Offset Right + si]   } { ; perform a left zig-zig operation }
  347.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  348.               MOV     [ES:DI+BX+OFFSET TBinaryTree.Left],DX
  349. {              mov     [Offset Left + bx], dx}
  350.               xchg    bx, dx
  351.               MOV     [ES:DI+BX+OFFSET TBinaryTree.Mom],DX
  352. {              mov     [Offset Mom + bx], dx}
  353.               ADD     DI,AX
  354.               MOV     BX,[ES:DI+OFFSET TBinaryTree.Right]
  355. {              mov     bx, [Offset Right + di]}
  356.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  357.               ADD     DI,SI
  358.               MOV     [ES:DI+OFFSET TBinaryTree.Left],BX
  359.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  360.               MOV     [ES:DI+BX+OFFSET TBinaryTree.Mom],SI
  361. {              mov     [Offset Left +si], bx
  362.               mov     [Offset Mom + bx], si}
  363.               mov     bx, dx
  364.               ADD     DI,SI
  365.               MOV     [ES:DI+OFFSET TBinaryTree.Right],BX
  366.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  367.               ADD     DI,AX
  368.               MOV     [ES:DI+OFFSET TBinaryTree.Right],SI
  369. {              mov     [Offset Right + si], bx
  370.               mov     [Offset Right + di], si}
  371.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  372.               MOV     [ES:DI+BX+OFFSET TBinaryTree.Mom],SI
  373.               ADD     DI,SI
  374.               MOV     [ES:DI+OFFSET TBinaryTree.Mom], AX
  375.               MOV     DI,AX
  376.               POP     AX
  377. {              mov     [Offset Mom + bx], si
  378.               mov     [Offset Mom + si], di}
  379.               jmp     @Splay9
  380.   @Splay6:
  381.               PUSH    AX
  382.               MOV     AX,SI
  383.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  384.               ADD     SI,DI
  385.               MOV     DX,[ES:SI+OFFSET TBinaryTree.Left]
  386. {              mov     dx, [Offset Left + di]}     { ; perform a left zig-zag operation }
  387.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  388.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],DX
  389. {              mov     [Offset Right + bx], dx}
  390.               xchg    bx, dx
  391.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DX
  392. {              mov     [Offset Mom + bx], dx}
  393.               ADD     SI,DI
  394.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Right]
  395. {              mov     bx, [Offset Right + di]}
  396.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  397.               ADD     SI,AX
  398.               MOV     [ES:SI+OFFSET TBinaryTree.Left],BX
  399. {              mov     [Offset Left + si], bx}
  400.               MOV     SI, PtrRec[OFFSET BinaryTree].Ofs
  401.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],AX
  402. {              mov     [Offset Mom + bx], si}
  403.               mov     bx, dx
  404.               ADD     SI,DI
  405.               MOV     [ES:SI+OFFSET TBinaryTree.Left],BX
  406. {              mov     [Offset Left + di], bx}
  407.               MOV     SI, PtrRec[OFFSET BinaryTree].Ofs
  408.               ADD     SI,DI
  409.               MOV     [ES:SI+OFFSET TBinaryTree.Right],AX
  410. {              mov     [Offset Right + di], si}
  411.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  412.               ADD     SI,AX
  413.               MOV     [ES:SI+OFFSET TBinaryTree.Mom],DI
  414. {              mov     [Offset Mom + si], di}
  415.               MOV     SI, PtrRec[OFFSET BinaryTree].Ofs
  416.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DI
  417.               MOV     SI,AX
  418.               POP     AX
  419. {              mov     [Offset Mom + bx], di}
  420.               jmp     @Splay9
  421.   @Splay7:
  422.               PUSH    DI
  423.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  424.               CMP     SI,[ES:DI+BX+OFFSET TBinaryTree.Right]
  425.               POP     DI
  426. {              cmp     si, [Offset Right + bx]}
  427.               jne     @Splay8
  428.               PUSH    AX
  429.               MOV     AX,SI
  430.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  431.               ADD     SI,AX
  432.               MOV     DX,[ES:SI+OFFSET TBinaryTree.Left]
  433. {              mov     dx, [Offset Left + si]}     { ; perform a right zig-zig }
  434.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  435.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],DX
  436. {              mov     [Offset Right + bx], dx}
  437.               xchg    bx, dx
  438.               MOV     SI, PtrRec[OFFSET BinaryTree].Ofs
  439.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DX
  440. {              mov     [Offset Mom + bx], dx}
  441.               ADD     SI,DI
  442.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Left]
  443. {              mov     bx, [Offset Left + di]}
  444.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  445.               ADD     SI,AX
  446.               MOV     [ES:SI+OFFSET TBinaryTree.Right],BX
  447. {              mov     [Offset Right + si], bx}
  448.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  449.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],AX
  450. {              mov     [Offset Mom + bx], si}
  451.               mov     bx, dx
  452.               ADD     SI,AX
  453.               MOV     [ES:SI+OFFSET TBinaryTree.Left],BX
  454. {              mov     [Offset Left + si], bx}
  455.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  456.               ADD     SI,DI
  457.               MOV     [ES:SI+OFFSET TBinaryTree.Left],AX
  458. {              mov     [Offset Left + di], si}
  459.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  460.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],AX
  461. {              mov     [Offset Mom + bx], si}
  462.               ADD     SI,AX
  463.               MOV     [ES:SI+OFFSET TBinaryTree.Mom],DI
  464. {              mov     [Offset Mom + si], di}
  465.               MOV     SI,AX
  466.               POP     AX
  467.               jmp     @Splay9
  468.   @Splay8:
  469.               PUSH    AX
  470.               MOV     AX,SI
  471.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  472.               ADD     SI,DI
  473.               MOV     DX,[ES:SI+OFFSET TBinaryTree.Right]
  474. {              mov     dx, [Offset Right + di]}    { ; perform a right zig-zag }
  475.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  476.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Left],DX
  477. {              mov     [Offset Left + bx], dx}
  478.               xchg    bx, dx
  479.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DX
  480. {              mov     [Offset Mom + bx], dx}
  481.               ADD     SI,DI
  482.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Left]
  483. {              mov     bx, [Offset Left + di]}
  484.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  485.               ADD     SI,AX
  486.               MOV     [ES:SI+OFFSET TBinaryTree.Right],BX
  487. {              mov     [Offset Right + si], bx}
  488.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  489.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],AX
  490. {              mov     [Offset Mom + bx], si}
  491.               mov     bx, dx
  492.               ADD     SI,DI
  493.               MOV     [ES:SI+OFFSET TBinaryTree.Right],BX
  494. {              mov     [Offset Right + di], bx}
  495.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  496.               ADD     SI,DI
  497.               MOV     [ES:SI+OFFSET TBinaryTree.Left],AX
  498. {              mov     [Offset Left + di], si}
  499.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  500.               ADD     SI,AX
  501.               MOV     [ES:SI+OFFSET TBinaryTree.Mom],DI
  502.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  503.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DI
  504. {              mov     [Offset Mom + si], di
  505.               mov     [Offset Mom + bx], di}
  506.               MOV     SI,AX
  507.               POP     AX
  508.   @Splay9:    mov     si, cx
  509.               cmp     si, NUL
  510.               ja      @Splay10
  511.               PUSH    DI
  512.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  513.               ADD     DI,SI
  514.               CMP     BX,[ES:DI+OFFSET TBinaryTree.Left]
  515.               POP     DI
  516. {              cmp     bx, [Offset Left + si]}
  517.               jne     @Splay10
  518.               PUSH    BX
  519.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  520.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Left],DI
  521.               POP     BX
  522. {              mov     [Offset Left + si], di}
  523.               jmp     @Splay11
  524.   @Splay10:
  525.               PUSH    BX
  526.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  527.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Right],DI
  528.               POP     BX
  529. {              mov     [Offset Right + si], di}
  530.   @Splay11:
  531.               PUSH    BX
  532.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  533.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Mom],SI
  534.               POP     BX
  535. {              mov     [Offset Mom + di], si}
  536.               jmp     @Splay1
  537.   @end:
  538. End; { SPlay }
  539.  
  540. Procedure InsertNode; assembler;
  541. {
  542.   insertNode : insert the new node to the corresponding tree.  Note that the
  543.                position of a string in the buffer also served as the node
  544.                number.
  545.              ENTRY : di = position in the buffer
  546. }
  547. Asm
  548.               push    si
  549.               push    dx
  550.               push    cx
  551.               push    bx
  552.               mov     dx, 1
  553.               xor     ax, ax
  554.               mov     matchLen, ax
  555.               mov     height, ax
  556.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  557.               ADD     SI,DI
  558.               MOV     AL,BYTE PTR [ES:SI]
  559. {             mov     al, byte ptr [Offset TextBuf + di]}
  560.               shl     di, Log2TLZSSWord
  561.               add     ax, N + 1
  562.               shl     ax, Log2TLZSSWord
  563.               mov     si, ax
  564.               mov     ax, NUL
  565.               PUSH    BX
  566.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  567.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Right],AX
  568. {              mov     word ptr [Offset Right + di], ax}
  569.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Left],AX
  570.               POP     BX
  571. {              mov     word ptr [Offset Left + di], ax}
  572.   @Ins1:      inc     height
  573.               test    dx, dx
  574.               mov     dx, Nul
  575.               js      @Ins3
  576.               PUSH    DI
  577.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  578.               ADD     DI,SI
  579.               MOV     AX,[ES:DI+OFFSET TBinaryTree.Right]
  580.               POP     DI
  581. {              mov     ax, word ptr [Offset Right + si]}
  582.               cmp     ax, dx
  583.               jne      @Ins5
  584.               PUSH    BX
  585.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  586.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Right],DI
  587. {              mov     word ptr [Offset Right + si], di}
  588.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Mom],SI
  589.               POP     BX
  590. {              mov     word ptr [Offset Mom + di], si}
  591.               jmp     @Ins11
  592.   @Ins3:
  593.               PUSH    BX
  594.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  595.               MOV     AX,[ES:BX+SI+OFFSET TBinaryTree.Left]
  596.               POP     BX
  597. {              mov     ax, word ptr [Offset Left + si]}
  598.               cmp     ax, dx
  599.               jne      @Ins5
  600.               PUSH    BX
  601.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  602.               MOV     [ES:BX+SI+OFFSET TBinaryTree.Left],DI
  603. {              mov     word ptr [Offset Left + si], di}
  604.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Mom],SI
  605.               POP     BX
  606. {              mov     word ptr [Offset Mom + di], si}
  607.               jmp     @Ins11
  608.  
  609.   @Ins5:      mov     si, ax
  610.               mov     bx, 1
  611.               shr     si, Log2TLZSSWord
  612.               shr     di, Log2TLZSSWord
  613.               xor     ch, ch
  614.               xor     dh, dh
  615.   @Ins6:
  616.               PUSH    SI
  617.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  618.               ADD     SI,DI
  619.               MOV     DL,[ES:SI+BX]
  620.               POP     SI
  621.               PUSH    DI
  622.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  623.               ADD     DI,SI
  624.               MOV     CL,[ES:DI+BX]
  625.               POP     DI
  626. {              mov     dl, byte ptr [Offset Textbuf + di + bx]
  627.               mov     cl, byte ptr [Offset TextBuf + si + bx]}
  628.               sub     dx, cx
  629.               jnz     @Ins7
  630.               inc     bx
  631.               cmp     bx, F
  632.               jb      @Ins6
  633.   @Ins7:      mov     ax, si
  634.               shl     si, Log2TLZSSWord
  635.               shl     di, Log2TLZSSWord
  636.               cmp     bx, matchLen
  637.               jbe     @Ins1
  638.               mov     matchPos, ax
  639.               mov     matchLen, bx
  640.               cmp     bx, F
  641.               jb      @Ins1
  642.   @Ins8:
  643.               PUSH    CX
  644.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  645.               MOV     AX,[ES:BX+SI+OFFSET TBinaryTree.Mom]
  646. {              mov     ax, word ptr [Offset Mom + si]}
  647.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Mom],AX
  648. {              mov     word ptr [Offset Mom + di], ax}
  649.               MOV     CX,[ES:BX+SI+OFFSET TBinaryTree.Left]
  650. {              mov     bx, word ptr [Offset Left + si]}
  651.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Left],CX
  652. {              mov     word ptr [Offset Left + di], bx}
  653.               ADD     BX,CX
  654.               MOV     [ES:BX+OFFSET TBinaryTree.Mom],DI
  655. {              mov     word ptr [Offset Mom + bx], di}
  656.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  657.               MOV     CX,[ES:BX+SI+OFFSET TBinaryTree.Right]
  658. {              mov     bx, word ptr [Offset Right + si]}
  659.               MOV     [ES:BX+DI+OFFSET TBinaryTree.Right],CX
  660. {              mov     word ptr [Offset Right + di], bx}
  661.               ADD     BX,CX
  662.               MOV     [ES:BX+OFFSET TBinaryTree.Mom],DI
  663. {              mov     word ptr [Offset Mom + bx], di}
  664.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  665.               MOV     BX,[ES:BX+SI+OFFSET TBinaryTree.Mom]
  666. {              mov     bx, word ptr [Offset Mom + si]}
  667.               POP     CX
  668.               PUSH    DI
  669.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  670.               CMP     SI,[ES:DI+BX+OFFSET TBinaryTree.Right]
  671.               POP     DI
  672. {              cmp     si, word ptr [Offset Right + bx]}
  673.               jne     @Ins9
  674.               PUSH    SI
  675.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  676.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],DI
  677.               POP     SI
  678. {              mov     word ptr [Offset Right + bx], di}
  679.               jmp     @Ins10
  680.   @Ins9:
  681.               PUSH    SI
  682.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  683.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Left],DI
  684.               POP     SI
  685. {              mov     word ptr [Offset Left + bx], di}
  686.   @Ins10:
  687.               PUSH    DI
  688.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  689.               ADD     DI,SI
  690.               MOV     WORD PTR [ES:DI+OFFSET TBinaryTree.Mom],Nul
  691.               POP     DI
  692. {              mov     word ptr [Offset Mom + si], NUL}
  693.   @Ins11:     cmp     height, 30
  694.               jb      @Ins12
  695.               call    Splay
  696.   @Ins12:     pop     bx
  697.               pop     cx
  698.               pop     dx
  699.               pop     si
  700.               shr     di, Log2TLZSSWord
  701. End; { InsertNode }
  702.  
  703.  
  704. Procedure DeleteNode; assembler;
  705. {
  706.    deleteNode : delete the node from the tree
  707.  
  708.             ENTRY : SI = position in the buffer
  709. }
  710. Asm
  711.               push    di
  712.               push    bx
  713.               shl     si, Log2TLZSSWord
  714.               PUSH    DI
  715.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  716.               ADD     DI,SI
  717.               CMP     WORD PTR [ES:DI+OFFSET TBinaryTree.Mom], Nul
  718.               POP     DI
  719. {              cmp     word ptr [Offset Mom + si], NUL}   { ; if it has no parent then exit }
  720.               je      @del7
  721.               PUSH    DI
  722.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  723.               ADD     DI,SI
  724.               CMP     WORD PTR [ES:DI+OFFSET TBinaryTree.Right],Nul
  725.               POP     DI
  726. {              cmp     word ptr [Offset Right + si], NUL} { ; does it have right child ? }
  727.               jne      @HasRight
  728.               PUSH    BX
  729.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  730.               MOV     DI,[ES:BX+SI+OFFSET TBinaryTree.Left]
  731.               POP     BX
  732. {              mov     di, word ptr [Offset Left + si]}
  733.               jmp     @del3
  734.   @HasRight:  PUSH    BX
  735.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  736.               MOV     DI,[ES:BX+SI+OFFSET TBinaryTree.Left]
  737.               POP     BX
  738. {              mov     di, word ptr [Offset Left + si] }  { ; does it have left child ? }
  739.               cmp     di, Nul
  740.               jne     @HasLeft
  741.               PUSH    BX
  742.               MOV     BX,PtrRec[OFFSET BinaryTree].Ofs
  743.               MOV     DI,[ES:BX+SI+OFFSET TBinaryTree.Right]
  744.               POP     BX
  745. {              mov     di, word ptr [Offset Right + si]}
  746.               jmp     @del3
  747.   @HasLeft:   PUSH    SI
  748.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  749.               ADD     SI,DI
  750.               MOV     AX,[ES:SI+OFFSET TBinaryTree.Right]
  751.               POP     SI
  752. {              mov     ax, word ptr [Offset Right + di]}  { ; does it have right grandchild ? }
  753.               cmp     ax, Nul
  754.               je      @del2                             { ; if no then skip }
  755.   @del1:      mov     di, ax                            { ; find the rightmost node in }
  756.               PUSH    SI
  757.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  758.               ADD     SI,DI
  759.               MOV     AX,[ES:SI+OFFSET TBinaryTree.Right]
  760.               POP     SI
  761. {              mov     ax, word ptr [Offset Right + di] } { ;   the right subtree }
  762.               cmp     ax, Nul
  763.               jne     @del1
  764.               PUSH    CX
  765.               MOV     CX,SI
  766.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  767.               ADD     SI,DI
  768.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Mom]
  769. {              mov     bx, word ptr [Offset Mom + di] }   { ; move this node as the root of }
  770.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  771.               ADD     SI,DI
  772.               MOV     AX,[ES:SI+OFFSET TBinaryTree.Left]
  773. {              mov     ax, word ptr [Offset Left + di]}   { ;   the subtree }
  774.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  775.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],AX
  776. {              mov     word ptr [Offset Right + bx], ax}
  777.               xchg    ax, bx
  778.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],AX
  779. {              mov     word ptr [Offset Mom + bx], ax}
  780.               ADD     SI,CX
  781.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Left]
  782. {              mov     bx, word ptr [Offset Left + si]}
  783.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  784.               ADD     SI,DI
  785.               MOV     [ES:SI+OFFSET TBinaryTree.Left],BX
  786. {              mov     word ptr [Offset Left + di], bx}
  787.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  788.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DI
  789. {              mov     word ptr [Offset Mom + bx], di}
  790.               MOV     SI,CX
  791.               POP     CX
  792.   @del2:
  793.               PUSH    CX
  794.               MOV     CX,SI
  795.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  796.               ADD     SI,CX
  797.               MOV     BX,[ES:SI+OFFSET TBinaryTree.Right]
  798. {              mov     bx, word ptr [Offset Right + si]}
  799.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  800.               ADD     SI,DI
  801.               MOV     [ES:SI+OFFSET TBinaryTree.Right],BX
  802. {              mov     word ptr [Offset Right + di], bx}
  803.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  804.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Mom],DI
  805.               MOV     SI,CX
  806.               POP     CX
  807. {              mov     word ptr [Offset Mom + bx], di}
  808.   @del3:
  809.               PUSH    CX
  810.               MOV     CX,DI
  811.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  812.               ADD     DI,SI
  813.               MOV     BX,[ES:DI+OFFSET TBinaryTree.Mom]
  814. {              mov     bx, word ptr [Offset Mom + si]}
  815.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  816.               ADD     DI,CX
  817.               MOV     [ES:DI+OFFSET TBinaryTree.Mom],BX
  818. {              mov     word ptr [Offset Mom + di], bx}
  819.               MOV     DI,CX
  820.               POP     CX
  821.               PUSH    DI
  822.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  823.               CMP     SI,[ES:DI+BX+OFFSET TBinaryTree.Right]
  824.               POP     DI
  825. {              cmp     si, word ptr [Offset Right + bx]}
  826.               jne     @del4
  827.               PUSH    SI
  828.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  829.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Right],DI
  830.               POP     SI
  831. {              mov     word ptr [Offset Right + bx], di}
  832.               jmp     @del5
  833.   @del4:
  834.               PUSH    SI
  835.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  836.               MOV     [ES:SI+BX+OFFSET TBinaryTree.Left],DI
  837.               POP     SI
  838. {              mov     word ptr [Offset Left + bx], di}
  839.   @del5:
  840.               PUSH    DI
  841.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  842.               ADD     DI,SI
  843.               MOV     WORD PTR [ES:DI+OFFSET TBinaryTree.Mom],Nul
  844.               POP     DI
  845. {              mov     word ptr [Offset Mom + si], NUL}
  846.   @del7:      pop     bx
  847.               pop     di
  848.               shr     si, Log2TLZSSWord
  849.   @end:
  850. End; { DeleteNode }
  851.  
  852. Procedure LZEncode; assembler;
  853. Asm
  854. {                                                   }
  855. { Load ES with segment of Binary Tree structure ... }
  856. {                                                   }
  857.               MOV     ES, PtrRec[OFFSET BinaryTree].&Seg
  858. {                }
  859. { Now encode ... }
  860. {                }
  861.               call    initTree
  862.               xor     bx, bx
  863.               mov     [Offset CodeBuf], bl
  864.               mov     dx, 1
  865.               mov     ch, dl
  866.               xor     si, si
  867.               mov     di, N - F
  868.   @Encode2:   call    getc
  869.               jnc     @ReadOK
  870.               or      bx, bx
  871.               je      @Encode19
  872.               jmp     @Encode4
  873.   @ReadOK:    PUSH    SI
  874.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  875.               ADD     SI,DI
  876.               MOV     [ES:SI+BX],AL
  877.               POP     SI
  878. {              mov     byte ptr [Offset TextBuf +di + bx], al}
  879.               inc     bx
  880.               cmp     bx, F
  881.               jb      @Encode2
  882.   @Encode4:   mov     cl, bl
  883.               xor     bx, bx
  884.               push    di
  885.               dec     di
  886.   @Encode5:   call    InsertNode
  887.               inc     bx
  888.               dec     di
  889.               cmp     bx, F
  890.               jb      @Encode5
  891.               pop     di
  892.               call    InsertNode
  893.   @Encode6:   mov     ax, matchLen
  894.               cmp     al, cl
  895.               jbe     @Encode7
  896.               mov     al, cl
  897.               mov     matchLen, ax
  898.   @Encode7:   cmp     al, THRESHOLD
  899.               ja      @Encode8
  900.               mov     matchLen, 1
  901.               or      byte ptr codeBuf, ch
  902.               mov     bx, dx
  903.               PUSH    SI
  904.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  905.               ADD     SI,DI
  906.               MOV     AL,[ES:SI]
  907.               POP     SI
  908. {              mov     al, byte ptr [Offset TextBuf + di]}
  909.               mov     byte ptr [Offset CodeBuf + bx], al
  910.               inc     dx
  911.               jmp     @Encode9
  912.   @Encode8:   mov     bx, dx
  913.               mov     ax, MatchPos
  914.               mov     byte ptr [Offset Codebuf + bx], al
  915.               inc     bx
  916.               push    cx
  917.               mov     cl, 4
  918.               shl     ah, cl
  919.               pop     cx
  920.               mov     al, byte ptr MatchLen
  921.               sub     al, THRESHOLD + 1
  922.               add     ah, al
  923.               mov     byte ptr [Offset Codebuf + bx], ah
  924.               inc     bx
  925.               mov     dx, bx
  926.   @Encode9:   shl     ch, 1
  927.               jnz     @Encode11
  928.               xor     bx, bx
  929.   @Encode10:  mov     al, byte ptr [Offset CodeBuf + bx]
  930.               call    putc
  931.               inc     bx
  932.               cmp     bx, dx
  933.               jb      @Encode10
  934.               mov     dx, 1
  935.               mov     ch, dl
  936.               mov     byte ptr codeBuf, dh
  937.   @Encode11:  mov     bx, matchLen
  938.               mov     lastLen, bx
  939.               xor     bx, bx
  940.   @Encode12:  call    getc
  941. {              jc      @Encode14}
  942.               jc      @EncodeY
  943.               push    ax
  944.               call    deleteNode
  945.               pop     ax
  946.               PUSH    DI
  947.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  948.               ADD     DI,SI
  949.               STOSB
  950.               POP     DI
  951. {              mov     byte ptr [Offset TextBuf + si], al}
  952.               cmp     si, F - 1
  953.               jae     @Encode13
  954.               PUSH    DI
  955.               MOV     DI,PtrRec[OFFSET BinaryTree].Ofs
  956.               ADD     DI,SI
  957.               MOV     [ES:DI+N],AL
  958.               POP     DI
  959. {              mov     byte ptr [Offset TextBuf + si + N], al}
  960.   @Encode13:  inc     si
  961.               and     si, N - 1
  962.               inc     di
  963.               and     di, N - 1
  964.               call    insertNode
  965.               inc     bx
  966.               cmp     bx, lastLen
  967.               jb      @Encode12
  968.               jmp     @Encode16
  969. (*  @Encode14:  sub     printCount, bx
  970.               jnc     @EncodeY
  971.               mov     ax, printPeriod
  972.               mov     printCount, ax
  973.               push    dx                 { Print out a period as a sign. }
  974.               mov     dl, DBLARROW
  975.               mov     ah, 2
  976.               int     21h
  977.               pop     dx *)
  978.   @EncodeX:   inc     bx
  979.               call    deleteNode
  980.               inc     si
  981.               and     si, N - 1
  982.               inc     di
  983.               and     di, N - 1
  984.               dec     cl
  985.               jz      @EncodeY
  986.               call    insertNode
  987.   @EncodeY:   cmp     bx, LastLen
  988.               jb      @EncodeX
  989.   @Encode16:  test    cl, cl
  990.               jnz     @Encode6
  991.   @Encode17:  test    dx, dx
  992.               jz      @Encode19
  993.               xor     bx, bx
  994.   @Encode18:  mov     al, byte ptr [Offset Codebuf + bx]
  995.               call    putc
  996.               inc     bx
  997.               cmp     bx, dx
  998.               jb      @Encode18
  999.   @Encode19:
  1000.               call    LZSS_Write
  1001. End; { Encode }
  1002.  
  1003. Procedure LZDecode; assembler;
  1004. Asm
  1005. {                                                   }
  1006. { Load ES with segment of Binary Tree structure ... }
  1007. {                                                   }
  1008.               MOV     ES, PtrRec[OFFSET BinaryTree].&Seg
  1009. {                }
  1010. { Now decode ... }
  1011. {                }
  1012.               xor     dx, dx
  1013.               mov     di, N - F
  1014.   @Decode2:   shr     dx, 1
  1015.               or      dh, dh
  1016.               jnz     @Decode3
  1017.               call    getc
  1018.               jc      @Decode9
  1019.               mov     dh, 0ffh
  1020.               mov     dl, al
  1021.   @Decode3:   call    getc
  1022.               jc      @Decode9
  1023.               test    dl, 1
  1024.               jz      @Decode4
  1025.               PUSH    SI
  1026.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  1027.               ADD     SI,DI
  1028.               MOV     [ES:SI],AL
  1029.               POP     SI
  1030. {              mov     byte ptr [Offset TextBuf + di], al}
  1031.               inc     di
  1032.               and     di, N - 1
  1033.               call    putc
  1034.               jmp     @Decode2
  1035.   @Decode4:   mov     bl, al
  1036.               call    getc
  1037.               jc      @Decode9
  1038.               mov     bh, al
  1039.             {$IFOPT G+}
  1040.               shr     bh, 4
  1041.             {$ELSE}
  1042.               mov     cl, 4
  1043.               shr     bh, cl
  1044.             {$ENDIF}
  1045.               mov     cl, al
  1046.               and     cl, 0fh
  1047.               add     cl, THRESHOLD
  1048.               inc     cl
  1049.   @Decode5:   and     bx, N - 1
  1050.               PUSH    SI
  1051.               MOV     SI,PtrRec[OFFSET BinaryTree].Ofs
  1052.               MOV     AL,[ES:SI+BX]
  1053.               ADD     SI,DI
  1054.               MOV     [ES:SI],AL
  1055.               POP     SI
  1056. {              mov     al, byte ptr [Offset TextBuf + bx]
  1057.               mov     byte ptr [Offset TextBuf + di], al}
  1058.               inc     di
  1059.               and     di, N - 1
  1060.               call    putc
  1061.               inc     bx
  1062.               dec     cl
  1063.               jnz     @Decode5
  1064.               jmp     @Decode2
  1065.   @Decode9:
  1066.               call    LZSS_Write
  1067. End; { Decode }
  1068.  
  1069. Function LZInit : boolean;
  1070. label
  1071.   LZAbort;
  1072. Begin
  1073. {
  1074.   *Non-interruptable* test for whether LZ unit is busy ...
  1075. }
  1076.   asm
  1077.     MOV AL, True          { if IsLZInitialized then goto LZAbort; }
  1078.     XCHG IsLZInitialized, AL  { IsLZInitialized := True;              }
  1079.     TEST AL, AL
  1080.     JNZ LZAbort
  1081.   end;
  1082. {
  1083.   Unit WASN'T busy, but it is now ...
  1084. }
  1085.   New(InBufP);
  1086.   New(OutBufP);
  1087.   New(BinaryTree);
  1088.   if (InBufP = nil) or (OutBufP = nil) or (BinaryTree = nil) then
  1089.     LZDone;
  1090. LZAbort:
  1091.   LZInit := IsLZInitialized
  1092. End; { LZInit }
  1093.  
  1094. Procedure LZDone;
  1095. Begin
  1096.   if InBufP <> nil then
  1097.     Dispose(InBufP);
  1098.   if OutBufP <> nil then
  1099.     Dispose(OutBufP);
  1100.   if BinaryTree <> nil then
  1101.     Dispose(BinaryTree);
  1102.   IsLZInitialized := False
  1103. End; { LZDone }
  1104.  
  1105. Procedure LZSquash;
  1106. Begin
  1107.   if IsLZInitialized then
  1108.   begin
  1109.     InBufPtr := LZRWBufSize;
  1110.     InBufSize := LZRWBufSize;
  1111.     OutBufPtr := 0;
  1112.     Height := 0;
  1113.     MatchPos := 0;
  1114.     MatchLen := 0;
  1115.     LastLen := 0;
  1116.  
  1117.     FillChar(BinaryTree^, SizeOf(TBinaryTree), 0);
  1118.     FillChar(CodeBuf, SizeOf(CodeBuf), 0);
  1119.  
  1120.     LZReadProc := ReadProc;
  1121.     LZWriteProc := WriteProc;
  1122.  
  1123.     LZEncode
  1124.   end
  1125. End; { LZSquash }
  1126.  
  1127. Procedure LZUnSquash;
  1128. Begin
  1129.   if IsLZInitialized then
  1130.   begin
  1131.     InBufPtr := LZRWBufSize;
  1132.     InBufSize := LZRWBufSize;
  1133.     OutBufPtr := 0;
  1134.     FillChar(BinaryTree^.TextBuf, SizeOf(TLZTextBuf), 0);
  1135.  
  1136.     LZReadProc := ReadProc;
  1137.     LZWriteProc := WriteProc;
  1138.  
  1139.     LZDecode;
  1140.   end
  1141. End; { LZUnSquash }
  1142.  
  1143. {$IFDEF Windows}
  1144. Function HeapFunc(Size : word) : integer; far; assembler;
  1145. Asm
  1146.   MOV AX,1
  1147. End; { HeapFunc }
  1148. {$ENDIF}
  1149.  
  1150. {$IFDEF Windows}
  1151. Begin
  1152.   HeapError := @HeapFunc;
  1153. {$ENDIF}
  1154. End. { LZSSUNIT }
  1155.