diff --git a/Caesar/Caesar/BitUtility.cs b/Caesar/Caesar/BitUtility.cs index c46290b..71f1fd1 100644 --- a/Caesar/Caesar/BitUtility.cs +++ b/Caesar/Caesar/BitUtility.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using System.Text; namespace Caesar @@ -80,6 +81,28 @@ public static byte[] PadBytes(byte[] inData, int finalSize) return result; } + [StructLayout(LayoutKind.Explicit)] + struct UIntFloat + { + [FieldOffset(0)] + public float FloatValue; + + [FieldOffset(0)] + public uint IntValue; + } + + /// + /// Directly converts an in-memory representation of an uint to a float. + /// + /// + /// + public static float ToFloat(uint value) + { + UIntFloat intermediate = new UIntFloat(); + intermediate.IntValue = value; + return intermediate.FloatValue; + } + // Caesar specific diff --git a/Caesar/Caesar/DiagPresentation.cs b/Caesar/Caesar/DiagPresentation.cs index 6afa3da..2ea490d 100644 --- a/Caesar/Caesar/DiagPresentation.cs +++ b/Caesar/Caesar/DiagPresentation.cs @@ -35,10 +35,10 @@ public class DiagPresentation public int Unk18; public int Unk19; public int TypeLength_1A; - public int Unk1b; + public int InternalDataType; // discovered by @prj : #37 public int Type_1C; public int Unk1d; - public int EnumType_1E; + public int SignBit; // discovered by @prj : #37 public int Unk1F; public int Unk20; @@ -126,11 +126,11 @@ public DiagPresentation(BinaryReader reader, long baseAddress, int presentations Unk19 = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); TypeLength_1A = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); - Unk1b = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); + InternalDataType = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); Type_1C = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); Unk1d = CaesarReader.ReadBitflagInt8(ref bitflags, reader); - EnumType_1E = CaesarReader.ReadBitflagInt8(ref bitflags, reader); + SignBit = CaesarReader.ReadBitflagInt8(ref bitflags, reader); Unk1F = CaesarReader.ReadBitflagInt8(ref bitflags, reader); Unk20 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); @@ -169,7 +169,7 @@ public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool 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)); + bool isEnumType = (SignBit == 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 @@ -212,11 +212,10 @@ public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool string humanReadableType = $"UnhandledType:{dataType}"; string parsedValue = BitUtility.BytesToHex(workingBytes, true); - if ((dataType == 6 || (dataType == 20))) + if (dataType == 20) { // parse as a regular int (BE) - - for (int i = 0; i < workingBytes.Length; i++) + for (int i = 0; i < workingBytes.Length; i++) { rawIntInterpretation <<= 8; rawIntInterpretation |= workingBytes[i]; @@ -225,7 +224,7 @@ public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool humanReadableType = "IntegerType"; parsedValue = rawIntInterpretation.ToString(); - if (dataType == 20) + if (dataType == 20) { humanReadableType = "ScaledType"; @@ -242,6 +241,31 @@ public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool parsedValue = valueToScale.ToString("0.000000"); } } + else if (dataType == 6) + { + // type 6 refers to either internal presentation types 8 (ieee754 float) or 5 (unsigned int?) + // these values are tagged with an exclamation [!] i (jglim) am not sure if they will work correctly yet + // specifically, i am not sure if the big endian float parsing is done correctly + uint rawUIntInterpretation = 0; + for (int i = 0; i < 4; i++) + { + rawUIntInterpretation <<= 8; + rawUIntInterpretation |= workingBytes[i]; + } + + if (InternalDataType == 8) + { + // interpret as big-endian float, https://github.com/jglim/CaesarSuite/issues/37 + parsedValue = BitUtility.ToFloat(rawUIntInterpretation).ToString(""); + humanReadableType = "Float [!]"; + } + else if (InternalDataType == 5) + { + // haven't seen this one around, will parse as a regular int (BE) for now + humanReadableType = "UnsignedIntegerType [!]"; + parsedValue = rawUIntInterpretation.ToString(); + } + } else if (dataType == 18) { humanReadableType = "HexdumpType"; @@ -315,7 +339,6 @@ public string InterpretData(byte[] inBytes, DiagPreparation inPreparation, bool public int GetDataType() { // see DIDiagServiceRealPresType - int result = -1; if (Unk14 != -1) { @@ -346,21 +369,21 @@ public int GetDataType() { return 18; // hexdump raw } - if (Unk1b != -1) + if (InternalDataType != -1) { - if (Unk1b == 6) + if (InternalDataType == 6) { return 17; // ascii dump } - else if (Unk1b == 7) + else if (InternalDataType == 7) { return 22; // ?? haven't seen this one around } - else if (Unk1b == 8) + else if (InternalDataType == 8) { - result = 6; // integer + result = 6; // IEEE754 float, discovered by @prj in https://github.com/jglim/CaesarSuite/issues/37 } - else if (Unk1b == 5) + else if (InternalDataType == 5) { // UNSIGNED integer (i haven't seen a const for uint around, sticking it into a regular int for now) // this will be an issue for 32-bit+ uints @@ -375,7 +398,7 @@ public int GetDataType() Console.WriteLine("typelength and type must be valid"); // might be good to throw an exception here } - if ((EnumType_1E == 1) || (EnumType_1E == 2)) + if ((SignBit == 1) || (SignBit == 2)) { result = 5; // ?? haven't seen this one around } @@ -424,10 +447,10 @@ public void PrintDebug() Console.WriteLine($"{nameof(Unk18)}: {Unk18}"); Console.WriteLine($"{nameof(Unk19)}: {Unk19}"); - Console.WriteLine($"{nameof(Unk1b)}: {Unk1b}"); + Console.WriteLine($"{nameof(InternalDataType)}: {InternalDataType}"); Console.WriteLine($"{nameof(Unk1d)}: {Unk1d}"); - Console.WriteLine($"{nameof(EnumType_1E)}: {EnumType_1E}"); + Console.WriteLine($"{nameof(SignBit)}: {SignBit}"); Console.WriteLine($"{nameof(Unk1F)}: {Unk1F}"); Console.WriteLine($"{nameof(Unk20)}: {Unk20}"); @@ -481,9 +504,9 @@ public string CopyMinDebug() sb.Append($" {nameof(Unk17)}: {Unk17}"); sb.Append($" {nameof(Unk18)}: {Unk18}"); sb.Append($" {nameof(Unk19)}: {Unk19}"); - sb.Append($" {nameof(Unk1b)}: {Unk1b}"); + sb.Append($" {nameof(InternalDataType)}: {InternalDataType}"); sb.Append($" {nameof(Unk1d)}: {Unk1d}"); - sb.Append($" {nameof(EnumType_1E)}: {EnumType_1E}"); + sb.Append($" {nameof(SignBit)}: {SignBit}"); sb.Append($" {nameof(Unk1F)}: {Unk1F}"); sb.Append($" {nameof(Unk20)}: {Unk20}"); sb.Append($" {nameof(TypeLengthBytesMaybe_21)}: {TypeLengthBytesMaybe_21}"); diff --git a/Caesar/Diogenes/Forms/AboutForm.Designer.cs b/Caesar/Diogenes/Forms/AboutForm.Designer.cs index f2e4ec5..21ec7c4 100644 --- a/Caesar/Diogenes/Forms/AboutForm.Designer.cs +++ b/Caesar/Diogenes/Forms/AboutForm.Designer.cs @@ -87,7 +87,7 @@ private void InitializeComponent() // this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnClose.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.btnClose.Location = new System.Drawing.Point(493, 325); + this.btnClose.Location = new System.Drawing.Point(493, 361); this.btnClose.Name = "btnClose"; this.btnClose.Size = new System.Drawing.Size(75, 23); this.btnClose.TabIndex = 4; @@ -97,6 +97,9 @@ private void InitializeComponent() // // lbCredits // + this.lbCredits.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.lbCredits.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40))))); this.lbCredits.BorderStyle = System.Windows.Forms.BorderStyle.None; this.lbCredits.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -105,16 +108,18 @@ private void InitializeComponent() this.lbCredits.ItemHeight = 17; this.lbCredits.Items.AddRange(new object[] { "Made possible with the help and support of these projects and individuals:", + "", "Mark James : http://www.famfamfam.com/about/", "Brian Humlicek : https://github.com/BrianHumlicek/J2534-Sharp/", "s30shiro (しーちゃん) : http://blog.livedoor.jp/s30shiro/", "@VladLupashevskyi (Vladyslav Lupashevskyi)", "@N0cynym (@N0cynym)", "@Feezex (Сергей)", - "@rnd-ash (Ashcon Mohseninia)"}); + "@rnd-ash (Ashcon Mohseninia)", + "@prj (@prj)"}); this.lbCredits.Location = new System.Drawing.Point(20, 180); this.lbCredits.Name = "lbCredits"; - this.lbCredits.Size = new System.Drawing.Size(548, 136); + this.lbCredits.Size = new System.Drawing.Size(548, 170); this.lbCredits.TabIndex = 5; // // AboutForm @@ -122,7 +127,7 @@ private void InitializeComponent() this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40))))); - this.ClientSize = new System.Drawing.Size(580, 360); + this.ClientSize = new System.Drawing.Size(580, 396); this.Controls.Add(this.lbCredits); this.Controls.Add(this.btnClose); this.Controls.Add(this.linkLabel1); diff --git a/Caesar/Diogenes/Forms/MainForm.cs b/Caesar/Diogenes/Forms/MainForm.cs index 6ba667b..c5c23fa 100644 --- a/Caesar/Diogenes/Forms/MainForm.cs +++ b/Caesar/Diogenes/Forms/MainForm.cs @@ -1130,16 +1130,13 @@ private void genericDebugToolStripMenuItem_Click(object sender, EventArgs e) { foreach (ECU ecu in container.CaesarECUs) { - foreach (DTC dtc in ecu.GlobalDTCs) + foreach (DiagPresentation pres in ecu.GlobalPresentations) { - byte[] dtcQualBytes = BitUtility.BytesFromHex(dtc.Qualifier.Substring(1)); - int dtcInt = (dtcQualBytes[0] << 16) | (dtcQualBytes[1] << 8) | dtcQualBytes[2]; - long remainder = dtcInt & 0xFFC00000; - if (remainder > 0) + Console.WriteLine($"Pres : {pres.Qualifier} : {pres.GetDataType()}"); + if (pres.InternalDataType == 8) { - throw new NotImplementedException("fail"); + throw new NotImplementedException("found a iee754 float!"); } - Console.WriteLine($"Q: {dtc.Qualifier} {dtcInt:X8} : {dtc.Description}"); } } } @@ -1168,7 +1165,7 @@ private void genericDebugToolStripMenuItem_Click(object sender, EventArgs e) if (scale.EnumUpBound >= 0) { string presOut = pres.InterpretData(BitUtility.BytesFromHex("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"), prep); - Console.WriteLine($"{ds.Qualifier} : {prep.Qualifier} @ {presOut} = {pres.Unk1b}, {pres.EnumMaxValue}"); + Console.WriteLine($"{ds.Qualifier} : {prep.Qualifier} @ {presOut} = {pres.InternalDataType}, {pres.EnumMaxValue}"); } } if (pres.Qualifier == "PRES_ZIELGANG")