Beispiel #1
0
 public void RunTextureJob(Mod.ModJob mj)
 {
     DbgPrint("Running Texture Replacement Job for: " + mj.respath);
     //Check Toc Files
     List<string> reducedTocPaths = new List<string>();
     bool found = false;
     foreach (string p in mj.tocPaths)
     {
         found = false;
         for (int i = 0; i < reducedTocPaths.Count; i++)
             if (p == reducedTocPaths[i])
             {
                 found = true;
                 break;
             }
         if (!found)
             reducedTocPaths.Add(p);
     }
     mj.tocPaths = reducedTocPaths;
     List<string> reducedBundlePaths = new List<string>();
     foreach (string p in mj.bundlePaths)
     {
         found = false;
         for (int i = 0; i < reducedBundlePaths.Count; i++)
             if (p == reducedBundlePaths[i])
             {
                 found = true;
                 break;
             }
         if (!found)
             reducedBundlePaths.Add(p);
     }
     mj.bundlePaths = reducedBundlePaths;
     foreach (string tocpath in mj.tocPaths)
     {
         if (tocpath.ToLower().Contains("\\patch\\"))
             continue;
         DbgPrint("Checking for : " + tocpath);
         if (!tocpath.ToLower().StartsWith("update"))
         {
             if (!File.Exists(outputPath + tocpath))
             {
                 string from = GlobalStuff.FindSetting("gamepath") + tocpath;
                 string to = outputPath + tocpath;
                 Directory.CreateDirectory(Path.GetDirectoryName(to) + "\\");
                 DbgPrint("TOC file not found, copying from base!");
                 try
                 {
                     File.Copy(from, to);
                 }
                 catch (Exception)
                 {
                     DbgPrint("Error: TOC file not found, can not copy from base!\n Tried to copy from:\n\t" + from + "\n to:\n\t" + to);
                     return;
                 }
                 from = GlobalStuff.FindSetting("gamepath") + tocpath.ToLower().Replace(".toc",".sb");
                 to = outputPath + tocpath.ToLower().Replace(".toc", ".sb");
                 Directory.CreateDirectory(Path.GetDirectoryName(to) + "\\");
                 try
                 {
                     File.Copy(from, to);
                 }
                 catch (Exception)
                 {
                     DbgPrint("Error: SB file not found, can not copy from base!\n Tried to copy from:\n\t" + from + "\n to:\n\t" + to);
                     return;
                 }
                 DbgPrint("Fixing layout.toc...");
                 TOCFile toc = new TOCFile(outputPath + "Data\\layout.toc");
                 BJSON.Entry root = toc.lines[0];
                 BJSON.Field sbun = root.FindField("superBundles");
                 List<BJSON.Entry> list = (List<BJSON.Entry>)sbun.data;
                 BJSON.Entry ne = new BJSON.Entry();
                 ne.type = 0x82;
                 ne.fields = new List<BJSON.Field>();
                 ne.fields.Add(new BJSON.Field(7, "name", tocpath.Replace(".toc", "")));
                 ne.fields.Add(new BJSON.Field(6, "delta", true));
                 list.Add(ne);
                 sbun.data = list;
                 toc.Save();
                 DbgPrint("SuperBundle added");
             }
         }
         else
         {
             if (!File.Exists(outputPath + Helpers.SkipSubFolder(tocpath, 2)))
             {
                 string from = GlobalStuff.FindSetting("gamepath") + tocpath;
                 string to = outputPath + Helpers.SkipSubFolder(tocpath, 2);
                 Directory.CreateDirectory(Path.GetDirectoryName(to) + "\\");
                 DbgPrint("TOC file not found, copying from base!");
                 try
                 {
                     File.Copy(from, to);
                 }
                 catch (Exception)
                 {
                     DbgPrint("Error: TOC file not found, can not copy from base!\n Tried to copy from:\n\t" + from + "\n to:\n\t" + to);
                     return;
                 }
                 from = GlobalStuff.FindSetting("gamepath") + tocpath.ToLower().Replace(".toc", ".sb");
                 to = outputPath + Helpers.SkipSubFolder(tocpath, 2).ToLower().Replace(".toc", ".sb");
                 Directory.CreateDirectory(Path.GetDirectoryName(to) + "\\");
                 try
                 {
                     File.Copy(from, to);
                 }
                 catch (Exception)
                 {
                     DbgPrint("Error: SB file not found, can not copy from base!\n Tried to copy from:\n\t" + from + "\n to:\n\t" + to);
                     return;
                 }
                 DbgPrint("Fixing layout.toc...");
                 TOCFile toc = new TOCFile(outputPath + "Data\\layout.toc");
                 BJSON.Entry root = toc.lines[0];
                 BJSON.Field sbun = root.FindField("superBundles");
                 List<BJSON.Entry> list = (List<BJSON.Entry>)sbun.data;
                 BJSON.Entry ne = new BJSON.Entry();
                 ne.type = 0x82;
                 ne.fields = new List<BJSON.Field>();
                 ne.fields.Add(new BJSON.Field(7, "name", Helpers.SkipSubFolder(tocpath, 2).Replace(".toc", "")));
                 ne.fields.Add(new BJSON.Field(6, "delta", true));
                 list.Add(ne);
                 sbun.data = list;
                 toc.Save();
                 DbgPrint("SuperBundle added");
             }
         }
     }
     DbgPrint("All found.");
     //create cas data
     int newcompressedsize = 0;
     byte[] newsha1 = CreateCASContainer(mj.data, out newcompressedsize);
     if (newsha1.Length != 0x14)
     {
         DbgPrint("Error: could not create CAS data, aborting!");
         return;
     }
     //walk through affected toc files
     foreach (string tocpath in mj.tocPaths)
         RunTextureResJob(mj, tocpath, newsha1, newcompressedsize);
 }
Beispiel #2
0
 public bool ImportBundleFromBase(TOCFile toc, string tocpath, int index, string bpath)
 {
     DbgPrint("  Its a base reference! Copying in from base...");
     //Find base toc
     string basepath = GlobalStuff.FindSetting("gamepath");
     if (!File.Exists(basepath + tocpath))
     {
         DbgPrint("Error: base TOC file not found, skipping!");
         return false;
     }
     TOCFile otoc = new TOCFile(basepath + tocpath);
     //get base bundle data
     byte[] buff = otoc.ExportBundleDataByPath(bpath);
     if (buff.Length == 0)
     {
         DbgPrint("Error: base bundle not found, skipping!");
         return false;
     }
     //get old sb file
     string oldSBpath = outputPath + Path.GetDirectoryName(tocpath) + "\\" + Path.GetFileNameWithoutExtension(tocpath) + ".sb";
     if (!File.Exists(oldSBpath))
     {
         DbgPrint("Error: patch SB file not found, skipping!");
         return false;
     }
     DbgPrint("  Got copy, recompiling...");
     //recompiling new sb in memory
     MemoryStream newSB = new MemoryStream();
     FileStream oldSB = new FileStream(oldSBpath, FileMode.Open, FileAccess.Read);
     long glob_off = 0;
     BJSON.Entry root = toc.lines[0];
     BJSON.Field bundles = root.fields[0];
     int count = ((List<BJSON.Entry>)bundles.data).Count();
     DbgPrint("  Recompiling SB...");
     //put one bundle after another that is not base as defined in toc
     for (int i = 0; i < count; i++)
     {
         //get entry infos
         BJSON.Entry b = ((List<BJSON.Entry>)bundles.data)[i];
         BJSON.Field f_offset = b.FindField("offset");
         BJSON.Field f_size = b.FindField("size");
         BJSON.Field f_isBase = b.FindField("base");
         //if not our target and not copied from base, copy from old SB
         if (i != index && f_isBase == null)
         {
             int size = BitConverter.ToInt32((byte[])f_size.data, 0);
             CopyFileStream(oldSB, newSB, BitConverter.ToInt64((byte[])f_offset.data, 0), size);
             f_offset.data = BitConverter.GetBytes(glob_off);
             glob_off += size;
         }
         //if target, replace data, make delta
         if (i == index)
         {
             f_offset.data = BitConverter.GetBytes(glob_off);
             f_size.data = BitConverter.GetBytes(buff.Length);
             f_isBase.fieldname = "delta";
             newSB.Write(buff, 0, buff.Length);
             glob_off += buff.Length;
         }
     }
     oldSB.Close();
     //rebuilding new SB
     oldSB = new FileStream(oldSBpath, FileMode.Create, FileAccess.Write);
     //creating bundle header field
     MemoryStream t = new MemoryStream();
     Helpers.WriteLEB128(t, (int)newSB.Length);
     newSB.WriteByte(0);
     int varsize = (int)t.Length;
     //add root entry
     oldSB.WriteByte(0x82);
     Helpers.WriteLEB128(oldSB, varsize + 9 + (int)newSB.Length);
     byte[] buff2 = { 0x01, 0x62, 0x75, 0x6E, 0x64, 0x6C, 0x65, 0x73, 0x00 };
     oldSB.Write(buff2, 0, 9);
     oldSB.Write(t.ToArray(), 0, varsize);
     //header done, grab header offset and put all bundles
     int rel_off = (int)oldSB.Position;
     oldSB.Write(newSB.ToArray(), 0, (int)newSB.Length);
     oldSB.Close();
     //removing idata
     DbgPrint("  removing idata...");
     SBFile sb = new SBFile(oldSBpath);
     BJSON.Entry newroot = sb.lines[0];
     BJSON.Field newbundles = newroot.FindField("bundles");
     List<BJSON.Entry> newbun_list = (List<BJSON.Entry>)newbundles.data;
     for (int i = 0; i < newbun_list.Count; i++)
     {
         BJSON.Field f_res = newbun_list[i].FindField("res");
         List<BJSON.Entry> newres_list = (List<BJSON.Entry>)f_res.data;
         for (int j = 0; j < newres_list.Count; j++)
             newres_list[j].RemoveField("idata");
     }
     sb.Save();
     DbgPrint("  Recompiling TOC...");
     //correct offsets in toc by new adding header offset
     count = ((List<BJSON.Entry>)bundles.data).Count();
     for (int i = 0; i < count; i++)
     {
         BJSON.Entry b = ((List<BJSON.Entry>)bundles.data)[i];
         BJSON.Field f_offset = b.FindField("offset");
         BJSON.Field f_isBase = b.FindField("base");
         //if is in sb file, update
         if (f_isBase == null)
         {
             long off = BitConverter.ToInt64((byte[])f_offset.data, 0);
             off += rel_off;
             f_offset.data = BitConverter.GetBytes(off);
         }
     }
     toc.Save();
     DbgPrint("  Bundle imported");
     return true;
 }
Beispiel #3
0
 public bool ImportBundleBinaryFromBase(TOCFile toc, string tocpath, string bpath, bool isbase = true)
 {
     if(isbase)
         DbgPrint("  Its a base reference! Copying in from base...");
     //Find base toc
     string basepath = GlobalStuff.FindSetting("gamepath");
     if (!File.Exists(basepath + tocpath))
     {
         DbgPrint("Error: base TOC file not found, skipping!");
         return false;
     }
     TOCFile otoc = new TOCFile(basepath + tocpath);
     //get base bundle data
     byte[] buff = otoc.ExportBundleDataByPath(bpath);
     if (buff.Length == 0)
     {
         DbgPrint("Error: base bundle not found, skipping!");
         return false;
     }
     //get old sb file
     string ttocpath = tocpath;
     if (tocpath.ToLower().Contains("update"))
         ttocpath = Helpers.SkipSubFolder(tocpath, 2);
     string oldSBpath = outputPath + Path.GetDirectoryName(ttocpath) + "\\" + Path.GetFileNameWithoutExtension(ttocpath) + ".sb";
     if (!File.Exists(oldSBpath))
     {
         DbgPrint("Error: patch SB file not found, skipping!");
         return false;
     }
     DbgPrint("  Got copy, recompiling...");
     //recompiling new sb in memory
     MemoryStream newSB = new MemoryStream();
     FileStream oldSB = new FileStream(oldSBpath, FileMode.Open, FileAccess.Read);
     long glob_off = 0;
     BJSON.Entry root = toc.lines[0];
     BJSON.Field bundles = root.fields[0];
     int count = ((List<BJSON.Entry>)bundles.data).Count();
     DbgPrint("  Recompiling SB...");
     //put one bundle after another that is not base as defined in toc
     for (int i = 0; i < count; i++)
     {
         //get entry infos
         BJSON.Entry b = ((List<BJSON.Entry>)bundles.data)[i];
         BJSON.Field f_id = b.FindField("id");
         BJSON.Field f_offset = b.FindField("offset");
         BJSON.Field f_size = b.FindField("size");
         BJSON.Field f_isBase = b.FindField("base");
         BJSON.Field f_isDelta = b.FindField("delta");
         //if not our target and not copied from base, copy from old SB
         if (((string)f_id.data).ToLower() != bpath && f_isBase == null)
         {
             int size = BitConverter.ToInt32((byte[])f_size.data, 0);
             CopyFileStream(oldSB, newSB, BitConverter.ToInt64((byte[])f_offset.data, 0), size);
             f_offset.data = BitConverter.GetBytes(glob_off);
             glob_off += size;
         }
         //if target, replace data, make delta
         if (((string)f_id.data).ToLower() == bpath)
         {
             f_offset.data = BitConverter.GetBytes(glob_off);
             f_size.data = BitConverter.GetBytes(buff.Length);
             if (f_isBase != null)
                 f_isBase.fieldname = "delta";
             newSB.Write(buff, 0, buff.Length);
             glob_off += buff.Length;
         }
     }
     oldSB.Close();
     //rebuilding new SB
     oldSB = new FileStream(oldSBpath, FileMode.Create, FileAccess.Write);
     oldSB.Write(newSB.ToArray(), 0, (int)newSB.Length);
     oldSB.Close();
     DbgPrint("  Recompiling TOC...");
     toc.Save();
     DbgPrint("  Bundle imported");
     return true;
 }
Beispiel #4
0
 public void UpdateTOC(TOCFile toc)
 {
     string path = toc.MyPath;
     path = path.ToLower().Replace(".toc",".sb");
     if (!toc.iscas)
         return;
     SBFile sb = new SBFile(path);
     BJSON.Entry root = sb.lines[0];
     BJSON.Field bundles = root.FindField("bundles");
     BJSON.Entry tocroot = toc.lines[0];
     BJSON.Field tocbundles = tocroot.FindField("bundles");
     foreach (BJSON.Entry bun in (List<BJSON.Entry>)bundles.data)
     {
         BJSON.Field f = bun.FindField("path");
         string bunpath = (string)f.data;
         foreach (BJSON.Entry tocbun in (List<BJSON.Entry>)tocbundles.data)
         {
             BJSON.Field f2 = tocbun.FindField("id");
             string bunpath2 = (string)f2.data;
             if (bunpath == bunpath2)
             {
                 BJSON.Field offset = tocbun.FindField("offset");
                 offset.data = BitConverter.GetBytes(bun.offset);
                 MemoryStream m = new MemoryStream();
                 BJSON.WriteEntry(m, bun);
                 string p = Path.GetDirectoryName(path);
                 File.WriteAllBytes(p + "\\" + Path.GetFileName(bunpath) + ".bin", m.ToArray());
                 BJSON.Field size = tocbun.FindField("size");
                 size.data = BitConverter.GetBytes((uint)m.Length);
             }
         }
     }
     toc.Save();
     DbgPrint("  TOC file offsets updated.");
 }
Beispiel #5
0
 public void RunTextureResJobOnBundleBinary(Mod.ModJob mj, TOCFile toc, string tocpath, string bpath)
 {
     GC.Collect();
     int count = 0;
     int index = -1;
     foreach (TOCFile.TOCBundleInfoStruct buni in toc.bundles)
         if (count++ > -1 && bpath.ToLower() == buni.id.ToLower())
         {
             DbgPrint(" Found bundle : " + bpath);
             index = count - 1;
             break;
         }
     //if bundle found
     if (index != -1)
     {
         //find out if base, delta or nothing
         BJSON.Entry root = toc.lines[0];
         BJSON.Field bundles = root.FindField("bundles");
         BJSON.Entry bun = ((List<BJSON.Entry>)bundles.data)[index];
         BJSON.Field isDeltaField = bun.FindField("delta");
         BJSON.Field isBaseField = bun.FindField("base");
         //if has base or delta prop, still from patch
         if (isBaseField != null)
             if (!ImportBundleBinaryFromBase(toc, tocpath, bpath))
                 return;
         toc = new TOCFile(toc.MyPath);//reload toc
         byte[] bundledataraw = toc.ExportBundleDataByPath(bpath);
         uint test = BitConverter.ToUInt32(bundledataraw, 4);
         if (test != 0xD58E799D)
         {
             DbgPrint("  Its a real delta bundle, importing from base...");
             if (!ImportBundleBinaryFromBase(toc, tocpath, bpath, false))
                 return;
             toc.Save();
             toc = new TOCFile(toc.MyPath);//reload toc
         }
         DbgPrint("  Updating SB file with new data...");
         bundledataraw = toc.ExportBundleDataByPath(bpath);
         BinaryBundle bundle = new BinaryBundle(new MemoryStream(bundledataraw));
         bool found = false;
         byte[] chunkidbuff = new byte[16];
         byte[] newchunkid = new byte[16];
         //find right res entry
         for (int j = 0; j < bundle.ResList.Count; j++)
             if (bundle.ResList[j]._name.ToLower() == mj.respath.ToLower())
             {
                 //get res data and extract chunk id
                 for (int k = 0; k < 16; k++)
                     chunkidbuff[k] = bundle.ResList[j]._data[k + 0x1C];
                 DbgPrint("  Found chunk id : " + Helpers.ByteArrayToHexString(chunkidbuff));
                 newchunkid = Guid.NewGuid().ToByteArray();
                 DbgPrint("  Creating new chunk id : " + Helpers.ByteArrayToHexString(newchunkid));
                 for (int k = 0; k < 16; k++)
                     bundle.ResList[j]._data[k + 0x1C] = newchunkid[k];
                 found = true;
             }
         if (!found)
         {
             DbgPrint("  Error: cant find res, skipping!");
             return;
         }
         found = false;
         //find right chunk entry
         MemoryStream m3 = new MemoryStream();
         Helpers.WriteLEInt(m3, BitConverter.ToInt32(chunkidbuff, 0));
         Helpers.WriteLEUShort(m3, BitConverter.ToUInt16(chunkidbuff, 4));
         Helpers.WriteLEUShort(m3, BitConverter.ToUInt16(chunkidbuff, 6));
         m3.Write(chunkidbuff, 8, 8);
         byte[] chunkidswapped = m3.ToArray();
         for (int j = 0; j < bundle.ChunkList.Count; j++)
             if (Helpers.ByteArrayCompare(bundle.ChunkList[j].id, chunkidswapped))
             {
                 DbgPrint("  Found chunk");
                 found = true;
                 BinaryBundle.ChunkEntry chunk = bundle.ChunkList[j];
                 m3 = new MemoryStream();
                 Helpers.WriteLEInt(m3, BitConverter.ToInt32(newchunkid, 0));
                 Helpers.WriteLEUShort(m3, BitConverter.ToUInt16(newchunkid, 4));
                 Helpers.WriteLEUShort(m3, BitConverter.ToUInt16(newchunkid, 6));
                 m3.Write(newchunkid, 8, 8);
                 chunk.id = m3.ToArray();
                 chunk._data = mj.data;
                 bundle.ChunkList[j] = chunk;
                 break;
             }
         if (!found)
         {
             DbgPrint("  Error: Could not find Chunk by id");
             return;
         }
         DbgPrint("  Recompiling bundle...");
         MemoryStream m = new MemoryStream();
         bundle.Save(m);
         DbgPrint("  Recompiling sb...");
         MemoryStream m2 = new MemoryStream();
         List<BJSON.Entry> list = ((List<BJSON.Entry>)bundles.data);
         foreach (TOCFile.TOCBundleInfoStruct buni in toc.bundles)
             if (!buni.isbase)
             {
                 byte[] buff = new byte[0];
                 if (bpath.ToLower() != buni.id.ToLower())
                     buff = toc.ExportBundleDataByPath(buni.id);
                 else
                     buff = m.ToArray();
                 for (int i = 0; i < list.Count; i++)
                     if ((string)list[i].FindField("id").data == buni.id)
                     {
                         BJSON.Entry e = list[i];
                         BJSON.Field f = e.fields[e.FindFieldIndex("offset")];
                         f.data = BitConverter.GetBytes(m2.Position);
                         e.fields[e.FindFieldIndex("offset")] = f;
                         f = e.fields[e.FindFieldIndex("size")];
                         f.data = BitConverter.GetBytes(buff.Length);
                         e.fields[e.FindFieldIndex("size")] = f;
                         list[i] = e;
                         break;
                     }
                 m2.Write(buff, 0, buff.Length);
             }
         bundles.data = list;
         root.fields[root.FindFieldIndex("bundles")] = bundles;
         toc.lines[0] = root;
         DbgPrint("  Updating TOC...");
         toc.Save();
         toc = new TOCFile(toc.MyPath);//reload toc
         DbgPrint("  Saving sb...");
         if (tocpath.ToLower().Contains("update"))
             File.WriteAllBytes(outputPath + Helpers.SkipSubFolder(tocpath.ToLower().Replace(".toc", ".sb"), 2), m2.ToArray());
         else
             File.WriteAllBytes(outputPath + tocpath.ToLower().Replace(".toc", ".sb"), m2.ToArray());
         DbgPrint("  Job successfull!");
     }
 }