public static byte[] Decompress(ReadStream compressed) { List <byte> decompressed = new List <byte>(); while (true) { // If an ff-byte is encountered the decompression has completed. if (compressed.Peek() == LzEnd) { break; } // Bits 5-7 are occupied by control command. int command = (compressed.Peek() & 0xe0) >> 5; int length = 1; // The long command is used when 5 bits aren't enough. if (command == LzLong) { // Bits 2-4 contain the new control code. command = (compressed.Peek() & 0x1c) >> 2; // Bits 0-1 are appended to a new byte as bits 8-9, allowing a 10-bit operand. length += (compressed.u8() & 0x3) << 8; length += compressed.u8(); } else { // If not a long command, bits 0-5 contain the command's operand. length += (compressed.u8() & 0x1f); } switch (command) { case LzLiteral: Literal(compressed, decompressed, length); break; case LzIterate: Iterate(compressed, decompressed, length); break; case LzAlternate: Alternate(compressed, decompressed, length); break; case LzBlank: Blank(compressed, decompressed, length); break; case LzRepeat: Repeat(compressed, decompressed, length, 1, false); break; case LzFlip: Repeat(compressed, decompressed, length, 1, true); break; case LzReverse: Repeat(compressed, decompressed, length, -1, false); break; } } return(decompressed.ToArray()); }
private void LoadSpecies() { const int maxIndexNumber = 190; int numBaseStats = IsYellow ? 151 : 150; byte[] pokedex = ROM.Subarray(SYM["PokedexOrder"], maxIndexNumber); ReadStream data = ROM.From("BaseStats"); for (int i = 0; i < numBaseStats; i++) { byte indexNumber = (byte)Array.IndexOf(pokedex, data.Peek()); Species.Add(new RbySpecies(this, ++indexNumber, data)); } if (this is RedBlue) { Species.Add(new RbySpecies(this, 21, ROM.From(SYM["MewBaseStats"]))); } // Add MISSINGNO data for (int i = 1; i <= maxIndexNumber; i++) { if (pokedex[i - 1] == 0) { RbySpecies species = new RbySpecies(this, (byte)i); Species.Add(new RbySpecies(this, (byte)i)); } } }
public static void Repeat(ReadStream compressed, List <byte> decompressed, int length, int direction, bool flipped) { // Repeater commands repeat any data already present in the decompressed stream. // They take an additional singed operand to mark the relative starting point. int offset = 0; if (compressed.Peek() >= 0x80) { // If the operand is negative, it wraps around from the current position. offset = compressed.u8() & 0x7f; offset = decompressed.Count - offset - 1; } else { // For positive operands, a 16-bit offset is used. offset = compressed.u16be(); } for (int i = 0; i < length; i++) { byte b = decompressed[offset + i * direction]; // Reverse the bits if the command desires it. if (flipped) { b = (byte)(((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16); } decompressed.Add(b); } }