Advertisement
Guest User

Untitled

a guest
Sep 1st, 2014
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.97 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.IO;
  10. using System.Diagnostics;
  11.  
  12. namespace Pack
  13. {
  14.  
  15.     public partial class Form1 : Form
  16.     {
  17.         private void Form_DragEnter(object sender, DragEventArgs e)
  18.         {
  19.             if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
  20.         }
  21.         private void Form_DragDrop(object sender, DragEventArgs e)
  22.         {
  23.             string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  24.             string path = files[0]; // open first D&D
  25.             textBox1.Text = path;
  26.  
  27.             if (chk_auto.Checked)
  28.             {
  29.                 B_Go_Click(sender, (EventArgs)e);
  30.             }
  31.  
  32.         }
  33.         public Form1()
  34.         {
  35.             InitializeComponent();
  36.  
  37.             this.DragEnter += new DragEventHandler(Form_DragEnter);
  38.             this.DragDrop += new DragEventHandler(Form_DragDrop);
  39.             RTB.Clear();
  40.         }
  41.  
  42.         private void B_Open_Click(object sender, EventArgs e)
  43.         {
  44.             OpenFileDialog ofd = new OpenFileDialog();
  45.             if (ofd.ShowDialog() == DialogResult.OK)
  46.             {
  47.                 textBox1.Text = ofd.FileName;
  48.             }
  49.         }
  50.         private void B_Go_Click(object sender, EventArgs e)
  51.         {
  52.             if (textBox1.Text.Length < 1) return;
  53.  
  54.             // Fetch file extension (first 4 bytes) to check if it is a GARC
  55.             BinaryReader brz = new BinaryReader(System.IO.File.OpenRead(textBox1.Text));
  56.             try {
  57.                 string s = new string(Reverse(brz.ReadChars(4)));
  58.                 if (s != "GARC")
  59.                 {
  60.                     RTB.Text += "Input file is not a .GARC";
  61.                     return;
  62.                 }
  63.                 RTB.Text = s;
  64.             }
  65.             catch (EncoderFallbackException)
  66.             {
  67.                 RTB.Text += "Invalid File.";
  68.                 return;
  69.             }
  70.             brz.Close();
  71.  
  72.             // Unpack the GARC
  73.             GARC garc = ARC.Unpack(textBox1.Text);
  74.             RTB.Text += "\r\nCount: " + garc.otaf.nFiles;
  75.             ProgressInit(garc.otaf.nFiles);
  76.             if (garc.otaf.nFiles > 50)
  77.             {
  78.                 cNoprint.Checked = true;
  79.             }
  80.  
  81.             // Get file path infos for exporting
  82.             FileInfo fileInfo = new FileInfo(textBox1.Text);
  83.             string path = fileInfo.DirectoryName;
  84.             string parentName = fileInfo.Name;
  85.             string basepath = path + "\\" + parentName + "_";
  86.             BinaryReader br = new BinaryReader(System.IO.File.OpenRead(textBox1.Text));
  87.  
  88.             // Create Extraction folder if it does not exist.
  89.             if (!Directory.Exists(basepath))
  90.             {
  91.                 DirectoryInfo di = Directory.CreateDirectory(basepath);
  92.             }
  93.            
  94.             // Pull out all the files
  95.             for (int i = 0; i < garc.otaf.nFiles; i++)
  96.             {
  97.                 string ext = "bin";
  98.                 bool compressed = false;
  99.  
  100.                 string newext;
  101.                 br.BaseStream.Position = garc.btaf.entries[i].start_offset + garc.data_offset;
  102.                 try
  103.                 {
  104.                     newext = TrimFromZero(new string(br.ReadChars(4)));
  105.                     if ((System.Text.RegularExpressions.Regex.IsMatch(newext, @"^[a-zA-Z0-9]+$")) && (!chk_binonly.Checked))
  106.                         ext = newext;
  107.                     else
  108.                     {
  109.                         compressed = true;
  110.                     }
  111.                 }
  112.                 catch { newext = null; }
  113.                
  114.                 string fileout = basepath + "\\" + i + "." + ext;
  115.                 BinaryWriter bw = new BinaryWriter(File.OpenWrite(fileout));
  116.                
  117.                 br.BaseStream.Position = garc.btaf.entries[i].start_offset + garc.data_offset;
  118.                 for (int x = 0; x < (garc.btaf.entries[i].end_offset - garc.btaf.entries[i].start_offset); x++)
  119.                 {
  120.                     bw.Write(br.ReadByte());
  121.                 }
  122.                 bw.Flush();
  123.                 bw.Close();
  124.                 printout("\r\nWrote to " + fileout);
  125.                 if (compressed)
  126.                 {
  127.                    
  128.                     string decout = path + "\\" + parentName + "_\\" + "dec_" + i;
  129.                     string result = LZSS.Decompress11LZS(fileout, decout);
  130.  
  131.                     if (result != null)
  132.                     {
  133.                         printout("\r\n" + result);
  134.                         if (delAfterD.Checked)
  135.                         {
  136.                             try { File.Delete(fileout); }
  137.                             catch { }
  138.                         }
  139.                     }
  140.                 }
  141.                 pBar1.PerformStep();
  142.             }
  143.             br.Close();
  144.  
  145.             RTB.Text += "\r\nDone!";
  146.             RTB.Select(RTB.Text.Length - 1, 0);
  147.             RTB.ScrollToCaret();
  148.         }
  149.  
  150.         private void printout(string str)
  151.         {
  152.             if (cNoprint.Checked)
  153.                 return;
  154.             RTB.Text += str;
  155.             RTB.Select(RTB.Text.Length - 1, 0);
  156.             RTB.ScrollToCaret();
  157.         }
  158.         public string TrimFromZero(string input)
  159.         {
  160.             int index = input.IndexOf('\0');
  161.             if (index != input.Length - 1)
  162.                 return input;
  163.  
  164.             return input.Substring(0, index);
  165.         }
  166.         public static uint Reverse(uint x)
  167.         {
  168.             uint y = 0;
  169.             for (int i = 0; i < 32; ++i)
  170.             {
  171.                 y <<= 1;
  172.                 y |= (x & 1);
  173.                 x >>= 1;
  174.             }
  175.             return y;
  176.         }
  177.         public static char[] Reverse(char[] charArray)
  178.         {
  179.             Array.Reverse(charArray);
  180.             return charArray;
  181.         }
  182.         private void clearTextbox(object sender, EventArgs e)
  183.         {
  184.             RTB.Clear();
  185.         }
  186.         private void ProgressInit(int count)
  187.         {
  188.             // Display the ProgressBar control.
  189.             pBar1.Visible = true;
  190.             pBar1.Minimum = 1;
  191.             pBar1.Maximum = count;
  192.             pBar1.Step = 1;
  193.             pBar1.Value = 1;
  194.         }
  195.     }
  196.     // Class code based off of
  197.     // https://code.google.com/p/tinke/source/browse/trunk/Plugins/Pack/Pack/NARC.cs
  198.     // by pleonex / benito356
  199.     #region garc destructuring
  200.     public class  ARC
  201.     {
  202.         public static uint Reverse(uint x)
  203.         {
  204.             uint y = 0;
  205.             for (int i = 0; i < 32; ++i)
  206.             {
  207.                 y <<= 1;
  208.                 y |= (x & 1);
  209.                 x >>= 1;
  210.             }
  211.             return y;
  212.         }
  213.         public static char[] Reverse(char[] charArray)
  214.         {
  215.             Array.Reverse(charArray);
  216.             return charArray;
  217.         }
  218.         public static GARC Unpack(string path)
  219.         {
  220.             GARC garc = new GARC();
  221.             BinaryReader br = new BinaryReader(System.IO.File.OpenRead(path));
  222.  
  223.             // GARC Header
  224.             garc.id = br.ReadChars(4);
  225.             garc.header_size = br.ReadUInt32();
  226.             garc.id_endian = br.ReadUInt16();
  227.             if (garc.id_endian == 0xFEFF)
  228.                 Reverse(garc.id);
  229.             garc.constant = br.ReadUInt16();
  230.             garc.file_size = br.ReadUInt32();
  231.  
  232.             garc.data_offset = br.ReadUInt32();
  233.             garc.file_length = br.ReadUInt32();
  234.             //garc.lastsize = br.ReadUInt32();
  235.  
  236.             // OTAF
  237.             garc.otaf.id = br.ReadChars(4);
  238.             garc.otaf.section_size = br.ReadUInt32();
  239.             garc.otaf.nFiles = br.ReadUInt16();
  240.             garc.otaf.padding = br.ReadUInt16();
  241.  
  242.             garc.otaf.entries = new OTAF_Entry[garc.otaf.nFiles];
  243.             // not really needed; plus it's wrong
  244.             for (int i = 0; i < garc.otaf.nFiles; i++)
  245.             {
  246.                 uint val = br.ReadUInt32();
  247.                 if (garc.otaf.padding == 0xffff)
  248.                 {
  249.                     val = Reverse(val);
  250.                 }
  251.                 garc.otaf.entries[i].name = val.ToString();
  252.             }
  253.  
  254.             // BTAF (File Allocation TaBle)
  255.             garc.btaf.id = br.ReadChars(4);
  256.             garc.btaf.section_size = br.ReadUInt32();
  257.             garc.btaf.nFiles = br.ReadUInt32();
  258.  
  259.             garc.btaf.entries = new BTAF_Entry[garc.btaf.nFiles];
  260.             for (int i = 0; i < garc.btaf.nFiles; i++)
  261.             {
  262.                 garc.btaf.entries[i].bits = br.ReadUInt32();
  263.                 garc.btaf.entries[i].start_offset = br.ReadUInt32();
  264.                 garc.btaf.entries[i].end_offset = br.ReadUInt32();
  265.                 //garc.btaf.entries[i].length = br.ReadUInt32();
  266.             }
  267.  
  268.             // BMIF
  269.             garc.gmif.id = br.ReadChars(4);
  270.             garc.gmif.section_size = br.ReadUInt32();
  271.             garc.gmif.data_size = br.ReadUInt32();
  272.  
  273.             // Files data
  274.  
  275.             br.Close();
  276.             return garc;
  277.         }
  278.     }
  279.     public struct GARC
  280.     {
  281.         public char[] id;           // Always GARC = 0x4E415243
  282.         public UInt32 header_size;  // Always 0x001C
  283.         public UInt16 id_endian;    // 0xFFFE
  284.         public UInt16 constant;     // Always 0x0400 chunk count
  285.         public UInt32 file_size;
  286.  
  287.         public UInt32 data_offset;
  288.         public UInt32 file_length;
  289.         public UInt32 lastsize;
  290.  
  291.         public OTAF otaf;
  292.         public BTAF btaf;
  293.         public GMIF gmif;
  294.     }
  295.     public struct OTAF
  296.     {
  297.         public char[] id;
  298.         public UInt32 section_size;
  299.         public UInt16 nFiles;
  300.         public UInt16 padding;
  301.  
  302.         public OTAF_Entry[] entries;
  303.     }
  304.     public struct OTAF_Entry
  305.     {
  306.         public string name;
  307.     }
  308.     public struct BTAF
  309.     {
  310.         public char[] id;
  311.         public UInt32 section_size;
  312.         public UInt32 nFiles;
  313.         public BTAF_Entry[] entries;
  314.     }
  315.     public struct BTAF_Entry
  316.     {
  317.         public UInt32 bits;
  318.         public UInt32 start_offset;
  319.         public UInt32 end_offset;
  320.         public UInt32 length;
  321.     }
  322.     public struct GMIF
  323.     {
  324.         public char[] id;
  325.         public UInt32 section_size;
  326.         public UInt32 data_size;
  327.     }
  328.     #endregion
  329.  
  330.     // Tinke LZSS Code (now slightly altered)
  331.     // https://code.google.com/p/tinke/source/browse/trunk/Plugins/Compresiones/Compresiones/LZSS.cs
  332.     // by pleonex / benito356
  333.     public static class LZSS
  334.     {
  335.         static int MAX_OUTSIZE = 0x1E00000;
  336.         const int N = 4096, F = 18;
  337.         const byte THRESHOLD = 2;
  338.         const int NIL = N;
  339.         static bool showAlways = true;
  340.  
  341.         const int LZ77_TAG = 0x10, LZSS_TAG = 0x11, RLE_TAG = 0x30, HUFF_TAG = 0x20, NONE_TAG = 0x00;
  342.  
  343.         #region tag 0x11 LZSS
  344.         public static string Decompress11LZS(string filein, string fileout)
  345.         {
  346.             /*  Data header (32bit)
  347.                   Bit 0-3   Reserved
  348.                   Bit 4-7   Compressed type (must be 1 for LZ77)
  349.                   Bit 8-31  Size of decompressed data. if 0, the next 4 bytes are decompressed length
  350.                 Repeat below. Each Flag Byte followed by eight Blocks.
  351.                 Flag data (8bit)
  352.                   Bit 0-7   Type Flags for next 8 Blocks, MSB first
  353.                 Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
  354.                   Bit 0-7   One data byte to be copied to dest
  355.                 Block Type 1 - Compressed - Copy LEN Bytes from Dest-Disp-1 to Dest
  356.                     If Reserved is 0: - Default
  357.                       Bit 0-3   Disp MSBs
  358.                       Bit 4-7   LEN - 3
  359.                       Bit 8-15  Disp LSBs
  360.                     If Reserved is 1: - Higher compression rates for files with (lots of) long repetitions
  361.                       Bit 4-7   Indicator
  362.                         If Indicator > 1:
  363.                             Bit 0-3    Disp MSBs
  364.                             Bit 4-7    LEN - 1 (same bits as Indicator)
  365.                             Bit 8-15   Disp LSBs
  366.                         If Indicator is 1:
  367.                             Bit 0-3 and 8-19   LEN - 0x111
  368.                             Bit 20-31          Disp
  369.                         If Indicator is 0:
  370.                             Bit 0-3 and 8-11   LEN - 0x11
  371.                             Bit 12-23          Disp
  372.                      
  373.              */
  374.             FileStream fstr = new FileStream(filein, FileMode.Open);
  375.             if (fstr.Length > int.MaxValue)
  376.                 return "Filer larger than 2GB cannot be LZSS-compressed files.";
  377.             BinaryReader br = new BinaryReader(fstr);
  378.  
  379.             int decomp_size = 0, curr_size = 0;
  380.             int i, j, disp, len;
  381.             bool flag;
  382.             byte b1, bt, b2, b3, flags;
  383.             int cdest;
  384.  
  385.             int threshold = 1;
  386.  
  387.             if (br.ReadByte() != LZSS_TAG)
  388.             {
  389.                 br.BaseStream.Seek(0x4, SeekOrigin.Begin);
  390.                 if (br.ReadByte() != LZSS_TAG)
  391.                     return null;
  392.                         // String.Format("File {0:s} is not a valid LZSS-11 file", filein);
  393.             }
  394.             for (i = 0; i < 3; i++)
  395.                 decomp_size += br.ReadByte() << (i * 8);
  396.             if (decomp_size > MAX_OUTSIZE)
  397.             {
  398.                 br.Close();
  399.                 return String.Format("{0:s} will be larger than 0x{1:x} (0x{2:x}) and will not be decompressed.", filein, MAX_OUTSIZE, decomp_size);
  400.             }
  401.             else if (decomp_size == 0)
  402.                 for (i = 0; i < 4; i++)
  403.                     decomp_size += br.ReadByte() << (i * 8);
  404.             /*if (decomp_size > MAX_OUTSIZE << 8)
  405.             {
  406.                 br.Close();
  407.                 return String.Format("{0:s} will be larger than 0x{1:x} (0x{2:x}) and will not be decompressed.", filein, MAX_OUTSIZE, decomp_size);
  408.             }*/
  409.  
  410.             if (showAlways)
  411.                 Console.WriteLine("Decompressing {0:s}. (outsize: 0x{1:x})", filein, decomp_size);
  412.  
  413.             byte[] outdata = new byte[decomp_size];
  414.  
  415.             while (curr_size < decomp_size)
  416.             {
  417.                 try { flags = br.ReadByte(); }
  418.                 catch (EndOfStreamException) { break; }
  419.  
  420.                 for (i = 0; i < 8 && curr_size < decomp_size; i++)
  421.                 {
  422.                     flag = (flags & (0x80 >> i)) > 0;
  423.                     if (flag)
  424.                     {
  425.                         try { b1 = br.ReadByte(); }
  426.                         catch (EndOfStreamException) { br.Close(); return "Incomplete data 1"; }
  427.  
  428.                         switch (b1 >> 4)
  429.                         {
  430.                             #region case 0
  431.                             case 0:
  432.                                 // ab cd ef
  433.                                 // =>
  434.                                 // len = abc + 0x11 = bc + 0x11
  435.                                 // disp = def
  436.  
  437.                                 len = b1 << 4;
  438.                                 try { bt = br.ReadByte(); }
  439.                                 catch (EndOfStreamException) { br.Close(); return "Incomplete data 2"; }
  440.                                 len |= bt >> 4;
  441.                                 len += 0x11;
  442.  
  443.                                 disp = (bt & 0x0F) << 8;
  444.                                 try { b2 = br.ReadByte(); }
  445.                                 catch (EndOfStreamException) { br.Close(); return "Incomplete data 3"; }
  446.                                 disp |= b2;
  447.                                 break;
  448.                             #endregion
  449.  
  450.                             #region case 1
  451.                             case 1:
  452.                                 // ab cd ef gh
  453.                                 // =>
  454.                                 // len = bcde + 0x111
  455.                                 // disp = fgh
  456.                                 // 10 04 92 3F => disp = 0x23F, len = 0x149 + 0x11 = 0x15A
  457.  
  458.                                 try { bt = br.ReadByte(); b2 = br.ReadByte(); b3 = br.ReadByte(); }
  459.                                 catch (EndOfStreamException) { br.Close(); return "Incomplete data 4"; }
  460.  
  461.                                 len = (b1 & 0xF) << 12; // len = b000
  462.                                 len |= bt << 4; // len = bcd0
  463.                                 len |= (b2 >> 4); // len = bcde
  464.                                 len += 0x111; // len = bcde + 0x111
  465.                                 disp = (b2 & 0x0F) << 8; // disp = f
  466.                                 disp |= b3; // disp = fgh
  467.                                 break;
  468.                             #endregion
  469.  
  470.                             #region other
  471.                             default:
  472.                                 // ab cd
  473.                                 // =>
  474.                                 // len = a + threshold = a + 1
  475.                                 // disp = bcd
  476.  
  477.                                 len = (b1 >> 4) + threshold;
  478.  
  479.                                 disp = (b1 & 0x0F) << 8;
  480.                                 try { b2 = br.ReadByte(); }
  481.                                 catch (EndOfStreamException) { br.Close(); return "Incomplete data 5"; }
  482.                                 disp |= b2;
  483.                                 break;
  484.                             #endregion
  485.                         }
  486.  
  487.                         if (disp > curr_size)
  488.                         {
  489.                             br.Close();
  490.                             return "Cannot go back more than already written";
  491.                         }
  492.  
  493.                         cdest = curr_size;
  494.  
  495.                         for (j = 0; j < len && curr_size < decomp_size; j++)
  496.                             outdata[curr_size++] = outdata[cdest - disp - 1 + j];
  497.  
  498.                         if (curr_size > decomp_size)
  499.                         {
  500.                             br.Close();
  501.                             return String.Format("File {0:s} is not a valid LZ77 file; actual output size > output size in header", filein);
  502.                             //Console.WriteLine(String.Format("File {0:s} is not a valid LZ77 file; actual output size > output size in header; {1:x} > {2:x}.", filein, curr_size, decomp_size));
  503.                             // break;
  504.                         }
  505.                     }
  506.                     else
  507.                     {
  508.                         try { outdata[curr_size++] = br.ReadByte(); }
  509.                         catch (EndOfStreamException) { break; }// throw new Exception("Incomplete data"); }
  510.  
  511.                         if (curr_size > decomp_size)
  512.                         {
  513.                             br.Close();
  514.                             return String.Format("File {0:s} is not a valid LZ77 file; actual output size > output size in header", filein);
  515.                             //Console.WriteLine(String.Format("File {0:s} is not a valid LZ77 file; actual output size > output size in header; {1:x} > {2:x}", filein, curr_size, decomp_size));
  516.                             // break;
  517.                         }
  518.                     }
  519.                 }
  520.  
  521.             }
  522.  
  523.             try
  524.             {
  525.                 while (br.ReadByte() == 0) { } // if we read a non-zero, print that there is still some data
  526.                 Console.WriteLine("Too much data in file; current INPOS = {0:x}", br.BaseStream.Position - 1);
  527.             }
  528.             catch (EndOfStreamException) { }
  529.             string newext = "bin";
  530.             if (outdata.Length > 4)
  531.             {
  532.                 newext = "";
  533.                 for (int c = 0; c < 4; c++)
  534.                 {
  535.                     newext += (char)outdata[c];
  536.                 }
  537.                 newext = TrimFromZero(newext);
  538.                 if (!(System.Text.RegularExpressions.Regex.IsMatch(newext, @"^[a-zA-Z0-9]+$")))
  539.                     newext = "bin";
  540.             }
  541.             else { newext = "bin"; }
  542.             string fn;
  543.             try
  544.             {
  545.                 fn = fileout + "." + newext;
  546.                 BinaryWriter bw = new BinaryWriter(new FileStream(fn, FileMode.Create));
  547.                 bw.Write(outdata);
  548.                 bw.Flush();
  549.                 bw.Close();
  550.             }
  551.             catch
  552.             {
  553.                 fn = fileout + ".bin";
  554.                 BinaryWriter bw = new BinaryWriter(new FileStream(fn, FileMode.Create));
  555.                 bw.Write(outdata);
  556.                 bw.Flush();
  557.                 bw.Close();
  558.             }
  559.  
  560.             br.Close();
  561.             fstr.Close();
  562.             fstr.Dispose();
  563.             Console.WriteLine("LZSS-11 Decompressed " + filein);
  564.             return String.Format("Decompressed to {0:s}", fn);
  565.         }
  566.  
  567.  
  568.         #endregion
  569.         public static string TrimFromZero(string input)
  570.         {
  571.             int index = input.IndexOf('\0');
  572.             if (index != input.Length - 1)
  573.                 return input;
  574.  
  575.             return input.Substring(0, index);
  576.         }
  577.     }
  578. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement