DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

decodes.c (25960B)


      1 /* decodes.c */
      2 
      3 #include "doomdef.h"
      4 
      5 #include "graph.h"
      6 
      7 /*=======*/
      8 /* TYPES */
      9 /*=======*/
     10 
     11 typedef struct {
     12     int dec_bit_count;
     13     int dec_bit_buffer;
     14     int enc_bit_count;
     15     int enc_bit_buffer;
     16     byte* ostart;
     17     byte* output;
     18     byte* istart;
     19     byte* input;
     20 } buffers_t;
     21 
     22 typedef struct {
     23     int offset;
     24     int incrBit;
     25     int unk1;
     26     int type;
     27 } encodeArgs_t;
     28 
     29 /*=========*/
     30 /* GLOBALS */
     31 /*=========*/
     32 
     33 static short ShiftTable[6] = { 4, 6, 8, 10, 12, 14 }; // 8005D8A0
     34 
     35 static int offsetTable[12];      // 800B2250
     36 static int offsetMaxSize, windowSize; // 800b2280 , 800b2284
     37 static encodeArgs_t encArgs;    // 800b2288
     38 
     39 #define HASH_SIZE (1 << 14)
     40 static short* hashtable;    // 800B2298
     41 static short* hashtarget;   // 800B229C
     42 static short* hashNext;     // 800B22A0
     43 static short* hashPrev;     // 800B22A4
     44 
     45 static short DecodeTable[2516]; // 800B22A8
     46 static short array01[1258];     // 800B3660
     47 
     48 static buffers_t buffers;       // 800B4034
     49 static byte* window;            // 800B4054
     50 
     51 static int OVERFLOW_READ;       // 800B4058
     52 static int OVERFLOW_WRITE;      // 800B405C
     53 
     54 /*
     55 ============================================================================
     56 
     57 DECODE BASED ROUTINES
     58 
     59 ============================================================================
     60 */
     61 
     62 /*
     63 ========================
     64 =
     65 = GetOutputSize
     66 =
     67 ========================
     68 */
     69 int GetOutputSize(void) // [GEC] New
     70 {
     71     return (int)((int)buffers.output - (int)buffers.ostart);
     72 }
     73 
     74 /*
     75 ========================
     76 =
     77 = GetReadSize
     78 =
     79 ========================
     80 */
     81 
     82 int GetReadSize(void) // [GEC] New
     83 {
     84     return (int)((int)buffers.input - (int)buffers.istart);
     85 }
     86 
     87 /*
     88 ========================
     89 =
     90 = ReadByte -> Old GetDecodeByte
     91 =
     92 ========================
     93 */
     94 
     95 static int ReadByte(void) // 8002D1D0
     96 {
     97     if ((int)(buffers.input - buffers.istart) >= OVERFLOW_READ)
     98         return -1;
     99 
    100     return *buffers.input++;
    101 }
    102 
    103 /*
    104 ========================
    105 =
    106 = WriteByte -> Old WriteOutput
    107 =
    108 ========================
    109 */
    110 
    111 static void WriteByte(byte outByte) // 8002D214
    112 {
    113     if ((int)(buffers.output - buffers.ostart) >= OVERFLOW_WRITE) {
    114         I_Error("Overflowed output buffer");
    115     }
    116 
    117     *buffers.output++ = outByte;
    118 }
    119 
    120 /*
    121 ========================
    122 =
    123 = WriteBinary
    124 = routine required for encoding
    125 =
    126 ========================
    127 */
    128 
    129 static void WriteBinary(int binary) // 8002D288
    130 {
    131     buffers.enc_bit_buffer = (buffers.enc_bit_buffer << 1);
    132 
    133     if (binary != 0)
    134         buffers.enc_bit_buffer = (buffers.enc_bit_buffer | 1);
    135 
    136     buffers.enc_bit_count = (buffers.enc_bit_count + 1);
    137     if (buffers.enc_bit_count == 8)
    138     {
    139         WriteByte((byte)buffers.enc_bit_buffer);
    140         buffers.enc_bit_count = 0;
    141     }
    142 }
    143 
    144 /*
    145 ========================
    146 =
    147 = ReadBinary -> old DecodeScan
    148 =
    149 ========================
    150 */
    151 
    152 static int ReadBinary(void) // 8002D2F4
    153 {
    154     int resultbyte;
    155 
    156     resultbyte = buffers.dec_bit_count;
    157 
    158     buffers.dec_bit_count = (resultbyte - 1);
    159     if ((resultbyte < 1))
    160     {
    161         resultbyte = ReadByte();
    162 
    163         buffers.dec_bit_buffer = resultbyte;
    164         buffers.dec_bit_count = 7;
    165     }
    166 
    167     resultbyte = (0 < (buffers.dec_bit_buffer & 0x80));
    168     buffers.dec_bit_buffer = (buffers.dec_bit_buffer << 1);
    169 
    170     return resultbyte;
    171 }
    172 
    173 /*
    174 ========================
    175 =
    176 = WriteCodeBinary
    177 = routine required for encoding
    178 =
    179 ========================
    180 */
    181 
    182 static void WriteCodeBinary(int binary, int shift) // 8002D364
    183 {
    184     int i;
    185 
    186     i = 0;
    187     if (shift > 0)
    188     {
    189         do
    190         {
    191             WriteBinary(binary & 1);
    192             binary = (binary >> 1);
    193         } while (++i != shift);
    194     }
    195 }
    196 
    197 /*
    198 ========================
    199 =
    200 = ReadCodeBinary -> old RescanByte
    201 =
    202 ========================
    203 */
    204 
    205 static int ReadCodeBinary(int byte) // 8002D3B8
    206 {
    207     int shift;
    208     int i;
    209     int resultbyte;
    210 
    211     resultbyte = 0;
    212     i = 0;
    213     shift = 1;
    214 
    215     if (byte <= 0)
    216         return resultbyte;
    217 
    218     do
    219     {
    220         if (ReadBinary() != 0)
    221             resultbyte |= shift;
    222 
    223         i++;
    224         shift = (shift << 1);
    225     } while (i != byte);
    226 
    227     return resultbyte;
    228 }
    229 
    230 /*
    231 ========================
    232 =
    233 = FlushBitBuffer
    234 = routine required for encoding
    235 =
    236 ========================
    237 */
    238 
    239 static void FlushBitBuffer(void) // 8002D424
    240 {
    241     if (buffers.enc_bit_count > 0) {
    242         WriteByte((byte)(buffers.enc_bit_buffer << (8 - buffers.enc_bit_count)) & 0xff);
    243     }
    244 }
    245 
    246 /*
    247 ========================
    248 =
    249 = InitTables -> old InitDecodeTable
    250 =
    251 ========================
    252 */
    253 
    254 static void InitTables(void) // 8002D468
    255 {
    256     int evenVal, oddVal, incrVal, i;
    257 
    258     short* curArray;
    259     short* incrTbl;
    260     short* evenTbl;
    261     short* oddTbl;
    262 
    263     int* Tbl1, * Tbl2;
    264 
    265     encArgs.incrBit = 3;
    266     encArgs.unk1 = 0;
    267     encArgs.type = 0;
    268 
    269     buffers.dec_bit_count = 0;
    270     buffers.dec_bit_buffer = 0;
    271     buffers.enc_bit_count = 0;
    272     buffers.enc_bit_buffer = 0;
    273 
    274     curArray = &array01[(0 + 2)];
    275     incrTbl = &DecodeTable[(1258 + 2)];
    276 
    277     incrVal = 2;
    278 
    279     do {
    280         *incrTbl++ = (short)(incrVal / 2);
    281         *curArray++ = 1;
    282     } while (++incrVal < 1258);
    283 
    284     oddTbl = &DecodeTable[(629 + 1)];
    285     evenTbl = &DecodeTable[(0 + 1)];
    286 
    287     evenVal = 1;
    288     oddVal = 3;
    289 
    290     do
    291     {
    292         *oddTbl++ = (short)oddVal;
    293         oddVal += 2;
    294 
    295         *evenTbl++ = (short)(evenVal * 2);
    296         evenVal++;
    297     } while (evenVal < 629);
    298 
    299     incrVal = 0;
    300     i = 0;
    301     Tbl2 = &offsetTable[6];
    302     Tbl1 = &offsetTable[0];
    303     do {
    304         *Tbl1++ = incrVal;
    305         incrVal += (1 << (ShiftTable[i] & 0x1f));
    306         *Tbl2++ = incrVal - 1;
    307     } while (++i <= 5);
    308 
    309     offsetMaxSize = incrVal - 1;
    310     windowSize = offsetMaxSize + (64 - 1);
    311 }
    312 
    313 /*
    314 ========================
    315 =
    316 = CheckTable
    317 =
    318 ========================
    319 */
    320 
    321 static void CheckTable(int a0, int a1, int a2) // 8002D624
    322 {
    323     int i;
    324     int idByte1;
    325     int idByte2;
    326     short* curArray;
    327     short* evenTbl;
    328     short* oddTbl;
    329     short* incrTbl;
    330 
    331     i = 0;
    332     evenTbl = &DecodeTable[0];
    333     oddTbl  = &DecodeTable[629];
    334     incrTbl = &DecodeTable[1258];
    335 
    336     idByte1 = a0;
    337 
    338     do {
    339         idByte2 = incrTbl[idByte1];
    340 
    341         array01[idByte2] = (array01[a1] + array01[a0]);
    342 
    343         a0 = idByte2;
    344 
    345         if (idByte2 != 1) {
    346             idByte1 = incrTbl[idByte2];
    347             idByte2 = evenTbl[idByte1];
    348 
    349             a1 = idByte2;
    350 
    351             if (a0 == idByte2) {
    352                 a1 = oddTbl[idByte1];
    353             }
    354         }
    355 
    356         idByte1 = a0;
    357     } while (a0 != 1);
    358 
    359     if (array01[1] != 0x7D0) {
    360         return;
    361     }
    362 
    363     array01[1] >>= 1;
    364 
    365     curArray = &array01[2];
    366     do
    367     {
    368         curArray[3] >>= 1;
    369         curArray[2] >>= 1;
    370         curArray[1] >>= 1;
    371         curArray[0] >>= 1;
    372         curArray += 4;
    373         i += 4;
    374     } while (i != 1256);
    375 }
    376 
    377 /*
    378 ========================
    379 =
    380 = UpdateTables -> old DecodeByte
    381 =
    382 ========================
    383 */
    384 
    385 static void UpdateTables(int tblpos) // 8002D72C
    386 {
    387     int incrIdx;
    388     int evenVal;
    389     int idByte1;
    390     int idByte2;
    391     int idByte3;
    392     int idByte4;
    393 
    394     short* evenTbl;
    395     short* oddTbl;
    396     short* incrTbl;
    397     short* tmpIncrTbl;
    398 
    399     evenTbl = &DecodeTable[0];
    400     oddTbl  = &DecodeTable[629];
    401     incrTbl = &DecodeTable[1258];
    402 
    403     idByte1 = (tblpos + 0x275);
    404     array01[idByte1] += 1;
    405 
    406     if (incrTbl[idByte1] != 1)
    407     {
    408         tmpIncrTbl = &incrTbl[idByte1];
    409         idByte2 = *tmpIncrTbl;
    410 
    411         if (idByte1 == evenTbl[idByte2]) {
    412             CheckTable(idByte1, oddTbl[idByte2], idByte1);
    413         }
    414         else {
    415             CheckTable(idByte1, evenTbl[idByte2], idByte1);
    416         }
    417 
    418         do
    419         {
    420             incrIdx = incrTbl[idByte2];
    421             evenVal = evenTbl[incrIdx];
    422 
    423             if (idByte2 == evenVal) {
    424                 idByte3 = oddTbl[incrIdx];
    425             }
    426             else {
    427                 idByte3 = evenVal;
    428             }
    429 
    430             if (array01[idByte3] < array01[idByte1])
    431             {
    432                 if (idByte2 == evenVal) {
    433                     oddTbl[incrIdx] = (short)idByte1;
    434                 }
    435                 else {
    436                     evenTbl[incrIdx] = (short)idByte1;
    437                 }
    438 
    439                 evenVal = evenTbl[idByte2];
    440 
    441                 if (idByte1 == evenVal) {
    442                     idByte4 = oddTbl[idByte2];
    443                     evenTbl[idByte2] = (short)idByte3;
    444                 }
    445                 else {
    446                     idByte4 = evenVal;
    447                     oddTbl[idByte2] = (short)idByte3;
    448                 }
    449 
    450                 incrTbl[idByte3] = (short)idByte2;
    451 
    452                 *tmpIncrTbl = (short)incrIdx;
    453                 CheckTable(idByte3, idByte4, idByte4);
    454 
    455                 tmpIncrTbl = &incrTbl[idByte3];
    456             }
    457 
    458             idByte1 = *tmpIncrTbl;
    459             tmpIncrTbl = &incrTbl[idByte1];
    460 
    461             idByte2 = *tmpIncrTbl;
    462         } while (idByte2 != 1);
    463     }
    464 }
    465 
    466 /*
    467 ========================
    468 =
    469 = StartDecodeByte
    470 =
    471 ========================
    472 */
    473 
    474 static int StartDecodeByte(void) // 8002D904
    475 {
    476     int lookup;
    477     short* evenTbl;
    478     short* oddTbl;
    479 
    480     lookup = 1;
    481 
    482     evenTbl = &DecodeTable[0];
    483     oddTbl  = &DecodeTable[629];
    484 
    485     while (lookup < 0x275) {
    486         if (ReadBinary() == 0) {
    487             lookup = evenTbl[lookup];
    488         }
    489         else {
    490             lookup = oddTbl[lookup];
    491         }
    492     }
    493 
    494     lookup = (lookup + -0x275);
    495     UpdateTables(lookup);
    496 
    497     return lookup;
    498 }
    499 
    500 /*
    501 ========================
    502 =
    503 = InsertNodeDirectory
    504 = routine required for encoding
    505 =
    506 ========================
    507 */
    508 
    509 void InsertNodeDirectory(int start) // 8002D990
    510 {
    511     int hashKey = ((window[start % windowSize] ^ (window[(start + 1) % windowSize] << 4)) ^ (window[(start + 2) % windowSize] << 8)) & (HASH_SIZE - 1);
    512 
    513     if (hashtable[hashKey] == -1) {
    514         hashtarget[hashKey] = start;
    515         hashNext[start] = -1;
    516     }
    517     else {
    518         hashNext[start] = hashtable[hashKey];
    519         hashPrev[hashtable[hashKey]] = start;
    520     }
    521 
    522     hashtable[hashKey] = start;
    523     hashPrev[start] = -1;
    524 }
    525 
    526 /*
    527 ========================
    528 =
    529 = DeleteNodeDirectory
    530 = routine required for encoding
    531 =
    532 ========================
    533 */
    534 
    535 void DeleteNodeDirectory(int start) // 8002DAD0
    536 {
    537     int hashKey = ((window[start % windowSize] ^ (window[(start + 1) % windowSize] << 4)) ^ (window[(start + 2) % windowSize] << 8)) & (HASH_SIZE - 1);
    538 
    539     if (hashtable[hashKey] == hashtarget[hashKey]) {
    540         hashtable[hashKey] = -1;
    541     }
    542     else {
    543         hashNext[hashPrev[hashtarget[hashKey]]] = -1;
    544         hashtarget[hashKey] = hashPrev[hashtarget[hashKey]];
    545     }
    546 }
    547 
    548 /*
    549 ========================
    550 =
    551 = FindMatch
    552 = routine required for encoding
    553 =
    554 ========================
    555 */
    556 
    557 
    558 int FindMatch(int start, int count) // 8002DC0C
    559 {
    560     int encodedlen;
    561     int offset;
    562     int i;
    563     int samelen;
    564     int next;
    565     int curr;
    566     int encodedpos;
    567     int hashKey;
    568 
    569     encodedlen = 0;
    570     if (start == windowSize) {
    571         start = 0;
    572     }
    573 
    574     hashKey = ((window[start % windowSize] ^ (window[(start + 1) % windowSize] << 4)) ^ (window[(start + 2) % windowSize] << 8)) & (HASH_SIZE - 1);
    575 
    576     offset = hashtable[hashKey];
    577 
    578     i = 0;
    579     while (offset != -1)
    580     {
    581         if (++i > count) {
    582             break;
    583         }
    584 
    585         if ((window[(start + encodedlen) % windowSize]) == (window[(offset + encodedlen) % windowSize]))
    586         {
    587             samelen = 0;
    588             curr = start;
    589             next = offset;
    590 
    591             while (window[curr] == window[next]) {
    592                 if (samelen >= 64) {
    593                     break;
    594                 }
    595                 if (next == start) {
    596                     break;
    597                 }
    598                 if (curr == encArgs.incrBit) {
    599                     break;
    600                 }
    601                 ++samelen;
    602                 if (++curr == windowSize) {
    603                     curr = 0;
    604                 }
    605                 if (++next == windowSize) {
    606                     next = 0;
    607                 }
    608             }
    609 
    610             encodedpos = start - offset;
    611             if (encodedpos < 0) {
    612                 encodedpos += windowSize;
    613             }
    614             encodedpos -= samelen;
    615             if ((encArgs.unk1) && (encodedpos > offsetTable[6])) {
    616                 break;
    617             }
    618 
    619             if (encodedlen < samelen && encodedpos <= offsetMaxSize && (samelen > 3 || offsetTable[6 + (encArgs.type + 3)] >= encodedpos)) {
    620                 encodedlen = samelen;
    621                 encArgs.offset = encodedpos;
    622             }
    623         }
    624 
    625         offset = hashNext[offset]; // try next in list
    626     }
    627     return encodedlen;
    628 }
    629 
    630 
    631 /*
    632 ========================
    633 =
    634 = FUN_8002df14
    635 = unknown Function
    636 =
    637 ========================
    638 */
    639 
    640 void FUN_8002df14(void) // 8002DF14
    641 {
    642     byte byte_val;
    643 
    644     int i, j, k;
    645     byte* curPtr;
    646     byte* nextPtr;
    647     byte* next2Ptr;
    648 
    649     curPtr = &window[0];
    650 
    651     k = 0;
    652     j = 0;
    653     i = 1;
    654     do
    655     {
    656         nextPtr = &window[j];
    657         if (curPtr[0] == 10)
    658         {
    659             j = i;
    660             if (nextPtr[0] == curPtr[1])
    661             {
    662                 next2Ptr = &window[i + 1];
    663                 do
    664                 {
    665                     nextPtr++;
    666                     byte_val = *next2Ptr++;
    667                     k++;
    668                 } while (*nextPtr == byte_val);
    669             }
    670         }
    671         curPtr++;
    672         i++;
    673     } while (i != 67);
    674 
    675     if (k >= 16) {
    676         encArgs.unk1 = 1;
    677     }
    678 }
    679 
    680 
    681 /*
    682 ========================
    683 =
    684 = DecodeD64
    685 =
    686 = Exclusive Doom 64
    687 =
    688 ========================
    689 */
    690 
    691 void DecodeD64(unsigned char* input, unsigned char* output) // 8002DFA0
    692 {
    693     int copyPos, storePos;
    694     int dec_byte, resc_byte;
    695     int incrBit, copyCnt, shiftPos, j;
    696 
    697     //PRINTF_D2(WHITE, 0, 15, "DecodeD64");
    698 
    699     InitTables();
    700 
    701     OVERFLOW_READ = MAXINT;
    702     OVERFLOW_WRITE = MAXINT;
    703 
    704     incrBit = 0;
    705 
    706     buffers.input = buffers.istart = input;
    707     buffers.output = buffers.ostart = output;
    708 
    709     window = (byte *)Z_Alloc(windowSize, PU_STATIC, NULL);
    710 
    711     dec_byte = StartDecodeByte();
    712 
    713     while (dec_byte != 256)
    714     {
    715         if (dec_byte < 256)
    716         {
    717             /*  Decode the data directly using binary data code */
    718 
    719             WriteByte((byte)(dec_byte & 0xff));
    720             window[incrBit] = (byte)dec_byte;
    721 
    722             /*  Resets the count once the memory limit is exceeded in allocPtr,
    723                 so to speak resets it at startup for reuse */
    724             incrBit += 1;
    725             if (incrBit == windowSize) {
    726                 incrBit = 0;
    727             }
    728         }
    729         else
    730         {
    731             /*  Decode the data using binary data code,
    732                 a count is obtained for the repeated data,
    733                 positioning itself in the root that is being stored in allocPtr previously. */
    734 
    735             /*  A number is obtained from a range from 0 to 5,
    736                 necessary to obtain a shift value in the ShiftTable*/
    737             shiftPos = (dec_byte + -257) / 62;
    738 
    739             /*  Get a count number for data to copy */
    740             copyCnt = (dec_byte - (shiftPos * 62)) + -254;
    741 
    742             /*  To start copying data, you receive a position number
    743                 that you must sum with the position of table tableVar01 */
    744             resc_byte = ReadCodeBinary(ShiftTable[shiftPos]);
    745 
    746             /*  with this formula the exact position is obtained
    747                 to start copying previously stored data */
    748             copyPos = incrBit - ((offsetTable[shiftPos] + resc_byte) + copyCnt);
    749 
    750             if (copyPos < 0) {
    751                 copyPos += windowSize;
    752             }
    753 
    754             storePos = incrBit;
    755 
    756             for (j = 0; j < copyCnt; j++)
    757             {
    758                 /* write the copied data */
    759                 WriteByte(window[copyPos]);
    760 
    761                 /* save copied data at current position in memory allocPtr */
    762                 window[storePos] = window[copyPos];
    763 
    764                 storePos++; /* advance to next allocPtr memory block to store */
    765                 copyPos++;  /* advance to next allocPtr memory block to copy */
    766 
    767                 /* reset the position of storePos once the memory limit is exceeded */
    768                 if (storePos == windowSize) {
    769                     storePos = 0;
    770                 }
    771 
    772                 /* reset the position of copyPos once the memory limit is exceeded */
    773                 if (copyPos == windowSize) {
    774                     copyPos = 0;
    775                 }
    776             }
    777 
    778             /*  Resets the count once the memory limit is exceeded in allocPtr,
    779                 so to speak resets it at startup for reuse */
    780             incrBit += copyCnt;
    781             if (incrBit >= windowSize) {
    782                 incrBit -= windowSize;
    783             }
    784         }
    785 
    786         dec_byte = StartDecodeByte();
    787     }
    788 
    789     Z_Free(window);
    790 
    791     //PRINTF_D2(WHITE, 0, 21, "DecodeD64:End");
    792 }
    793 
    794 // ENCODE MODE BY GEC Erick Vasquez Garcia (ERICK194)
    795 // Updated version, compresses too fast and exact.
    796 
    797 void StartEncodeCode(int lookup)
    798 {
    799     // Encodes data from a table
    800     int lookupCode, lookupCheck;
    801     short* oddTbl;
    802     short* incrTbl;
    803     int binCnt = 0;
    804     byte binary[64];
    805     //static std::vector<byte> binary;
    806 
    807     //binary.clear();
    808     oddTbl = &DecodeTable[629];
    809     incrTbl = &DecodeTable[1258];
    810 
    811     lookupCode = lookup + 0x275;
    812     while (1) {
    813 
    814         if (lookupCode <= 1) { break; }
    815 
    816         lookupCheck = oddTbl[incrTbl[lookupCode]];
    817 
    818         //binary.push_back((lookupCheck == lookupCode) ? 1 : 0);
    819         binary[binCnt++] = (lookupCheck == lookupCode) ? 1 : 0;
    820 
    821         lookupCode = incrTbl[lookupCode];
    822     };
    823 
    824     // Write bits in bytes
    825     while (binCnt) {
    826         WriteBinary(binary[--binCnt]);
    827     }
    828 
    829     /*auto it = binary.rbegin();
    830     for (int k = 0; k < (int)binary.size(); k++) {
    831         WriteBinary(*it++);
    832     }*/
    833 
    834     // Update table
    835     UpdateTables(lookup);
    836 }
    837 
    838 unsigned char* EncodeD64(unsigned char* input, int inputlen, int* size) {
    839     int i, readPos, nodePos, looKupCode, byteData;
    840     int cpyCountNext, cpyCount, cntMin, cntMax;
    841     boolean deleteNode, skipCopy;
    842 
    843     unsigned char* output = (unsigned char*)Z_Alloc(inputlen * 2, PU_STATIC, NULL);
    844 
    845     InitTables();
    846 
    847     OVERFLOW_READ = inputlen;
    848     OVERFLOW_WRITE = inputlen * 2;
    849 
    850     deleteNode = false;
    851     skipCopy = false;
    852     readPos = encArgs.incrBit;
    853     nodePos = 0;
    854 
    855     buffers.input = buffers.istart = input;
    856     buffers.output = buffers.ostart = output;
    857 
    858     hashtable = (short*)Z_Alloc(HASH_SIZE * sizeof(short), PU_STATIC, NULL);
    859     hashtarget = (short*)Z_Alloc(HASH_SIZE * sizeof(short), PU_STATIC, NULL);
    860     hashNext = (short*)Z_Alloc(windowSize * sizeof(short), PU_STATIC, NULL);
    861     hashPrev = (short*)Z_Alloc(windowSize * sizeof(short), PU_STATIC, NULL);
    862     D_memset(hashNext, 0, windowSize * sizeof(short));
    863     D_memset(hashPrev, 0, windowSize * sizeof(short));
    864 
    865     window = (byte*)Z_Alloc(windowSize * sizeof(byte), PU_STATIC, NULL);
    866     D_memset(window, 0, windowSize * sizeof(byte));
    867 
    868     // Initializes hash encoding tables
    869     for (i = 0; i < HASH_SIZE; i++) {
    870         hashtable[i] = -1;
    871         hashtarget[i] = -1;
    872     }
    873 
    874     // Copy the first 3 bytes in the data window
    875     for (i = 0; i < encArgs.incrBit; i++) {
    876         byteData = ReadByte();
    877         if (byteData != -1) {
    878             // Encode a simple byte data.
    879             StartEncodeCode(byteData);
    880             window[i] = byteData;
    881         }
    882     }
    883 
    884     if (GetReadSize() < OVERFLOW_READ) { // Does not copy any data if the input data reached the limit
    885         // Copy the first 64 bytes in the data window
    886         for (i = 0; i < 64; i++) {
    887             byteData = ReadByte();
    888 
    889             // For some unknown reason if a byte is greater than or equal to 128 the form of the encoding changes
    890             // This happens depending on the file an example the BLANK and SPACEO texture results in 0
    891             // Textures such as C101, result in 1
    892             // MAP01, result in 1
    893             if (byteData >= 128) {
    894                 encArgs.type = 1;
    895             }
    896 
    897             if (byteData != -1) {
    898                 window[encArgs.incrBit++] = byteData;
    899             }
    900         }
    901     }
    902 
    903     // Determines the number of bytes to compare
    904     cntMin = (encArgs.type == 1) ? 20 : 50;
    905     cntMax = (encArgs.type == 1) ? 200 : 1000;
    906 
    907     if (GetReadSize() < OVERFLOW_READ) { // Does not encode any data if the input data reached the limit
    908 
    909         while (readPos != encArgs.incrBit) {
    910             // Add the data in the node directory table
    911             // update the hash table
    912             InsertNodeDirectory(nodePos);
    913 
    914             if (!skipCopy) {
    915 
    916                 cpyCountNext = FindMatch(readPos + 1, cntMin);
    917                 cpyCount = FindMatch(readPos, cntMax);
    918 
    919                 //printf("cpyCount %d\n", cpyCount);
    920                 //printf("cpyCountNext %d\n", cpyCountNext);
    921 
    922                 // Check if there is a possibility to copy the data by routes
    923                 if (cpyCount >= 3 && cpyCount >= cpyCountNext) {
    924 
    925                     int count = cpyCount;
    926                     int ValExtra = encArgs.offset;
    927                     int Shift = 0x04;
    928 
    929                     if ((ValExtra >= offsetTable[1]) && (ValExtra < offsetTable[2]))
    930                     {
    931                         Shift = 0x06;
    932                         ValExtra -= offsetTable[1];
    933                     }
    934                     if ((ValExtra >= offsetTable[2]) && (ValExtra < offsetTable[3]))
    935                     {
    936                         Shift = 0x08;
    937                         ValExtra -= offsetTable[2];
    938                     }
    939                     if ((ValExtra >= offsetTable[3]) && (ValExtra < offsetTable[4]))
    940                     {
    941                         Shift = 0x0A;
    942                         ValExtra -= offsetTable[3];
    943                     }
    944                     if ((ValExtra >= offsetTable[4]) && (ValExtra < offsetTable[5]))
    945                     {
    946                         Shift = 0x0C;
    947                         ValExtra -= offsetTable[4];
    948                     }
    949                     if ((ValExtra >= offsetTable[5]))
    950                     {
    951                         Shift = 0x0E;
    952                         ValExtra -= offsetTable[5];
    953                     }
    954 
    955                     if (Shift == 0x04) { looKupCode = (0x0101 + (count - 3)); }
    956                     else if (Shift == 0x06) { looKupCode = (0x013F + (count - 3)); }
    957                     else if (Shift == 0x08) { looKupCode = (0x017D + (count - 3)); }
    958                     else if (Shift == 0x0A) { looKupCode = (0x01BB + (count - 3)); }
    959                     else if (Shift == 0x0C) { looKupCode = (0x01F9 + (count - 3)); }
    960                     else if (Shift == 0x0E) { looKupCode = (0x0237 + (count - 3)); }
    961 
    962                     //printf("Code 0x%04X ValExtra 0x%04X\n", LooKupCode2, ValExtra);
    963 
    964                     // Writes the startup code and address to copy data from the data window.
    965                     StartEncodeCode(looKupCode);
    966                     // Writes the amount of data to copy from the data window.
    967                     WriteCodeBinary(ValExtra, Shift);
    968 
    969                     skipCopy = true;
    970                 }
    971                 else { // Encode a simple byte data.
    972                     StartEncodeCode(window[readPos]);
    973                 }
    974             }
    975 
    976             // Skip copy data
    977             if (--cpyCount == 0) {
    978                 skipCopy = false;
    979             }
    980 
    981             // Advance to the next position to check in matching
    982             if (++readPos == windowSize) {
    983                 readPos = 0;
    984             }
    985 
    986             // Advance to the next position to add to the nodes of the directory
    987             if (++nodePos == windowSize) {
    988                 nodePos = 0;
    989             }
    990 
    991             // Copy input data to the data window
    992             if (GetReadSize() < OVERFLOW_READ) { // Does not copy any data if the input data reached the limit
    993                 byteData = ReadByte();
    994                 if (byteData != -1) {
    995                     window[encArgs.incrBit++] = byteData;
    996                 }
    997 
    998                 // Enables the deletion of nodes in the directory once the first block of the data window is reached
    999                 if (encArgs.incrBit == windowSize) {
   1000                     encArgs.incrBit = 0;
   1001                     deleteNode = true;
   1002                 }
   1003             }
   1004 
   1005             // Delete the data in the node directory table
   1006             if (deleteNode && GetReadSize() < OVERFLOW_READ) {
   1007                 DeleteNodeDirectory(encArgs.incrBit);
   1008             }
   1009         }
   1010     }
   1011 
   1012     // Write the code to finish the encoding
   1013     StartEncodeCode(0x100);
   1014     FlushBitBuffer();
   1015 
   1016     *size = GetOutputSize();
   1017 
   1018     Z_Free(hashtable);
   1019     Z_Free(hashtarget);
   1020     Z_Free(hashNext);
   1021     Z_Free(hashPrev);
   1022     Z_Free(window);
   1023 
   1024     return output;
   1025 }
   1026 
   1027 /*
   1028 == == == == == == == == == ==
   1029 =
   1030 = DecodeJaguar (decode original name)
   1031 =
   1032 = Exclusive Psx Doom / Doom 64 from Jaguar Doom
   1033 =
   1034 == == == == == == == == == ==
   1035 */
   1036 
   1037 #define WINDOW_SIZE	4096
   1038 #define LOOKAHEAD_SIZE	16
   1039 
   1040 #define LENSHIFT 4		/* this must be log2(LOOKAHEAD_SIZE) */
   1041 
   1042 void DecodeJaguar(unsigned char *input, unsigned char *output) // 8002E1f4
   1043 {
   1044     int getidbyte = 0;
   1045 	int len;
   1046 	int pos;
   1047 	int i;
   1048 	unsigned char *source;
   1049 	int idbyte = 0;
   1050 
   1051 	while (1)
   1052 	{
   1053 		/* get a new idbyte if necessary */
   1054 		if (!getidbyte) idbyte = *input++;
   1055 		getidbyte = (getidbyte + 1) & 7;
   1056 
   1057 		if (idbyte & 1)
   1058 		{
   1059 			/* decompress */
   1060 			pos = *input++ << LENSHIFT;
   1061 			pos = pos | (*input >> LENSHIFT);
   1062 			source = output - pos - 1;
   1063 			len = (*input++ & 0xf) + 1;
   1064 			if (len == 1) break;
   1065 
   1066 			//for (i = 0; i<len; i++)
   1067 				//*output++ = *source++;
   1068 
   1069             i = 0;
   1070             if (len > 0)
   1071             {
   1072                 if ((len & 3))
   1073                 {
   1074                     while(i != (len & 3))
   1075                     {
   1076                         *output++ = *source++;
   1077                         i++;
   1078                     }
   1079                 }
   1080                 while(i != len)
   1081                 {
   1082                     output[0] = source[0];
   1083                     output[1] = source[1];
   1084                     output[2] = source[2];
   1085                     output[3] = source[3];
   1086                     output += 4;
   1087                     source += 4;
   1088                     i += 4;
   1089                 }
   1090             }
   1091 		}
   1092 		else
   1093         {
   1094 			*output++ = *input++;
   1095 		}
   1096 
   1097 		idbyte = idbyte >> 1;
   1098 	}
   1099 }