/// <summary> /// Returns the game header for the currently loaded game. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static T ReadHeader <T>() where T : GameHeader { using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read), Encoding.ASCII)) { byte[] buffer = new byte[Marshal.SizeOf(typeof(T))]; reader.BaseStream.Position = IsGameBoyAdvance(filePath) ? gbaHeaderOffset : gbHeaderOffset; buffer = reader.ReadBytes(buffer.Length); return((T)StructureHelper.BytesToClass <T>(ref buffer)); } }
/// <summary> /// Extract a .zip archive file content to the target path. /// </summary> /// <param name="zipBuffer">The input to extract.</param> /// <param name="targetDirectory">The destination of the extracted files.</param> /// <param name="overwrite">true to overwrite existing files; false otherwhise.</param> /// <returns>true if all the files were extracted successfully; false if some problems occurred.</returns> public static bool Extract(byte[] zipBuffer, string targetDirectory, bool overwrite) { byte[] buffer = new byte[Marshal.SizeOf(typeof(CentralDirectoryEnd))]; if (zipBuffer.Length <= buffer.Length) { return(false); } uint signatureValue = (uint)Signature.CentralDirectoryEnd; byte[] signature = new byte[] { (byte)(signatureValue & 0xff), (byte)((signatureValue >> 0x8) & 0xff), (byte)((signatureValue >> 0x10) & 0xff), (byte)(signatureValue >> 0x18), }; for (int i = zipBuffer.Length - signature.Length; i >= 0; i--) { if (zipBuffer[i] == signature[0] && zipBuffer[i + 1] == signature[1] && zipBuffer[i + 2] == signature[2] && zipBuffer[i + 3] == signature[3]) { Array.Copy(zipBuffer, i, buffer, 0, buffer.Length); break; } } CentralDirectoryEnd cde = StructureHelper.BytesToClass <CentralDirectoryEnd>(ref buffer); if (cde.TotalEntries == 0 || cde.CentralDirectorySize == 0) { return(false); } CentralFileHeader cfh; buffer = new byte[Marshal.SizeOf(typeof(CentralFileHeader))]; uint count = cde.CentralDirectorySize; uint offset = cde.CentralDirectoryOffset; uint skip = 0; List <uint> lfhOffsets = new List <uint>(); do { Array.Copy(zipBuffer, offset, buffer, 0, buffer.Length); cfh = StructureHelper.BytesToClass <CentralFileHeader>(ref buffer); if (cfh.Signature == (uint)Signature.CentralFileHeader && (cfh.CompressionMethod == (ushort)CompressionMethod.Store || cfh.CompressionMethod == (ushort)CompressionMethod.Deflate) && cfh.FileNameLength > 0) { lfhOffsets.Add(cfh.HeaderRelativeOffset); } skip = (uint)buffer.Length + cfh.FileNameLength + cfh.ExtraFieldLength + cfh.FileCommentLength; count -= skip; offset += skip; } while (count > 0); if (lfhOffsets.Count != cde.TotalEntries) { return(false); } LocalFileHeader lfh; buffer = new byte[Marshal.SizeOf(typeof(LocalFileHeader))]; for (int i = 0; i < lfhOffsets.Count; i++) { Array.Copy(zipBuffer, lfhOffsets[i], buffer, 0, buffer.Length); lfh = StructureHelper.BytesToClass <LocalFileHeader>(ref buffer); if (lfh.Signature == (uint)Signature.LocalFileHeader && lfh.FileNameLength > 0) { byte[] uncompressedData = new byte[0]; if (lfh.UncompressedSize > 0) { byte[] compressedData = new byte[lfh.CompressedSize]; Array.Copy(zipBuffer, lfhOffsets[i] + buffer.Length + lfh.FileNameLength + lfh.ExtraFieldLength, compressedData, 0, lfh.CompressedSize); if (lfh.CompressionMethod == (ushort)CompressionMethod.Deflate) { uncompressedData = Inflate(compressedData); } else if (lfh.CompressionMethod == (ushort)CompressionMethod.Store) { uncompressedData = new byte[lfh.UncompressedSize]; compressedData.CopyTo(uncompressedData, 0); } } if (uncompressedData.Length == lfh.UncompressedSize && Crc.ComputeCrc32(uncompressedData) == lfh.Crc32) { int codePage = 0; if (((lfh.GeneralPurposeBitFlag >> 0xB) & 1) != 1) { codePage = (int)LanguageEncoding.IBM437; } else { codePage = (int)LanguageEncoding.UTF8; } string outputPath = Path.Combine(targetDirectory, Encoding.GetEncoding(codePage).GetString(zipBuffer, (int)lfhOffsets[i] + buffer.Length, lfh.FileNameLength)); if (!File.Exists(outputPath) || overwrite) { File.WriteAllBytes(outputPath, uncompressedData); } } else { return(false); } } } return(true); }