Advertisement
charleysdrpepper

Camelot GBA Decompression Functions

Apr 28th, 2015
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.29 KB | None | 0 0
  1.         byte[] decompress(byte[] src, int srcPos, int desPos) {
  2.             byte[] des = new byte[0x10000]; //Largest size ever needed.
  3.             int bits, readcount, i, _byte; //offset;
  4.             uint n; ulong z = 0xFEDCBA9876543210;
  5.             int format = src[srcPos++];
  6.             if (format == 0 || format == 2) {
  7.                 bits = 0;
  8.                 int bitnum = 0;
  9.                 if ((srcPos & 1) == 1) {  bits = src[srcPos++]; bitnum = 8; } //Optional
  10.                 bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  11.                 while (true) {
  12.                     readcount = 0;
  13.                     if ((bits & 1) == 1) {
  14.                         bits >>= 1; bitnum -= 1;
  15.                         if (format == 0) { //Format 0: Constant
  16.                             des[desPos++] = (byte)bits; bits >>= 8; bitnum -= 8;
  17.                         } else { //Format 2: Recent Priority
  18.                             if ((bits & 1) == 1) {
  19.                                 i = 2; bits >>= 1; bitnum -= 1;
  20.                             } else if ((bits & 2) == 2) {
  21.                                 i = 3; bits >>= 2; bitnum -= 2;
  22.                             } else {
  23.                                 i = 4; bits >>= 2; bitnum -= 2;
  24.                             }
  25.                             for (int offset = 0; offset < 8; offset += 4) {
  26.                                 _byte = (bits & ((1 << i) - 1)); bits >>= i; bitnum -= i; //Read from compressed data.
  27.                                 n = (uint)(0xF & (z >> (int)(_byte << 2))); //Get selected value.
  28.                                 if (_byte != 0xF) { // Check 0xF because <<0x40 does nothing. (ex: no-op?)
  29.                                     z = (z & (unchecked((ulong)-1) << ((_byte + 1) << 2))) //Keep tail end.
  30.                                         | ((z & ((((ulong)1) << (_byte << 2)) - 1)) << 4) //Close gap.
  31.                                         | n; //Put selected value in front.
  32.                                 } else { z = (z << 4) | n; }
  33.                                 des[desPos] |= (byte)(n << offset); //Write decompressed 4-bit.
  34.                             }
  35.                             desPos++;
  36.                         }
  37.                         if (bitnum < 0) {
  38.                             bitnum += 16;
  39.                             bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  40.                         }
  41.                     } else if ((bits & 3) == 0) { //Format 0 & 2: Distance Length: Length
  42.                         readcount = 2; bits >>= 2; bitnum -= 2;
  43.                     } else if ((bits & 7) == 2) {
  44.                         readcount = 3; bits >>= 3; bitnum -= 3;
  45.                     } else if ((bits & 0xF) == 6) {
  46.                         readcount = 4; bits >>= 4; bitnum -= 4;
  47.                     } else if ((bits & 0x1F) == 0xE) {
  48.                         readcount = 5; bits >>= 5; bitnum -= 5;
  49.                     } else if ((bits & 0x7F) == 0x1E) {
  50.                         readcount = 6; bits >>= 7; bitnum -= 7;
  51.                     } else if ((bits & 0x7F) == 0x5E) {
  52.                         readcount = 7; bits >>= 7; bitnum -= 7;
  53.                     } else if ((bits & 0x3F) == 0x3E) {
  54.                         readcount = 7 + ((bits >> 6) & 3); bits >>= 8; bitnum -= 8;
  55.                         if (readcount == 7) {
  56.                             readcount = 10 + (bits & 127); bits >>= 7; bitnum -= 7;
  57.                             if (readcount == 10) { return des; }
  58.                         }
  59.                     }
  60.                     if (bitnum < 0) {
  61.                         bitnum += 16;
  62.                         bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  63.                     }
  64.                     if (readcount != 0) { //Format 0 & 2: Distance Length: Distance
  65.                         uint offset = 0;
  66.                         if ((bits & 1) == 0) { //Long Distance - 0~12-bit distance
  67.                             bits >>= 1; bitnum -= 1;
  68.                             offset = (uint)desPos - 33;
  69.                             _byte = 12;
  70.                             while (offset < (1 << (_byte - 1))) {
  71.                                 _byte -= 1;
  72.                             }
  73.                             offset = (uint)(32 + (bits & ((1 << _byte) - 1))); bits >>= _byte; bitnum -= _byte;
  74.                         } else { //Short Distance - 5-bit distance
  75.                             bits >>= 1; bitnum -= 1;
  76.                             offset = (uint)(bits & 31); bits >>= 5; bitnum -= 5;
  77.                         }
  78.                         if (bitnum < 0) {
  79.                             bitnum += 16;
  80.                             bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  81.                         }
  82.                         //if (desPos < offset) { return null; }
  83.                         while (readcount-- > 0) {
  84.                             des[desPos] = des[desPos - offset - 1]; desPos++;
  85.                         }
  86.                     }
  87.                 }
  88.             } else { //Format 1
  89.                 while (true) {
  90.                     bits = src[srcPos++];
  91.                     for (int j = 0x80; j > 0; j >>= 1) {
  92.                         if ((bits & j) == 0) {
  93.                             des[desPos++] = src[srcPos++];
  94.                         } else {
  95.                             readcount = src[srcPos++];
  96.                             int offset = src[srcPos++] | ((readcount & 0xF0) << 4);
  97.                             readcount = readcount & 15;
  98.                             if (readcount == 0) {
  99.                                 if (offset == 0) { return des; }
  100.                                 readcount = src[srcPos++] + 16;
  101.                             }
  102.                             //if (desPos < offset) { return null; }
  103.                             while (readcount-- >= 0) {
  104.                                 des[desPos] = des[desPos - offset]; desPos++;
  105.                             }
  106.                         }
  107.                     }
  108.                 }
  109.             }
  110.             //return des;
  111.         }
  112.  
  113.         byte[] decompress16(byte[] src, int srcPos, int desPos) {
  114.             byte[] des = new byte[0x4000];
  115.             int bits = 0, i = 0, bitnum = 0;
  116.             uint n; ulong z = 0xFEDCBA9876543210;
  117.             bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  118.             while (true) {
  119.                 if ((bits & 0x1) == 0x0) {
  120.                     i = 0; bits >>= 1; bitnum -= 1;
  121.                 } else if ((bits & 0x7) == 0x1) {
  122.                     i = 1; bits >>= 3; bitnum -= 3;
  123.                 } else if ((bits & 0xF) == 0x5) {
  124.                     i = 2; bits >>= 4; bitnum -= 4;
  125.                 } else if ((bits & 0xF) == 0xD) {
  126.                     i = 3; bits >>= 4; bitnum -= 4;
  127.                 } else if ((bits & 0xF) == 0x3) {
  128.                     i = 4; bits >>= 4; bitnum -= 4;
  129.                 } else if ((bits & 0xF) == 0xB) {
  130.                     i = 5; bits >>= 4; bitnum -= 4;
  131.                 } else if ((bits & 0xF) == 0x7) {
  132.                     i = 6; bits >>= 4; bitnum -= 4;
  133.                 } else if ((bits & 0x3F) == 0xF) {
  134.                     i = 7; bits >>= 6; bitnum -= 6;
  135.                 } else if ((bits & 0x3F) == 0x2F) {
  136.                     i = 8; bits >>= 6; bitnum -= 6;
  137.                 } else if ((bits & 0x3F) == 0x1F) {
  138.                     i = 9; bits >>= 6; bitnum -= 6;
  139.                 } else if ((bits & 0xFF) == 0x3F) {
  140.                     i = 10; bits >>= 8; bitnum -= 8;
  141.                 } else if ((bits & 0xFF) == 0xBF) {
  142.                     i = 11; bits >>= 8; bitnum -= 8;
  143.                 } else if ((bits & 0xFF) == 0x7F) {
  144.                     i = 12; bits >>= 8; bitnum -= 8;
  145.                 } else if ((bits & 0x3FF) == 0xFF) {
  146.                     i = 13; bits >>= 10; bitnum -= 10;
  147.                 } else if ((bits & 0x3FF) == 0x2FF) {
  148.                     i = 14; bits >>= 10; bitnum -= 10;
  149.                 } else if ((bits & 0x3FF) == 0x1FF) {
  150.                     i = 15; bits >>= 10; bitnum -= 10;
  151.                 } else if ((bits & 0x3FF) == 0x3FF) {
  152.                     return des;
  153.                 }
  154.                 n = (uint)(0xF & (z >> (int)(i << 2))); //Get selected value.
  155.                 if (i != 0xF) { // Check 0xF because <<0x40 does nothing. (ex: no-op?)
  156.                     z = (z & (unchecked((ulong)-1) << ((i + 1) << 2))) //Keep tail end.
  157.                         | ((z & ((((ulong)1) << (i << 2)) - 1)) << 4) //Close gap.
  158.                         | n; //Put selected value in front.
  159.                 } else { z = (z << 4) | n; }
  160.                 des[desPos++] = (byte)n; //Write decompressed 4-bit.
  161.  
  162.                 if (bitnum < 0) {
  163.                     bitnum += 16;
  164.                     bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  165.                 }
  166.             }
  167.         }
  168.         int[] bitTable = {0x1, 0x0, 0x3, 0x1, 0x4, 0x5, 0x4, 0xD,
  169.                                  0x4, 0x3, 0x4, 0xB, 0x4, 0x7, 0x6, 0xF,
  170.                                  0x6, 0x2F, 0x6, 0x1F, 0x8, 0x3F, 0x8, 0xBF,
  171.                                  0x8, 0x7F, 0xA, 0xFF, 0xA, 0x2FF, 0xA, 0x1FF,
  172.                                  0xA, 0x3FF};
  173.         void compress16(byte[] src, int srcPos, byte[] des, int desPos) { //Not tested.
  174.             int bitnum = 0, bits = 0, i = 0;
  175.             uint n = 0; ulong z = 0xFEDCBA9876543210;
  176.             while (srcPos < src.Length) { //Length may be changed?
  177.                 while ((((z >> i) & 0xF) != src[srcPos])) {
  178.                     i += 4;
  179.                 }
  180.                 bits = bits | (bitTable[(i >> 1) + 1] << bitnum); bitnum += bitTable[i >> 1];
  181.                 while (bitnum >= 8) {
  182.                     des[desPos] = (byte)bits; bits >>= 8; bitnum -= 8;
  183.                 }
  184.  
  185.                 n = (uint)(0xF & (z >> (int)i)); //Get selected value.
  186.                 if (i != 0x3C) { // Check 0xF because <<0x40 does nothing. (ex: no-op?)
  187.                     z = (z & (unchecked((ulong)-1) << (i + 4))) //Keep tail end.
  188.                         | ((z & ((((ulong)1) << i) - 1)) << 4) //Close gap.
  189.                         | n; //Put selected value in front.
  190.                 } else { z = (z << 4) | n; }
  191.                 srcPos++;
  192.             }
  193.             bits = bits | (bitTable[0x21] << bitnum); bitnum += bitTable[0x20];
  194.             while (bitnum > 0) {
  195.                 des[desPos] = (byte)bits; bits >>= 8; bitnum -= 8;
  196.             }
  197.         }
  198.         byte[] decompBtlBG(byte[] src, int srcPos) {
  199.             byte[] des = new byte[0x8000]; int desPos = 0;
  200.             int bits = 0, i = 0x60, bitnum = 0;
  201.             bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  202.             for (int j = 0; j < 0x7800; j++) {
  203.                 switch (bits & 7) {
  204.                     case 0:
  205.                     case 4:
  206.                         bits >>= 2; bitnum -= 2;
  207.                         break;
  208.                     case 1:
  209.                         bits >>= 3; bitnum -= 3;
  210.                         i += 1 + (bits & 1); bits >>= 1; bitnum -= 1;
  211.                         break;
  212.                     case 2:
  213.                         bits >>= 3; bitnum -= 3;
  214.                         if ((bits & 1) == 0) {
  215.                             bits >>= 1; bitnum -= 1;
  216.                             i += 11 + (bits & 0xF); bits >>= 4; bitnum -= 4;
  217.                         } else {
  218.                             bits >>= 1; bitnum -= 1;
  219.                             i -= 11 + (bits & 0xF); bits >>= 4; bitnum -= 4;
  220.                         }
  221.                         break;
  222.                     case 3:
  223.                         bits >>= 3; bitnum -= 3;
  224.                         i += 3 + (bits & 7); bits >>= 3; bitnum -= 3;
  225.                         break;
  226.                     case 5:
  227.                         bits >>= 3; bitnum -= 3;
  228.                         i -= 1 + (bits & 1); bits >>= 1; bitnum -= 1;
  229.                         break;
  230.                     case 6:
  231.                         bits >>= 3; bitnum -= 3;
  232.                         i = 0x60 + (bits & 0x7F); bits >>= 7; bitnum -= 7;
  233.                         break;
  234.                     case 7:
  235.                         bits >>= 3; bitnum -= 3;
  236.                         i -= 3 + (bits & 7); bits >>= 3; bitnum -= 3;
  237.                         break;
  238.                 }
  239.                 des[desPos++] = (byte)i;
  240.                 if (bitnum < 0) {
  241.                     bitnum += 16;
  242.                     bits += ((int)src[srcPos++] << bitnum) + ((int)src[srcPos++] << (8 + bitnum));
  243.                 }
  244.             }
  245.             return des;
  246.         }
  247.         byte[] decompText(byte[] src, int srcInd) { // int srcPos) {
  248.             byte[] des = new byte[0x8000]; int desPos = 0;
  249.             int textTree = Bits.getInt32(src, 0xA9F54 + ((srcInd >> 8) << 3)) - 0x08000000;
  250.             int textLenAddr = Bits.getInt32(src, 0xA9F54 + ((srcInd >> 8) << 3) + 4) - 0x08000000;
  251.             srcInd &= 0xFF;
  252.             while (srcInd-- != 0) {
  253.                 int cLen;
  254.                 do {
  255.                     cLen = src[textLenAddr++];
  256.                     textTree += cLen;
  257.                 } while (cLen == 0xFF);
  258.             }
  259.             int initChar = 0;
  260.             int chardata = Bits.getInt32(rom, 0x60C30) - 0x08000000;
  261.             int charpntrs = Bits.getInt32(rom, 0x60C34) - 0x08000000;
  262.             textTree <<= 3;
  263.             do {
  264.                 int charTree = (chardata + Bits.getInt16(rom, charpntrs + (initChar << 1))) << 3;
  265.                 int charSlot = charTree - 12;
  266.                 while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) {
  267.                     if (((src[textTree >> 3] >> (textTree++ & 7)) & 1) == 1) {
  268.                         int depth = 0;
  269.                         while (depth >= 0) {
  270.                             while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) {
  271.                                 depth++;
  272.                             }
  273.                             charSlot-=12;
  274.                             depth--;
  275.                         }
  276.                     }
  277.                 }
  278.                 initChar = (Bits.getInt16(rom, charSlot >> 3) >> (charSlot & 7)) & 0xFFF;
  279.                 des[desPos++] = (byte)initChar;
  280.             } while (initChar != 0);
  281.             return des;
  282.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement