'
' This is an implementation of the Lempel Ziv Data Compression (LZ77).
'
' http://en.wikipedia.org/wiki/LZ77_and_LZ78
'
' This type of encoding works good with reucrring patterns, for example with TXT files.
' It does not work good with files containing random binary data.
'
' (c) PvE - Oct 2012. Needs BaCon build 28 or higher.
'--------------------------------------------------------------------------------------------

' Get the separate arguments
OPTION COLLAPSE TRUE
SPLIT ARGUMENT$ BY " " TO arg$ SIZE amount

' Show usage
IF amount < 2 THEN
    PRINT "Usage: ", arg$[0], " <file>"
    END
ENDIF

' Check if the file exists
IF NOT(FILEEXISTS(arg$[1])) THEN
    PRINT "File ", arg$[1], " not found!"
    END 1
END IF

' Get filesize
FileSize = FILELEN(arg$[1])

' Reserve some memory to start with
FileData = MEMORY(FileSize+1)

' Get the file into memory
OPEN arg$[1] FOR READING AS myfile
    GETBYTE FileData FROM myfile SIZE FileSize
CLOSE FILE myfile

DECLARE newtable[255]

' Get the index table
FOR x = 0 TO 254
    newtable[x] = (int)PEEK(FileData+x*2)<<8 | (int)PEEK(FileData+x*2+1)&255
NEXT

' Create memory for the decompressed file
FileDest = MEMORY(FileSize*2)

' Keeps track of position where to write data
pos = 0

' Loop through memory
FOR x = 508+2 TO FileSize-1
    current = PEEK(FileData+x)

    ' We have an index number in the table
    IF current < 255 THEN
        POKE FileDest+pos, newtable[current]>>8
        POKE FileDest+pos+1, newtable[current]&255
        INCR pos, 2

    ' Just a sequence of RAW bytes
    ELSE
        FOR y = x + 2 TO x + 2 + PEEK(FileData+x+1)-1
            POKE FileDest+pos, PEEK(FileData+y)
            INCR pos
        NEXT
        INCR x, 2 + PEEK(FileData+x+1)
    ENDIF
NEXT

' Show some statistics
PRINT "Resulting filesize: ", pos, " bytes. ";

' Determine new name
newname$ = LEFT$(arg$[1], INSTRREV(arg$[1], ".")-1)

' Save compressed data from memory to file
OPEN newname$ FOR WRITING AS myfile
    PUTBYTE FileDest TO myfile SIZE pos
CLOSE FILE myfile

PRINT "File '", arg$[1], "' decompressed from LZ77 and saved as '", newname$, "'."

' Free claimed memory
FREE FileData
FREE FileDest

END