home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / Basic / SLENCODE.ZIP / SLDECODE.ASM next >
Encoding:
Assembly Source File  |  1992-08-25  |  12.9 KB  |  445 lines

  1. ;//////////////////////////////////////////////////////////////////////////////
  2. ;/                  QuickBASIC & PDS Callable LZSS Decoder                    /  
  3. ;/                          By Rich Geldreich 1992                            /
  4. ;/                                                                            /
  5. ;/ Anyone may freely use and distribute this program as long as proper credit /
  6. ;/ is given when it is used. Thanks!                                          /
  7. ;/                                                                            /
  8. ;//////////////////////////////////////////////////////////////////////////////
  9.  
  10. ;Assembled with Turbo Assembler v2.0
  11. ;ToDo list: Add critical error handler for those hard to beat "abort, retry,
  12. ;ignore?" messages
  13.  
  14. .286 ;<-- sorry, needs at least a 286!
  15. Ideal
  16. Model Small
  17.  
  18. BufferSize = 4096
  19. DiskBuffer = 12000;24,000 bytes total used for disk buffers! Ouch!
  20.                   ;The procedure should be modified so it dynamically allocates
  21.                   ;the buffers when it's ran... That's your job!
  22.                    
  23. MaxMatch   = 74
  24. Threshold  = 2
  25.  
  26. DataSeg
  27.  
  28. Assume  ds:@data, es:@data, cs:@code, ss:nothing
  29.  
  30.                 Even
  31.  
  32. R               dw 0
  33. InAddress       dw 0
  34. OutAddress      dw 0
  35.  
  36. InHandle        dw 0
  37. OutHandle       dw 0
  38.  
  39. TempChar        db 0
  40. Bitsleft        db 0
  41.  
  42. RingBuffer      db BufferSize dup(?)
  43.  
  44. InBuffer        db DiskBuffer dup(?)
  45. Outbuffer       db DiskBuffer dup(?)
  46.  
  47. CodesLeft       dw ?
  48.                 dw ?
  49.  
  50. CodeSeg
  51. Public SlDecode
  52.  
  53. SourceOffset    equ [ss:bp+12]
  54. SourceSegment   equ [ss:bp+10]
  55. DestOffset      equ [ss:bp+8]
  56. DestSegment     equ [ss:bp+6]
  57. ;//////////////////////////////////////////////////////////////////////////////
  58. ;Main QB callable routine                
  59. Proc    SlDecode 
  60.         Push    bp
  61.         Mov     bp, sp
  62.         Push    ds es si di
  63.         
  64.         Call    Init            ;Initialize everything
  65.  
  66.         Call    OpenFiles       ;Open the files
  67.         Jc      @@FError        ;Error?
  68.         
  69.         Call    Decompress      ;Decompress 
  70.         Jc      @@DError        ;Error?
  71.         
  72.         Xor     ax, ax          ;No error
  73.         
  74. @@Exit: Call    CloseFiles      ;Close the open files
  75.         Pop     di si es ds bp  ;Pop regs and return to caller
  76.         Retf    8
  77. @@FError:
  78.         Mov     ax, -1          ;File error
  79.         Jmp     @@Exit
  80. @@DError:
  81.         Mov     ax, -2          ;Decompression error
  82.         Jmp     @@Exit
  83. Endp    SlDecode
  84. ;//////////////////////////////////////////////////////////////////////////////
  85. ;Opens files.                        
  86. Proc    OpenFiles
  87.         Mov     ax, @data
  88.         Mov     es, ax
  89.                 
  90.         Mov     ds, SourceSegment
  91.         Mov     dx, SourceOffset
  92.         Mov     ax, 03D00h
  93.         Int     021h
  94.         Jc      @@Error
  95.         Mov     [es:InHandle], ax
  96.         
  97.         Mov     ds, DestSegment
  98.         Mov     dx, DestOffset
  99.         Mov     ax, 03C00h
  100.         Xor     cx, cx
  101.         Int     021h
  102.         Jc      @@Error
  103.         Mov     [es:OutHandle], ax
  104. @@Error:
  105.         Ret
  106. Endp    OpenFiles
  107. ;//////////////////////////////////////////////////////////////////////////////
  108. ;Closes any open files.
  109. Proc    CloseFiles
  110.         Push    ax
  111.         Mov     bx, [ds:InHandle]
  112.         Cmp     bx, 0ffffh
  113.         Je      @@NextFile       ;Is this file really open?
  114.         Mov     ah, 03Eh 
  115.         Int     021h             ;Close it then
  116. @@NextFile:
  117.         Mov     bx, [ds:OutHandle]
  118.         Cmp     bx, 0ffffh
  119.         Je      @@Alldone
  120.         Mov     ah, 03Eh 
  121.         Int     021h
  122. @@AllDone:        
  123.         Pop     ax
  124.         Ret
  125. Endp    CloseFiles
  126. ;//////////////////////////////////////////////////////////////////////////////
  127. ;Fills up the input buffer.
  128. Proc    FillBuffer
  129.         Push    ax bx cx dx
  130.         Mov     ah, 03fh
  131.         Mov     bx, [ds:InHandle]
  132.         Mov     cx, DiskBuffer
  133.         Mov     dx, offset InBuffer
  134.         Int     021h                    ;CF now has error, if any
  135.         Mov     si, offset Inbuffer
  136.         Pop     dx cx bx ax
  137.         Ret
  138. Endp    FillBuffer
  139. ;//////////////////////////////////////////////////////////////////////////////
  140. ;Flushes the output buffer.
  141. Proc    FlushBuffer
  142.         
  143.         Push    ax bx cx dx
  144.         
  145.         Mov     di, offset Outbuffer
  146.  
  147.         Mov     ah, 040h
  148.         Mov     bx, [ds:OutHandle]
  149.         Mov     cx, [ds:OutAddress]
  150.         Sub     cx, di
  151.         Mov     dx, offset OutBuffer
  152.         Int     021h
  153.  
  154.         Jc      @@Error         ;Error while flushing?
  155.         Cmp     ax, cx          ;All bytes written?
  156.         Je      @@OK
  157.         Stc
  158.         Jmp     short @@Error
  159. @@OK:        
  160.         Clc
  161. @@Error:        
  162.         Pop     dx cx bx ax
  163.         Ret
  164. Endp    FlushBuffer 
  165.  
  166. ;//////////////////////////////////////////////////////////////////////////////
  167. ;Gets a multibit code from the input stream- CH has # of bits wanted.
  168.         Even
  169. Proc    GetCode
  170.         Mov     si, [ds:InAddress]
  171.         Mov     ax, [word ds:TempChar]
  172.         Mov     cl, ah
  173.         Xor     ah, ah
  174.         Mov     di, offset InBuffer+DiskBuffer
  175.         Mov     bh, 8
  176.                      
  177.         Mov     dl, cl          ;Work=TempChar >> (8-Bitsleft)
  178.         Neg     cl
  179.         Jz      @@FillUp        ;Get 8 more bits if none
  180.         Add     cl, bh
  181. @@NZ:
  182.         Mov     bp, ax
  183.         Shr     bp, cl
  184.         Mov     cl, dl
  185.  
  186.         Cmp     ch, cl          ;Enough bits?
  187.         Jna     @@20            
  188. @@15:        
  189.         Cmp     si, di          ;End of input buffer?
  190.         Je      @@FillBuffer2   ;Fill up if so
  191. @@BF2:
  192.         Lodsb                   ;TempChar=Byte
  193.         Mov     dx, ax
  194.         Shl     dx, cl          ;Work=Work or TempChar << BitsLeft
  195.         Or      bp, dx
  196.         Add     cl, bh
  197.         Cmp     ch, cl          ;Enough bits?
  198.         Ja      @@15            ;Nope, get more
  199. @@20:
  200.         Sub     cl, ch          ;Less bits now
  201.         Mov     ah, cl          ;Save TempChar and BitsLeft
  202.         Mov     [word ds:TempChar], ax
  203.         Mov     [ds:InAddress], si      ;Save in address
  204.         Clc                             ;No errors
  205.         Ret
  206.         
  207.         Even
  208. @@FillUp:
  209.         Cmp     si, di
  210.         Je      @@FillBuffer1
  211. @@BF1:
  212.         Lodsb
  213.         
  214.         Mov     dl, bh          ;8 more bits now
  215.         Jmp     @@NZ            ;CL=0 DL=8 now
  216.  
  217. @@FillBuffer1:
  218.         Call    FillBuffer
  219.         Jnc     @@BF1
  220.         Ret
  221.  
  222. @@FillBuffer2:
  223.         Call    FillBuffer
  224.         Jnc     @@BF2
  225.         Ret
  226. Endp    GetCode
  227.  
  228. ;//////////////////////////////////////////////////////////////////////////////
  229. ;Initializes the ring buffer to space characters, sets the read & write 
  230. ;pointers to their starting states, etc.
  231. Proc    Init    
  232.         Mov     ax, @data
  233.         Mov     es, ax
  234.         Mov     ds, ax
  235.                 
  236.         Mov     di, offset RingBuffer
  237.         Mov     cx, BufferSize-MaxMatch
  238.         Mov     al, 32
  239.         Rep     Stosb           ;Clears ring buffer with space characters
  240.         
  241.         ;Make sure the input buffer gets filled up on next read
  242.         Mov     [ds:InAddress], offset InBuffer+DiskBuffer
  243.  
  244.         ;Next byte outputted goes to the start of the output buffer
  245.         Mov     [ds:OutAddress], offset OutBuffer
  246.  
  247.         ;R=BufferSize-MaxMatch                        
  248.         Mov     [ds:R], (BufferSize-MaxMatch)+Offset RingBuffer
  249.         
  250.         Mov     ax, 0ffffh
  251.         Mov     [ds:InHandle], ax
  252.         Mov     [ds:OutHandle], ax
  253.         Mov     [ds:BitsLeft], 0
  254.         
  255.         Ret
  256. Endp    Init
  257. ;//////////////////////////////////////////////////////////////////////////////
  258. ;Actuall decompression subroutine. 
  259. Proc    Decompress
  260.         Mov     ax, @Data
  261.         Mov     ds, ax
  262.         Mov     es, ax
  263.                 
  264.         ;Retrieve # of codes to process and check to see
  265.         ;if the source file has the correct header("RG")
  266.         Mov     bx, [ds:InHandle]
  267.         Mov     dx, offset CodesLeft-2
  268.         Mov     cx, 6
  269.         Mov     ah, 03Fh
  270.         Int     021h
  271.         Jc      @@Error
  272.         Cmp     [word ds:CodesLeft-2], 'R'+'G'*256
  273.         Jne     @@Error
  274.         
  275.         Jmp     @@MainLoop      ;Start decompressing
  276.  
  277. @@Error:
  278.         Stc
  279.         Ret
  280.         
  281. @@CheckHigh:
  282.         Sub     [ds:CodesLeft+2], 1
  283.         Jnc     @@Continue
  284.         Call    FlushBuffer     ;Save what's in the disk buffer
  285.         Ret                     ;CF has error, if any
  286.  
  287. @@FlushBuffer:
  288.         Mov     [ds:OutAddress], di
  289.         Call    FlushBuffer
  290.         Jc      @@Error
  291.         Jmp     @@Flushed
  292.  
  293. @@WrapBack:
  294.         Mov     di, offset RingBuffer
  295.         Jmp     @@Wraped
  296.  
  297.         Even         
  298. @@MainLoop:
  299.         Sub     [ds:Codesleft], 1 ;Sets carry if decrement goes to 0ffffh
  300.         Jc      @@CheckHigh
  301. @@Continue:
  302.         Mov     ch, 9           ;Get 9 bits of code
  303.         Call    GetCode
  304.         Jc      @@Error         ;Exit if error
  305.         Shr     bp, 1           ;Put flag bit in carry
  306.         Jc      @@Match         ;Is it a character or position/length pair?
  307.  
  308.         Mov     ax, bp          ;It's a character...
  309.         Mov     di, [ds:OutAddress]
  310.         Stosb                   ;Put the character in the disk buffer
  311.         Cmp     di, offset OutBuffer+DiskBuffer
  312.         Je      @@Flushbuffer   ;Flush if full
  313. @@Flushed:
  314.         Mov     [ds:OutAddress], di
  315.         Mov     di, [ds:R]
  316.         Stosb                   ;Put the character in the ring buffer
  317.         Cmp     di, offset RingBuffer+BufferSize
  318.         Je      @@WrapBack      ;Increment position MOD buffersize
  319. @@Wraped:
  320.         Mov     [ds:R], di
  321.         Jmp     @@MainLoop      ;Do it again
  322.  
  323. @@Error2:
  324.         Ret
  325.         Even
  326. @@LongMatch:
  327.         Mov     ch, 11
  328.         Call    GetCode
  329.         Jc      @@Error2
  330.         Mov     si, bp
  331.         
  332.         Shl     bl, 1
  333.         Shl     bl, 1
  334.         Rcl     si, 1
  335.         Shr     bl, 1
  336.         Shr     bl, 1
  337.         
  338.         Mov     cx, bx
  339.         And     cx, 63
  340.         Add     cl, 11
  341.         Jmp     @@LMReady
  342.         Even
  343. @@Match:        
  344.         Shr     bp, 1
  345.         Mov     bx, bp
  346.         Jc      @@LongMatch
  347.         Mov     ch, 8           ;(7+8)=(12+3)
  348.         Call    GetCode         
  349.         Jc      @@Error2        ;Exit if error
  350.         Mov     cx, bp          
  351.         Shl     cx, 7
  352.         And     bl, 127
  353.         Or      cl, bl
  354.         Mov     si, cx          ;SI = buffer address
  355.         Shr     si, 3           ;Skip the match length
  356.         And     cx, 7
  357.         Add     cl, Threshold+1
  358. @@LMReady:
  359.         
  360.         And     si, 4095
  361.         Add     si, offset RingBuffer
  362.  
  363.         Mov     di, [ds:OutAddress]
  364.         Mov     bx, [ds:R]
  365.  
  366.         Mov     ax, ((offset RingBuffer)+BufferSize-(MaxMatch+1))
  367.  
  368.         ;Can a fast copy safely be used?
  369.         ;(is there any danger of a pointer wrapping back, if so then
  370.         ;do a slow copy)
  371.         
  372.         Cmp     si, ax          
  373.         Jnb     @@SlowCopyInit  
  374.  
  375.         Cmp     bx, ax
  376.         Jnb     @@SlowCopyInit
  377.  
  378.         Cmp     di, ((offset OutBuffer)+DiskBuffer-(MaxMatch+1))
  379.         Jnb     @@SlowCopyInit
  380.  
  381.         ;CX/2 for in-line coding
  382.         Shr     cx, 1
  383.         Jnc     @@FastCopy      ;Not odd number of bytes to copy?
  384.         Lodsb                   ;Copy one byte
  385.         Stosb
  386.         Mov     [ds:bx], al
  387.         Inc     bx
  388.         Even
  389. @@FastCopy:
  390.        Rept    2                ;Copy two bytes- a word move cannot
  391.         Lodsb                   ;be used, unless a special case is taken care
  392.         Stosb                   ;of; but a byte at a time should do
  393.         Mov     [ds:bx], al
  394.         Inc     bx
  395.        Endm
  396.         Loop    @@FastCopy
  397.  
  398.         Mov     [ds:R], bx      ;Save pointers and get next code
  399.         Mov     [ds:OutAddress], di
  400.         Jmp     @@MainLoop
  401.                 
  402.  ;The following does a slow copy, the pointers are checked as they are 
  403.  ;modified to see if they need wrapping back.
  404.  
  405. @@SlowCopyInit:                
  406.         Mov     dx, offset RingBuffer+BufferSize
  407.         Mov     bp, offset OutBuffer+DiskBuffer
  408.         Even
  409. @@SlowCopy:
  410.         Lodsb
  411.         Stosb
  412.         Mov     [ds:bx], al
  413.         Inc     bx
  414.         Cmp     si, dx
  415.         Je      @@WrapBack2
  416. @@WB2:
  417.         Cmp     bx, dx
  418.         Je      @@WrapBack3
  419. @@WB3:
  420.         Cmp     di, bp
  421.         Je      @@FlushBuffer2
  422. @@FB2:
  423.         Loop    @@SlowCopy
  424.         Mov     [ds:R], bx
  425.         Mov     [ds:OutAddress], di
  426.         Jmp     @@MainLoop
  427.  
  428.         
  429. @@WrapBack2:
  430.         Mov     si, offset RingBuffer
  431.         Jmp     @@WB2
  432.  
  433. @@WrapBack3:
  434.         Mov     bx, offset RingBuffer
  435.         Jmp     @@WB3
  436.  
  437. @@FlushBuffer2:
  438.         Mov     [ds:OutAddress], di
  439.         Call    FlushBuffer
  440.         Jnc     @@FB2
  441.         Ret                                        
  442. Endp    Decompress
  443. ;///////////////////////////End of SLDECODE.ASM/////////////////////////////////
  444. End
  445.