static TKMKHuffmanTreeNode NewNewSetUp5BitBuffers(uint val, byte[] data) // 80040BC0/0417C0 { TKMKHuffmanTreeNode newTree = new TKMKHuffmanTreeNode(); newTree.Value = (int)val; //uint startingVal = val; NewGetNextChannelCommand(data, 0, out v0); //Grabs the buffer set up information if (v0 != 0) { val++; TKMKHuffmanTreeNode left = NewNewSetUp5BitBuffers(val, data); //buffer80_u16[startingVal] = (ushort)v0; TKMKHuffmanTreeNode right = NewNewSetUp5BitBuffers(val, data); //bufferFE_u16[startingVal] = (ushort)v0; //v0 = (int)startingVal; newTree.Left = left; newTree.Right = right; return(newTree); } s0 = 0; s1 = 5; do { NewGetNextChannelCommand(data, 0, out v0); s0 = s0 * 2 + v0; //basically bitshifts s0 to the left and adds v0, aka it's loading 5 bytes straight from the 0th some_ptr s1 -= 1; } while (s1 != 0); newTree.Value = s0; return(newTree); }
// inputs: t1 // outputs: s4 //Only called when creating new rgba value. follows the maze of the color buffers to return the correct value static void NewNewRetrieve5BitValue(byte[] data) // 80040C54/041854 { TKMKHuffmanTreeNode currentNode = treeHead; //s4 = t1; while (currentNode.Value >= 0x20 && !currentNode.IsEndNode) { v1 = 0; NewGetNextChannelCommand(data, v1, out v0); if (v0 == 0) { //s4 = buffer80_u16[s4]; currentNode = currentNode.Left; } else { //s4 = bufferFE_u16[s4]; currentNode = currentNode.Right; } } s4 = currentNode.Value; }
// 80040BC0/0417C0 static TKMKHuffmanTreeNode NewNewSetUp5BitBuffers(uint val, byte[] data) { TKMKHuffmanTreeNode newTree = new TKMKHuffmanTreeNode(); newTree.Value = (int)val; //uint startingVal = val; NewGetNextChannelCommand(data, 0, out v0); //Grabs the buffer set up information if (v0 != 0) { val++; TKMKHuffmanTreeNode left = NewNewSetUp5BitBuffers(val, data); //buffer80_u16[startingVal] = (ushort)v0; TKMKHuffmanTreeNode right = NewNewSetUp5BitBuffers(val, data); //bufferFE_u16[startingVal] = (ushort)v0; //v0 = (int)startingVal; newTree.Left = left; newTree.Right = right; return newTree; } s0 = 0; s1 = 5; do { NewGetNextChannelCommand(data, 0, out v0); s0 = s0 * 2 + v0; //basically bitshifts s0 to the left and adds v0, aka it's loading 5 bytes straight from the 0th some_ptr s1 -= 1; } while (s1 != 0); newTree.Value = s0; return newTree; }
// a0[in]: pointer to TKMK00 data // a1[out]: pointer to output (1 byte per pixel) // a2[out]: pointer to output (RGBA16, 2 bytes per pixel) // a3[in]: RGBA color to set alpha to 0, values observed: 0x01, 0xBE public static void tkmk00decode(byte[] data, int tkmkOffset, out byte[] singleByteOutput, out byte[] doubleByteOutput, uint alphaFlagParam) // 800405D0/0411D0 { //TO DO: CLEAR THE BUFFERS BETWEEN DECODINGS uint offset; uint test_bits; int width, height; int col, row; int pixels; int alpha; uint i; ushort rgba0; ushort rgba1; byte red0, red1, green0, green1, blue0, blue1; width = ByteHelper.ReadUShort(data, tkmkOffset + 0x8); // read_u16_be(&tkmkOffset[0x8]); height = ByteHelper.ReadUShort(data, tkmkOffset + 0xA); //read_u16_be(&tkmkOffset[0xA]); alpha = (int)alphaFlagParam; channelCommandMode = data[tkmkOffset + 0x6]; for (int iii = 0; iii < 0x8; iii++) //Convert the channel command mode to bools { channelCommandRepeatMode[iii] = (((channelCommandMode >> iii) & 0x1) != 0); } pixels = width * height; for (int iCount = 0; iCount < rgba_buf.Length; iCount++) { rgba_buf[iCount] = 0xFF; } doubleByteOutput = new byte[2 * pixels]; singleByteOutput = new byte[pixels]; int doubleByteIndex = 0; int singleByteIndex = 0; for (i = 0; i < 8; i++) { offset = ByteHelper.ReadUInt(data, tkmkOffset + 0xC + (int)i * 4); //read_u32_be(&tkmkOffset[0xC + i*4]); if (0 == (channelCommandMode & (0x1 << (int)i))) { offset -= 4; } else { offset--; } channelPtrs[i] = tkmkOffset + (int)offset; } Array.Clear(channelCommandRemainingBits, 0, channelCommandRemainingBits.Length); //masterCommandOffset = 0x0; // no idea, used in proc_80040A60 masterCommandBuffer = ByteHelper.ReadInt(data, tkmkOffset + 0x2C); // read_u32_be(&tkmkOffset[0x2C]); // used in proc_80040A60 masterCommandRemainingBits = 0x20; masterCommandPtr = tkmkOffset + 0x2C; //ByteHelper.ReadInt(data, tkmkOffset + 0x30);//&tkmkOffset[0x30]; uint val = 0x20; //SetUp5BitBuffers((uint)some_u32s.Length - 4, ref val, data); // recursive, init buffers??? //treeHead = new TKMKHuffmanTreeNode(); //treeHead.Value = 0x20; treeHead = NewNewSetUp5BitBuffers(val, data); // recursive, init buffers??? t1 = v0; t7 = 0; //the last used rgba color StreamWriter writer = new StreamWriter("process.txt"); for (row = 0; row != height; row++) { for (col = 0; col != width; col++) { t9 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex);// ????????? read_u16_be(doubleByteOutput); //read the existing color of the byte if (t9 == 0) //Not set yet { v1 = singleByteOutput[singleByteIndex]; } else { //Test to make sure that the curent color is not the alpha value with the incorrect alpha channel value s3 = t9 & 0xFFFE; //All the color but the alpha channel t7 = t9; if (alpha != s3) { writer.WriteLine("UseExistingPixel"); goto goto_AdvanceToNextPixel; } //if alpha IS s3, then write it out ByteHelper.WriteUShort((ushort)s3, doubleByteOutput, doubleByteIndex);// write_u16_be(doubleByteOutput, s3); t7 = s3; writer.WriteLine("RewriteAlphaPixel"); goto goto_AdvanceToNextPixel; } writer.Write("NewPixel-"); v1 += 1; NewGetNextChannelCommand(data, v1, out v0); //Determine here if we use the previous color or a different one if (v0 == 0) //use last color here { ByteHelper.WriteUShort((ushort)t7, doubleByteOutput, doubleByteIndex); //write_u16_be(doubleByteOutput, t7); writer.WriteLine("Previous color"); goto goto_AdvanceToNextPixel; } v1 = 1; NewReadNextCommand(data, v1, out v0); //Check for creating new or re-using old RGBA value if (v0 != 0) { //Create new rgba value writer.WriteLine("NewColor"); NewNewRetrieve5BitValue(data); //Read red component s0 = s4; //store red component into s0 NewNewRetrieve5BitValue(data); //Read green component s1 = s4; //store green component into s0 NewNewRetrieve5BitValue(data); //Read blue component and store into s0 rgba0 = 0; //pixel above this one rgba1 = 0; //pixel before this one if (row != 0) { rgba0 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - (width * 2)); // read_u16_be(doubleByteOutput - (width * 2)); rgba1 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - 2); //read_u16_be(doubleByteOutput - 2); } else { if (col != 0) { rgba1 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - 2);//read_u16_be(doubleByteOutput - 2); } } green0 = (byte)((rgba0 & 0x7C0) >> 6); green1 = (byte)((rgba1 & 0x7C0) >> 6); t8 = (green0 + green1) / 2; t9 = s0; //proc_80040C94(); //Get the red component ColorCombine(t8, ref t9); s0 = t9; v1 = t9 - t8; red0 = (byte)((rgba0 & 0xF800) >> 11); red1 = (byte)((rgba1 & 0xF800) >> 11); t8 = v1 + (red0 + red1) / 2; if (t8 >= 0x20) { t8 = 0x1F; } else if (t8 < 0) { t8 = 0; } t9 = s1; //proc_80040C94(); //Get the green component ColorCombine(t8, ref t9); s1 = t9; blue0 = (byte)((rgba0 & 0x3E) >> 1); blue1 = (byte)((rgba1 & 0x3E) >> 1); t8 = v1 + (blue0 + blue1) / 2; if (t8 >= 0x20) { t8 = 0x1F; } else if (t8 < 0) { t8 = 0; } t9 = s4; //proc_80040C94(); //Get the blue component ColorCombine(t8, ref t9); t7 = (s1 << 11) | (s0 << 6) | (t9 << 1); //Combine the color components into the ushort if (t7 != alpha) { t7 |= 0x1; } // insert new value by shifting others to right for (i = (uint)rgba_buf.Length - 1; i > 0; i--) { rgba_buf[i] = rgba_buf[i - 1]; } rgba_buf[0] = (ushort)t7; } else { //Use existing rgba value writer.WriteLine("ExistingColor"); v1 = 6; NewReadNextCommand(data, v1, out v0); //Read in the index of the rgba in the rgba buffer to use t7 = rgba_buf[v0]; if (v0 != 0) { for (i = (uint)v0; i > 0; i--) { rgba_buf[i] = rgba_buf[i - 1]; } rgba_buf[0] = (ushort)t7; } } //Write the RGBA to the doubleByteIndex location ByteHelper.WriteUShort((ushort)t7, doubleByteOutput, doubleByteIndex); //write_u16_be(doubleByteOutput, t7); test_bits = 0; //stores flags marking the existence of pixels around the current pixel if (col != 0) { test_bits |= 0x01; } if (col < (width - 1)) { test_bits |= 0x02; } if (col < (width - 2)) { test_bits |= 0x04; } if (row < (height - 1)) { test_bits |= 0x08; } if (row < (height - 2)) { test_bits |= 0x10; } if (0x2 == (test_bits & 0x2)) //if a pixel exists to the right 1 { singleByteOutput[singleByteIndex + 1]++; } if (0x4 == (test_bits & 0x4)) //if a pixel exists to the right 2 { singleByteOutput[singleByteIndex + 2]++; } if (0x9 == (test_bits & 0x9)) //if a pixel exists below 1 and to the left 1 { singleByteOutput[singleByteIndex + width - 1]++; } if (0x8 == (test_bits & 0x8)) //if a pixel exists below 1 { singleByteOutput[singleByteIndex + width]++; } if (0xA == (test_bits & 0xA)) //if a pixel exists below 1 and right 1 { singleByteOutput[singleByteIndex + width + 1]++; } if (0x10 == (test_bits & 0x10)) //if a pixel exists 2 below this one { singleByteOutput[singleByteIndex + 2 * width]++; } v1 = 1; NewReadNextCommand(data, v1, out v0); //Check if we need to preload this color onto rows below this one if (v0 != 0) { int outOffset = 0; s0 = width * 2; //Length of a row in bytes s3 = t7 | 0x1; //Previous RGBA, with alpha forced on do { v1 = 2; NewReadNextCommand(data, v1, out v0); //0 - advanced move, 1 - back one, 2 - no lateral move, 3 - forward one if (v0 == 0) { v1 = 1; NewReadNextCommand(data, v1, out v0); //0 - stop advanced move, 1 - continue if (v0 == 0) { break; } else { v1 = 1; NewReadNextCommand(data, v1, out v0); //0 - move back 2, 1 - move forward 2 outOffset += 4; if (v0 == 0) { outOffset -= 8; } } } else if (v0 == 1) { outOffset -= 2; } else if (v0 == 3) { outOffset += 2; } outOffset += s0; //Move down a row ByteHelper.WriteUShort((ushort)s3, doubleByteOutput, doubleByteIndex + outOffset); //write_u16_be(out, s3); } while (true); } goto_AdvanceToNextPixel: //Advance the pointers one forward singleByteIndex += 1; doubleByteIndex += 2; } } writer.Close(); }
// 800405D0/0411D0 // a0[in]: pointer to TKMK00 data // a1[out]: pointer to output (1 byte per pixel) // a2[out]: pointer to output (RGBA16, 2 bytes per pixel) // a3[in]: RGBA color to set alpha to 0, values observed: 0x01, 0xBE public static void tkmk00decode(byte[] data, int tkmkOffset, out byte[] singleByteOutput, out byte[] doubleByteOutput, uint alphaFlagParam) { //TO DO: CLEAR THE BUFFERS BETWEEN DECODINGS uint offset; uint test_bits; int width, height; int col, row; int pixels; int alpha; uint i; ushort rgba0; ushort rgba1; byte red0, red1, green0, green1, blue0, blue1; width = ByteHelper.ReadUShort(data, tkmkOffset + 0x8);// read_u16_be(&tkmkOffset[0x8]); height = ByteHelper.ReadUShort(data, tkmkOffset + 0xA);//read_u16_be(&tkmkOffset[0xA]); alpha = (int)alphaFlagParam; channelCommandMode = data[tkmkOffset+0x6]; for (int iii = 0; iii < 0x8; iii++) //Convert the channel command mode to bools channelCommandRepeatMode[iii] = (((channelCommandMode >> iii) & 0x1) != 0); pixels = width * height; for(int iCount = 0; iCount < rgba_buf.Length; iCount++) rgba_buf[iCount] = 0xFF; doubleByteOutput = new byte[2 * pixels]; singleByteOutput = new byte[pixels]; int doubleByteIndex = 0; int singleByteIndex = 0; for (i = 0; i < 8; i++) { offset = ByteHelper.ReadUInt(data, tkmkOffset + 0xC + (int)i * 4); //read_u32_be(&tkmkOffset[0xC + i*4]); if (0 == (channelCommandMode & (0x1 << (int)i))) offset -= 4; else offset--; channelPtrs[i] = tkmkOffset + (int)offset; } Array.Clear(channelCommandRemainingBits, 0, channelCommandRemainingBits.Length); //masterCommandOffset = 0x0; // no idea, used in proc_80040A60 masterCommandBuffer = ByteHelper.ReadInt(data, tkmkOffset + 0x2C);// read_u32_be(&tkmkOffset[0x2C]); // used in proc_80040A60 masterCommandRemainingBits = 0x20; masterCommandPtr = tkmkOffset + 0x2C;//ByteHelper.ReadInt(data, tkmkOffset + 0x30);//&tkmkOffset[0x30]; uint val = 0x20; //SetUp5BitBuffers((uint)some_u32s.Length - 4, ref val, data); // recursive, init buffers??? //treeHead = new TKMKHuffmanTreeNode(); //treeHead.Value = 0x20; treeHead = NewNewSetUp5BitBuffers(val, data); // recursive, init buffers??? t1 = v0; t7 = 0; //the last used rgba color StreamWriter writer = new StreamWriter("process.txt"); for (row = 0; row != height; row++) { for (col = 0; col != width; col++) { t9 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex);// ????????? read_u16_be(doubleByteOutput); //read the existing color of the byte if (t9 == 0) { //Not set yet v1 = singleByteOutput[singleByteIndex]; } else { //Test to make sure that the curent color is not the alpha value with the incorrect alpha channel value s3 = t9 & 0xFFFE; //All the color but the alpha channel t7 = t9; if (alpha != s3) { writer.WriteLine("UseExistingPixel"); goto goto_AdvanceToNextPixel; } //if alpha IS s3, then write it out ByteHelper.WriteUShort((ushort)s3, doubleByteOutput, doubleByteIndex);// write_u16_be(doubleByteOutput, s3); t7 = s3; writer.WriteLine("RewriteAlphaPixel"); goto goto_AdvanceToNextPixel; } writer.Write("NewPixel-"); v1 += 1; NewGetNextChannelCommand(data, v1, out v0); //Determine here if we use the previous color or a different one if (v0 == 0) { //use last color here ByteHelper.WriteUShort((ushort)t7, doubleByteOutput, doubleByteIndex);//write_u16_be(doubleByteOutput, t7); writer.WriteLine("Previous color"); goto goto_AdvanceToNextPixel; } v1 = 1; NewReadNextCommand(data, v1, out v0); //Check for creating new or re-using old RGBA value if (v0 != 0) { //Create new rgba value writer.WriteLine("NewColor"); NewNewRetrieve5BitValue(data); //Read red component s0 = s4; //store red component into s0 NewNewRetrieve5BitValue(data); //Read green component s1 = s4; //store green component into s0 NewNewRetrieve5BitValue(data); //Read blue component and store into s0 rgba0 = 0; //pixel above this one rgba1 = 0; //pixel before this one if (row != 0) { rgba0 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - (width * 2));// read_u16_be(doubleByteOutput - (width * 2)); rgba1 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - 2);//read_u16_be(doubleByteOutput - 2); } else { if (col != 0) { rgba1 = ByteHelper.ReadUShort(doubleByteOutput, doubleByteIndex - 2);//read_u16_be(doubleByteOutput - 2); } } green0 = (byte)((rgba0 & 0x7C0) >> 6); green1 = (byte)((rgba1 & 0x7C0) >> 6); t8 = (green0 + green1) / 2; t9 = s0; //proc_80040C94(); //Get the red component ColorCombine(t8, ref t9); s0 = t9; v1 = t9 - t8; red0 = (byte)((rgba0 & 0xF800) >> 11); red1 = (byte)((rgba1 & 0xF800) >> 11); t8 = v1 + (red0 + red1) / 2; if (t8 >= 0x20) { t8 = 0x1F; } else if (t8 < 0) { t8 = 0; } t9 = s1; //proc_80040C94(); //Get the green component ColorCombine(t8, ref t9); s1 = t9; blue0 = (byte)((rgba0 & 0x3E) >> 1); blue1 = (byte)((rgba1 & 0x3E) >> 1); t8 = v1 + (blue0 + blue1) / 2; if (t8 >= 0x20) { t8 = 0x1F; } else if (t8 < 0) { t8 = 0; } t9 = s4; //proc_80040C94(); //Get the blue component ColorCombine(t8, ref t9); t7 = (s1 << 11) | (s0 << 6) | (t9 << 1); //Combine the color components into the ushort if (t7 != alpha) { t7 |= 0x1; } // insert new value by shifting others to right for (i = (uint)rgba_buf.Length - 1; i > 0; i--) { rgba_buf[i] = rgba_buf[i - 1]; } rgba_buf[0] = (ushort)t7; } else { //Use existing rgba value writer.WriteLine("ExistingColor"); v1 = 6; NewReadNextCommand(data, v1, out v0); //Read in the index of the rgba in the rgba buffer to use t7 = rgba_buf[v0]; if (v0 != 0) { for (i = (uint)v0; i > 0; i--) { rgba_buf[i] = rgba_buf[i - 1]; } rgba_buf[0] = (ushort)t7; } } //Write the RGBA to the doubleByteIndex location ByteHelper.WriteUShort((ushort)t7, doubleByteOutput, doubleByteIndex);//write_u16_be(doubleByteOutput, t7); test_bits = 0; //stores flags marking the existence of pixels around the current pixel if (col != 0) { test_bits |= 0x01; } if (col < (width - 1)) { test_bits |= 0x02; } if (col < (width - 2)) { test_bits |= 0x04; } if (row < (height - 1)) { test_bits |= 0x08; } if (row < (height - 2)) { test_bits |= 0x10; } if (0x2 == (test_bits & 0x2)) { //if a pixel exists to the right 1 singleByteOutput[singleByteIndex+1]++; } if (0x4 == (test_bits & 0x4)) { //if a pixel exists to the right 2 singleByteOutput[singleByteIndex+2]++; } if (0x9 == (test_bits & 0x9)) { //if a pixel exists below 1 and to the left 1 singleByteOutput[singleByteIndex+width - 1]++; } if (0x8 == (test_bits & 0x8)) { //if a pixel exists below 1 singleByteOutput[singleByteIndex+width]++; } if (0xA == (test_bits & 0xA)) { //if a pixel exists below 1 and right 1 singleByteOutput[singleByteIndex+width + 1]++; } if (0x10 == (test_bits & 0x10)) { //if a pixel exists 2 below this one singleByteOutput[singleByteIndex+2 * width]++; } v1 = 1; NewReadNextCommand(data, v1, out v0); //Check if we need to preload this color onto rows below this one if (v0 != 0) { int outOffset = 0; s0 = width * 2; //Length of a row in bytes s3 = t7 | 0x1; //Previous RGBA, with alpha forced on do { v1 = 2; NewReadNextCommand(data, v1, out v0); //0 - advanced move, 1 - back one, 2 - no lateral move, 3 - forward one if (v0 == 0) { v1 = 1; NewReadNextCommand(data, v1, out v0); //0 - stop advanced move, 1 - continue if (v0 == 0) { break; } else { v1 = 1; NewReadNextCommand(data, v1, out v0); //0 - move back 2, 1 - move forward 2 outOffset += 4; if (v0 == 0) { outOffset -= 8; } } } else if (v0 == 1) { outOffset -= 2; } else if (v0 == 3) { outOffset += 2; } outOffset += s0; //Move down a row ByteHelper.WriteUShort((ushort)s3, doubleByteOutput, doubleByteIndex + outOffset);//write_u16_be(out, s3); } while (true); } goto_AdvanceToNextPixel: //Advance the pointers one forward singleByteIndex += 1; doubleByteIndex += 2; } } writer.Close(); }