public void ReadAll() { BaseStream.Seek(0, SeekOrigin.Begin); if (Magic != ReadUInt32()) { throw new InvalidCR2WFileException("Not a CR2W file"); } fileheader.fileversion = ReadUInt32(); if (!(fileheader.fileversion >= 159 && fileheader.fileversion <= 163)) { throw new InvalidCR2WFileException($"Unknown Version: {fileheader.fileversion}"); } fileheader.flags = ReadUInt32(); fileheader.timestamp = ReadUInt64(); fileheader.buildversion = ReadUInt32(); fileheader.disksize = ReadUInt32(); fileheader.memsize = ReadUInt32(); fileheader.crc32 = ReadUInt32(); fileheader.numchunks = ReadUInt32(); var ts = new CDateTime(fileheader.timestamp); Writer.WriteLine("FileName: {0}", Path.GetFileName(FilePath)); Writer.WriteLine("FileVersion: {0}", fileheader.fileversion); Writer.WriteLine("Flags: {0}", fileheader.flags); Writer.WriteLine("DateTime: {0}.{1}", ts.ToString(), ts.Value.Millisecond); Writer.WriteLine("BuildVersion: {0}", fileheader.buildversion); Writer.WriteLine("DiskSize: {0}", fileheader.disksize); Writer.WriteLine("MemSize: {0}", fileheader.memsize); Writer.WriteLine("CRC32: 0x{0:X}", fileheader.crc32); Writer.WriteLine("NumChunks: {0}", fileheader.numchunks); GetHeaders(); Writer.WriteLine("\nComputed CRC32: 0x{0:X}", CalculateHeaderCRC32(fileheader)); GetStrings(); GetNames(); GetResources(); GetTable4(); GetObjects(); GetBuffers(); GetEmbedded(); ReadObjectData(); }
void ParseVariale(string type, int size, string offset) { var arr = type.Split(new char[] { ':' }, 2); switch (arr[0]) { #region .NET Types case "Uint8": { Writer.WriteLine(" {0}", ReadByte()); } return; case "Uint16": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "Uint32": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "Uint64": { Writer.WriteLine(" {0}", ReadUInt64()); } return; case "Int8": { Writer.WriteLine(" {0}", ReadSByte()); } return; case "Int16": { Writer.WriteLine(" {0}", ReadInt16()); } return; case "Int32": { Writer.WriteLine(" {0}", ReadInt32()); } return; case "Int64": { Writer.WriteLine(" {0}", ReadInt64()); } return; case "Float": { Writer.WriteLine(" {0}", ReadSingle()); } return; case "String": { var(flag, length) = ReadVLQInt32(); var encoding = flag ? Encoding.ASCII : Encoding.Unicode; var chars = new char[length]; var byteSize = encoding.GetByteCount(chars); var bytes = ReadBytes(byteSize); encoding.GetChars(bytes, 0, byteSize, chars, 0); Writer.WriteLine(" {0}", new string(chars)); } return; case "Bool": { Writer.WriteLine(" {0}", ReadBoolean()); } return; #endregion #region RED Types case "StringAnsi": { var length = ReadByte(); var bytes = ReadBytes(length); Writer.WriteLine(" {0}", new StringAnsi(bytes)); } return; case "CName": { Writer.WriteLine(" {0}", names[ReadUInt16()].Value); } return; case "CGUID": { Writer.WriteLine(" {0}", new CGUID(ReadBytes(16)).ToString()); } return; case "LocalizedString": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "ptr": { Writer.WriteLine(" Object {0}", ReadUInt32()); } return; case "soft": { var id = ReadUInt16(); if (id == 0) { Writer.WriteLine(" NULL"); return; } var res = resources[id - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } return; case "array": { arr = arr[1].Split(new char[] { ',' }, 3); var len = ReadUInt32(); Writer.WriteLine(" {0}", len); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < len; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[2], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "handle": { var id = ReadInt32(); if (id >= 0) { Writer.WriteLine(" Object: {0}", id); } else { id *= -1; var res = resources[id - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } } return; case "SAppearanceAttachment": { Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); var bytecount = ReadInt32(); var unknown = ReadBytes(bytecount - 4); Writer.WriteLine("{0}Unknown Bytes: {1}", offset, bytecount - 4); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "IdTag": { var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } } return; case "EngineTransform": { Writer.Write(" [ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "EngineQsTransform": { Writer.Write(" [ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2},{3} ", ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "TagList": { // This could be a vlq int value but so far there is no tag list // size big enough to use more than one bytes. var count = ReadByte(); var tags = new string[count]; for (var i = 0; i < count; i++) { tags[i] = names[ReadUInt16()].Value; } Writer.WriteLine(" [{0}]", string.Join(",", tags)); } return; case "EntityHandle": { /* * Read the first byte which will tell you what type of entity handle it is. * Values: * 0 - None - 0 bytes * 1 - Entity Guid - 32 bytes * 2 - IdTag - 17 bytes * * Then read off that variable type. * * IdTag: * 1 Byte - 0 = Static, 1 = Dynamic * 16 Bytes - Guid Value * Entity: * 16 Bytes - Guid Value * 16 Bytes - Unknown */ var handletype = ReadByte(); switch (handletype) { //Entity case 1: var eguid = new CGUID(ReadBytes(16)); var unkn = ReadBytes(16); Writer.WriteLine(" [Entity - {0}]", eguid.ToString()); break; //IdTag case 2: var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } break; } } return; case "static": { var length = ReadUInt32(); arr = arr[1].Split(new char[] { ',' }, 2); Writer.WriteLine(" {0}", length); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < length; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[1], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "CDateTime": { var datetime = new CDateTime(ReadUInt64()); Writer.WriteLine(" {0}.{1}", datetime.ToString(), datetime.Value.Millisecond); } return; case "SharedDataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DeferredDataBuffer": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "SMeshTypeResourceLODLevel": { Writer.WriteLine(" {0}", ReadSingle()); } return; case "CPhysicalCollision": { var unknown = ReadUInt32(); var nameCount = ReadByte(); Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); Writer.WriteLine("{0}unknown Uint32 {1}", offset, unknown); Writer.WriteLine("{0}Types", offset); Writer.WriteLine("{0}{{", offset); for (byte i = 0; i < nameCount; i++) { Writer.WriteLine("\t{0}Id {1}: {2}", offset, i, names[ReadUInt16()].Value); } Writer.WriteLine("{0}}}", offset); Writer.WriteLine("{0}Bytes {1}", offset, String.Join(", ", ReadBytes(16))); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; #endregion } //Detects types such as [7]Float etc... var regEx = Regex.Match(type, @"^\[([0-9]+)\]([\x00-\x7F]+)$"); if (regEx.Success) { var arraySize = ReadUInt32(); if (arraySize != Convert.ToUInt32(regEx.Groups[1].Value)) { throw new FormatException(); } Writer.WriteLine(" {0}", arraySize); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < arraySize; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(regEx.Groups[2].Value, size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); return; } var myType = AssemblyDictionary.GetTypeByName(type); if (myType != null && myType.IsEnum) { if (myType.IsDefined(typeof(FlagsAttribute), false)) { var values = new List <string>(); while (true) { var flag = ReadUInt16(); if (flag == 0) { break; } values.Add(names[flag].Value); } if (values.Count != 0) { Writer.WriteLine(" {0}", Enum.Parse(myType, String.Join(",", values))); } else { Writer.WriteLine(" {0}", "None"); } } else { var value = names[ReadUInt16()].Value; Writer.WriteLine(" {0}", value); } return; } Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); Writer.WriteLine("{0}}}", offset.Substring(1)); }
void ParseVariale(string type, int size, string offset) { var arr = type.Split(new char[] { ':' }, 2); switch (arr[0]) { case "Uint8": { Writer.WriteLine(" {0}", ReadByte()); } return; case "Uint16": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "Uint32": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "Uint64": { Writer.WriteLine(" {0}", ReadUInt64()); } return; case "Int8": { Writer.WriteLine(" {0}", ReadSByte()); } return; case "Int16": { Writer.WriteLine(" {0}", ReadInt16()); } return; case "Int32": { Writer.WriteLine(" {0}", ReadInt32()); } return; case "Int64": { Writer.WriteLine(" {0}", ReadInt64()); } return; case "Float": { Writer.WriteLine(" {0}", ReadSingle()); } return; case "Double": { Writer.WriteLine(" {0}", ReadDouble()); } return; case "String": { var length = ReadVLQInt32(); if (length < 0) { Writer.WriteLine(" {0}", Encoding.ASCII.GetString(ReadBytes(length * -1))); } else { Writer.WriteLine(" {0}", Encoding.Unicode.GetString(ReadBytes(length * 2))); } } return; case "StringAnsi": { var b = ReadByte(); var nxt = (b & (1 << 7)) != 0; int len = b & ((1 << 7) - 1); if (nxt) { Writer.WriteLine(" {0}", Encoding.Unicode.GetString(ReadBytes(len * 2))); } else { Writer.WriteLine(" {0}", Encoding.ASCII.GetString(ReadBytes(len))); } } return; case "Bool": { Writer.WriteLine(" {0}", ReadBoolean()); } return; case "CName": { Writer.WriteLine(" {0}", names[ReadUInt16()].Value); } return; case "CGUID": { Writer.WriteLine(" {0}", new CGUID(ReadBytes(16)).ToString()); } return; case "LocalizedString": { Writer.WriteLine(" {0}", ReadUInt32()); } return; case "ptr": { Writer.WriteLine(" Object {0}", ReadUInt32()); } return; case "soft": { var res = resources[ReadUInt16() - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } return; case "array": { var len = ReadUInt32(); arr = arr[1].Split(new char[] { ',' }, 3); Writer.WriteLine(" {0}", len); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < len; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[2], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "handle": { var id = ReadInt32(); if (id >= 0) { Writer.WriteLine(" Object: {0}", id); } else { id *= -1; var res = resources[id - 1]; Writer.WriteLine(" {0} {1} ({2})", res.Type, res.Path, res.Flags); } } return; case "SAppearanceAttachment": { Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); var bytecount = ReadInt32(); var unknown = ReadBytes(bytecount - 4); Writer.WriteLine("{0}Unknown Bytes: {1}", offset, bytecount - 4); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "IdTag": { var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } } return; case "EngineTransform": { Writer.Write(" [ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "EngineQsTransform": { Writer.Write("[ "); var flags = ReadByte(); if ((flags & 1) == 1) { Writer.Write("Posistion:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 2) == 2) { Writer.Write("Rotation:{0},{1},{2},{3} ", ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); } if ((flags & 4) == 4) { Writer.Write("Scale:{0},{1},{2} ", ReadSingle(), ReadSingle(), ReadSingle()); } Writer.WriteLine("]"); } return; case "TagList": { var count = ReadByte(); var tags = new string[count]; for (var i = 0; i < count; i++) { tags[i] = names[ReadUInt16()].Value; } Writer.WriteLine(" [{0}]", string.Join(",", tags)); } return; case "EntityHandle": { /* * Read the first byte which will tell you what type of entity handle it is. * Values: * 0 - None - 0 bytes * 1 - Entity Guid - 32 bytes * 2 - IdTag - 17 bytes * * Then read off that variable type. * * IdTag: * 1 Byte - 0 = Static, 1 = Dynamic * 16 Bytes - Guid Value * Entity: * 16 Bytes - Guid Value * 16 Bytes - Unknown * */ var handletype = ReadByte(); switch (handletype) { //Entity case 1: var eguid = new CGUID(ReadBytes(16)); var unkn = ReadBytes(16); Writer.WriteLine(" [Entity - {0}]", eguid.ToString()); break; //IdTag case 2: var dynamic = ReadBoolean(); var guid = new CGUID(ReadBytes(16)); if (dynamic) { Writer.WriteLine(" [Dynamic: {0}]", guid.ToString()); } else { Writer.WriteLine(" [Static: {0}]", guid.ToString()); } break; } } return; case "static": { var length = ReadUInt32(); arr = arr[1].Split(new char[] { ',' }, 2); Writer.WriteLine(" {0}", length); Writer.WriteLine("{0}{{", offset.Substring(1)); for (uint i = 0; i < length; i++) { Writer.Write("{0}Id {1}:", offset, i); ParseVariale(arr[1], size, $"\t{offset}"); } Writer.WriteLine("{0}}}", offset.Substring(1)); } return; case "CDateTime": { var datetime = new CDateTime(ReadUInt64()); Writer.WriteLine(" {0}.{1}", datetime.ToString(), datetime.Value.Millisecond); } return; case "SharedDataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DataBuffer": { var datasize = ReadInt32(); var bytes = ReadBytes(datasize); Writer.WriteLine(" {0} bytes", datasize); } return; case "DeferredDataBuffer": { Writer.WriteLine(" {0}", ReadUInt16()); } return; case "CPhysicalCollision": { var unknown = ReadUInt32(); var nameCount = ReadByte(); Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); Writer.WriteLine("{0}unknown Uint32 {1}", offset, unknown); Writer.WriteLine("{0}Types", offset); Writer.WriteLine("{0}{{", offset); for (byte i = 0; i < nameCount; i++) { Writer.WriteLine("\t{0}Id {1}: {2}", offset, i, names[ReadUInt16()].Value); } Writer.WriteLine("{0}}}", offset); Writer.WriteLine("{0}Bytes {1}", offset, String.Join(", ", ReadBytes(16))); Writer.WriteLine("{0}}}", offset.Substring(1)); } return; } Type myType = Type.GetType($"CR2W.Types.W3.{type}"); if (myType != null) { if (myType.IsEnum) { if (myType.IsDefined(typeof(FlagsAttribute), false)) { var values = new List <string>(); while (true) { var flag = ReadUInt16(); if (flag == 0) { break; } values.Add(names[flag].Value); } if (values.Count != 0) { Writer.WriteLine(" {0}", Enum.Parse(myType, String.Join(",", values))); } else { Writer.WriteLine(" {0}", "None"); } } else { var value = names[ReadUInt16()].Value; Writer.WriteLine(" {0}", value); } return; } } Writer.WriteLine(); Writer.WriteLine("{0}{{", offset.Substring(1)); ReadVariable(offset); Writer.WriteLine("{0}}}", offset.Substring(1)); }