#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA008_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E_G14ED_G20E_G21E
BOOLEAN G0663_B_LZW_RepetitionEnabled;
int16_t G0664_i_LZW_CodeBitCount;
int16_t G0665_i_LZW_CurrentMaximumCode;
int16_t G0666_i_LZW_AbsoluteMaximumCode = 4096;
char G0667_ac_LZW_InputBuffer[12];
int16_t G0668_i_LZW_DictionaryNextAvailableCode;
BOOLEAN G0669_B_LZW_DictionaryFlushed;


#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
overlay "memory"
#endif
#ifdef MEDIA351_G14ED_G20E_G21E
segment "memory"
#endif

int16_t F0495_LZW_GetNextInputCode(P0908_i_InputFileHandle, P0909_pl_InputByteCount)
int16_t P0908_i_InputFileHandle;
long* P0909_pl_InputByteCount;
{
        REGISTER int16_t L1554_i_NextInputCode;
        REGISTER int16_t L1555_i_BitIndex;
        REGISTER int16_t L1556_i_RequiredInputBitCount;
        REGISTER unsigned char* L1557_puc_InputBuffer;
        static unsigned char G0670_auc_LZW_Unreferenced[9] = { 0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00 }; /* BUG0_00 Useless code */
        static unsigned char G0671_auc_LZW_LeastSignificantBitMasks[9] = { 0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF };
        static int16_t G0672_i_LZW_InputBufferBitIndex = 0;
        static int16_t G0673_i_LZW_InputBufferBitCount = 0;


        L1557_puc_InputBuffer = (unsigned char*)G0667_ac_LZW_InputBuffer;
        if ((G0669_B_LZW_DictionaryFlushed > 0) || (G0672_i_LZW_InputBufferBitIndex >= G0673_i_LZW_InputBufferBitCount) || (G0668_i_LZW_DictionaryNextAvailableCode > G0665_i_LZW_CurrentMaximumCode)) {
                if (G0668_i_LZW_DictionaryNextAvailableCode > G0665_i_LZW_CurrentMaximumCode) {
                        G0664_i_LZW_CodeBitCount++;
                        if (G0664_i_LZW_CodeBitCount == 12) {
                                G0665_i_LZW_CurrentMaximumCode = G0666_i_LZW_AbsoluteMaximumCode;
                        } else {
                                G0665_i_LZW_CurrentMaximumCode = (1 << G0664_i_LZW_CodeBitCount) - 1;
                        }
                }
                if (G0669_B_LZW_DictionaryFlushed > 0) {
                        G0665_i_LZW_CurrentMaximumCode = (1 << (G0664_i_LZW_CodeBitCount = 9)) - 1;
                        G0669_B_LZW_DictionaryFlushed = C0_FALSE;
                }
                if (*P0909_pl_InputByteCount > G0664_i_LZW_CodeBitCount) {
                        G0673_i_LZW_InputBufferBitCount = G0664_i_LZW_CodeBitCount;
                } else {
                        G0673_i_LZW_InputBufferBitCount = *P0909_pl_InputByteCount;
                }
                if (G0673_i_LZW_InputBufferBitCount > 0) {
#ifdef MEDIA007_S10EA_S10EB_S11E_S12E_S12G_S13FA_S13FB_S20E_S21E
                        Fread(P0908_i_InputFileHandle, (long)G0673_i_LZW_InputBufferBitCount, G0667_ac_LZW_InputBuffer) == (long)G0673_i_LZW_InputBufferBitCount; /* Result of fread is ignored */
#endif
#ifdef MEDIA351_G14ED_G20E_G21E
                        F0772_FILE_Read(P0908_i_InputFileHandle, (long)G0673_i_LZW_InputBufferBitCount, G0667_ac_LZW_InputBuffer);
#endif
                        *P0909_pl_InputByteCount -= (long)G0673_i_LZW_InputBufferBitCount;
                } else {
                        return -1;
                }
                G0672_i_LZW_InputBufferBitIndex = 0;
                G0673_i_LZW_InputBufferBitCount = (G0673_i_LZW_InputBufferBitCount << 3) - (G0664_i_LZW_CodeBitCount - 1);
        }
        L1555_i_BitIndex = G0672_i_LZW_InputBufferBitIndex;
        L1556_i_RequiredInputBitCount = G0664_i_LZW_CodeBitCount;
        L1557_puc_InputBuffer += L1555_i_BitIndex >> 3; /* Address of byte in input buffer containing current bit */
        L1555_i_BitIndex &= 0x0007; /* Bit index of the current bit in the byte */
        L1554_i_NextInputCode = *L1557_puc_InputBuffer++ >> L1555_i_BitIndex; /* Get the first bits of the next input code from the input buffer byte */
        L1556_i_RequiredInputBitCount -= 8 - L1555_i_BitIndex; /* Remaining number of bits to get for a complete input code */
        L1555_i_BitIndex = 8 - L1555_i_BitIndex;
        if (L1556_i_RequiredInputBitCount >= 8) {
                L1554_i_NextInputCode |= *L1557_puc_InputBuffer++ << L1555_i_BitIndex;
                L1555_i_BitIndex += 8;
                L1556_i_RequiredInputBitCount -= 8;
        }
        L1554_i_NextInputCode |= (*L1557_puc_InputBuffer & G0671_auc_LZW_LeastSignificantBitMasks[L1556_i_RequiredInputBitCount]) << L1555_i_BitIndex;
        G0672_i_LZW_InputBufferBitIndex += G0664_i_LZW_CodeBitCount;
        return L1554_i_NextInputCode;
}

void F0496_LZW_OutputCharacter(P0910_uc_Character, P0911_ppc_Output)
REGISTER unsigned char P0910_uc_Character;
char** P0911_ppc_Output;
{
        REGISTER char* L1558_pc_Output;
        static int16_t G0674_i_LZW_CharacterToRepeat;


        L1558_pc_Output = *P0911_ppc_Output;
        switch (G0663_B_LZW_RepetitionEnabled) {
                case C0_FALSE:
                        if (P0910_uc_Character == 0x90) {
                                G0663_B_LZW_RepetitionEnabled = C1_TRUE;
                        } else {
                                *L1558_pc_Output++ = G0674_i_LZW_CharacterToRepeat = P0910_uc_Character;
                        }
                        *P0911_ppc_Output = L1558_pc_Output;
                        return;
                case C1_TRUE:
                        if (P0910_uc_Character) { /* If character following 0x90 is not 0x00 then it is the repeat count */
                                while (--P0910_uc_Character) {
                                        *L1558_pc_Output++ = G0674_i_LZW_CharacterToRepeat;
                                }
                        } else { /* else output a 0x90 character */
                                *L1558_pc_Output++ = 0x90;
                        }
                        G0663_B_LZW_RepetitionEnabled = C0_FALSE;
                        *P0911_ppc_Output = L1558_pc_Output;
                        return;
                default:
                        for (;;); /*_Infinite loop_*/
        }
}

long F0497_LZW_Decompress(P0912_i_InputFileHandle, P0913_l_InputByteCount, P0914_l_OutputAddress, P0915_puc_Dictionary, P0916_puc_TemporaryBuffer)
int16_t P0912_i_InputFileHandle;
long P0913_l_InputByteCount;
long P0914_l_OutputAddress;
unsigned char* P0915_puc_Dictionary;
unsigned char* P0916_puc_TemporaryBuffer; /* 5004 bytes buffer max decoded string size */
{
        unsigned char* L1565_puc_ReversedDecodedStringEnd;
        unsigned char* L1566_puc_ReversedDecodedStringStart;
        REGISTER int16_t* L1563_pi_PrefixCode;
        REGISTER unsigned char* L1564_puc_AppendCharacter;
        REGISTER int16_t L1559_i_Character;
        REGISTER int16_t L1560_i_Code;
        REGISTER int16_t L1561_i_OldCode;
        REGISTER int16_t L1562_i_NewCode;
        long L1567_l_OutputAddress;


        L1563_pi_PrefixCode = (int16_t*)P0915_puc_Dictionary;
        L1564_puc_AppendCharacter = P0915_puc_Dictionary + (5003 * sizeof(int16_t)); /* Splits the 15232 bytes buffer in two parts 10006 + 5226 (= enough for 5003 bytes)
                10006 = space necessary to store 5003 codes (integers). 5004 is the space to store 5003 characters + 1 padding byte so the size if even.
                5003 is a prime number, around 22% larger than 4096 which is the maximum code value when codes are 12 bits large.
                This particular size is useful when compressing data (in order to use a hash algorithm to search for strings in the dictionary) */
        L1565_puc_ReversedDecodedStringEnd = L1566_puc_ReversedDecodedStringStart = P0916_puc_TemporaryBuffer;
        L1567_l_OutputAddress = (long)P0914_l_OutputAddress;
        G0663_B_LZW_RepetitionEnabled = C0_FALSE;
        L1560_i_Code = 12; /* BUG0_00 Useless code */
        G0664_i_LZW_CodeBitCount = 9;
        G0669_B_LZW_DictionaryFlushed = C0_FALSE;
        G0665_i_LZW_CurrentMaximumCode = (1 << (G0664_i_LZW_CodeBitCount = 9)) - 1;
        for (L1560_i_Code = 255; L1560_i_Code >= 0; L1560_i_Code--) {
                L1563_pi_PrefixCode[L1560_i_Code] = 0;
                L1564_puc_AppendCharacter[L1560_i_Code] = (unsigned char)L1560_i_Code;
        }
        G0668_i_LZW_DictionaryNextAvailableCode = 257;
        L1559_i_Character = L1561_i_OldCode = F0495_LZW_GetNextInputCode(P0912_i_InputFileHandle, &P0913_l_InputByteCount);
        if (L1561_i_OldCode == -1) {
                return -1L;
        }
        F0496_LZW_OutputCharacter((int16_t)((char)L1559_i_Character), &P0914_l_OutputAddress);
        while ((L1560_i_Code = F0495_LZW_GetNextInputCode(P0912_i_InputFileHandle, &P0913_l_InputByteCount)) > -1) {
                if (L1560_i_Code == 256) { /* This code is used to flush the dictionary */
                        F0008_MAIN_ClearBytes(L1563_pi_PrefixCode, 256 * sizeof(int16_t));
                        G0669_B_LZW_DictionaryFlushed = C1_TRUE;
                        G0668_i_LZW_DictionaryNextAvailableCode = 256; /* BUG0_82 LZW compressed data fails to decompress. If code 256 to flush the LZW dictionary is encountered in the compressed data then the remaining data fails to uncompress correctly because the next available code is reset to 256 instead of 257. This never happens in the original games because the dictionary flush code is not used in the graphics or hint oracle compressed data */
                        if ((L1560_i_Code = F0495_LZW_GetNextInputCode(P0912_i_InputFileHandle, &P0913_l_InputByteCount)) == -1) {
                                break;
                        }
                }
                /* This code checks for the special STRING+CHARACTER+STRING+CHARACTER+STRING case which generates an undefined code. It handles it by decoding the last code, adding a single character to the end of the decoded string */
                L1562_i_NewCode = L1560_i_Code;
                if (L1560_i_Code >= G0668_i_LZW_DictionaryNextAvailableCode) { /* If code is not defined yet */
                        *L1565_puc_ReversedDecodedStringEnd++ = L1559_i_Character;
                        L1560_i_Code = L1561_i_OldCode;
                }
                /* Use the string table to decode the string corresponding to the code and store the string in the temporary buffer */
                while (L1560_i_Code >= 256) {
                        *L1565_puc_ReversedDecodedStringEnd++ = L1564_puc_AppendCharacter[L1560_i_Code];
                        L1560_i_Code = L1563_pi_PrefixCode[L1560_i_Code];
                }
                *L1565_puc_ReversedDecodedStringEnd++ = (L1559_i_Character = L1564_puc_AppendCharacter[L1560_i_Code]);
                /* Output the decoded string in reverse order */
                do {
                        F0496_LZW_OutputCharacter(*(--L1565_puc_ReversedDecodedStringEnd), &P0914_l_OutputAddress);
                } while (L1565_puc_ReversedDecodedStringEnd > L1566_puc_ReversedDecodedStringStart);
                /* If possible, add a new code to the string table */
                if ((L1560_i_Code = G0668_i_LZW_DictionaryNextAvailableCode) < G0666_i_LZW_AbsoluteMaximumCode) {
                        L1563_pi_PrefixCode[L1560_i_Code] = (int16_t)L1561_i_OldCode;
                        L1564_puc_AppendCharacter[L1560_i_Code] = L1559_i_Character;
                        G0668_i_LZW_DictionaryNextAvailableCode = L1560_i_Code + 1;
                }
                L1561_i_OldCode = L1562_i_NewCode;
        }
        return P0914_l_OutputAddress - L1567_l_OutputAddress; /* Byte count of decompressed data */
}
#endif
