/// <summary> /// Stream the field from a buffer /// </summary> /// <param name="input"></param> public override void Read(IO.EndianReader input) { Internal = input.ReadBytes(Value); #if DEBUG if (TracingEnabled && Value > 5) { byte[] data = input.ReadBytes(Value); for (int x = 0, y = 0, z = 0; x < data.Length; x++) { if (data[x] != 0) { if (y == 0 || x == 0) { y = x; } z++; } else if (x != 0 && data[x - 1] != 0) { trace.WriteLine("Found data at offset 0x{0:X} covering 0x{1:X} bytes, in a pad field with a count of {1}", y, z, Value); } } data = null; } #endif }
/// <summary>Read a multi-byte CString from an endian stream</summary> /// <param name="s">Endian stream to read from</param> /// <param name="ms">Stream to write the character's bytes to</param> void ReadCStringMultiByte(IO.EndianReader s, System.IO.MemoryStream ms) { byte[] characters; if (!mStorage.IsFixedLength) { characters = new byte[mNullCharacterSize]; while (!ReadStringMultiByteIsNull(s.ByteOrder, s.Read(characters), 0)) { ms.Write(characters, 0, characters.Length); } } else { characters = s.ReadBytes(mFixedLengthByteLength); int x; for (x = 0; x < characters.Length - mNullCharacterSize; x += mNullCharacterSize) { if (ReadStringMultiByteIsNull(s.ByteOrder, characters, x)) { break; } } ms.Write(characters, 0, x); } }
public void Read(IO.EndianReader s) { s.Owner = this; Flags = s.Read(FileFlagsStreamer.Instance); Version = s.ReadUInt16(); if (Version != kVersion) { throw new IO.VersionMismatchException(s.BaseStream, kVersion, Version); } Read(s, EnumFlags.Test(Flags, FileFlags.EncryptHeader), Header, MediaHeader.kSizeOf); GenerateHash(); if (EnumFlags.Test(Flags, FileFlags.CompressContent)) { using (var cs = new CompressedStream(true)) { Read(s, EnumFlags.Test(Flags, FileFlags.EncryptContent), cs, userKey: Header.DataCryptKey, readLeftovers: ReadLeftovers); cs.Decompress(); Content = cs.UncompressedData; } } else { Content = s.ReadBytes((int)(s.BaseStream.Length - s.BaseStream.Position)); } }
/// <summary> /// Stream the field from a buffer /// </summary> /// <param name="input"></param> public override void Read(IO.EndianReader input) { #if false//DEBUG if (Value < 5) { input.Seek(Value, System.IO.SeekOrigin.Current); } else { byte[] data = input.ReadBytes(Value); for (int x = 0, y = 0, z = 0; x < data.Length; x++) { if (data[x] != 0) { if (y == 0 || x == 0) { y = x; } z++; } else if (x != 0 && data[x - 1] != 0) { trace.WriteLine("Found data at offset 0x{0:X} covering 0x{1:X} bytes, in a pad field with a count of {1}", y, z, Value); } } data = null; } #else input.Seek(Value, System.IO.SeekOrigin.Current); #endif }
byte[] ReadStrCharArray(IO.EndianReader s, int length, out int actualCount) { byte[] bytes = s.ReadBytes(mStorage.IsFixedLength ? mFixedLengthByteLength : GetMaxCleanByteCount(length)); actualCount = mNullCharacterSize == sizeof(byte) ? ReadStrCharArrayGetRealCountSingleByte(bytes) : ReadStrCharArrayGetRealCountMultiByte(s.ByteOrder, bytes); return(bytes); }
int ReadChunk(IO.EndianReader s, System.IO.MemoryStream ms) { ushort chunk_size = s.ReadUInt16(), negate_chunk_size = s.ReadUInt16(); ushort expected_negate = (ushort)~chunk_size; if (expected_negate != negate_chunk_size) { throw new IO.SignatureMismatchException(s.BaseStream, expected_negate, negate_chunk_size); } byte[] bytes = s.ReadBytes(chunk_size); ms.Write(bytes, 0, bytes.Length); return(chunk_size); }
byte[] ReadStrPascal(IO.EndianReader s, out int actualCount) { actualCount = TypeExtensions.kNone; int length; // One would think that the length prefix would be of the same endian as the stream, but just in case... using (s.BeginEndianSwitch(mStorage.ByteOrder)) switch (mStorage.LengthPrefix) { case StringStorageLengthPrefix.Int7: length = s.Read7BitEncodedInt(); break; case StringStorageLengthPrefix.Int8: length = s.ReadByte(); break; case StringStorageLengthPrefix.Int16: length = s.ReadInt16(); break; case StringStorageLengthPrefix.Int32: length = s.ReadInt32(); break; default: throw new Debug.UnreachableException(); } return(s.ReadBytes(GetMaxCleanByteCount(length))); }
/// <summary>Read a CString from an endian stream</summary> /// <param name="s">Endian stream to read from</param> /// <param name="length">Optional length specification</param> /// <param name="actualCount">On return, the actual character byte count, or -1 if all bytes are valid</param> /// <returns>The character's bytes for the string we're reading</returns> byte[] ReadStrCString(IO.EndianReader s, int length, out int actualCount) { byte[] bytes; actualCount = TypeExtensions.kNone; // complete string case // the user was nice and saved us some CPU trying to feel around for the null // because we don't have a fixed length to speed things up if (!mStorage.IsFixedLength && length > 0) { bytes = s.ReadBytes(GetMaxCleanByteCount(length)); s.Seek(mNullCharacterSize, System.IO.SeekOrigin.Current); } // F**K: figure out the length ourselves. Or maybe we're a fixed length CString... // in which case we'll ignore anything the user tried to tell us about the length else { using (var ms = new System.IO.MemoryStream(!mStorage.IsFixedLength ? 512 : mStorage.FixedLength)) { // The N-byte methods take care of reading past the // null character, no need to do it in this case. if (mNullCharacterSize == 1) { ReadCStringSingleByte(s, ms); } else { ReadCStringMultiByte(s, ms); } // We use ToArray instead of GetArray so all of [ms] can theoretically be disposed of bytes = ms.ToArray(); } } return(bytes); }
bool CacheRead(BlamLib.Blam.CacheFile c, out byte[] data) { data = null; ResourcePtr offset = GetOffset(0); int size = GetSize(0); var rsrc_cache = Program.Halo2.FromLocation(c as Halo2.CacheFile, offset); // the shared cache isn't loaded, break if (rsrc_cache == null) { return(false); } // get the input stream we need IO.EndianReader er = rsrc_cache.InputStream; // read the bitmap er.Seek(offset.Offset); data = er.ReadBytes(size); return(true); }
public override void Read(IO.EndianReader s) { int k_local_sizeof = Blam.CacheFile.ValidateHeader(s, kSizeOf); s.Seek(4); version = s.ReadInt32(); if (version != 11 && version != 12) { throw new InvalidCacheFileException(s.FileName); } fileLength = s.ReadInt32(); s.ReadInt32(); tagIndexAddress = s.ReadUInt32(); memoryBufferOffset = s.ReadInt32(); memoryBufferSize = s.ReadInt32(); sourceFile = s.ReadAsciiString(256); build = s.ReadTagString(); cacheType = (Blam.CacheType)s.ReadInt16(); sharedType = (Cache.SharedType)s.ReadInt16(); s.ReadBool(); s.ReadBool(); // false if it belongs to a untracked build s.ReadBool(); // PATCH: this is '3' in main menu patches s.ReadByte(); // appears to be an ODST-only field s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); #region string id table // 0x158 stringIdsCount = s.ReadInt32(); stringIdsBufferSize = s.ReadInt32(); stringIdIndicesOffset = s.ReadInt32(); stringIdsBufferOffset = s.ReadInt32(); #endregion #region filetimes? // pretty sure this is a flags field // used to tell which of the following 64bit values // are used. Damn sure this are FILETIME structures, but // hex workshop doesn't like them so I can't be for sure... needsShared = s.ReadInt32() != 0; // just a little 'hack' if you will. if zero, the map is self reliant, so no worries Filetime.dwHighDateTime = s.ReadInt32(); Filetime.dwLowDateTime = s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnMainMenu); } s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnShared); } s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnCampaign); } s.ReadInt32(); #endregion name = s.ReadTagString(); s.ReadInt32(); scenarioPath = s.ReadAsciiString(256); // PATCH: this is -1 in main menu patches s.ReadInt32(); // minor version, normally not used #region tag paths tagNamesCount = s.ReadInt32(); tagNamesBufferOffset = s.ReadInt32(); // cstring buffer tagNamesBufferSize = s.ReadInt32(); // cstring buffer total size in bytes tagNameIndicesOffset = s.ReadInt32(); TagsUnknown1Count = s.ReadInt32(); TagsUnknown1Offset = s.ReadInt32(); // PATCH: zero for non-patch data TagsUnknown2Count = s.ReadInt32(); TagsUnknown2Offset = s.ReadInt32(); #endregion checksum = s.ReadUInt32(); // 0x2D4 s.Seek(32, System.IO.SeekOrigin.Current); // these bytes are always the same. first 8 changed in Halo4 baseAddress = s.ReadUInt32(); // expected base address xdkVersion = s.ReadInt32(); // xdk version #region memory partitions // 0x300 // memory partitions memoryPartitions = new Partition[6]; memoryPartitions[0].BaseAddress = s.ReadUInt32(); // cache resource buffer memoryPartitions[0].Size = s.ReadInt32(); // readonly memoryPartitions[1].BaseAddress = s.ReadUInt32(); // cache gestalt resource buffer memoryPartitions[1].Size = s.ReadInt32(); memoryPartitions[2].BaseAddress = s.ReadUInt32(); // global tags buffer (cache sound tags likes this memory space too) memoryPartitions[2].Size = s.ReadInt32(); memoryPartitions[3].BaseAddress = s.ReadUInt32(); // shared tag blocks? (havok data likes this memory space too) memoryPartitions[3].Size = s.ReadInt32(); memoryPartitions[4].BaseAddress = s.ReadUInt32(); // address memoryPartitions[4].Size = s.ReadInt32(); // readonly memoryPartitions[5].BaseAddress = s.ReadUInt32(); // map tags buffer memoryPartitions[5].Size = s.ReadInt32(); #endregion int count = s.ReadInt32(); s.Seek(4 + 8, System.IO.SeekOrigin.Current); // these bytes are always the same // if there is a hash in the header, this is the ONLY // place where it can be s.Seek(20 /*SHA1*/ + 40 + 256 /*RSA*/, System.IO.SeekOrigin.Current); // ??? // 0x47C cacheInterop.Read(s); cacheInterop.PostprocessForCacheRead(k_local_sizeof); s.Seek(16, System.IO.SeekOrigin.Current); // GUID?, these bytes are always the same. ODST is different from Halo 3 // PATCH: main menu patches have a single entry (where stock has none) #region blah 1 // 0x4AC // campaign has a shit load of these // but shared doesn't nor mainmenu // I compared the sc110 french and english and both have the SAME counts and element data. So // I don't think this is a hash or something. At least, if it is, it's not runtime relative so // nothing we have to worry about s.ReadInt16(); // I've only seen this be two different values (besides zero). count = s.ReadInt16(); // I think the above specifies the size of the structure this count represents? s.ReadInt32(); // seems to always be zero CompressionGuid = new Guid(s.ReadBytes(16)); s.Seek(count * 28, System.IO.SeekOrigin.Current); // seek past the elements // dword // long // buffer [0x14] (probably a sha1 hash) s.Seek((3600 - count) * 28, System.IO.SeekOrigin.Current); // seek past the unused elements #endregion // PATCH: main menu patches have a count of '1' but doesn't appear to have #region blah 2 s.Seek(sizeof(uint) + 0x4E9C, System.IO.SeekOrigin.Current); #if false { // 0x18E94 // going to punt and just assume there is a max count of 13 of these possible // maybe related to bsp\'zones'? const int blah2_sizeof = 0x60C; count = (int)(s.ReadUInt32() >> 24); // did someone forget to f*****g byte swap something? s.Seek(count * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the elements s.Seek((13 - count) * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the unused elements } #endif #endregion s.Seek(712 + sizeof(uint), System.IO.SeekOrigin.Current); ReadPostprocessForInterop(); if (!cacheInterop.IsNull) { int debug_mask = (int)cacheInterop[CacheSectionType.Debug].AddressMask; if (TagsUnknown1Offset != 0) { TagsUnknown1Offset -= debug_mask; } if (TagsUnknown2Offset != 0) { TagsUnknown2Offset -= debug_mask; } } ReadPostprocessForBaseAddresses(s); }
void ReadInt(IO.EndianReader s) { switch (TypeDesc.SizeOf) { case sizeof(byte): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadByte() : (uint)s.ReadSByte(); } else { if (TypeDesc.IsUnsigned) { var array = s.ReadBytes(ArrayLength); OpaqueArrayRef = array; } else { var array = new sbyte[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadSByte(); } OpaqueArrayRef = array; } } } break; case sizeof(ushort): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadUInt16() : (uint)s.ReadInt16(); } else { if (TypeDesc.IsUnsigned) { var array = new ushort[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt16(); } OpaqueArrayRef = array; } else { var array = new short[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt16(); } OpaqueArrayRef = array; } } } break; case sizeof(uint): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadUInt32() : (uint)s.ReadInt32(); } else { if (TypeDesc.IsUnsigned) { var array = new uint[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt32(); } OpaqueArrayRef = array; } else { var array = new int[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt32(); } OpaqueArrayRef = array; } } } break; case sizeof(ulong): { if (ArrayLength == 1) { Int64 = TypeDesc.IsUnsigned ? (ulong)s.ReadUInt64() : (ulong)s.ReadInt64(); } else { if (TypeDesc.IsUnsigned) { var array = new ulong[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt64(); } OpaqueArrayRef = array; } else { var array = new long[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt64(); } OpaqueArrayRef = array; } } } break; default: throw new KSoft.Debug.UnreachableException(TypeDesc.SizeOf.ToString()); } }
public void ExtractSounds(string path, System.IO.StreamWriter towav, IO.EndianReader pckReader, bool overwriteExisting = false) { Dictionary <uint, SoundBank.AkSoundBankHierarchyObjectBase> sounds; if (!mObjects.TryGetValue(SoundBank.HircType.Sound, out sounds)) { Debug.Trace.FilePackage.TraceInformation("{0} - No sounds to extract?", PackageFileName); return; } foreach (var kv in sounds) { var snd = kv.Value as SoundBank.AkSoundBankHierarchySound; if (snd.Name == null && mDupObjects.Contains(kv.Key)) { continue; } uint src_id = snd.Source.MediaInfo.SourceID; mUntouched.Remove(src_id); if (snd.Source.MediaInfo.FileID == 0) { towav.WriteLine("REM NoData {0}", snd.Name); continue; } string dir = null; string filename = (snd.Name ?? ("unknown_" + kv.Key.ToString("X8"))) + ".xma"; uint bank_id = snd.BankId; string bank_name; if (!Package.IdToName.TryGetValue(bank_id, out bank_name)) { bank_name = bank_id.ToString("X8"); } SoundBank.AkSoundBankData bank_data = null; bool streamed = snd.Source.StreamType != SoundBank.AkBankSourceData.SourceType.Data; if (!streamed) { bank_data = mIdToBank[bank_id].mData; } dir = System.IO.Path.Combine(path, bank_name); System.IO.Directory.CreateDirectory(dir); string full_path = System.IO.Path.Combine(dir, filename); towav.WriteLine("towav.exe {0}", full_path); if (System.IO.File.Exists(full_path) && !overwriteExisting) { continue; } using (var fs = System.IO.File.Create(full_path)) { if (streamed) { var file = Package.FindStreamedFileById(snd.Source.MediaInfo.FileID); pckReader.Seek(file.FileOffset); byte[] data = pckReader.ReadBytes((int)file.FileSize32); fs.Write(data, 0, data.Length); } else { fs.Write(bank_data.Buffer, (int)snd.Source.MediaInfo.FileOffset, (int)snd.Source.MediaInfo.MediaSize); } } } ////////////////////////////////////////////////////////////////////////// foreach (var kv in mUntouched) { var mr = kv.Value; string name = "unknown2_" + mr.Media.ID.ToString("X8"); if (mr.Media.Size == 0) { towav.WriteLine("REM NoData2 {0}", name); continue; } string filename = name + ".xma"; uint bank_id = mr.BankId; string bank_name; if (!Package.IdToName.TryGetValue(bank_id, out bank_name)) { bank_name = bank_id.ToString("X8"); } SoundBank.AkSoundBankData bank_data = mIdToBank[bank_id].mData; string dir = System.IO.Path.Combine(path, bank_name); System.IO.Directory.CreateDirectory(dir); string full_path = System.IO.Path.Combine(dir, filename); towav.WriteLine("towav.exe {0}", full_path); if (System.IO.File.Exists(full_path)) { continue; } using (var fs = System.IO.File.Create(full_path)) { fs.Write(bank_data.Buffer, (int)mr.Media.Offset, (int)mr.Media.Size); } } }
public void Read(IO.EndianReader s) { var context = s.UserData as XmbFileContext; using (s.ReadSignatureWithByteSwapSupport(kSignature)) { if (context.PointerSize == Shell.ProcessorSize.x64) { // #HACK to deal with xmb files which weren't updated with new tools if (s.ByteOrder == Shell.EndianFormat.Big) { context.PointerSize = Shell.ProcessorSize.x32; } } s.VirtualAddressTranslationInitialize(context.PointerSize); Values.PtrHandle elements_offset_pos; if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } #region Initialize elements { int count = s.ReadInt32(); if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } s.ReadVirtualAddress(out elements_offset_pos); mElements = new List <Element>(count); } #endregion #region Initialize and read pool { int size = s.ReadInt32(); if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } Values.PtrHandle pool_offset_pos = s.ReadVirtualAddress(); s.Seek((long)pool_offset_pos); byte[] buffer = s.ReadBytes(size); mPool = new XmbVariantMemoryPool(buffer, s.ByteOrder); } #endregion if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad64(); } s.Seek((long)elements_offset_pos); for (int x = 0; x < mElements.Capacity; x++) { var e = new Element(); mElements.Add(e); e.Index = x; e.Read(this, context, s); } foreach (var e in mElements) { e.ReadAttributes(this, s); e.ReadChildren(s); } } }