public override void Load(ExtendedBinaryReader reader, bool keepOpen = false) { string header = reader.ReadNullTerminatedString(); reader.FixPadding(16); uint textureOffset = reader.ReadUInt32(); uint textureCount = reader.ReadUInt32(); int layerOffset = reader.ReadInt32(); int layerCount = reader.ReadInt32(); int unknownOffset = reader.ReadInt32(); int unknownCount = reader.ReadInt32(); uint unknown28 = reader.ReadUInt32(); uint unknown2C = reader.ReadUInt32(); string projectDir = reader.ReadStringElsewhere(); uint unknown34 = reader.ReadUInt32(); uint unknown38 = reader.ReadUInt32(); uint unknown3C = reader.ReadUInt32(); reader.JumpTo(textureOffset); for (int i = 0; i < textureCount; ++i) { Textures.Add(new MATexture(reader)); } reader.JumpTo(layerOffset); for (int i = 0; i < layerCount; ++i) { Layers.Add(new MALayer(reader)); } }
// TODO protected void LoadShadowArchive(ExtendedBinaryReader reader) { reader.JumpAhead(0x4); // Unknown, Seems to always be 0 uint fileSize = reader.ReadUInt32(); // File Size - 0xC uint magic = reader.ReadUInt32(); // Magic string ONEVersion = reader.ReadNullTerminatedString(); // Gets the version String reader.FixPadding(); // Aligns the reader uint fileCount = reader.ReadUInt32(); // File Count reader.JumpAhead(0x38 * 2 + 0x20); // Jump to the third/first entry bool isVersion6 = ONEVersion == "ONE Ver 0.60"; // Checks if its version is 0.60 int fileNameLength = isVersion6 ? 0x2C : 0x20; // The max file name size // Read File List var files = new FileEntry[FileEntryCount]; for (int i = 0; i < fileCount; i++) { var entry = new FileEntry(); entry.FileName = reader.ReadSignature( fileNameLength).Replace("\0", string.Empty); entry.UncompressedSize = reader.ReadUInt32(); entry.DataOffset = reader.ReadUInt32(); reader.JumpAhead(4); // Unknown, Seems to always be 1 if (!isVersion6) { reader.JumpAhead(0xC); // Unknown, Seems to always be 0 } files[i] = entry; } // Read File Data if (files.Length > 0) { reader.JumpTo(files[0].DataOffset + 0xC); for (int i = 0; i < fileCount; ++i) { // Compute the file's data length files[i].DataLength = ((i == fileCount - 1) ? fileSize + 0xC : files[i + 1].DataOffset) - files[i].DataOffset; var file = new ArchiveFile() { Name = files[i].FileName, Data = reader.ReadBytes( (int)files[i].DataLength) // TODO: Decompress file }; Data.Add(file); } } }
protected void FixPadding(ExtendedBinaryReader reader, Type t) { uint padding = GetPadding(t); if (padding < 2) { return; } reader.FixPadding(padding); }
public override void Load(ExtendedBinaryReader reader, bool keepOpen = false) { // Store the current reader _internalReader = reader; // Filename Section // This section contains an array of addresses to each of the file's name and the strings // itself right after, this section is only used for finding file indices from within game // This is a workaround for reading different versions of PCK files as some files seem to // have smaller padding (0x08 for Signatures, 0x04 for Padding) // while DAL: RR has larger padding (0x14 for Signatures, 0x08 for Padding) // This workaround works by checking the padding in the signature to determine the version int sigSize = reader.CheckDALSignature("Filename"); bool oldPCK = false; if (sigSize < 0x14) { oldPCK = true; } // The length of the Filename section int fileNameSectionSize = reader.ReadInt32(); // Address to the list of filenames int fileNameSectionAddress = (int)reader.BaseStream.Position; // Jump to the Pack section reader.JumpTo(fileNameSectionSize); // Makes sure the reader is aligned reader.FixPadding(oldPCK ? 0x04u : 0x08u); // Pack Section // This section contains an array of file information and then all of it's data // Check Signature string packSig = reader.ReadDALSignature("Pack"); if (packSig != "Pack" && packSig.Length <= 4) { throw new SignatureMismatchException("Pack", packSig); } // The length of the Pack section int packSectionSize = reader.ReadInt32(); int fileCount = reader.ReadInt32(); // Read file entries for (int i = 0; i < fileCount; ++i) { FileEntries.Add(new FileEntry()); FileEntries[i].DataPosition = reader.ReadInt32(); FileEntries[i].DataLength = reader.ReadInt32(); } // Jump back to the Filename section so we can get all of the file names reader.JumpTo(fileNameSectionAddress); // Reads all the file names for (int i = 0; i < fileCount; ++i) { int position = reader.ReadInt32() + (oldPCK ? 0xC : 0x18); FileEntries[i].FileName = reader.ReadStringElsewhere(position); } // Load all data into memory if the loader plans to close the stream if (!keepOpen) { Preload(); } }
private static SetObject ReadObject(ExtendedBinaryReader reader, SetObjectType objTemplate, string objType, SOBJType type, bool rawDataMode = false) // true = full, false = only remaining bytes { // For some reason these separate values are saved as one uint rather than two ushorts. // Because of this, the values are in a different order depending on endianness, and // this is the easiest known way to read them. uint unknownValue = reader.ReadUInt32(); ushort unknown1 = (ushort)((unknownValue >> 16) & 0xFFFF); ushort objID = (ushort)(unknownValue & 0xFFFF); var obj = new SetObject() { ObjectType = objType, ObjectID = objID }; uint unknown2 = reader.ReadUInt32(); uint unknown3 = reader.ReadUInt32(); float unknown4 = reader.ReadSingle(); float rangeIn = reader.ReadSingle(); float rangeOut = reader.ReadSingle(); uint parent = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; uint transformsOffset = reader.ReadUInt32(); uint transformCount = reader.ReadUInt32(); uint unknown5 = reader.ReadUInt32(); uint unknown6 = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; uint unknown7 = (type == SOBJType.LostWorld) ? reader.ReadUInt32() : 0; // Call me crazy, but I have a weird feeling these values aren't JUST padding if (unknown3 != 0 || unknown5 != 0 || unknown6 != 0 || unknown7 != 0) { Console.WriteLine("WARNING: Not padding?! ({0},{1},{2},{3})", unknown3, unknown5, unknown6, unknown7); } // Add custom data to object obj.CustomData.Add("Unknown1", new SetObjectParam(typeof(ushort), unknown1)); obj.CustomData.Add("Unknown2", new SetObjectParam(typeof(uint), unknown2)); obj.CustomData.Add("Unknown3", new SetObjectParam(typeof(uint), unknown3)); obj.CustomData.Add("Unknown4", new SetObjectParam(typeof(float), unknown4)); obj.CustomData.Add("RangeIn", new SetObjectParam(typeof(float), rangeIn)); obj.CustomData.Add("RangeOut", new SetObjectParam(typeof(float), rangeOut)); if (type == SOBJType.LostWorld) { obj.CustomData.Add("Parent", new SetObjectParam(typeof(uint), parent)); } // Skip loading parameters if template doesn't exist if (objTemplate != null) { // Get Raw Byte Length var rawDataLenExtra = objTemplate.GetExtra("RawByteLength"); long paramBegin = reader.BaseStream.Position; int rawLength = 0; if (rawDataLenExtra != null && !string.IsNullOrEmpty(rawDataLenExtra.Value)) { int.TryParse(rawDataLenExtra.Value, out rawLength); } // Read all the data then return to beginning if (rawDataMode == true && rawLength != 0) { obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]), reader.ReadBytes(rawLength))); reader.JumpTo(paramBegin); } // Parameters foreach (var param in objTemplate.Parameters) { // For compatibility with SonicGlvl templates. if (param.Name == "Unknown1" || param.Name == "Unknown2" || param.Name == "Unknown3" || param.Name == "RangeIn" || param.Name == "RangeOut" || param.Name == "Parent") { continue; } // Read Special Types/Fix Padding if (param.DataType == typeof(uint[])) { // Data Info reader.FixPadding(4); uint arrOffset = reader.ReadUInt32(); uint arrLength = reader.ReadUInt32(); uint arrUnknown = reader.ReadUInt32(); long curPos = reader.BaseStream.Position; // Data var arr = new uint[arrLength]; reader.JumpTo(arrOffset, false); for (uint i = 0; i < arrLength; ++i) { arr[i] = reader.ReadUInt32(); } obj.Parameters.Add(new SetObjectParam(param.DataType, arr)); reader.BaseStream.Position = curPos; continue; } else if (param.DataType == typeof(string)) { // Data Info uint strOffset = reader.ReadUInt32(); uint strUnknown = reader.ReadUInt32(); string str = null; // Data if (strOffset != 0) { long curPos = reader.BaseStream.Position; reader.JumpTo(strOffset, false); str = reader.ReadNullTerminatedString(); reader.BaseStream.Position = curPos; } obj.Parameters.Add(new SetObjectParam(param.DataType, str)); continue; } else if (param.DataType == typeof(float) || param.DataType == typeof(int) || param.DataType == typeof(uint)) { reader.FixPadding(4); } else if (type == SOBJType.LostWorld && param.DataType == typeof(Vector3)) { reader.FixPadding(16); } // Read Data var objParam = new SetObjectParam(param.DataType, reader.ReadByType(param.DataType)); obj.Parameters.Add(objParam); } if (rawDataMode == false) { long knownParamLength = (reader.BaseStream.Position - paramBegin); long remainingBytes = (rawLength - knownParamLength); obj.CustomData.Add("RawParamData", new SetObjectParam(typeof(byte[]), reader.ReadBytes((int)remainingBytes))); } } // Transforms uint childCount = transformCount - 1; obj.Children = new SetObjectTransform[childCount]; reader.JumpTo(transformsOffset, false); obj.Transform = ReadTransform(reader, type == SOBJType.LostWorld); for (uint i = 0; i < childCount; ++i) { obj.Children[i] = ReadTransform(reader, type == SOBJType.LostWorld); } return(obj); }