home *** CD-ROM | disk | FTP | other *** search
- 'SLDECODE.BAS - Sample decompression program for SLENCODE.BAS
- 'By Rich Geldreich 1992
- 'Note: SLDECODE.ASM is a _much_ faster version of this program. I have mainly
- 'included this program for reference purposes only. Ooops! Last minute
- 'warning: don't compile this program without first renaming the SLDECODE.OBJ
- 'file to something else! Especially if you don't have Turbo Assembler.
-
- 'ToDo list: Add more terse error checking, make into callable subroutine,
- 'add CRC-32 routine, etc.
-
- 'Warning: Do NOT press CTRL+Break and then continue this program while
- 'you are running it in the environment! At best, the resulting decompressed
- 'file will be invalid. At worst, your machine will lock up.
-
- 'QuickBASIC 4.5 users: As this program is, it will not work correctly with
- 'QB 4.5. To make it QB 4.5 compatible, simply change all of the "SSEG" strings
- 'in this program to "VARSEG" strings with the search and replace function.
- 'Note that the SLDECODE.ASM routine should not require any changes for it to
- 'work properly.
-
- DEFINT A-Z
-
- DECLARE FUNCTION GetDat (C)
- DECLARE SUB FillInputBuf ()
-
- CONST BufferSize = 4096
- CONST MaxMatch = 74
- CONST Threshold = 2
- CONST Null = BufferSize
-
- CONST True = -1, False = 0
-
- DIM Ring.Buffer(BufferSize - 1)
-
- DIM SHARED InBuffer$, ISeg, IAddress, IEndAddress
- DIM SHARED OutBuffer$, OSeg, OAddress, OStartAddress, OEndAddress
- DIM SHARED Powers(7), LongPowers(11) AS LONG, Masks(12), BitsLeft, TempChar
-
- PRINT "SLDECODE.BAS v1.0 - LZSS Decoder in QuickBASIC 4.5"
- PRINT "By Rich Geldreich 1992"
- A$ = COMMAND$
- IF A$ = "" THEN INPUT "File to decompress"; A$: A$ = UCASE$(A$)
- IF A$ = "" THEN END
-
- Powers(0) = 1: Powers(1) = 2: Powers(2) = 4: Powers(3) = 8: Powers(4) = 16
- Powers(5) = 32: Powers(6) = 64: Powers(7) = 128
-
- LongPowers(1) = 2: LongPowers(2) = 4: LongPowers(3) = 8: LongPowers(4) = 16
- LongPowers(5) = 32: LongPowers(6) = 64: LongPowers(7) = 128: LongPowers(8) = 256
- LongPowers(9) = 512: LongPowers(10) = 1024: LongPowers(11) = 2048
-
- Masks(1) = 1: Masks(8) = 255: Masks(12) = 4095: Masks(3) = 7: Masks(6) = 63
-
- InBuffer$ = SPACE$(4096)
- IAddress = 0: IEndAddress = 1
-
- OutBuffer$ = SPACE$(4096)
- A& = SADD(OutBuffer$)
- IF A& < 0 THEN A& = A& + 65536
- OSeg = SSEG(OutBuffer$) + (A& \ 16)
- OAddress = A& AND 15
- OStartAddress = OAddress
- OEndAddress = OAddress + 4096
- DEF SEG = OSeg
-
- R = BufferSize - MaxMatch
- FOR A = 0 TO R - 1
- Ring.Buffer(A) = 32
- NEXT
-
- OPEN A$ FOR BINARY AS #2
-
- OPEN "OUTPUT.SL1" FOR BINARY AS #1
- GET #1, 3, CodesLeft&
- Codes& = CodesLeft&
-
- FOR CodesLeft& = CodesLeft& TO 1 STEP -1
-
- IF G = 0 THEN GOSUB UpdatePercent
- G = (G + 1) AND 255
-
- DEF SEG = ISeg
- IF GetDat(1) = 0 THEN
- Char = GetDat(8)
-
- DEF SEG = OSeg
-
- IF OAddress = OEndAddress THEN
- PUT #2, , OutBuffer$
- OAddress = OStartAddress
- END IF
- POKE OAddress, Char
- OAddress = OAddress + 1
-
- Ring.Buffer(R) = Char
- R = (R + 1) AND (BufferSize - 1)
- ELSE
- IF GetDat(1) THEN
- Match.Length = GetDat(6) + 11
- ELSE
- Match.Length = GetDat(3) + (Threshold + 1)
- END IF
-
- Match.Position = GetDat(12)
-
- DEF SEG = OSeg
-
- FOR A = 1 TO Match.Length
- Char = Ring.Buffer(Match.Position)
-
- IF OAddress = OEndAddress THEN
- PUT #2, , OutBuffer$
- OAddress = OStartAddress
- END IF
- POKE OAddress, Char
- OAddress = OAddress + 1
-
- Ring.Buffer(R) = Char
- R = (R + 1) AND (BufferSize - 1)
- Match.Position = (Match.Position + 1) AND (BufferSize - 1)
- NEXT
- END IF
-
- NEXT
-
- OutBuffer$ = LEFT$(OutBuffer$, OAddress - OStartAddress)
- PUT #2, , OutBuffer$
- CLOSE #1, #2
- LOCATE , 1
- PRINT "Done. "
- END
-
- UpdatePercent:
- LOCATE , 1
- PRINT 100 - (CodesLeft& * 100&) \ Codes&; "% done";
- RETURN
-
- SUB FillInputBuf
-
- GET #1, , InBuffer$
- A& = SADD(InBuffer$): A& = A& - 65536 * (A& < 0)
- ISeg = SSEG(InBuffer$) + (A& \ 16)
- IAddress = A& AND 15
- IEndAddress = IAddress + 4096
- DEF SEG = ISeg
-
- END SUB
-
- FUNCTION GetDat (C) STATIC
- IF BitsLeft = 0 THEN
- IAddress = IAddress + 1
- IF IAddress = IEndAddress THEN FillInputBuf
-
- TempChar = PEEK(IAddress)
- BitsLeft = 8
- END IF
- WorkCode& = TempChar \ Powers(8 - BitsLeft)
- DO WHILE C > BitsLeft
- IAddress = IAddress + 1
- IF IAddress = IEndAddress THEN FillInputBuf
-
- TempChar = PEEK(IAddress)
- WorkCode& = WorkCode& OR TempChar * LongPowers(BitsLeft)
- BitsLeft = BitsLeft + 8
- LOOP
- BitsLeft = BitsLeft - C
- GetDat = WorkCode& AND Masks(C)
- END FUNCTION
-
-