public void ToAbsolute() { long Position = BaseStream.Position; for (int Offset = 0; Offset < Header.RelocationLength; Offset += 4) { BaseStream.Seek(Header.RelocationAddress + Offset, SeekOrigin.Begin); uint Value = Reader.ReadUInt32(); uint PtrAddress = Value & 0x1ffffff; H3DSection Target = (H3DSection)((Value >> 25) & 0xf); H3DSection Source = (H3DSection)(Value >> 29); Target += GetLegacyRelocDiff(Target, Header.BackwardCompatibility); if (Target != H3DSection.Strings) { PtrAddress <<= 2; } Accumulate32(GetAddress(Source) + PtrAddress, GetAddress(Target)); } BaseStream.Seek(Position, SeekOrigin.Begin); }
private uint GetAddress(H3DSection Section) { switch (Section) { case H3DSection.Contents: return((uint)Header.ContentsAddress); case H3DSection.Strings: return((uint)Header.StringsAddress); case H3DSection.Commands: return((uint)Header.CommandsAddress); case H3DSection.CommandsSrc: return((uint)Header.CommandsAddress); case H3DSection.RawData: return((uint)Header.RawDataAddress); case H3DSection.RawDataTexture: return((uint)Header.RawDataAddress); case H3DSection.RawDataVertex: return((uint)Header.RawDataAddress); case H3DSection.RawDataIndex16: return((uint)Header.RawDataAddress | (1u << 31)); case H3DSection.RawDataIndex8: return((uint)Header.RawDataAddress); case H3DSection.RawExt: return((uint)Header.RawExtAddress); case H3DSection.RawExtTexture: return((uint)Header.RawExtAddress); case H3DSection.RawExtVertex: return((uint)Header.RawExtAddress); case H3DSection.RawExtIndex16: return((uint)Header.RawExtAddress | (1u << 31)); case H3DSection.RawExtIndex8: return((uint)Header.RawExtAddress); } return(0); }
private uint ToRelative(long Position, H3DSection Relocation) { switch (Relocation) { case H3DSection.Contents: return((uint)(Position - Header.ContentsAddress)); case H3DSection.Strings: return((uint)(Position - Header.StringsAddress)); case H3DSection.Commands: return((uint)(Position - Header.CommandsAddress)); case H3DSection.RawData: return((uint)(Position - Header.RawDataAddress)); case H3DSection.RawExt: return((uint)(Position - Header.RawExtAddress)); } return((uint)Position); }
public static void AddCmdReloc(BinarySerializer Serializer, H3DSection Target, long Pointer) { Section Commands = Serializer.Sections[(uint)H3DSectionId.Commands]; Section Relocation = Serializer.Sections[(uint)H3DSectionId.Relocation]; uint PointerAddress = (uint)(Pointer - Commands.Position) >> 2; Target -= GetLegacyRelocDiff(Target, Serializer.FileVersion); uint Flags; Flags = (uint)Target; Flags |= (uint)H3DSection.Commands << 4; CheckPtrOvr(PointerAddress); Relocation.Values.Add(new RefValue(PointerAddress | (Flags << 25))); }
public void ToRelative(BinarySerializer Serializer) { foreach (long Pointer in Serializer.Pointers) { long Position = BaseStream.Position; BaseStream.Seek(Pointer, SeekOrigin.Begin); uint TargetAddress = Peek32(); H3DSection Target = GetRelocation(TargetAddress); H3DSection Source = GetRelocation(Pointer); uint PointerAddress = ToRelative(Pointer, Source); if (Target != H3DSection.Strings) { PointerAddress >>= 2; } Writer.Write(ToRelative(TargetAddress, Target)); Target -= GetLegacyRelocDiff(Target, Header.BackwardCompatibility); uint Flags; Flags = (uint)Target; Flags |= (uint)Source << 4; CheckPtrOvr(PointerAddress); BaseStream.Seek(Position, SeekOrigin.Begin); //Commands are written right before the command is serialized. //The AddCmdReloc is used for that, so we don't need to write it agian. //The reason for this is because Commands needs flags that depends on the data format. if (Source != H3DSection.Commands) { Writer.Write(PointerAddress | (Flags << 25)); } } Header.RelocationLength = (int)(BaseStream.Length - Header.RelocationAddress); }
bool ICustomSerialization.Serialize(BinarySerializer Serializer) { Serializer.Writer.Write(Type); Serializer.Writer.Write((byte)DrawMode); Serializer.Writer.Write((ushort)Indices.Length); H3DSection Section = H3DSection.RawDataIndex16; object Data; if (MaxIndex <= byte.MaxValue) { Section = H3DSection.RawDataIndex8; byte[] Buffer = new byte[Indices.Length]; for (int Index = 0; Index < Indices.Length; Index++) { Buffer[Index] = (byte)Indices[Index]; } Data = Buffer; } else { Data = Indices; } long Position = Serializer.BaseStream.Position; H3DRelocator.AddCmdReloc(Serializer, Section, Position); Serializer.Sections[(uint)H3DSectionId.RawData].Values.Add(new RefValue() { Parent = this, Position = Position, Value = Data }); Serializer.BaseStream.Seek(4, SeekOrigin.Current); return(true); }
private static int GetLegacyRelocDiff(H3DSection Section, int BC) { //The enumeration for older H3D versions was different because some sections //didn't exist at the time, so we need to account for that. //This is done returning an offset to be applied to the enumeration value, //when the data is deserialized, this offset is added to the value from //the file, and when it's serialized it is subtracted from the value computed by //the serializer. if (BC > 7 && BC < 0x21 && Section >= H3DSection.RawDataVertex) { return(-1); } else if (BC < 7 && Section >= H3DSection.CommandsSrc) { return(1); } else { return(0); } }