Advertisement
Guest User

Untitled

a guest
Apr 5th, 2020
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.61 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Globalization;
  11. using System.Diagnostics;
  12.  
  13. namespace ExtractQrc
  14. {
  15.     public partial class FormMain : Form
  16.     {
  17.         int _version;
  18.         long _treeOffset, _nameOffset, _dataOffset;
  19.  
  20.         public FormMain()
  21.         {
  22.             InitializeComponent();
  23.         }
  24.  
  25.         private void ButtonSelectFile_Click(object sender, EventArgs e)
  26.         {
  27.             if (string.IsNullOrEmpty(textBoxTree.Text) || string.IsNullOrEmpty(textBoxName.Text) || string.IsNullOrEmpty(textBoxData.Text))
  28.             {
  29.                 MessageBox.Show("Ben faut mettre des trucs dans les cases :o");
  30.                 return;
  31.             }
  32.  
  33.             if (!long.TryParse(textBoxTree.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _treeOffset))
  34.             {
  35.                 MessageBox.Show("Pas un nombre le tree offset ...");
  36.                 return;
  37.             }
  38.  
  39.             if (!long.TryParse(textBoxName.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _nameOffset))
  40.             {
  41.                 MessageBox.Show("Pas un nombre le name offset ...");
  42.                 return;
  43.             }
  44.  
  45.             if (!long.TryParse(textBoxData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _dataOffset))
  46.             {
  47.                 MessageBox.Show("Pas un nombre le data offset ...");
  48.                 return;
  49.             }
  50.  
  51.             _version = (int)numericUpDownVersion.Value;
  52.  
  53.             OpenFileDialog ofd = new OpenFileDialog();
  54.             if (ofd.ShowDialog(this) != DialogResult.OK)
  55.                 return;
  56.  
  57.             try
  58.             {
  59.                 using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
  60.                 {
  61.                     ExtractQrc(fs);
  62.                 }
  63.             }
  64.             catch (Exception ex)
  65.             {
  66.                 MessageBox.Show("Erreur : " + ex.Message);
  67.             }
  68.         }
  69.  
  70.         enum Flags
  71.         {
  72.             // must match rcc.h
  73.             Compressed = 0x01,
  74.             Directory = 0x02,
  75.             CompressedZstd = 0x04
  76.         };
  77.  
  78.         private void ExtractQrc(FileStream fs)
  79.         {
  80.             fs.Seek(_treeOffset, SeekOrigin.Begin);
  81.  
  82.             string currentPath = string.Empty;
  83.  
  84.             int nameOff = ReadInt32BE(fs);
  85.             short flags = ReadInt16BE(fs);
  86.  
  87.             if ((flags & (short)Flags.Directory) > 0)
  88.             {
  89.                 //currentPath += GetName(fs, nameOff) + Path.DirectorySeparatorChar;
  90.                 //Directory.CreateDirectory(currentPath);
  91.  
  92.                 int child_count = ReadInt32BE(fs);
  93.                 int child_node = ReadInt32BE(fs);
  94.  
  95.                 Trace.WriteLine("Path: \"root\" Child count: " + child_count + " Child node: " + child_node);
  96.  
  97.                 ExtractNode(fs, currentPath, child_node, 1);
  98.             }
  99.             else
  100.             {
  101.                 MessageBox.Show("o.O le root node n'est pas un fichier, j'y crois pas une seconde");
  102.             }
  103.         }
  104.  
  105.         private void ExtractNode(FileStream fs, string currentPath, int node, int count)
  106.         {
  107.             Trace.WriteLine("ExtractNode > " + node);
  108.  
  109.             for (int i = node; i < node + count; ++i)
  110.             {
  111.                 fs.Seek(_treeOffset + i * (14 + (_version >= 0x02 ? 8 : 0)), SeekOrigin.Begin);
  112.  
  113.                 int nameOff = ReadInt32BE(fs);
  114.                 short flags = ReadInt16BE(fs);
  115.  
  116.                 if ((flags & (short)Flags.Directory) > 0)
  117.                 {
  118.                     string segment = GetName(fs, nameOff);
  119.                     string newPath = currentPath + segment + Path.DirectorySeparatorChar;
  120.                     Directory.CreateDirectory(newPath);
  121.  
  122.                     int child_count = ReadInt32BE(fs);
  123.                     int child_node = ReadInt32BE(fs);
  124.  
  125.                     uint hash = qt_hash(segment);
  126.  
  127.                     Trace.WriteLine("Dir Path: \"" + newPath + "\" Current node : " + i + " Child count: " + child_count + " Child node: " + child_node + " hash : 0x" + hash.ToString("X8"));
  128.  
  129.                     long pos = fs.Position;
  130.                     ExtractNode(fs, newPath, child_node, child_count);
  131.                     fs.Seek(pos, SeekOrigin.Begin);
  132.                 }
  133.                 else
  134.                 {
  135.                     short country = ReadInt16BE(fs);
  136.                     short language = ReadInt16BE(fs);
  137.  
  138.                     string filename = GetName(fs, nameOff);
  139.  
  140.                     Trace.WriteLine("File Path: \"" + currentPath + "\" Current node : " + i + " Filename : " + filename);
  141.                 }
  142.             }
  143.  
  144.             Trace.WriteLine("< ExtractNode");
  145.         }
  146.  
  147.         private string GetName(FileStream fs, long offset)
  148.         {
  149.             long pos = fs.Position;
  150.             fs.Seek(_nameOffset + offset, SeekOrigin.Begin);
  151.  
  152.             ushort len = ReadUInt16BE(fs);
  153.             fs.Position += 4; //jump past hash
  154.  
  155.             byte[] bname = new byte[len * 2];
  156.             fs.Read(bname, 0, len * 2);
  157.             string sname = Encoding.BigEndianUnicode.GetString(bname);
  158.  
  159.             fs.Seek(pos, SeekOrigin.Begin);
  160.             return sname;
  161.         }
  162.  
  163.         private static uint qt_hash(string key, uint chained = 0)
  164.         {
  165.             int n = key.Length;
  166.             uint h = chained;
  167.  
  168.             for (int i = 0; i < n; i++)
  169.             {
  170.                 h = (h << 4) + key[i];
  171.                 h ^= (h & 0xf0000000) >> 23;
  172.                 h &= 0x0fffffff;
  173.             }
  174.             return h;
  175.         }
  176.  
  177.         private static int ReadInt32BE(FileStream fs)
  178.         {
  179.             byte[] buffer = new byte[4];
  180.             fs.Read(buffer, 0, 4);
  181.  
  182.             if (BitConverter.IsLittleEndian)
  183.                 Array.Reverse(buffer);
  184.  
  185.             return BitConverter.ToInt32(buffer, 0);
  186.         }
  187.  
  188.         private static short ReadInt16BE(FileStream fs)
  189.         {
  190.             byte[] buffer = new byte[2];
  191.             fs.Read(buffer, 0, 2);
  192.  
  193.             if (BitConverter.IsLittleEndian)
  194.                 Array.Reverse(buffer);
  195.  
  196.             return BitConverter.ToInt16(buffer, 0);
  197.         }
  198.  
  199.         private static ushort ReadUInt16BE(FileStream fs)
  200.         {
  201.             byte[] buffer = new byte[2];
  202.             fs.Read(buffer, 0, 2);
  203.  
  204.             if (BitConverter.IsLittleEndian)
  205.                 Array.Reverse(buffer);
  206.  
  207.             return BitConverter.ToUInt16(buffer, 0);
  208.         }
  209.     }
  210. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement