home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / Basic / SLENCODE.ZIP / SLDECODE.BAS < prev    next >
Encoding:
BASIC Source File  |  1992-06-20  |  4.8 KB  |  170 lines

  1. 'SLDECODE.BAS - Sample decompression program for SLENCODE.BAS
  2. 'By Rich Geldreich 1992
  3. 'Note: SLDECODE.ASM is a _much_ faster version of this program. I have mainly
  4. 'included this program for reference purposes only. Ooops! Last minute
  5. 'warning: don't compile this program without first renaming the SLDECODE.OBJ
  6. 'file to something else! Especially if you don't have Turbo Assembler.
  7.  
  8. 'ToDo list: Add more terse error checking, make into callable subroutine,
  9. 'add CRC-32 routine, etc.
  10.  
  11. 'Warning: Do NOT press CTRL+Break and then continue this program while
  12. 'you are running it in the environment! At best, the resulting decompressed
  13. 'file will be invalid. At worst, your machine will lock up.
  14.  
  15. 'QuickBASIC 4.5 users: As this program is, it will not work correctly with
  16. 'QB 4.5. To make it QB 4.5 compatible, simply change all of the "SSEG" strings
  17. 'in this program to "VARSEG" strings with the search and replace function.
  18. 'Note that the SLDECODE.ASM routine should not require any changes for it to
  19. 'work properly.
  20.  
  21. DEFINT A-Z
  22.  
  23. DECLARE FUNCTION GetDat (C)
  24. DECLARE SUB FillInputBuf ()
  25.  
  26. CONST BufferSize = 4096
  27. CONST MaxMatch = 74
  28. CONST Threshold = 2
  29. CONST Null = BufferSize
  30.  
  31. CONST True = -1, False = 0
  32.  
  33. DIM Ring.Buffer(BufferSize - 1)
  34.  
  35. DIM SHARED InBuffer$, ISeg, IAddress, IEndAddress
  36. DIM SHARED OutBuffer$, OSeg, OAddress, OStartAddress, OEndAddress
  37. DIM SHARED Powers(7), LongPowers(11) AS LONG, Masks(12), BitsLeft, TempChar
  38.         
  39.  PRINT "SLDECODE.BAS v1.0 - LZSS Decoder in QuickBASIC 4.5"
  40.  PRINT "By Rich Geldreich 1992"
  41.  A$ = COMMAND$
  42.  IF A$ = "" THEN INPUT "File to decompress"; A$: A$ = UCASE$(A$)
  43.  IF A$ = "" THEN END
  44.  
  45.  Powers(0) = 1: Powers(1) = 2: Powers(2) = 4: Powers(3) = 8: Powers(4) = 16
  46.  Powers(5) = 32: Powers(6) = 64: Powers(7) = 128
  47.  
  48.  LongPowers(1) = 2: LongPowers(2) = 4: LongPowers(3) = 8: LongPowers(4) = 16
  49.  LongPowers(5) = 32: LongPowers(6) = 64: LongPowers(7) = 128: LongPowers(8) = 256
  50.  LongPowers(9) = 512: LongPowers(10) = 1024: LongPowers(11) = 2048
  51.  
  52.  Masks(1) = 1: Masks(8) = 255: Masks(12) = 4095: Masks(3) = 7: Masks(6) = 63
  53.  
  54.  InBuffer$ = SPACE$(4096)
  55.  IAddress = 0: IEndAddress = 1
  56.  
  57.  OutBuffer$ = SPACE$(4096)
  58.  A& = SADD(OutBuffer$)
  59.  IF A& < 0 THEN A& = A& + 65536
  60.  OSeg = SSEG(OutBuffer$) + (A& \ 16)
  61.  OAddress = A& AND 15
  62.  OStartAddress = OAddress
  63.  OEndAddress = OAddress + 4096
  64.  DEF SEG = OSeg
  65.  
  66.  R = BufferSize - MaxMatch
  67.  FOR A = 0 TO R - 1
  68.     Ring.Buffer(A) = 32
  69.  NEXT
  70.  
  71.  OPEN A$ FOR BINARY AS #2
  72.  
  73.  OPEN "OUTPUT.SL1" FOR BINARY AS #1
  74.  GET #1, 3, CodesLeft&
  75.  Codes& = CodesLeft&
  76.  
  77.  FOR CodesLeft& = CodesLeft& TO 1 STEP -1
  78.  
  79.     IF G = 0 THEN GOSUB UpdatePercent
  80.     G = (G + 1) AND 255
  81.  
  82.     DEF SEG = ISeg
  83.     IF GetDat(1) = 0 THEN
  84.         Char = GetDat(8)
  85.         
  86.          DEF SEG = OSeg
  87.  
  88.          IF OAddress = OEndAddress THEN
  89.              PUT #2, , OutBuffer$
  90.              OAddress = OStartAddress
  91.          END IF
  92.          POKE OAddress, Char
  93.          OAddress = OAddress + 1
  94.  
  95.         Ring.Buffer(R) = Char
  96.         R = (R + 1) AND (BufferSize - 1)
  97.     ELSE
  98.         IF GetDat(1) THEN
  99.             Match.Length = GetDat(6) + 11
  100.         ELSE
  101.             Match.Length = GetDat(3) + (Threshold + 1)
  102.         END IF
  103.  
  104.         Match.Position = GetDat(12)
  105.  
  106.         DEF SEG = OSeg
  107.  
  108.         FOR A = 1 TO Match.Length
  109.             Char = Ring.Buffer(Match.Position)
  110.  
  111.              IF OAddress = OEndAddress THEN
  112.                  PUT #2, , OutBuffer$
  113.                  OAddress = OStartAddress
  114.              END IF
  115.              POKE OAddress, Char
  116.              OAddress = OAddress + 1
  117.  
  118.             Ring.Buffer(R) = Char
  119.             R = (R + 1) AND (BufferSize - 1)
  120.             Match.Position = (Match.Position + 1) AND (BufferSize - 1)
  121.         NEXT
  122.     END IF
  123.  
  124.  NEXT
  125.  
  126.  OutBuffer$ = LEFT$(OutBuffer$, OAddress - OStartAddress)
  127.  PUT #2, , OutBuffer$
  128.  CLOSE #1, #2
  129.  LOCATE , 1
  130.  PRINT "Done.       "
  131.  END
  132.  
  133. UpdatePercent:
  134.     LOCATE , 1
  135.     PRINT 100 - (CodesLeft& * 100&) \ Codes&; "% done";
  136. RETURN
  137.  
  138. SUB FillInputBuf
  139.  
  140.     GET #1, , InBuffer$
  141.     A& = SADD(InBuffer$): A& = A& - 65536 * (A& < 0)
  142.     ISeg = SSEG(InBuffer$) + (A& \ 16)
  143.     IAddress = A& AND 15
  144.     IEndAddress = IAddress + 4096
  145.     DEF SEG = ISeg
  146.  
  147. END SUB
  148.  
  149. FUNCTION GetDat (C) STATIC
  150.     IF BitsLeft = 0 THEN
  151.          IAddress = IAddress + 1
  152.          IF IAddress = IEndAddress THEN FillInputBuf
  153.  
  154.         TempChar = PEEK(IAddress)
  155.         BitsLeft = 8
  156.     END IF
  157.     WorkCode& = TempChar \ Powers(8 - BitsLeft)
  158.     DO WHILE C > BitsLeft
  159.          IAddress = IAddress + 1
  160.          IF IAddress = IEndAddress THEN FillInputBuf
  161.  
  162.         TempChar = PEEK(IAddress)
  163.         WorkCode& = WorkCode& OR TempChar * LongPowers(BitsLeft)
  164.         BitsLeft = BitsLeft + 8
  165.     LOOP
  166.     BitsLeft = BitsLeft - C
  167.     GetDat = WorkCode& AND Masks(C)
  168. END FUNCTION
  169.  
  170.