#ifndef COMPILE_H
#include "COMPILE.H"
#endif
#ifdef MEDIA774_SU1E_AU1E_AU2E
extern long F1857_PerformIORequestOperation();
extern void F1956_EndProgram();

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;
/* statics from LZW */


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 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;
        long L5740_;


        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 ((long)G0664_i_LZW_CodeBitCount < *P0909_pl_InputByteCount) {
                        G0673_i_LZW_InputBufferBitCount = G0664_i_LZW_CodeBitCount;
                } else {
                        G0673_i_LZW_InputBufferBitCount = *P0909_pl_InputByteCount;
                }
                if (G0673_i_LZW_InputBufferBitCount > 0) {
                        F1859_SetIORequestValue(P0908_i_InputFileHandle, 16, (long)G0673_i_LZW_InputBufferBitCount);
                        F1859_SetIORequestValue(P0908_i_InputFileHandle, 8, (long)&G0667_ac_LZW_InputBuffer);
                        L5740_ = F1857_PerformIORequestOperation(P0908_i_InputFileHandle, C07_READ_FILE);
                        if (L5740_) {
#ifdef MEDIA772_SU1E
                                F1956_EndProgram(3, 18, 93L);
#endif
#ifdef MEDIA763_AU1E_AU2E
                                F1956_EndProgram(3, 18, 94L);
#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 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 */
{
        REGISTER int16_t L1559_i_Character;
        REGISTER int16_t L1560_i_Code;
        REGISTER int16_t L1561_i_OldCode;
        REGISTER int16_t L1562_i_NewCode;
        REGISTER int16_t* L1563_pi_PrefixCode;
        REGISTER unsigned char* L1564_puc_AppendCharacter;
        unsigned char* L1565_puc_ReversedDecodedStringEnd;
        unsigned char* L1566_puc_ReversedDecodedStringStart;
        long L1567_l_OutputAddress;


#ifdef MEDIA763_AU1E_AU2E
        if (F1857_PerformIORequestOperation(P0912_i_InputFileHandle, 11));
#endif
        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;
        }
#ifdef MEDIA772_SU1E
        F0496_LZW_OutputCharacter((unsigned char)L1559_i_Character, &P0914_l_OutputAddress);
#endif
#ifdef MEDIA763_AU1E_AU2E
        F0496_LZW_OutputCharacter((unsigned char)L1559_i_Character, (char**)&P0914_l_OutputAddress);
#endif
        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 * (long)sizeof(int16_t));
                        G0669_B_LZW_DictionaryFlushed = C1_TRUE;
                        G0668_i_LZW_DictionaryNextAvailableCode = 256;
                        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;
        }
#ifdef MEDIA763_AU1E_AU2E
        if (F1857_PerformIORequestOperation(P0912_i_InputFileHandle, 11));
        L1560_i_Code = 0;
        L1566_puc_ReversedDecodedStringStart = (unsigned char*)L1567_l_OutputAddress;
        while ((unsigned long)L1566_puc_ReversedDecodedStringStart < P0914_l_OutputAddress) {
                L1560_i_Code += *L1566_puc_ReversedDecodedStringStart;
                L1566_puc_ReversedDecodedStringStart++;
        }
#endif
        return P0914_l_OutputAddress - L1567_l_OutputAddress; /* Byte count of decompressed data */
}
#endif
