|
|
- using System;
- using System.IO;
- using System.Diagnostics;
- using System.Text;
- using Hack.Xenosaga.Common;
-
- namespace Hack.Xenosaga.Process
- {
- class Unpack
- {
- private static BinaryWriter _bw;
- private const string _listExtension = ".lst";
- private const string _copyright = "Hacked by BahaBulle (c)2016\0";
- private const int _sectorSize = 0x800;
- private const int _maxSizeFile = 0x40000000;
-
- private struct element
- {
- public bool isDirectory;
- public bool isCompressed;
- public byte level;
- public string name;
- public UInt32 sector;
- public UInt32 position;
- public UInt32 sizeIn;
- public UInt32 sizeOut;
- }
-
-
- #region Private methods
-
- private static int getIdFile(UInt32 position, int indexSize)
- {
- double d = (position - indexSize) / _maxSizeFile;
-
- return (int)Math.Floor(d) + 1;
- }
-
- private static bool readElement(BinaryReader br, ref element e)
- {
- byte size = br.ReadByte();
- if (size == 0)
- return false;
-
- if ((size & 0x80) != 0)
- {
- size -= 2;
- e.isDirectory = true;
- e.level = br.ReadByte();
- e.name = Encoding.ASCII.GetString(br.ReadBytes(size & 0x7F));
- }
- else
- {
- size--;
- e.isDirectory = false;
- e.level = 0;
- e.name = Encoding.ASCII.GetString(br.ReadBytes(size & 0x3F));
- e.sector = br.ReadUInt16() + (uint)br.ReadByte() * 0x10000;
- e.position = e.sector * _sectorSize;
- e.sizeIn = br.ReadUInt32();
- if ((size & 0x40) != 0)
- {
- e.sizeOut = br.ReadUInt16() + (uint)br.ReadByte() * 0x10000;
- e.isCompressed = true;
- }
- else
- {
- e.sizeOut = e.sizeIn;
- e.isCompressed = false;
- }
- }
-
- return true;
- }
-
- private static byte readIndex(string asIndexName, listPathElement path)
- {
- byte bIndexNbSector = 0;
- int num = 0;
- int level;
-
- using (BinaryReader brIndex = new BinaryReader(File.Open(asIndexName, FileMode.Open)))
- {
- pathElement current = new pathElement(true);
-
- bIndexNbSector = brIndex.ReadByte();
-
- element e = new element();
- while (readElement(brIndex, ref e))
- {
- level = e.level;
-
- while (e.level-- > 0)
- current = current.Parent;
-
- pathElement entry = new pathElement(e.isDirectory) { Name = e.name, Position = e.position, Sector = e.sector, SizeIn = e.sizeIn, SizeOut = e.sizeOut, Id = num++, Level = level, IsCompressed = e.isCompressed };
- current.addEntry(entry);
- path.addToIndex(entry);
-
- if (e.isDirectory)
- current = entry;
- }
- }
-
- return bIndexNbSector;
- }
-
- private static void writeIndex(string as_file, byte ai_nbSector, listPathElement index)
- {
- index.SortById();
-
- using (BinaryWriter bwIndex = new BinaryWriter(File.Open(Variables.dirPack + as_file, FileMode.Create)))
- {
- bwIndex.Write(ai_nbSector);
-
- foreach (pathElement entryPath in index.getEntries())
- {
- if (entryPath.Name != "")
- {
- if (entryPath.IsDirectory)
- {
- bwIndex.Write((byte)(entryPath.Name.Length + 0x82));
- bwIndex.Write((byte)entryPath.Level);
- bwIndex.Write(entryPath.Name.ToCharArray());
- }
- else
- {
- if (entryPath.IsCompressed)
- bwIndex.Write((byte)(entryPath.Name.Length + 0x41));
- else
- bwIndex.Write((byte)(entryPath.Name.Length + 1));
-
- bwIndex.Write(entryPath.Name.ToCharArray());
- bwIndex.Write((UInt16)entryPath.Sector);
- bwIndex.Write((byte)(entryPath.Sector / 0x10000));
- bwIndex.Write((UInt32)entryPath.SizeIn);
-
- if (entryPath.IsCompressed)
- {
- bwIndex.Write((UInt16)entryPath.SizeOut);
- bwIndex.Write((byte)(entryPath.SizeOut / 0x10000));
- }
- }
- }
- }
-
- bwIndex.Write((byte)0);
-
- int size = (int)bwIndex.BaseStream.Length;
- padding(bwIndex, ref size);
- }
- }
-
- private static void padding(BinaryWriter a_bw, ref int size)
- {
- char[] hack = _copyright.ToCharArray();
-
- int id = 0;
- while (size % _sectorSize != 0)
- {
- a_bw.Write(hack[id++]);
- size++;
-
- if (id >= hack.Length)
- id = 0;
- }
- }
-
- private static int AddFileToStream(string pathname, ref int num, BinaryReader br, int size, bool regroup)
- {
- if (_bw == null)
- _bw = new BinaryWriter(File.Open(string.Format("{0}{1:00}", pathname, num), FileMode.Create));
-
- long pos = _bw.BaseStream.Position;
- int size_rest = _maxSizeFile - (int)_bw.BaseStream.Length;
-
- if (!regroup && size > size_rest)
- {
- _bw.Write(br.ReadBytes(size_rest), 0, size_rest);
- _bw.Close();
- _bw.Dispose();
-
- num++;
- _bw = new BinaryWriter(File.Open(string.Format("{0}{1:00}", pathname, num), FileMode.Create));
-
- _bw.Write(br.ReadBytes(size - size_rest), 0, size - size_rest);
- }
- else
- _bw.Write(br.ReadBytes(size), 0, size);
-
- padding(_bw, ref size);
-
- return size;
- }
-
- private static int findFile(pathElement entry, string numberFile)
- {
- // Check if the file is in the INSERT directory
- if (File.Exists(Variables.dirInsert + entry.Name))
- return 1;
-
- // Check if the file is in the UNPACK directory
- if (File.Exists(Variables.dirUnpack + numberFile + entry.FullPath))
- return 2;
-
- // Otherwise, get the file from iso files
- return -1;
- }
-
- #endregion
-
- #region Public methods
-
- /// <summary>
- /// Unpack all files from an index
- /// </summary>
- /// <param name="indexName">Pathname of the index</param>
- public static void unpackIsoFiles(string indexName)
- {
- BinaryReader br = null;
- byte bIndexNbSector = 0;
- int numFileIndex;
- int numFileOpen = -1;
- int iIndexSize = 0;
- string fileNameBase = Path.GetFileNameWithoutExtension(indexName);
-
- int.TryParse(Path.GetExtension(indexName).Substring(1), out numFileIndex);
- string directoryName = Variables.dirUnpack + string.Format("{0:D2}", numFileIndex);
-
- listPathElement index = new listPathElement();
-
- Trace.Write(string.Format("Reading index ({0}) : ", indexName));
-
- // Lecture de l'index
- try
- {
- bIndexNbSector = readIndex(indexName, index);
- index.SortBySector();
- }
- catch (Exception ex)
- {
- Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
- return;
- }
- Trace.WriteLine("OK");
-
- iIndexSize = bIndexNbSector * _sectorSize;
-
- try
- {
- Trace.WriteLine("Extracting files");
- Trace.Indent();
-
- foreach (pathElement entryPath in index.getEntries())
- {
- if (!entryPath.IsDirectory)
- {
- Trace.WriteLine(string.Format("Create file {0}", entryPath.FullPath));
- Directory.CreateDirectory(directoryName + Path.GetDirectoryName(entryPath.FullPath));
-
- int id = getIdFile(entryPath.Position, iIndexSize) + numFileIndex;
-
- double pos = (entryPath.Position - iIndexSize) % _maxSizeFile;
-
- if (numFileOpen == -1 || numFileOpen != id)
- {
- if (br != null)
- {
- br.Close();
- br.Dispose();
- }
-
- br = new BinaryReader(File.Open(string.Format("{0}.{1:D2}", fileNameBase, id), FileMode.Open));
- numFileOpen = id;
- }
-
- br.BaseStream.Seek((int)pos, SeekOrigin.Begin);
-
- int size_rest = (int)br.BaseStream.Length - (int)pos;
- using (BinaryWriter bw = new BinaryWriter(File.Open(directoryName + entryPath.FullPath, FileMode.Create)))
- {
- if (size_rest >= entryPath.SizeIn)
- bw.Write(br.ReadBytes((int)entryPath.SizeIn));
- else
- {
- bw.Write(br.ReadBytes(size_rest));
- int num = id + 1;
-
- if (br != null)
- {
- br.Close();
- br.Dispose();
- }
-
- br = new BinaryReader(File.Open(string.Format("{0}.{1:D2}", fileNameBase, num), FileMode.Open));
- numFileOpen = num;
-
- bw.Write(br.ReadBytes((int)entryPath.SizeIn - size_rest));
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- Trace.WriteLine(string.Format("==> ERROR : {0}", ex.Message));
- return;
- }
- finally
- {
- Trace.Unindent();
- }
- }
-
- /// <summary>
- /// Pack all files to index
- /// </summary>
- /// <param name="indexName">Pathname of the index</param>
- /// <param name="regroup">Used to know if the program pack files in 1 ou more files</param>
- public static void packIsoFiles(string indexName, bool regroup)
- {
- BinaryReader br = null;
- byte bIndexNbSector = 0;
- long l_sector = 0;
- long l_position = 0;
- int iIndexSize = 0;
- int numFileIndex;
- int numFileWrite = -1;
- int idSave = -1;
- int.TryParse(Path.GetExtension(indexName).Substring(1), out numFileIndex);
-
- string fileNameBase = Path.GetFileNameWithoutExtension(indexName);
- string filename = "";
- string directoryUnpackName = Variables.dirUnpack + string.Format("{0:D2}", numFileIndex);
-
- listPathElement index = new listPathElement();
-
- Trace.Write(string.Format("Reading index ({0}) : ", indexName));
-
- // Lecture de l'index
- try
- {
- bIndexNbSector = readIndex(indexName, index);
- index.SortBySector();
- }
- catch (Exception ex)
- {
- Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
- return;
- }
-
- l_sector += bIndexNbSector;
- iIndexSize = bIndexNbSector * _sectorSize;
- l_position += iIndexSize;
-
- numFileWrite = numFileIndex + 1;
- try
- {
- Trace.WriteLine("Inserting files");
- Trace.Indent();
-
- string s_pathname = string.Format("{0}{1}.", Variables.dirPack, fileNameBase);
- Directory.CreateDirectory(Variables.dirPack);
-
- foreach (pathElement entryPath in index.getEntries())
- {
- if (!entryPath.IsDirectory)
- {
- long size = 0;
-
- int idFile = findFile(entryPath, string.Format("{0:D2}", numFileIndex));
-
- if (idFile == 1 || idFile == 2)
- {
- if (idFile == 1)
- {
- Trace.WriteLine(string.Format("From {0} : file {1}", Variables.dirInsert, entryPath.FullPath));
-
- filename = Variables.dirInsert + entryPath.Name;
- }
- else
- {
- Trace.WriteLine(string.Format("From {0} : file {1}", Variables.dirUnpack, entryPath.FullPath));
-
- filename = directoryUnpackName + entryPath.FullPath;
- }
-
- using (BinaryReader brFile = new BinaryReader(File.Open(filename, FileMode.Open)))
- {
- size = brFile.BaseStream.Length;
-
- if (entryPath.IsCompressed)
- {
- // Compression du fichier
- entryPath.SizeIn = (UInt32)size;
- //entryPath.SizeOut = entryPath.SizeIn;
- }
- else
- {
- entryPath.SizeIn = (UInt32)size;
- //entryPath.SizeOut = entryPath.SizeIn;
- }
-
- int size_new = AddFileToStream(s_pathname, ref numFileWrite, brFile, (int)size, regroup);
-
- entryPath.Position = (UInt32)l_position;
- entryPath.Sector = entryPath.Position / _sectorSize;
- l_position += size_new;
- }
- }
- else
- {
- int id = getIdFile(entryPath.Position, iIndexSize) + numFileIndex;
- filename = string.Format("{0}.{1:D2}", fileNameBase, id);
-
- Trace.WriteLine(string.Format("From {0} : file {1}", filename, entryPath.FullPath));
-
- size = entryPath.SizeIn;
-
- double pos = (entryPath.Position - iIndexSize) % _maxSizeFile;
-
- int size_new = 0;
-
- if (br != null && id != idSave)
- {
- br.Close();
- br.Dispose();
- br = null;
- }
-
- if (br == null)
- {
- br = new BinaryReader(File.Open(filename, FileMode.Open));
- idSave = id;
- }
-
- br.BaseStream.Seek((int)pos, SeekOrigin.Begin);
-
- int size_rest = (int)br.BaseStream.Length - (int)pos;
-
- if (size_rest >= size)
- size_new = AddFileToStream(s_pathname, ref numFileWrite, br, (int)size, regroup);
- else
- {
- int sizeTemp = AddFileToStream(s_pathname, ref numFileWrite, br, size_rest, regroup);
- int num = id + 1;
- size_new = sizeTemp;
-
- if (br != null)
- {
- br.Close();
- br.Dispose();
- }
-
- filename = string.Format("{0}.{1:D2}", fileNameBase, num);
- br = new BinaryReader(File.Open(filename, FileMode.Open));
- idSave = num;
-
- sizeTemp = AddFileToStream(s_pathname, ref numFileWrite, br, (int)entryPath.SizeIn - size_rest, regroup);
- size_new += sizeTemp;
- }
-
- entryPath.Position = (UInt32)l_position;
- entryPath.Sector = entryPath.Position / _sectorSize;
- l_position += size_new;
- }
- }
- }
-
- _bw.Close();
- _bw.Dispose();
-
- writeIndex(indexName, bIndexNbSector, index);
- }
- catch (Exception ex)
- {
- Trace.WriteLine(string.Format("==> ERROR : {0}", ex.Message));
- return;
- }
- finally
- {
- Trace.Unindent();
- }
- }
-
- /// <summary>
- /// List files of an index
- /// </summary>
- /// <param name="indexName">Pathname of the index</param>
- public static void listFiles(string indexName)
- {
- string outputName;
- byte bIndexNbSector = 0;
- int iIndexSize;
- int numFile;
- int.TryParse(Path.GetExtension(indexName).Substring(1), out numFile);
-
- listPathElement index = new listPathElement();
-
- Trace.Write(string.Format("Reading index file ({0}) : ", indexName));
-
- try
- {
- Directory.CreateDirectory(Variables.dirUnpack);
- outputName = string.Format("{0}{1}{2}", Variables.dirUnpack, indexName, _listExtension);
-
- using (StreamWriter sw = new StreamWriter(outputName))
- {
- Functions.ManageListener(false, true, sw);
-
- bIndexNbSector = readIndex(indexName, index);
- index.SortBySector();
- iIndexSize = bIndexNbSector * _sectorSize;
-
- foreach (pathElement entryPath in index.getEntries())
- {
- if (!entryPath.IsDirectory)
- {
- double d = (entryPath.Position - iIndexSize) / _maxSizeFile;
- int id = (int)Math.Floor(d) + 1;
-
- Trace.WriteLine(string.Format("{0,-36}Sector={1,-15}SizeIn={2,-15}SizeOut={3,-15}File=xenosaga.{4:D2}", entryPath.FullPath, entryPath.Sector, entryPath.SizeIn, entryPath.SizeOut, id + numFile));
- }
- }
-
- Functions.ManageListener(true, false);
- }
-
- Trace.WriteLine("OK");
- }
- catch (Exception ex)
- {
- Trace.WriteLine(string.Format("ERROR : {0}", ex.Message));
- return;
- }
- }
-
- #endregion
- }
- }
|