static public RecordSpec[] Parse(byte[] data) { var records = new List <RecordSpec>(); int pos = 0; //A packet can contain more than one record. while (pos < data.Length - 2) //-2 for CRC bytes at end of packet. { if (data[pos] != 'U') //Check magic byte { pos += 1; //Console.WriteLine("PARSE ERROR!!!"); continue; } var len = data[pos + 1]; if (data[pos + 2] != 0)//Should always be zero (so far) { pos += 1; //Console.WriteLine("SIZE OVERFLOW!!!"); break; } var crc = data[pos + 3]; //todo Check crc. var id = BitConverter.ToUInt16(data, pos + 4); var xorBuf = new byte[256]; byte xorValue = data[pos + 6]; var recSpecId = /*len + "_" +*/ id.ToString(); //Console.WriteLine(recSpecId); if (recordSpecLookup.Keys.Contains(recSpecId)) { for (var i = 0; i < len; i++)//Decrypt payload. { xorBuf[i] = (byte)(data[pos + i] ^ xorValue); } int baseOffset = 10; var record = recordSpecLookup[recSpecId]; var newRecord = new RecordSpec() { name = record.name, id = record.id, definedIn = record.definedIn, len = record.len, fields = new List <FieldSpec>() }; var fields = record.fields; foreach (var field in fields) { var newField = new FieldSpec() { name = field.name, type = field.type, offset = field.offset, }; switch (field.type) { case "byte": field.value = xorBuf[baseOffset + field.offset]; break; case "short": field.value = BitConverter.ToInt16(xorBuf, baseOffset + field.offset); break; case "UInt16": field.value = BitConverter.ToUInt16(xorBuf, baseOffset + field.offset); break; case "int": field.value = BitConverter.ToInt32(xorBuf, baseOffset + field.offset); break; case "UInt32": field.value = BitConverter.ToUInt32(xorBuf, baseOffset + field.offset); break; case "float": field.value = BitConverter.ToSingle(xorBuf, baseOffset + field.offset); break; case "double": field.value = BitConverter.ToDouble(xorBuf, baseOffset + field.offset); break; case "string": field.value = System.Text.Encoding.Default.GetString(xorBuf, baseOffset + field.offset, len - 15); break; } newField.value = field.value; newRecord.fields.Add(newField); } //Console.WriteLine(record.ToString()); records.Add(newRecord); } else { Console.WriteLine("Not found:" + recSpecId + " len:" + len); } pos += len; } return(records.ToArray()); }
static void Main(string[] args) { var srcPath = "C:/Users/v-chph/Downloads/DatCon-master/DatCon/src/DatConRecs/"; var fileNames = Directory.GetFiles(srcPath, "*.java", SearchOption.AllDirectories); var typeLookup = new Dictionary <string, string> { { ".getByte(", "byte" }, { ".getUnsignedByte(", "byte" }, { ".getUnsignedInt(", "UInt32" }, { ".getUnsignedShort(", "UInt16" }, { ".getFloat(", "float" }, { ".getShort(", "short" }, { ".getInt(", "int" }, { ".getDouble(", "double" }, { ".getString(", "string" }, { ".getCleanString(", "string" } }; var specString = "new RecClassSpec("; var recSpecs = new Dictionary <string, RecordSpec>(); foreach (var fn in fileNames) { var lines = File.ReadAllLines(fn); foreach (var l in lines) { if (l.Contains(specString)) { if (l.Trim().StartsWith("//")) { continue; } var ia = l.IndexOf(specString) + specString.Length; var ib = l.IndexOf(".class"); if (ib < 0) { continue; } var name = l.Substring(ia, ib - ia); var parts = l.Substring(ib).Split(new char[] { ',', ')' }); if (parts.Length < 3) { continue; } var id = parts[1].Trim(); var len = parts[2].Trim(); Console.WriteLine("{0},{1},{2}", name, id, len); var cleanName = name.TrimEnd(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_' }); var dirName = Path.GetFileName(Directory.GetParent(fn).ToString()); recSpecs[name] = new RecordSpec { name = cleanName, id = id, len = len, definedIn = dirName }; } } } var allLines = new List <string>(); var validLines = new List <string>(); var invalidLines = new List <string>(); validLines.Add("definedIn,groupName,groupId,groupLen,name,offset,type,validParse,sourceLine"); foreach (var fn in fileNames) { var lines = File.ReadAllLines(fn); foreach (var l in lines) { foreach (var key in typeLookup.Keys) { if (l.Trim().StartsWith("//")) { continue; } if (l.Contains(key)) { var name = l.Split('=')[0].Trim(); var ia = l.IndexOf(key) + key.Length; var ib = l.IndexOf(')', ia); var offStr = l.Substring(ia, ib - ia); var valid = true; int off; if (typeLookup[key] == "string") { off = 0; } else if (!int.TryParse(offStr, out off)) { valid = false; } var groupName = Path.GetFileNameWithoutExtension(fn); var recSpec = new RecordSpec { name = "unk", id = "0", len = "0" }; if (recSpecs.Keys.Contains(groupName)) { recSpec = recSpecs[groupName]; } else { valid = false; } if (name.StartsWith("double "))//special case for a few lines that are defined like this. { name = name.Substring("double ".Length); } //groupName = groupName.TrimEnd(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_' }); var outLine = String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}", Path.GetFileName(Directory.GetParent(fn).ToString()), recSpec.name, recSpec.id, recSpec.len, name, off, typeLookup[key], valid, l.Trim()); if (recSpec.id == "65533") { } if (valid) { var field = new FieldSpec() { name = name, offset = off, type = typeLookup[key] }; recSpec.fields.Add(field); validLines.Add(outLine); } else { invalidLines.Add(outLine); } } } } } var destPath = "../../../TelloLib/"; File.WriteAllLines(destPath + "parsedRecSpecs.csv", validLines.Concat(invalidLines).ToArray()); string json = JsonConvert.SerializeObject(recSpecs.Values.ToArray(), Formatting.Indented); File.WriteAllText(destPath + "parsedRecSpecs.json", json); //var xx = JsonConvert.DeserializeObject(json); }