public VCSubfragment(BinaryReader reader, VCFragment parentFragment, CTFLanguage language, long baseAddress) { // see DIOpenCBF_FragValHandle reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt16(); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); if (parentFragment.CCFHandle == 5) { // fragment should be parsed as PBSGetDumpAsStringFn, though internally we perceive this as the same } Dump = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, parentFragment.VarcodeDumpSize, baseAddress); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); QualifierUsuallyDisabled = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Unk3 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Unk4 = CaesarReader.ReadBitflagInt16(ref bitflags, reader, -1); SupplementKey = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); NameCTFResolved = language.GetString(Description_CTF); //int subfragmentIdk2 = reader.ReadInt32(); //int subfragmentName = reader.ReadInt32(); //int subfragmentIdkIncremented = reader.ReadInt32(); //Console.WriteLine($"Subfragment: {subfragmentIdk1:X} {subfragmentIdk2:X} {language.GetString(subfragmentName)} {subfragmentIdkIncremented:X}"); //PrintDebug(); }
public void PrintDebug() { Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(BitPosition)} : {BitPosition}"); Console.WriteLine($"{nameof(ModeConfig)} : 0x{ModeConfig:X}"); Console.WriteLine($"Mode H : 0x{ModeConfig & 0xFF0:X}, L : 0x{ModeConfig & 0xF:X}"); Console.WriteLine($"{nameof(SizeInBits)} : 0x{SizeInBits:X}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Name_CTF)} : {Language.GetString(Name_CTF)}"); Console.WriteLine($"{nameof(Unk1)} : {Unk1}"); Console.WriteLine($"{nameof(Unk2)} : {Unk2}"); Console.WriteLine($"{nameof(AlternativeBitWidth)} : {AlternativeBitWidth}"); Console.WriteLine($"{nameof(IITOffset)} : {IITOffset}"); Console.WriteLine($"{nameof(InfoPoolIndex)} : {InfoPoolIndex}"); Console.WriteLine($"{nameof(PresPoolIndex)} : {PresPoolIndex}"); Console.WriteLine($"{nameof(Field1E)} : {Field1E}"); Console.WriteLine($"{nameof(SystemParam)} : {SystemParam}"); // Console.WriteLine($"{nameof(noIdea_T)} : {language.GetString(noIdea_T)}"); Console.WriteLine($"{nameof(Dump)} : {BitUtility.BytesToHex(Dump)}"); Console.WriteLine("---------------"); }
public ECU(BinaryReader reader, CTFLanguage language, CFFHeader header, long baseAddress, CaesarContainer parentContainer) { ParentContainer = parentContainer; BaseAddress = baseAddress; // Read 32+16 bits ulong ecuBitFlags = reader.ReadUInt32(); // after exhausting the 32 bits, load these additional 16 bits ulong ecuBitFlagsExtended = reader.ReadUInt16(); // Console.WriteLine($"ECU bitflags: {ecuBitFlags:X}"); // advancing forward to ecuBase + 10 int ecuHdrIdk1 = reader.ReadInt32(); // no idea // Console.WriteLine($"Skipping: {ecuHdrIdk1:X8}"); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress); EcuName_CTF = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader, -1); EcuDescription_CTF = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader, -1); EcuXmlVersion = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress); InterfaceBlockCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); InterfaceTableOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); SubinterfacesCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); SubinterfacesOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); EcuClassName = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress); UnkStr7 = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress); UnkStr8 = CaesarReader.ReadBitflagStringWithReader(ref ecuBitFlags, reader, BaseAddress); int dataBufferOffsetRelativeToFile = header.StringPoolSize + StubHeader.StubHeaderSize + header.CffHeaderSize + 4; // Console.WriteLine($"{nameof(dataBufferOffsetRelativeToFile)} : 0x{dataBufferOffsetRelativeToFile:X}"); IgnitionRequired = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader); Unk2 = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader); UnkBlockCount = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader); UnkBlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); EcuSgmlSource = CaesarReader.ReadBitflagInt16(ref ecuBitFlags, reader); Unk6RelativeOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); EcuVariant_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; EcuVariant_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); EcuVariant_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); EcuVariant_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); DiagJob_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; DiagJob_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); DiagJob_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); DiagJob_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Dtc_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; Dtc_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Dtc_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Dtc_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Env_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; Env_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Env_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); // bitflags will be exhausted at this point, load the extended bitflags ecuBitFlags = ecuBitFlagsExtended; Env_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); VcDomain_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; VcDomain_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); VcDomain_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); VcDomain_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Presentations_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; Presentations_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Presentations_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Presentations_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Info_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; Info_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Info_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Info_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Unk_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; Unk_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Unk_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Unk_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); Unk39 = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); // read ecu's supported interfaces and subtypes // try to read interface block from the interface buffer table // this address is relative to the definitions block long interfaceTableAddress = BaseAddress + InterfaceTableOffset; // Console.WriteLine($"Interface table address: {interfaceTableAddress:X}, given offset: {interfaceTableOffset:X}"); ECUInterfaces = new List <ECUInterface>(); for (int interfaceBufferIndex = 0; interfaceBufferIndex < InterfaceBlockCount; interfaceBufferIndex++) { // Console.WriteLine($"Parsing interface {interfaceBufferIndex + 1}/{interfaceBlockCount}"); // find our interface block offset reader.BaseStream.Seek(interfaceTableAddress + (interfaceBufferIndex * 4), SeekOrigin.Begin); // seek to the actual block (ambiguity: is this relative to the interface table or the current array?) int interfaceBlockOffset = reader.ReadInt32(); long ecuInterfaceBaseAddress = interfaceTableAddress + interfaceBlockOffset; ECUInterface ecuInterface = new ECUInterface(reader, ecuInterfaceBaseAddress); ECUInterfaces.Add(ecuInterface); } // try to read interface subtype block from the interface buffer table // this address is relative to the definitions block ECUInterfaceSubtypes = new List <ECUInterfaceSubtype>(); long ctTableAddress = BaseAddress + SubinterfacesOffset; // Console.WriteLine($"Interface subtype table address: {ctTableAddress:X}, given offset: {ecuChildTypesOffset:X}"); for (int ctBufferIndex = 0; ctBufferIndex < SubinterfacesCount; ctBufferIndex++) { // Console.WriteLine($"Parsing interface subtype {ctBufferIndex + 1}/{ecuNumberOfEcuChildTypes}"); // find our ct block offset reader.BaseStream.Seek(ctTableAddress + (ctBufferIndex * 4), SeekOrigin.Begin); // seek to the actual block (ambiguity: is this relative to the ct table or the current array?) int actualBlockOffset = reader.ReadInt32(); long ctBaseAddress = ctTableAddress + actualBlockOffset; ECUInterfaceSubtype ecuInterfaceSubtype = new ECUInterfaceSubtype(reader, ctBaseAddress, ctBufferIndex); ECUInterfaceSubtypes.Add(ecuInterfaceSubtype); } CreateDiagServices(reader, language); CreateEcuVariants(reader, language); CreatePresentations(reader, language); ECUDescriptionTranslated = language.GetString(EcuDescription_CTF); }
public VCDomain(BinaryReader reader, ECU parentEcu, CTFLanguage language, int variantCodingDomainEntry) { ParentECU = parentEcu; byte[] variantCodingPool = parentEcu.ReadVarcodingPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(variantCodingPool))) { poolReader.BaseStream.Seek(variantCodingDomainEntry * parentEcu.VcDomain_EntrySize, SeekOrigin.Begin); int entryOffset = poolReader.ReadInt32(); int entrySize = poolReader.ReadInt32(); uint entryCrc = poolReader.ReadUInt32(); long vcdBlockAddress = entryOffset + parentEcu.VcDomain_BlockOffset; // Console.WriteLine($"VCD Entry @ 0x{entryOffset:X} with size 0x{entrySize:X} and CRC {entryCrc:X8}, abs addr {vcdBlockAddress:X8}"); long baseAddress = vcdBlockAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt16(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); ReadServiceName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); WriteServiceName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); FragmentCount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FragmentTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader) + (int)baseAddress; // demoting long (warning) DumpSize = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DefaultStringCount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); StringTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Unk1 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); // PrintDebug(); VCFragments = new List <VCFragment>(); for (int fragmentIndex = 0; fragmentIndex < FragmentCount; fragmentIndex++) { VCFragment fragment = new VCFragment(reader, this, FragmentTableOffset, fragmentIndex, language); VCFragments.Add(fragment); } // ValidateFragmentCoverage(); if (DefaultStringCount > 0) { DefaultData = new List <Tuple <string, byte[]> >(); long stringTableBaseAddress = StringTableOffset + baseAddress; // this could almost be a class of its own but there isn't a distinct name to it for (int stringTableIndex = 0; stringTableIndex < DefaultStringCount; stringTableIndex++) { reader.BaseStream.Seek(stringTableBaseAddress + (4 * stringTableIndex), SeekOrigin.Begin); int offset = reader.ReadInt32(); long stringBaseAddress = stringTableBaseAddress + offset; reader.BaseStream.Seek(stringBaseAddress, SeekOrigin.Begin); ulong strBitflags = reader.ReadUInt16(); int nameUsuallyAbsent_T = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1); int offsetToBlob = CaesarReader.ReadBitflagInt32(ref strBitflags, reader); int blobSize = CaesarReader.ReadBitflagInt32(ref strBitflags, reader); int valueType_T = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1); string noIdeaStr1 = CaesarReader.ReadBitflagStringWithReader(ref strBitflags, reader, stringBaseAddress); int noIdea2_T = CaesarReader.ReadBitflagInt32(ref strBitflags, reader, -1); int noIdea3 = CaesarReader.ReadBitflagInt16(ref strBitflags, reader); string noIdeaStr2 = CaesarReader.ReadBitflagStringWithReader(ref strBitflags, reader, stringBaseAddress); byte[] blob = new byte[] { }; if (blobSize > 0) { long blobFileAddress = stringBaseAddress + offsetToBlob; reader.BaseStream.Seek(blobFileAddress, SeekOrigin.Begin); blob = reader.ReadBytes(blobSize); // memcpy } string valueType = language.GetString(valueType_T); DefaultData.Add(new Tuple <string, byte[]>(valueType, blob)); //Console.WriteLine($"Blob: {BitUtility.BytesToHex(blob)} @ {valueType}"); //Console.WriteLine($"String base address: 0x{stringBaseAddress:X}"); } } } }
public void PrintDebug() { Console.WriteLine($"DTC: {Qualifier}: {Language.GetString(Description_CTF)} : {Language.GetString(Reference_CTF)}"); }
public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool describe = true) { // might be relevant: DMPrepareSingleDatum, DMPresentSingleDatum bool isDebugBuild = false; #if DEBUG isDebugBuild = true; #endif string descriptionPrefix = describe ? $"{DescriptionString}: " : ""; byte[] workingBytes = inBytes.Skip(inPreparation.BitPosition / 8).Take(TypeLength_1A).ToArray(); bool isEnumType = (EnumType_1E == 0) && ((Type_1C == 1) || (ScaleCountMaybe > 1)); // hack: sometimes hybrid types (regularly parsed as an scaled value if within bounds) are misinterpreted as pure enums // this is a temporary fix for kilometerstand until there's a better way to ascertain its type // this also won't work on other similar cases without a unit string e.g. error instance counter (Häufigkeitszähler) if (DisplayedUnitString == "km") { isEnumType = false; } if (workingBytes.Length != TypeLength_1A) { return($"InBytes [{BitUtility.BytesToHex(workingBytes)}] length mismatch (expecting {TypeLength_1A})"); } // handle booleans first since they're the edge case where they can cross byte boundaries if (inPreparation.SizeInBits == 1) { int bytesToSkip = (int)(inPreparation.BitPosition / 8); int bitsToSkip = inPreparation.BitPosition % 8; byte selectedByte = inBytes[bytesToSkip]; int selectedBit = (selectedByte >> bitsToSkip) & 1; if (isEnumType && (Scales.Count > selectedBit)) { return($"{descriptionPrefix}{Language.GetString(Scales[selectedBit].EnumDescription)} {DisplayedUnitString}"); } else { return($"{descriptionPrefix}{selectedBit} {DisplayedUnitString}"); } } // everything else should be aligned to byte boundaries if (inPreparation.BitPosition % 8 != 0) { return("BitOffset was outside byte boundary (skipped)"); } int dataType = GetDataType(); int rawIntInterpretation = 0; string humanReadableType = $"UnhandledType:{dataType}"; string parsedValue = BitUtility.BytesToHex(workingBytes, true); if ((dataType == 6 || (dataType == 20))) { // parse as a regular int (BE) for (int i = 0; i < workingBytes.Length; i++) { rawIntInterpretation <<= 8; rawIntInterpretation |= workingBytes[i]; } humanReadableType = "IntegerType"; parsedValue = rawIntInterpretation.ToString(); if (dataType == 20) { humanReadableType = "ScaledType"; double valueToScale = rawIntInterpretation; // if there's only one scale, use it as-is // if there's more than one, use the first scale as an interim solution; // the results of stacking scales does not make sense // there might be a better, non-hardcoded (0) solution to this, and perhaps with a sig-fig specifier valueToScale *= Scales[0].MultiplyFactor; valueToScale += Scales[0].AddConstOffset; parsedValue = valueToScale.ToString("0.000000"); } } else if (dataType == 18) { humanReadableType = "HexdumpType"; } else if (dataType == 17) { humanReadableType = "StringType"; parsedValue = Encoding.UTF8.GetString(workingBytes); } if (isEnumType) { // discovered by @VladLupashevskyi in https://github.com/jglim/CaesarSuite/issues/27 // if an enum is specified, the inclusive upper bound and lower bound will be defined in the scale object bool useNewInterpretation = false; foreach (Scale scale in Scales) { if ((scale.EnumUpBound > 0) || (scale.EnumLowBound > 0)) { useNewInterpretation = true; break; } } if (useNewInterpretation) { foreach (Scale scale in Scales) { if ((rawIntInterpretation >= scale.EnumLowBound) && (rawIntInterpretation <= scale.EnumUpBound)) { return($"{descriptionPrefix}{Language.GetString(scale.EnumDescription)} {DisplayedUnitString}"); } } } else { // original implementation, probably incorrect if (rawIntInterpretation < Scales.Count) { return($"{descriptionPrefix}{Language.GetString(Scales[rawIntInterpretation].EnumDescription)} {DisplayedUnitString}"); } } return($"{descriptionPrefix}(Enum not found) {DisplayedUnitString}"); // this bit below for troubleshooting problematic presentations /* * if (rawIntInterpretation < Scales.Count) * { * return $"{descriptionPrefix}{Language.GetString(Scales[rawIntInterpretation].EnumDescription)} {DisplayedUnitString}"; * } * else * { * // seems like an enum-like value broke * return $"{descriptionPrefix}{Language.GetString(Scales[0].EnumDescription)} {DisplayedUnitString} [!]"; * } */ } else { if (isDebugBuild) { return($"{descriptionPrefix}{parsedValue} {DisplayedUnitString} ({humanReadableType})"); } else { return($"{descriptionPrefix}{parsedValue} {DisplayedUnitString}"); } } }
public string GetDescription() { return(Language.GetString(Description_CTF)); }
// 0x05 [6, 4,4,4,4, 4,4,4,4, 4,4,4,4, 2,2,2,4, 4,4,4,4, 4,4,4,4, 4,4,1,1, 1,1,1,4, 4,4,2,4, 4,4], public DiagPresentation(BinaryReader reader, long baseAddress, int presentationsIndex, CTFLanguage language) { BaseAddress = baseAddress; PresentationIndex = presentationsIndex; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); ulong extendedBitflags = reader.ReadUInt16(); // skip 2 bytes Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); ScaleTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); ScaleCountMaybe = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk5 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk6 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk7 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk8 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk9 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unka = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unkb = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unkc = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unkd = CaesarReader.ReadBitflagInt16(ref bitflags, reader); unke = CaesarReader.ReadBitflagInt16(ref bitflags, reader); unkf = CaesarReader.ReadBitflagInt16(ref bitflags, reader); DisplayedUnit_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk11 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk12 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk13 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk14 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk15 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Description2_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk17 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk18 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk19 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); TypeLength_1a = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk1b = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); Type_1c = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); unk1d = CaesarReader.ReadBitflagInt8(ref bitflags, reader); unk1e = CaesarReader.ReadBitflagInt8(ref bitflags, reader); unk1f = CaesarReader.ReadBitflagInt8(ref bitflags, reader); unk20 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); bitflags = extendedBitflags; unk21 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk22 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); unk23 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); unk24 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk25 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); unk26 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DescriptionString = language.GetString(Description_CTF); DisplayedUnitString = language.GetString(DisplayedUnit_CTF); DescriptionString2 = language.GetString(Description2_CTF); long scaleTableBase = BaseAddress + ScaleTableOffset; Scales = new List <Scale>(); for (int i = 0; i < ScaleCountMaybe; i++) { reader.BaseStream.Seek(scaleTableBase + (i * 4), SeekOrigin.Begin); int entryRelativeOffset = reader.ReadInt32(); Scale scale = new Scale(reader, scaleTableBase + entryRelativeOffset); Scales.Add(scale); } }
public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool describe = true) { // might be relevant: DMPrepareSingleDatum, DMPresentSingleDatum bool isDebugBuild = false; #if DEBUG isDebugBuild = true; #endif string descriptionPrefix = describe ? $"{DescriptionString}: " : ""; byte[] workingBytes = inBytes.Skip(inPreparation.BitPosition / 8).Take(TypeLength_1A).ToArray(); bool isEnumType = (EnumType_1E == 0) && ((Type_1C == 1) || (ScaleCountMaybe > 1)); if (workingBytes.Length != TypeLength_1A) { return($"InBytes [{BitUtility.BytesToHex(workingBytes)}] length mismatch (expecting {TypeLength_1A})"); } // handle booleans first since they're the edge case where they can cross byte boundaries if (inPreparation.SizeInBits == 1) { int bytesToSkip = (int)(inPreparation.BitPosition / 8); int bitsToSkip = inPreparation.BitPosition % 8; byte selectedByte = inBytes[bytesToSkip]; int selectedBit = (selectedByte >> bitsToSkip) & 1; if (isEnumType && (Scales.Count > selectedBit)) { return($"{descriptionPrefix}{Language.GetString(Scales[selectedBit].EnumDescription)} {DisplayedUnitString}"); } else { return($"{descriptionPrefix}{selectedBit} {DisplayedUnitString}"); } } // everything else should be aligned to byte boundaries if (inPreparation.BitPosition % 8 != 0) { return("BitOffset was outside byte boundary (skipped)"); } int dataType = GetDataType(); int rawIntInterpretation = 0; string humanReadableType = $"UnhandledType:{dataType}"; string parsedValue = BitUtility.BytesToHex(workingBytes, true); if ((dataType == 6 || (dataType == 20))) { // parse as a regular int (BE) for (int i = 0; i < workingBytes.Length; i++) { rawIntInterpretation <<= 8; rawIntInterpretation |= workingBytes[i]; } humanReadableType = "IntegerType"; parsedValue = rawIntInterpretation.ToString(); if (dataType == 20) { humanReadableType = "ScaledType"; double valueToScale = rawIntInterpretation; // if there's only one scale, use it as-is // if there's more than one, use the first scale as an interim solution; // the results of stacking scales does not make sense // there might be a better, non-hardcoded (0) solution to this, and perhaps with a sig-fig specifier valueToScale *= Scales[0].MultiplyFactor; valueToScale += Scales[0].AddConstOffset; parsedValue = valueToScale.ToString("0.000000"); } } else if (dataType == 18) { humanReadableType = "HexdumpType"; } else if (dataType == 17) { humanReadableType = "StringType"; parsedValue = Encoding.UTF8.GetString(workingBytes); } if (isEnumType && (rawIntInterpretation < Scales.Count)) { return($"{descriptionPrefix}{Language.GetString(Scales[rawIntInterpretation].EnumDescription)} {DisplayedUnitString}"); // this bit below for troubleshooting problematic presentations /* * if (rawIntInterpretation < Scales.Count) * { * return $"{descriptionPrefix}{Language.GetString(Scales[rawIntInterpretation].EnumDescription)} {DisplayedUnitString}"; * } * else * { * // seems like an enum-like value broke * return $"{descriptionPrefix}{Language.GetString(Scales[0].EnumDescription)} {DisplayedUnitString} [!]"; * } */ } else { if (isDebugBuild) { return($"{descriptionPrefix}{parsedValue} {DisplayedUnitString} ({humanReadableType})"); } else { return($"{descriptionPrefix}{parsedValue} {DisplayedUnitString}"); } } }