Repository: jglim/CaesarSuite Branch: main Commit: f8e8463f94aa Files: 110 Total size: 1.1 MB Directory structure: gitextract_yphdzm_6/ ├── .gitignore ├── Caesar/ │ ├── Caesar/ │ │ ├── App.config │ │ ├── BitUtility.cs │ │ ├── CFFHeader.cs │ │ ├── CTFHeader.cs │ │ ├── CTFLanguage.cs │ │ ├── Caesar.csproj │ │ ├── CaesarContainer.cs │ │ ├── CaesarReader.cs │ │ ├── CaesarStructure.cs │ │ ├── ComParameter.cs │ │ ├── DSCContext.cs │ │ ├── DTC.cs │ │ ├── DiagPreparation.cs │ │ ├── DiagPresentation.cs │ │ ├── DiagService.cs │ │ ├── ECU.cs │ │ ├── ECUInterface.cs │ │ ├── ECUInterfaceSubtype.cs │ │ ├── ECUVariant.cs │ │ ├── ECUVariantPattern.cs │ │ ├── Flash/ │ │ │ ├── CaesarFlashContainer.cs │ │ │ ├── FlashDataBlock.cs │ │ │ ├── FlashDescriptionHeader.cs │ │ │ ├── FlashHeader.cs │ │ │ ├── FlashSecurity.cs │ │ │ └── FlashSegment.cs │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Scale.cs │ │ ├── StubHeader.cs │ │ ├── VCDomain.cs │ │ ├── VCFragment.cs │ │ ├── VCSubfragment.cs │ │ └── packages.config │ ├── Caesar.sln │ ├── Diogenes/ │ │ ├── App.config │ │ ├── DiagnosticProtocol/ │ │ │ ├── BaseProtocol.cs │ │ │ ├── KW2C3PE.cs │ │ │ ├── UDS.cs │ │ │ └── UnsupportedProtocol.cs │ │ ├── Diogenes.csproj │ │ ├── ECUConnection.cs │ │ ├── ECUFlashMetadata.cs │ │ ├── ECUIdentification.cs │ │ ├── ECUMetadata.cs │ │ ├── Forms/ │ │ │ ├── AboutForm.Designer.cs │ │ │ ├── AboutForm.cs │ │ │ ├── AboutForm.resx │ │ │ ├── BlockDownload.Designer.cs │ │ │ ├── BlockDownload.cs │ │ │ ├── BlockDownload.resx │ │ │ ├── DTCForm.Designer.cs │ │ │ ├── DTCForm.cs │ │ │ ├── DTCForm.resx │ │ │ ├── FlashSplicer.Designer.cs │ │ │ ├── FlashSplicer.cs │ │ │ ├── FlashSplicer.resx │ │ │ ├── GenericLoader.Designer.cs │ │ │ ├── GenericLoader.cs │ │ │ ├── GenericLoader.resx │ │ │ ├── GenericPicker.Designer.cs │ │ │ ├── GenericPicker.cs │ │ │ ├── GenericPicker.resx │ │ │ ├── MainForm.Designer.cs │ │ │ ├── MainForm.cs │ │ │ ├── MainForm.resx │ │ │ ├── PickDiagForm.Designer.cs │ │ │ ├── PickDiagForm.cs │ │ │ ├── PickDiagForm.resx │ │ │ ├── RunDiagForm.Designer.cs │ │ │ ├── RunDiagForm.cs │ │ │ ├── RunDiagForm.resx │ │ │ ├── SecurityLevelForm.Designer.cs │ │ │ ├── SecurityLevelForm.cs │ │ │ ├── SecurityLevelForm.resx │ │ │ ├── TraceForm.Designer.cs │ │ │ ├── TraceForm.cs │ │ │ ├── TraceForm.resx │ │ │ ├── UDSHexEditor.Designer.cs │ │ │ ├── UDSHexEditor.cs │ │ │ ├── UDSHexEditor.resx │ │ │ ├── VCForm.Designer.cs │ │ │ ├── VCForm.cs │ │ │ └── VCForm.resx │ │ ├── Preferences.cs │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── Reports/ │ │ │ ├── DTCReport.cs │ │ │ └── VCReport.cs │ │ ├── SecurityAccess/ │ │ │ ├── DllContext.cs │ │ │ ├── ExportDefinition.cs │ │ │ └── SecurityAutoLogin.cs │ │ ├── Simulation/ │ │ │ ├── SimulatedDevice.cs │ │ │ └── Simulated_CRD3.cs │ │ ├── TextboxWriter.cs │ │ ├── UnmanagedUtility.cs │ │ ├── VariantCoding.cs │ │ └── packages.config │ └── Trafo/ │ ├── App.config │ ├── Program.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── Trafo.csproj │ └── packages.config ├── LICENSE └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Mono auto generated files mono_crash.* # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUnit *.VisualState.xml TestResult.xml nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # NuGet Symbol Packages *.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx *.appxbundle *.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser *- [Bb]ackup.rdl *- [Bb]ackup ([0-9]).rdl *- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ # BeatPulse healthcheck temp database healthchecksdb # Backup folder for Package Reference Convert tool in Visual Studio 2017 MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ ================================================ FILE: Caesar/Caesar/App.config ================================================  ================================================ FILE: Caesar/Caesar/BitUtility.cs ================================================ using System; using System.Runtime.InteropServices; using System.Text; namespace Caesar { /// /// Utilities for bit and byte operations. /// (Frequently copied-and-pasted across my projects) /// public class BitUtility { /// /// Sets all values in an array of bytes to a specific value /// /// Value to set byte array to /// Target byte array buffer public static void Memset(byte value, byte[] buf) { for (int i = 0; i < buf.Length; i++) { buf[i] = value; } } // Internally used by BytesFromHex private static byte[] StringToByteArrayFastest(string hex) { // see https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array if (hex.Length % 2 == 1) { throw new Exception("The binary key cannot have an odd number of digits"); } byte[] arr = new byte[hex.Length >> 1]; for (int i = 0; i < hex.Length >> 1; ++i) { arr[i] = (byte)((GetHexValue(hex[i << 1]) << 4) + (GetHexValue(hex[(i << 1) + 1]))); } return arr; } // Internally used by StringToByteArrayFastest private static int GetHexValue(char hex) { int val = (int)hex; return val - (val < 58 ? 48 : 55); } /// /// Converts an array of bytes into its hex-string equivalent /// /// Input byte array /// Option to add spaces between individual bytes /// Hex-string based on the input byte array public static string BytesToHex(byte[] inBytes, bool spacedOut = false) { return BitConverter.ToString(inBytes).Replace("-", spacedOut ? " " : ""); } /// /// Converts an array of bytes into a printable hex-string /// /// Input hex-string to convert into a byte array /// Byte array based on the input hex-string public static byte[] BytesFromHex(string hexString) { return StringToByteArrayFastest(hexString.Replace(" ", "")); } /// /// Resize a smaller array of bytes to a larger array. The padding bytes will be 0. /// /// Input byte array /// New size for the input array /// Resized byte array public static byte[] PadBytes(byte[] inData, int finalSize) { if (inData.Length > finalSize) { return inData; } byte[] result = new byte[finalSize]; Buffer.BlockCopy(inData, 0, result, 0, inData.Length); 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 public static byte[] BitArrayToByteArray(byte[] inArray, bool littleEndian = true) { if (inArray.Length % 8 != 0) { throw new NotImplementedException("Bits must be byte-aligned"); } byte[] result = new byte[inArray.Length / 8]; byte workingByte = 0; int arrayIndex = 0; for (int i = 0; i < inArray.Length; i++) { if (littleEndian) { workingByte >>= 1; workingByte |= (inArray[i] == 0) ? (byte)0 : (byte)0x80; } else { workingByte <<= 1; workingByte |= inArray[i]; } if (i % 8 == 7) { result[arrayIndex] = workingByte; arrayIndex++; } } return result; } public static byte[] ByteArrayToBitArray(byte[] inArray, bool littleEndian = true) { byte[] result = new byte[inArray.Length * 8]; int arrayIndex = 0; foreach (byte inByte in inArray) { if (littleEndian) { for (int i = 0; i < 8; i++) { bool bitSet = ((1 << i) & inByte) > 0; result[arrayIndex] = (bitSet ? (byte)1 : (byte)0); arrayIndex++; } } else { for (int i = 7; i >= 0; i--) { bool bitSet = ((1 << i) & inByte) > 0; result[arrayIndex] = (bitSet ? (byte)1 : (byte)0); arrayIndex++; } } } return result; } public static string BytesToBitString(byte[] inArray) { StringBuilder sb = new StringBuilder(); foreach (byte b in inArray) { sb.Append(Convert.ToString(b, toBase: 2).PadLeft(8, '0') + " "); } return sb.ToString().TrimEnd(); } public static string BytesToDecimalString(byte[] inArray) { StringBuilder sb = new StringBuilder(); foreach (byte b in inArray) { sb.Append(Convert.ToString(b, toBase: 10).PadLeft(3, '0') + " "); } return sb.ToString().TrimEnd(); } public static byte[] BytesFromDecimalString(string inData) { string[] chunks = inData.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); byte[] result = new byte[chunks.Length]; for (int i = 0; i < chunks.Length; i++) { result[i] = byte.Parse(chunks[i]); } return result; } public static string BitsToString(byte[] inArray) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < inArray.Length; i++) { sb.Append(inArray[i]); if (i % 8 == 7) { sb.Append(" "); } } return sb.ToString(); } public void BitRoundtripTest() { byte[] bitarray = new byte[] { 1,1,1,1, 1,1,1,1, 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1, 0,0,0,0, 0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0, 1,1,1,1, }; byte[] testByteArray = BitUtility.BitArrayToByteArray(bitarray, false); Console.WriteLine($"test in 1: {BitUtility.BytesToBitString(testByteArray)}"); Console.WriteLine($"test in 1: {BitUtility.BytesToHex(testByteArray)}"); foreach (byte b in bitarray) { Console.Write(b); } Console.WriteLine(); byte[] testBitArray = BitUtility.ByteArrayToBitArray(testByteArray, false); testByteArray = BitUtility.BitArrayToByteArray(testBitArray); Console.WriteLine($"test in 2: {BitUtility.BytesToBitString(testByteArray)}"); Console.WriteLine($"test in 2: {BitUtility.BytesToHex(testByteArray)}"); foreach (byte b in testBitArray) { Console.Write(b); } Console.WriteLine(); } public static bool CheckHexValid(string inHex) { string cleanedText = inHex.Replace(" ", "").Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("-", "").ToUpper(); if (cleanedText.Length % 2 != 0) { return false; } if (!System.Text.RegularExpressions.Regex.IsMatch(cleanedText, @"\A\b[0-9a-fA-F]+\b\Z")) { return false; } return true; } } } ================================================ FILE: Caesar/Caesar/CFFHeader.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class CFFHeader { public int CaesarVersion; public int GpdVersion; public int EcuCount; public int EcuOffset; public int CtfOffset; // nCtfHeaderRpos public int StringPoolSize; private int DscOffset; private int DscCount; private int DscEntrySize; public string CbfVersionString; public string GpdVersionString; public string XmlString; [Newtonsoft.Json.JsonIgnore] public int CffHeaderSize; [Newtonsoft.Json.JsonIgnore] public long BaseAddress; public long DscBlockOffset; private int DscBlockSize; [Newtonsoft.Json.JsonIgnore] public byte[] DSCPool = new byte[] { }; // DIIAddCBFFile public CFFHeader() { } public CFFHeader(BinaryReader reader) { reader.BaseStream.Seek(StubHeader.StubHeaderSize, SeekOrigin.Begin); CffHeaderSize = reader.ReadInt32(); BaseAddress = reader.BaseStream.Position; ulong bitFlags = reader.ReadUInt16(); CaesarVersion = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); GpdVersion = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); EcuCount = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); EcuOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); CtfOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); StringPoolSize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); DscOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); DscCount = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); DscEntrySize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); CbfVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); GpdVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); XmlString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); long dataBufferOffsetAfterStrings = StringPoolSize + CffHeaderSize + 0x414; if (DscCount > 0) { DscBlockOffset = DscOffset + dataBufferOffsetAfterStrings; DscBlockSize = DscEntrySize * DscCount; reader.BaseStream.Seek(DscBlockOffset, SeekOrigin.Begin); DSCPool = reader.ReadBytes(DscBlockSize); } } public void PrintDebug() { Console.WriteLine($"{nameof(CaesarVersion)} : {CaesarVersion}"); Console.WriteLine($"{nameof(GpdVersion)} : {GpdVersion}"); Console.WriteLine($"{nameof(EcuCount)} : {EcuCount}"); Console.WriteLine($"{nameof(EcuOffset)} : {EcuOffset} 0x{EcuOffset:X}"); Console.WriteLine($"{nameof(CtfOffset)} : 0x{CtfOffset:X}"); Console.WriteLine($"{nameof(StringPoolSize)} : {StringPoolSize} 0x{StringPoolSize:X}"); Console.WriteLine($"{nameof(DscEntrySize)} : {DscEntrySize}"); Console.WriteLine($"{nameof(CbfVersionString)} : {CbfVersionString}"); Console.WriteLine($"{nameof(GpdVersionString)} : {GpdVersionString}"); Console.WriteLine($"{nameof(DscOffset)} : {DscOffset} 0x{DscOffset:X}"); Console.WriteLine($"{nameof(DscBlockOffset)} : {DscBlockOffset} 0x{DscBlockOffset:X}"); Console.WriteLine($"{nameof(DscCount)} : {DscCount}"); Console.WriteLine($"{nameof(DscBlockSize)} : {DscCount}"); } } } ================================================ FILE: Caesar/Caesar/CTFHeader.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class CTFHeader { public int CtfUnk1; public string Qualifier; public int CtfUnk3; public int CtfUnk4; private int CtfLanguageCount; private int CtfLanguageTableOffset; public string CtfUnkString; public List CtfLanguages; public long BaseAddress; public CTFHeader() { } public CTFHeader(BinaryReader reader, long baseAddress, int headerSize) { BaseAddress = baseAddress; reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong ctfBitflags = reader.ReadUInt16(); CtfUnk1 = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref ctfBitflags, reader, BaseAddress); CtfUnk3 = CaesarReader.ReadBitflagInt16(ref ctfBitflags, reader); CtfUnk4 = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader); CtfLanguageCount = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader); CtfLanguageTableOffset = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader); CtfUnkString = CaesarReader.ReadBitflagStringWithReader(ref ctfBitflags, reader, BaseAddress); long ctfLanguageTableOffsetRelativeToDefintions = CtfLanguageTableOffset + BaseAddress; // parse every language record CtfLanguages = new List(); for (int languageEntry = 0; languageEntry < CtfLanguageCount; languageEntry++) { long languageTableEntryOffset = ctfLanguageTableOffsetRelativeToDefintions + (languageEntry * 4); reader.BaseStream.Seek(languageTableEntryOffset, SeekOrigin.Begin); long realLanguageEntryAddress = reader.ReadInt32() + ctfLanguageTableOffsetRelativeToDefintions; CTFLanguage language = new CTFLanguage(reader, realLanguageEntryAddress, headerSize); CtfLanguages.Add(language); } } public void PrintDebug() { Console.WriteLine("----------- CTF header ----------- "); Console.WriteLine($"{nameof(CtfUnk1)} : {CtfUnk1}"); Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(CtfUnk3)} : {CtfUnk3}"); Console.WriteLine($"{nameof(CtfUnk4)} : {CtfUnk4}"); Console.WriteLine($"{nameof(CtfLanguageCount)} : {CtfLanguageCount}"); Console.WriteLine($"{nameof(CtfLanguageTableOffset)} : 0x{CtfLanguageTableOffset:X}"); Console.WriteLine($"{nameof(CtfUnkString)} : {CtfUnkString}"); } } } ================================================ FILE: Caesar/Caesar/CTFLanguage.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class CTFLanguage { public string Qualifier; public int LanguageIndex; private int StringPoolSize; private int MaybeOffsetFromStringPoolBase; private int StringCount; public List StringEntries; public long BaseAddress; public CTFLanguage() { } public CTFLanguage(BinaryReader reader, long baseAddress, int headerSize) { BaseAddress = baseAddress; reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong languageEntryBitflags = reader.ReadUInt16(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref languageEntryBitflags, reader, BaseAddress); LanguageIndex = CaesarReader.ReadBitflagInt16(ref languageEntryBitflags, reader); StringPoolSize = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader); MaybeOffsetFromStringPoolBase = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader); StringCount = CaesarReader.ReadBitflagInt32(ref languageEntryBitflags, reader); LoadStrings(reader, headerSize, CaesarReader.DefaultEncoding); } public void LoadStrings(BinaryReader reader, int headerSize, Encoding encoding) { StringEntries = new List(); int caesarStringTableOffset = headerSize + 0x410 + 4; // header.CffHeaderSize; strange that this has to be manually computed for (int i = 0; i < StringCount; i++) { reader.BaseStream.Seek(caesarStringTableOffset + (i * 4), SeekOrigin.Begin); int stringOffset = reader.ReadInt32(); reader.BaseStream.Seek(caesarStringTableOffset + stringOffset, SeekOrigin.Begin); string result = CaesarReader.ReadStringFromBinaryReader(reader, encoding); StringEntries.Add(result); } } public string GetString(int stringId) { return GetString(StringEntries, stringId); } public static string GetString(List language, int stringId) { if (stringId < 0) { return ""; } if (stringId > language.Count) { return ""; } return language[stringId]; } public void PrintDebug() { Console.WriteLine($"Language: {Qualifier} stringCount: {StringCount} stringPoolSize 0x{StringPoolSize:X}, unknowns: {LanguageIndex} {MaybeOffsetFromStringPoolBase}, base: {BaseAddress:X} "); } } } ================================================ FILE: Caesar/Caesar/Caesar.csproj ================================================  Debug AnyCPU {71C43C61-7DC7-4D47-9947-1DD73E559911} Library Caesar Caesar v4.6 512 true true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 false AnyCPU pdbonly true bin\Release\ TRACE prompt 4 false caesar_256.ico ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll ================================================ FILE: Caesar/Caesar/CaesarContainer.cs ================================================ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace Caesar { public class CaesarContainer { public CFFHeader CaesarCFFHeader; public CTFHeader CaesarCTFHeader; public List CaesarECUs = new List(); [Newtonsoft.Json.JsonIgnore] public byte[] FileBytes = new byte[] { }; public uint FileChecksum; public CaesarContainer() { } // fixup serialization/deserialization: // language strings should be properties; resolve to actual string only when called public CaesarContainer(byte[] fileBytes) { Stopwatch sw = new Stopwatch(); sw.Start(); FileBytes = fileBytes; // work from int __cdecl DIIAddCBFFile(char *fileName) using (BinaryReader reader = new BinaryReader(new MemoryStream(fileBytes, 0, fileBytes.Length, false, true))) { byte[] header = reader.ReadBytes(StubHeader.StubHeaderSize); StubHeader.ReadHeader(header); int cffHeaderSize = reader.ReadInt32(); byte[] cffHeaderData = reader.ReadBytes(cffHeaderSize); // expensive, probably an impediment for modders // VerifyChecksum(fileBytes, out uint checksum); FileChecksum = ReadFileChecksum(fileBytes); ReadCFFDefinition(reader); // language is the highest priority since all our strings come from it ReadCTF(reader); ReadECU(reader); } sw.Stop(); #if DEBUG Console.WriteLine($"Loaded {CaesarECUs[0].Qualifier} in {sw.ElapsedMilliseconds}ms"); #endif } public static string SerializeContainer(CaesarContainer container) { return JsonConvert.SerializeObject(container); } public static CaesarContainer DeserializeContainer(string json) { CaesarContainer container = JsonConvert.DeserializeObject(json); // at this point, the container needs to restore its internal object references before it is fully usable CTFLanguage language = container.CaesarCTFHeader.CtfLanguages[0]; foreach (ECU ecu in container.CaesarECUs) { ecu.Restore(language, container); } return container; } public static CaesarContainer DeserializeCompressedContainer(byte[] containerBytes) { string json = Encoding.UTF8.GetString(Inflate(containerBytes)); return DeserializeContainer(json); } public static byte[] SerializeCompressedContainer(CaesarContainer container) { return Deflate(Encoding.UTF8.GetBytes(SerializeContainer(container))); } private static byte[] Inflate(byte[] input) { using (MemoryStream ms = new MemoryStream(input)) { using (MemoryStream msInner = new MemoryStream()) { using (DeflateStream z = new DeflateStream(ms, CompressionMode.Decompress)) { z.CopyTo(msInner); } return msInner.ToArray(); } } } private static byte[] Deflate(byte[] input) { using (MemoryStream compressedStream = new MemoryStream()) { DeflateStream deflateStream = new DeflateStream(compressedStream, CompressionLevel.Optimal, true); deflateStream.Write(input, 0, input.Length); deflateStream.Close(); return compressedStream.ToArray(); } } public static bool VerifyChecksum(byte[] fileBytes, out uint checksum) { uint computedChecksum = CaesarReader.ComputeFileChecksumLazy(fileBytes); uint providedChecksum = ReadFileChecksum(fileBytes); checksum = providedChecksum; if (computedChecksum != providedChecksum) { Console.WriteLine($"WARNING: Checksum mismatch : computed/provided: {computedChecksum:X8}/{providedChecksum:X8}"); return false; } return true; } public static string GetCaesarVersionString() { System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); return fvi.FileVersion; } public static uint ReadFileChecksum(byte[] fileBytes) { return BitConverter.ToUInt32(fileBytes, fileBytes.Length - 4); } public ECUVariant GetECUVariantByName(string name) { foreach (ECU ecu in CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { if (variant.Qualifier == name) { return variant; } } } return null; } public ECU GetECUByName(string name) { foreach (ECU ecu in CaesarECUs) { if (ecu.Qualifier == name) { return ecu; } } return null; } public string[] GetECUVariantNames() { List result = new List(); foreach (ECU ecu in CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { result.Add(variant.Qualifier); } } return result.ToArray(); } public CTFLanguage GetLanguage() { if (CaesarCTFHeader.CtfLanguages is null) { throw new NotImplementedException("stringtable not initialized"); } if (CaesarCTFHeader.CtfLanguages.Count != 0) { return CaesarCTFHeader.CtfLanguages[0]; } throw new NotImplementedException("no idea how to handle missing stringtable"); } void ReadECU(BinaryReader fileReader) { CaesarECUs = new List(); // read all ecu definitions long ecuTableOffset = CaesarCFFHeader.EcuOffset + CaesarCFFHeader.BaseAddress; for (int ecuIndex = 0; ecuIndex < CaesarCFFHeader.EcuCount; ecuIndex++) { // seek to an entry the ecu offsets table fileReader.BaseStream.Seek(ecuTableOffset + (ecuIndex * 4), SeekOrigin.Begin); // read the offset to the ecu entry, then seek to the actual address int offsetToActualEcuEntry = fileReader.ReadInt32(); CaesarECUs.Add(new ECU(fileReader, GetLanguage(), CaesarCFFHeader, ecuTableOffset + offsetToActualEcuEntry, this)); } } void ReadCTF(BinaryReader fileReader) { // parse CTF language stuff // approx 0x1304 / 4 number of strings? if (CaesarCFFHeader.CtfOffset == 0) { throw new NotImplementedException("No idea how to handle nonexistent ctf header"); } long ctfOffset = CaesarCFFHeader.BaseAddress + CaesarCFFHeader.CtfOffset; CaesarCTFHeader = new CTFHeader(fileReader, ctfOffset, CaesarCFFHeader.CffHeaderSize); } void ReadCFFDefinition(BinaryReader fileReader) { CaesarCFFHeader = new CFFHeader(fileReader); // CaesarCFFHeader.PrintDebug(); if (CaesarCFFHeader.CaesarVersion < 400) { throw new NotImplementedException($"Unhandled Caesar version: {CaesarCFFHeader.CaesarVersion}"); } int caesarStringTableOffset = CaesarCFFHeader.CffHeaderSize + 0x410 + 4; int formEntryTable = caesarStringTableOffset + CaesarCFFHeader.StringPoolSize; //Console.WriteLine($"{nameof(caesarStringTableOffset)} : 0x{caesarStringTableOffset:X}"); //Console.WriteLine($"{nameof(afterStringTableOffset)} : 0x{afterStringTableOffset:X}"); /* if (CaesarCFFHeader.FormEntries > 0) { int formOffsetTable = CaesarCFFHeader.unk2RelativeOffset + formEntryTable; int formOffsetTableSize = CaesarCFFHeader.FormEntrySize * CaesarCFFHeader.FormEntries; Console.WriteLine($"after string table block (*.fm) is present: {nameof(formEntryTable)} : 0x{formEntryTable:X}\n\n"); Console.WriteLine($"{nameof(formOffsetTable)} : 0x{formOffsetTable:X}\n\n"); Console.WriteLine($"{nameof(formOffsetTableSize)} : 0x{formOffsetTableSize:X}\n\n"); } */ } public string GetFileSize() { return BytesToString(FileBytes.Length); } private static string BytesToString(long byteCount) { string[] suf = { " B", " KB", " MB", " GB", " TB", " PB", " EB" }; //Longs run out around EB if (byteCount == 0) { return "0" + suf[0]; } long bytes = Math.Abs(byteCount); int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); double num = Math.Round(bytes / Math.Pow(1024, place), 3); return (Math.Sign(byteCount) * num).ToString() + suf[place]; } public override bool Equals(object obj) { var container = obj as CaesarContainer; if (container == null) { return false; } return this.FileChecksum == container.FileChecksum; } public override int GetHashCode() { return (int)FileChecksum; } } } ================================================ FILE: Caesar/Caesar/CaesarReader.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class CaesarReader { public static Encoding DefaultEncoding = Encoding.UTF8; // slightly more complex because it jumps to the string position for reading public static string ReadBitflagStringWithReader(ref ulong bitFlags, BinaryReader reader, long virtualBase = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { // read the string's offset relative to our current block int stringOffset = reader.ReadInt32(); // save our reading cursor long readerPosition = reader.BaseStream.Position; // seek to the specified offset, then read out the string reader.BaseStream.Seek(stringOffset + virtualBase, SeekOrigin.Begin); string result = ReadStringFromBinaryReader(reader); // restore our reading cursor reader.BaseStream.Seek(readerPosition, SeekOrigin.Begin); return result; } else { // Console.WriteLine("Bitflag was off for string"); return "(flag disabled)"; } } public static byte[] ReadBitflagDumpWithReader(ref ulong bitFlags, BinaryReader reader, int dumpSize, long virtualBase = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { // read the dump's offset relative to our current block int dumpOffset = reader.ReadInt32(); // save our reading cursor long readerPosition = reader.BaseStream.Position; // seek to the specified offset, then read out the dump reader.BaseStream.Seek(dumpOffset + virtualBase, SeekOrigin.Begin); byte[] result = reader.ReadBytes(dumpSize); // restore our reading cursor reader.BaseStream.Seek(readerPosition, SeekOrigin.Begin); return result; } else { return new byte[] { }; } } public static string ReadBitflagDumpWithReaderAsString(ref ulong bitFlags, BinaryReader reader, int dumpSize, long virtualBase = 0) { byte[] stringBytes = ReadBitflagDumpWithReader(ref bitFlags, reader, dumpSize, virtualBase); return DefaultEncoding.GetString(stringBytes); // lazy: no encoding is specified } public static string ReadStringFromBinaryReader(BinaryReader reader, Encoding encoding = null) { if (encoding is null) { encoding = DefaultEncoding; } // slightly better performance than the original below at the expense of compiling with unsafe long stringStartPosition = reader.BaseStream.Position; byte[] underlyingBuffer = ((MemoryStream)reader.BaseStream).GetBuffer(); long cursor = stringStartPosition; while (underlyingBuffer[cursor++] != 0) { } int difference = (int)(cursor - stringStartPosition) - 1; byte[] stringBytes = new byte[difference]; Buffer.BlockCopy(underlyingBuffer, (int)stringStartPosition, stringBytes, 0, difference); return encoding.GetString(stringBytes); /* // significant performance bottleneck: (original) // read out a string, stopping at the first null terminator using (BinaryWriter writer = new BinaryWriter(new MemoryStream())) { while (true) { byte nextByte = reader.ReadByte(); if (nextByte == 0) { byte[] stringRaw = ((MemoryStream)writer.BaseStream).ToArray(); return encoding.GetString(stringRaw); } else { writer.Write(nextByte); } } } */ } public static bool CheckAndAdvanceBitflag(ref ulong bitFlag) { bool flagIsSet = (bitFlag & 1) > 0; bitFlag >>= 1; return flagIsSet; } public static byte[] ReadBitflagRawBytes(ref ulong bitFlags, BinaryReader reader, int bytes) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadBytes(bytes); } return new byte[] { }; } public static float ReadBitflagFloat(ref ulong bitFlags, BinaryReader reader, float defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { byte[] floatBytes = reader.ReadBytes(4); return BitConverter.ToSingle(floatBytes, 0); } return defaultResult; } public static int ReadBitflagInt32(ref ulong bitFlags, BinaryReader reader, int defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadInt32(); } return defaultResult; } public static uint ReadBitflagUInt32(ref ulong bitFlags, BinaryReader reader, uint defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadUInt32(); } return defaultResult; } public static short ReadBitflagInt16(ref ulong bitFlags, BinaryReader reader, short defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadInt16(); } return defaultResult; } public static ushort ReadBitflagUInt16(ref ulong bitFlags, BinaryReader reader, ushort defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadUInt16(); } return defaultResult; } public static int ReadBitflagInt8(ref ulong bitFlags, BinaryReader reader, int defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadChar(); } return defaultResult; } public static byte ReadBitflagUInt8(ref ulong bitFlags, BinaryReader reader, byte defaultResult = 0) { if (CheckAndAdvanceBitflag(ref bitFlags)) { return reader.ReadByte(); } return defaultResult; } public static int ReadIntWithSize(BinaryReader reader, int size, long offset) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); if (size == 1) { return reader.ReadChar(); } else if (size == 2) { return reader.ReadInt16(); } else if (size == 4) { return reader.ReadInt32(); } else { throw new NotImplementedException($"Requested an unknown integer size to read: {size}"); } } public static uint ReadUIntWithSize(BinaryReader reader, int size, long offset) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); if (size == 1) { return reader.ReadByte(); } else if (size == 2) { return reader.ReadUInt16(); } else if (size == 4) { return reader.ReadUInt32(); } else { throw new NotImplementedException($"Requested an unknown integer size to read: {size}"); } } private static uint[] CrcTable = { 0x00000000, 0x77073096, 0x0EE0E612C, 0x990951BA, 0x76DC419, 0x706AF48F, 0x0E963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0x0E0D5E91E, 0x97D2D988, 0x9B64C2B, 0x7EB17CBD, 0x0E7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0x0F3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0x0F4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0x0FD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0x0FA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0x0D56041E4, 0x0A2677172, 0x3C03E4D1, 0x4B04D447, 0x0D20D85FD, 0x0A50AB56B, 0x35B5A8FA, 0x42B2986C, 0x0DBBBC9D6, 0x0ACBCF940, 0x32D86CE3, 0x45DF5C75, 0x0DCD60DCF, 0x0ABD13D59, 0x26D930AC, 0x51DE003A, 0x0C8D75180, 0x0BFD06116, 0x21B4F4B5, 0x56B3C423, 0x0CFBA9599, 0x0B8BDA50F, 0x2802B89E, 0x5F058808, 0x0C60CD9B2, 0x0B10BE924, 0x2F6F7C87, 0x58684C11, 0x0C1611DAB, 0x0B6662D3D, 0x76DC4190, 0x1DB7106, 0x98D220BC, 0x0EFD5102A, 0x71B18589, 0x6B6B51F, 0x9FBFE4A5, 0x0E8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0x0E10E9818, 0x7F6A0DBB, 0x86D3D2D, 0x91646C97, 0x0E6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0x0F262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0x0F50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0x0FCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0x0FBD44C65, 0x4DB26158, 0x3AB551CE, 0x0A3BC0074, 0x0D4BB30E2, 0x4ADFA541, 0x3DD895D7, 0x0A4D1C46D, 0x0D3D6F4FB, 0x4369E96A, 0x346ED9FC, 0x0AD678846, 0x0DA60B8D0, 0x44042D73, 0x33031DE5, 0x0AA0A4C5F, 0x0DD0D7CC9, 0x5005713C, 0x270241AA, 0x0BE0B1010, 0x0C90C2086, 0x5768B525, 0x206F85B3, 0x0B966D409, 0x0CE61E49F, 0x5EDEF90E, 0x29D9C998, 0x0B0D09822, 0x0C7D7A8B4, 0x59B33D17, 0x2EB40D81, 0x0B7BD5C3B, 0x0C0BA6CAD, 0x0EDB88320, 0x9ABFB3B6, 0x3B6E20C, 0x74B1D29A, 0x0EAD54739, 0x9DD277AF, 0x4DB2615, 0x73DC1683, 0x0E3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0x0E40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0x0F00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0x0F762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0x0FED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0x0F9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0x0D6D6A3E8, 0x0A1D1937E, 0x38D8C2C4, 0x4FDFF252, 0x0D1BB67F1, 0x0A6BC5767, 0x3FB506DD, 0x48B2364B, 0x0D80D2BDA, 0x0AF0A1B4C, 0x36034AF6, 0x41047A60, 0x0DF60EFC3, 0x0A867DF55, 0x316E8EEF, 0x4669BE79, 0x0CB61B38C, 0x0BC66831A, 0x256FD2A0, 0x5268E236, 0x0CC0C7795, 0x0BB0B4703, 0x220216B9, 0x5505262F, 0x0C5BA3BBE, 0x0B2BD0B28, 0x2BB45A92, 0x5CB36A04, 0x0C2D7FFA7, 0x0B5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0x0EC63F226, 0x756AA39C, 0x26D930A, 0x9C0906A9, 0x0EB0E363F, 0x72076785, 0x5005713, 0x95BF4A82, 0x0E2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0x0E5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0x0F1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0x0F6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0x0FF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0x0F862AE69, 0x616BFFD3, 0x166CCF45, 0x0A00AE278, 0x0D70DD2EE, 0x4E048354, 0x3903B3C2, 0x0A7672661, 0x0D06016F7, 0x4969474D, 0x3E6E77DB, 0x0AED16A4A, 0x0D9D65ADC, 0x40DF0B66, 0x37D83BF0, 0x0A9BCAE53, 0x0DEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0x0BDBDF21C, 0x0CABAC28A, 0x53B39330, 0x24B4A3A6, 0x0BAD03605, 0x0CDD70693, 0x54DE5729, 0x23D967BF, 0x0B3667A2E, 0x0C4614AB8, 0x5D681B02, 0x2A6F2B94, 0x0B40BBE37, 0x0C30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; public static UInt32 CrcAccumulate(byte[] inputBuffer, uint currentChecksum = 0, int length = 0) { length = length == 0 ? inputBuffer.Length : length; for (int i = 0; i < length; i++) { uint tableIndex = (currentChecksum ^ inputBuffer[i]) & 0xFF; uint tableValue = CrcTable[tableIndex]; // mix in the loaded byte into the crc on the most significant byte currentChecksum >>= 8; currentChecksum &= 0xFFFFFF; currentChecksum ^= tableValue; } return currentChecksum; } public static uint ComputeFileChecksum(byte[] fileBytes) { // caesar uses a 0x8000 block size // const int blockSize = 0x8000; const int blockSize = int.MaxValue; // skip the appended checksum fileBytes = fileBytes.Take(fileBytes.Length - 4).ToArray(); int fileCursor = 0; uint currentChecksum = 0xFFFFFFFF; while (fileCursor < fileBytes.Length) { byte[] blockToRead = fileBytes.Skip(fileCursor).Take(blockSize).ToArray(); fileCursor += blockSize; currentChecksum = CaesarReader.CrcAccumulate(blockToRead, currentChecksum); } return currentChecksum; } public static uint ComputeFileChecksumLazy(byte[] fileBytes) { return CaesarReader.CrcAccumulate(fileBytes, 0xFFFFFFFF, fileBytes.Length - 4); } } } ================================================ FILE: Caesar/Caesar/CaesarStructure.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { class CaesarStructure { // offsets public enum StructureName { CBFHEADER = 0, UNK1 = 1, UNK2 = 2, UNK3 = 3, UNK4 = 4, PRESENTATION_STRUCTURE = 0x5, UNK6 = 6, UNK7 = 7, UNK8 = 8, UNK9 = 9, UNK10 = 0xA, SCALEINTERVAL_STRUCTURE = 0xB, UNK12 = 0xC, UNK13 = 0xD, UNK14 = 0xE, UNK15 = 0xF, FLASH_DESCRIPTION_HEADER = 0x10, FLASH_TABLE_STRUCTURE = 0x11, UNK18 = 0x12, UNK19 = 0x13, SESSION_TABLE_STRUCTURE = 0x14, UNK21 = 0x15, DATA_BLOCK_TABLE_STRUCTURE = 0x16, UNK23 = 0x17, UNK24 = 0x18, UNK25 = 0x19, UNK26 = 0x1A, SEGMENT_TABLE_STRUCTURE = 0x1B, UNK28 = 0x1C, CTFHEADER = 0x1D, LANGUAGE_TABLE = 0x1E, CCFHEADER = 0x1F, UNK32 = 0x20, CCFFRAGMENT = 0x21, UNK34 = 0x22, UNK35 = 0x23, UNK36 = 0x24, } /* raw values from ida: [ [2,4,4,4,4,4,4,4,4,4,4,4,4], [4,4,4,2,2,4,4,4,4,4,2,2,2,4,4,4,4,4,4,4,4,4,4,1,1,2,1], [6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2], [6,4,4,2,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,2,2,4,4,2,1,4,4,4,4,4,4], [4,4,4,4,4,4,4,2,2,2,2,1,1,1,1,1,5,1,1,1,1,4,4,4,4,4], [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], [2,4,4,2,4,4,4,4,4,4,4,4,4], [2,4,4,4,4,2,4,2,4], [2,4,4,4,4,4,4,4,4,4,4,2], [2,4,4,4,4,4,4,4,4], [2,4,4,4], [2,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,1,1], [2,4,2,2,2,4,2,2,4,4,4], [2,4,4,4,4,4,4,4,4,1,1], [6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1], [4,4,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,4], [2,4,4,4,4,4,4,4,4,4,2], [2,4,4,4,4,4], [6,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,4], [2,4,4,4,4,4,4], [2,4,4], [2,2,4,4,2,4,4,2,4,4,2,4,4], [2,4,4,4,4,4,4,4], [2,4,4], [2,4,4,2,4,4,4,4,4], [2,4,2,4,4,4], [6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2], [6,4,4,4,4,4,4,4,4,4,4,4,4], [2,4,4,4,4,4,2,4], [2,4,4,4,4,4,2,4], [2,4,4,4,4,4,4,2,4], [2,2,2,2,2,2,2,2,4,4,0,0,0] ] */ public static List CaesarTypes = new List(); public static void GetOffset(StructureName name, int memberIndex) { FillCaesarTypes(); } public static byte[] GetCaesarLayout(StructureName name) { FillCaesarTypes(); return CaesarTypes[(int)name]; } public static void FillCaesarTypes() { if (CaesarTypes.Count != 0) { return; } CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // CBFHEADER CaesarTypes.Add(new byte[] { 4, 4, 4, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 1 }); // UNK1 CaesarTypes.Add(new byte[] { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 }); // UNK2 CaesarTypes.Add(new byte[] { 6, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 1, 4, 4, 4, 4, 4, 4 }); // UNK3 CaesarTypes.Add(new byte[] { 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 4, 4, 4, 4, 4 }); // UNK4 CaesarTypes.Add(new byte[] { 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 }); // PRESENTATION_STRUCTURE CaesarTypes.Add(new byte[] { 2, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // UNK6 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 2, 4, 2, 4 }); // UNK7 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 }); // UNK8 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4 }); // UNK9 CaesarTypes.Add(new byte[] { 2, 4, 4, 4 }); // UNK10 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // SCALEINTERVAL_STRUCTURE CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 1, 1 }); // UNK12 CaesarTypes.Add(new byte[] { 2, 4, 2, 2, 2, 4, 2, 2, 4, 4, 4 }); // UNK13 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1 }); // UNK14 CaesarTypes.Add(new byte[] { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1 }); // 0xF : FlashHeader : FLASH_DESCRIPTION_HEADER CaesarTypes.Add(new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // 0x10 : FLASH_DESCRIPTION_HEADER CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // UNK18 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4 }); // UNK19 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 }); // SESSION_TABLE_STRUCTURE CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4 }); // UNK21 CaesarTypes.Add(new byte[] { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // DATA_BLOCK_TABLE_STRUCTURE CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4 }); // UNK23 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4 }); // UNK24 CaesarTypes.Add(new byte[] { 2, 4, 4 }); // UNK25 CaesarTypes.Add(new byte[] { 2, 2, 4, 4, 2, 4, 4, 2, 4, 4, 2, 4, 4 }); // UNK26 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 4 }); // SEGMENT_TABLE_STRUCTURE CaesarTypes.Add(new byte[] { 2, 4, 4 }); // UNK28 CaesarTypes.Add(new byte[] { 2, 4, 4, 2, 4, 4, 4, 4, 4 }); // CTFHEADER CaesarTypes.Add(new byte[] { 2, 4, 2, 4, 4, 4 }); // LANGUAGE_TABLE CaesarTypes.Add(new byte[] { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2 }); // CCFHEADER CaesarTypes.Add(new byte[] { 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }); // UNK32 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 2, 4 }); // CCFFRAGMENT CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 2, 4 }); // UNK34 CaesarTypes.Add(new byte[] { 2, 4, 4, 4, 4, 4, 4, 2, 4 }); // UNK35 CaesarTypes.Add(new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 0, 0, 0 }); // UNK36 } // this is an artifact from implementing the reverse-engineered code as-is; since Caesar loads all objects in a greedy strategy (for serialization), // use of ReadCBFWithOffset should be discontinued public static int ReadCBFWithOffset(int memberIndex, StructureName structureName, byte[] input) { int byteOffset = CaesarStructure.GetCBFOffset(memberIndex, structureName, input); using (BinaryReader reader = new BinaryReader(new MemoryStream(input))) { byte[] layout = CaesarStructure.GetCaesarLayout(structureName); return CaesarReader.ReadIntWithSize(reader, layout[memberIndex], byteOffset); } } public static uint ReadCBFWithOffsetUnsigned(int memberIndex, StructureName structureName, byte[] input) { int byteOffset = CaesarStructure.GetCBFOffset(memberIndex, structureName, input); using (BinaryReader reader = new BinaryReader(new MemoryStream(input))) { byte[] layout = CaesarStructure.GetCaesarLayout(structureName); return CaesarReader.ReadUIntWithSize(reader, layout[memberIndex], byteOffset); } } public static int GetCBFOffset(int memberIndex, StructureName structureName, byte[] cbfInput) { // test: // byte[] cbfInput = new byte[] { 0x03, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x63, 0x54, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x50, 0x52, 0x45, 0x50, 0x5F, 0x55, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x5F, 0x31, 0x42, 0x79, 0x74, 0x65, 0x00 }; // int member_type = 0x1C; // CaesarStructure.StructureName.PRESENTATION_STRUCTURE // result = 0x13 // essentially checks if a bitflag is active, then returns the byte offset to the member byte[] structureLayout = GetCaesarLayout(structureName); byte bitmask = 1; int arrayOffset = structureLayout[0]; // first structure element is always a static offset, to skip past the bitflags int cbfOffset = 0; for (int i = 1; i < memberIndex; ++i) { bool bitflagIsEnabled = (bitmask & cbfInput[cbfOffset]) > 0; if (bitflagIsEnabled) { if (memberIndex != i) { arrayOffset += structureLayout[i]; } } else if ((memberIndex == i) && !bitflagIsEnabled) { // found the requested member, but the member is marked as absent in the bitflag, so there is no value arrayOffset = 0; } // move on to the next bit, and if our bitflag is fully read, move to the next bitflag if (bitmask == 0x80) { ++cbfOffset; bitmask = 1; } else { bitmask *= 2; } } return arrayOffset; } } } ================================================ FILE: Caesar/Caesar/ComParameter.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class ComParameter { public int ComParamIndex; // this takes precedence over SubinterfaceIndex for KW2C3PE public int ParentInterfaceIndex; public int SubinterfaceIndex; public int Unk5; public int Unk_CTF; public int Phrase; private int DumpSize; public byte[] Dump; public int ComParamValue; public string ParamName = ""; private long BaseAddress; CTFLanguage Language; public void Restore(CTFLanguage language) { Language = language; } public ComParameter() { } // looks exactly like the definition in DIOpenDiagService (#T) public ComParameter(BinaryReader reader, long baseAddress, List parentEcuInterfaceList, CTFLanguage language) { BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt16(); ComParamIndex = CaesarReader.ReadBitflagInt16(ref bitflags, reader); ParentInterfaceIndex = CaesarReader.ReadBitflagInt16(ref bitflags, reader); SubinterfaceIndex = CaesarReader.ReadBitflagInt16(ref bitflags, reader, 0); Unk5 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); Unk_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader); // no -1? ctf strings should have -1 Phrase = CaesarReader.ReadBitflagInt16(ref bitflags, reader); DumpSize = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Dump = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, DumpSize, baseAddress); ComParamValue = 0; if (DumpSize == 4) { ComParamValue = BitConverter.ToInt32(Dump, 0); } ECUInterface parentEcuInterface = parentEcuInterfaceList[ParentInterfaceIndex]; if (ComParamIndex >= parentEcuInterface.ComParameterNames.Count) { // throw new Exception("Invalid communication parameter : parent interface has no matching key"); ParamName = "CP_UNKNOWN_MISSING_KEY"; Console.WriteLine($"Warning: Tried to load a communication parameter without a parent (value: {ComParamValue}), parent: {parentEcuInterface.Qualifier}."); } else { ParamName = parentEcuInterface.ComParameterNames[ComParamIndex]; } } public void PrintDebug() { Console.WriteLine($"ComParam: id {ComParamIndex} ({ParamName}), v {ComParamValue} 0x{ComParamValue:X8} SI_Index:{SubinterfaceIndex} | parentIndex:{ParentInterfaceIndex} 5:{Unk5} DumpSize:{DumpSize} D: {BitUtility.BytesToHex(Dump)}"); Console.WriteLine($"Pos 0x{BaseAddress:X}"); } } } ================================================ FILE: Caesar/Caesar/DSCContext.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class DSCContext { public DSCContext(byte[] dscContainerBytes) { const int fnTableEntrySize = 50; using (BinaryReader reader = new BinaryReader(new MemoryStream(dscContainerBytes, 0, dscContainerBytes.Length, true, true))) { reader.BaseStream.Seek(0x10, SeekOrigin.Begin); int fnTableOffset = reader.ReadInt32(); // @ 0x10, originally i16 int numberOfFunctions = reader.ReadInt16(); // @ 0x14 int dscOffsetA = reader.ReadInt32(); // @ 0x16, originally i16 int caesarHash = reader.ReadInt16(); // @ 0x1A, size is u32? int idk_field_1c = reader.ReadInt16(); // ?? @ 1C, padding int globalVarAllocSize = reader.ReadInt16(); // @ 1E int idk_field_20 = reader.ReadInt16(); // ?? @ 20, padding int globalVariablesBufferPtr = reader.ReadInt32(); // ?? @ 22 int globalVariablesCount = reader.ReadInt16(); // ?? @ 26 int globalVariablesIdk1 = reader.ReadInt32(); // ?? @ 28 int globalVariablesIdk2 = reader.ReadInt16(); // ?? @ 2C int globalVariablesPreinitBufferPtr = reader.ReadInt32(); // ?? @ 2E int globalVariablesBytesToRead = reader.ReadInt16(); // ?? @ 32 byte[] globalVarByteBuffer = new byte[globalVarAllocSize]; Console.WriteLine($"{nameof(dscOffsetA)} : {dscOffsetA} (0x{dscOffsetA:X})\n"); Console.WriteLine($"{nameof(caesarHash)} : {caesarHash} (0x{caesarHash:X})\n"); Console.WriteLine($"{nameof(globalVarAllocSize)} : {globalVarAllocSize} (0x{globalVarAllocSize:X})\n"); Console.WriteLine($"{nameof(globalVariablesBufferPtr)} : {globalVariablesBufferPtr} (0x{globalVariablesBufferPtr:X})"); Console.WriteLine($"{nameof(globalVariablesCount)} : {globalVariablesCount} (0x{globalVariablesCount:X})\n"); Console.WriteLine($"{nameof(globalVariablesIdk1)} : {globalVariablesIdk1} (0x{globalVariablesIdk1:X})"); Console.WriteLine($"{nameof(globalVariablesIdk2)} : {globalVariablesIdk2} (0x{globalVariablesIdk2:X})\n"); Console.WriteLine($"{nameof(globalVariablesPreinitBufferPtr)} : {globalVariablesPreinitBufferPtr} (0x{globalVariablesPreinitBufferPtr:X})"); Console.WriteLine($"{nameof(globalVariablesBytesToRead)} : {globalVariablesBytesToRead} (0x{globalVariablesBytesToRead:X})\n"); // assemble global vars: MIGlobalVarBuild (parent: MIInterpreterRun) int gvBytesRemaining = globalVariablesBytesToRead; reader.BaseStream.Seek(globalVariablesPreinitBufferPtr, SeekOrigin.Begin); while (gvBytesRemaining > 0) { int gvAddress = reader.ReadInt16(); int gvSize = reader.ReadByte(); byte[] gvData = reader.ReadBytes(gvSize); Console.WriteLine($"GV Fill: 0x{gvAddress:X} ({gvSize} bytes) : {BitUtility.BytesToHex(gvData)}"); Buffer.BlockCopy(gvData, 0, globalVarByteBuffer, gvAddress, gvSize); gvBytesRemaining -= gvSize; gvBytesRemaining -= 3; } if (gvBytesRemaining != 0) { throw new Exception("Global variable preinit has leftover data in the read cursor"); } // CreateGlobalVar for (int gvIndex = 0; gvIndex < globalVariablesCount; gvIndex++) { /* guesses: base 1 -> char 2 -> word 3 -> dword derived 1 -> native 2 -> array 3 -> pointer */ reader.BaseStream.Seek(globalVariablesBufferPtr + (gvIndex * 12), SeekOrigin.Begin); int varName = reader.ReadInt32(); DSCBasicType baseType = (DSCBasicType)reader.ReadInt16(); DSCDerivedType derivedType = (DSCDerivedType)reader.ReadInt16(); int arraySize = reader.ReadInt16(); int positionInGlobalBuffer = reader.ReadInt16(); reader.BaseStream.Seek(varName, SeekOrigin.Begin); string varNameResolved = CaesarReader.ReadStringFromBinaryReader(reader, CaesarReader.DefaultEncoding); int dataSizeInBytes = GetDscTypeSize((int)baseType, (int)derivedType); if (derivedType == DSCDerivedType.Array) { dataSizeInBytes *= arraySize; } byte[] varBytes = new byte[dataSizeInBytes]; Buffer.BlockCopy(globalVarByteBuffer, positionInGlobalBuffer, varBytes, 0, dataSizeInBytes); Console.WriteLine($"\nVar: {baseType}/{derivedType} [{arraySize}] @ {positionInGlobalBuffer} : {varNameResolved}"); Console.WriteLine($"{BitUtility.BytesToHex(varBytes)}"); // actual insertion into global var list is in MIGlobalVarCallback, stored in interpreter's ->GlobalVarList } for (int fnIndex = 0; fnIndex < numberOfFunctions; fnIndex++) { long fnBaseAddress = fnTableEntrySize * fnIndex + fnTableOffset; reader.BaseStream.Seek(fnBaseAddress, SeekOrigin.Begin); int fnIdentifier = reader.ReadInt16(); // @ 0 int fnNameOffset = reader.ReadInt32(); // @ 2 // not exactly sure if int32 is right -- the first fn's ep looks incorrect in both cases. // 16 bit would limit the filesize to ~32KB which seems unlikely int fnEntryPoint = reader.ReadInt32(); // @ 6 //int fnEntryPoint = reader.ReadInt16(); // @ 6 //int fnIdkIsThisStandalone = reader.ReadInt16(); // @ 6 reader.BaseStream.Seek(fnBaseAddress + 38, SeekOrigin.Begin); int inputParamOffset = reader.ReadInt32(); // @ 38 int inputParamCount = reader.ReadInt16(); // @ 42 int outputParamOffset = reader.ReadInt32(); // @ 44 int outputParamCount = reader.ReadInt16(); // @ 48 reader.BaseStream.Seek(fnNameOffset, SeekOrigin.Begin); string fnName = CaesarReader.ReadStringFromBinaryReader(reader); Console.WriteLine($"Fn: {fnName} Ordinal: {fnIdentifier} EP: 0x{fnEntryPoint:X}, InParam: {inputParamCount} @ 0x{inputParamOffset:X}, OutParam: {outputParamCount} @ 0x{outputParamOffset}"); // the EP points to an int16 to initialize the stack height // after the EP, the raw bytecode can be directly interpreted } } } public enum DSCBasicType { Undefined, Char, Word, DWord, Unk_1Byte, Unk_2Byte, Unk_4Byte, Unk_4Byte_2, } public enum DSCDerivedType { Undefined, Primitive, Array, Pointer, // DWORD PTR } public static int GetDscTypeSize(int basicType, int derivedType) { // MISizeofVarDataType int[] typeSizes = new int[] { -1, 1, 2, 4, 1, 2, 4, 4 }; // char, word, dword, ??, ??, ??, ?? if (derivedType == 3) { return 4; // DWORD PTR } else if (derivedType < 3) { if ((basicType > 0) && (basicType < 8)) { return typeSizes[basicType]; } else { throw new Exception("Unrecognized DSC Type: basic type is out of bounds"); } } else { throw new Exception("Unrecognized DSC Type: derived type is out of bounds"); } } } } ================================================ FILE: Caesar/Caesar/DTC.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class DTC { public enum DTCStatusByte : uint { TestFailedAtRequestTime = 0x01, TestFailedAtCurrentCycle = 0x02, PendingDTC = 0x04, ConfirmedDTC = 0x08, TestIncompleteSinceLastClear = 0x10, TestFailedSinceLastClear = 0x20, TestIncompleteAtCurrentCycle = 0x40, WarningIndicatorActive = 0x80, } // see : const char *__cdecl DIGetComfortErrorCode(DI_ECUINFO *ecuh, unsigned int dtcIndex) public string Qualifier; public int Description_CTF; public int Reference_CTF; public int XrefStart = -1; public int XrefCount = -1; private long BaseAddress; public int PoolIndex; [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; [Newtonsoft.Json.JsonIgnore] CTFLanguage Language; [Newtonsoft.Json.JsonIgnore] public string Description { get { return Language.GetString(Description_CTF); } } public void Restore(CTFLanguage language, ECU parentEcu) { ParentECU = parentEcu; Language = language; } public DTC() { } public DTC(BinaryReader reader, CTFLanguage language, long baseAddress, int poolIndex, ECU parentEcu) { ParentECU = parentEcu; PoolIndex = poolIndex; BaseAddress = baseAddress; Language = language; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt16(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Reference_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); #if DEBUG if (bitflags > 0) { Console.WriteLine($"DTC {Qualifier} has additional unparsed fields : 0x{bitflags:X}"); } #endif } /* public string GetDescription() { return Language.GetString(Description_CTF); } */ public static DTC FindDTCById(string id, ECUVariant variant) { foreach (DTC dtc in variant.DTCs) { if (dtc.Qualifier.EndsWith(id)) { return dtc; } } return null; } public void PrintDebug() { Console.WriteLine($"DTC: {Qualifier}: {Language.GetString(Description_CTF)} : {Language.GetString(Reference_CTF)}"); } } } ================================================ FILE: Caesar/Caesar/DiagPreparation.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class DiagPreparation { public string Qualifier; public int Name_CTF; public int Unk1; public int Unk2; public int AlternativeBitWidth; public int IITOffset; public int InfoPoolIndex; public int PresPoolIndex; public int Field1E; public int SystemParam; public int DumpMode; private int DumpSize; public byte[] Dump; public int BitPosition; public ushort ModeConfig; public int SizeInBits = 0; private CTFLanguage Language; public static readonly byte[] IntegerSizeMapping = new byte[] { 0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40 }; long BaseAddress; [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; private DiagService ParentDiagService; public InferredDataType FieldType; public enum InferredDataType { UnassignedType, IntegerType, NativeInfoPoolType, NativePresentationType, UnhandledITType, UnhandledSP17Type, UnhandledType, BitDumpType, ExtendedBitDumpType, } public void Restore(CTFLanguage language, ECU parentEcu, DiagService parentDiagService) { Language = language; ParentECU = parentEcu; ParentDiagService = parentDiagService; } public DiagPreparation() { } // void __cdecl DiagServiceReadPresentation(int *inBase, DECODED_PRESENTATION *outPresentation) // Looks like its actually a presentation // See DIDiagservice* functions public DiagPreparation(BinaryReader reader, CTFLanguage language, long baseAddress, int bitPosition, ushort modeConfig, ECU parentEcu, DiagService parentDiagService) { BitPosition = bitPosition; ModeConfig = modeConfig; Language = language; BaseAddress = baseAddress; ParentECU = parentEcu; ParentDiagService = parentDiagService; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Unk1 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk2 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); AlternativeBitWidth = CaesarReader.ReadBitflagInt32(ref bitflags, reader); IITOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); InfoPoolIndex = CaesarReader.ReadBitflagInt32(ref bitflags, reader); PresPoolIndex = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Field1E = CaesarReader.ReadBitflagInt32(ref bitflags, reader); SystemParam = CaesarReader.ReadBitflagInt16(ref bitflags, reader, -1); DumpMode = CaesarReader.ReadBitflagInt16(ref bitflags, reader); DumpSize = CaesarReader.ReadBitflagInt32(ref bitflags, reader); if (DumpMode == 5) { // dump is actually a string, use // CaesarReader.ReadBitflagDumpWithReaderAsString } Dump = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, DumpSize, baseAddress); SizeInBits = GetSizeInBits(reader); // PrintDebug(); } // look at.. DIInternalRetrieveConstParamPreparation // public int GetSizeInBits(BinaryReader reader, bool verbose = true) { // if (modeConfig & 0xF00) == 0x300, the value is a const param: DIIsConstParameter // VCFragment does the same thing.. with the same ITT exception // BitPosition /= 8 // look for the string "nImplType <= 6" uint modeE = (uint)ModeConfig & 0xF000; uint modeH = (uint)ModeConfig & 0xFF0; uint modeL = (uint)ModeConfig & 0xF; int resultBitSize = 0; if ((ModeConfig & 0xF00) == 0x300) // this check is made in DIDiagServiceRetrievePreparation { if (modeL > 6) { throw new Exception("nImplType <= 6; trying to map a data type that cannot exist"); } // const params : 0x320, 0x330, 0x340 if (modeH == 0x320) { // this behavior is confirmed resultBitSize = IntegerSizeMapping[modeL]; FieldType = InferredDataType.IntegerType; } else if (modeH == 0x330) { // this behavior is also okay resultBitSize = AlternativeBitWidth; // inPres + 20 FieldType = InferredDataType.BitDumpType; } else if (modeH == 0x340) { // from dasm, but unimplemented // DIInternalRetrieveConstParamPreparation FieldType = InferredDataType.UnhandledITType; throw new NotImplementedException("WARNING: valid but unhandled data size (ITT not parsed)"); // resultBitSize = 0; // inPres + 20 } } else { // if systemparam is -1.. load a default system type if (SystemParam == -1) { // apparently both 0x2000 and 0x8000 source from different pools, but use the same PRESENTATION structure if (modeE == 0x8000) { FieldType = InferredDataType.NativeInfoPoolType; byte[] poolBytes = ParentECU.ReadECUInfoPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(poolBytes))) { DiagPresentation pres = ParentECU.GlobalInternalPresentations[InfoPoolIndex]; /* // depreciate use of ReadCBFWithOffset poolReader.BaseStream.Seek(ParentECU.Info_EntrySize * InfoPoolIndex, SeekOrigin.Begin); int presentationStructOffset = poolReader.ReadInt32(); int presentationStructSize = poolReader.ReadInt32(); reader.BaseStream.Seek(presentationStructOffset + ParentECU.Info_BlockOffset, SeekOrigin.Begin); byte[] presentationStruct = reader.ReadBytes(presentationStructSize); int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength if (presentationLength > 0) { resultBitSize = presentationLength; } else { resultBitSize = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? } */ resultBitSize = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { resultBitSize *= 8; } } } else if (modeE == 0x2000) { FieldType = InferredDataType.NativePresentationType; byte[] presPool = ParentECU.ReadECUPresentationsPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(presPool))) { DiagPresentation pres = ParentECU.GlobalPresentations[PresPoolIndex]; /* // depreciate use of ReadCBFWithOffset poolReader.BaseStream.Seek(ParentECU.Presentations_EntrySize * PresPoolIndex, SeekOrigin.Begin); int presentationStructOffset = poolReader.ReadInt32(); int presentationStructSize = poolReader.ReadInt32(); reader.BaseStream.Seek(presentationStructOffset + ParentECU.Presentations_BlockOffset, SeekOrigin.Begin); byte[] presentationStruct = reader.ReadBytes(presentationStructSize); int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength if (presentationLength > 0) { resultBitSize = presentationLength; } else { resultBitSize = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? } */ resultBitSize = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { resultBitSize *= 8; } } } else { // should throw an exception? //Console.WriteLine($"WARNING: Unknown or unhandled type for for {qualifier}"); throw new Exception($"Attempted to load an unknown system type for {Qualifier}"); } } else { // not a const param, not a native param, this is a special param, parsed at DIInternalRetrieveSpecialPreparation // DIInternalRetrieveSpecialPreparation officially supports 0x410, 0x420 only if (modeH == 0x410) { int reducedSysParam = SystemParam - 0x10; if (reducedSysParam == 0) { // specifically requests for LOBYTE (& 0xFF) int resultByteSize = (ParentDiagService.RequestBytes.Length & 0xFF) - (BitPosition / 8); resultBitSize = resultByteSize * 8; FieldType = InferredDataType.ExtendedBitDumpType; // Console.WriteLine($"0x{modeH:X} debug for {qualifier} (L: {modeL}) (BitWidth: {AlternativeBitWidth} SP: {SystemParam}), sz: {resultBitSize} b ({resultBitSize/8} B)"); } else if (reducedSysParam == 17) { // open a diagservice based on inputRef name // this is experimental, haven't seen a cbf that uses this yet Console.WriteLine($"Parsing experimental 0x410 prep with sysparam 17 at {Qualifier}"); DiagService referencedDs = ParentECU.GlobalDiagServices.Find(x => x.Qualifier == ParentDiagService.InputRefNameMaybe); if (referencedDs != null) { bool referencedDsHasRequestData = referencedDs.RequestBytes.Length > 0; // supposed to check if requestMessage is valid too int internalType = referencedDs.DataClass_ServiceTypeShifted; if (((referencedDs.DataClass_ServiceTypeShifted & 0xC) > 0) && referencedDsHasRequestData) { if ((referencedDs.DataClass_ServiceTypeShifted & 4) > 0) { internalType = 0x10000000; } else { internalType = 0x20000000; } } if ((internalType & 0x10000) != 0) { // referenced type is a global variable resultBitSize = ParentDiagService.P_Count * 8; FieldType = InferredDataType.UnhandledSP17Type; } else { // use pres dump length FieldType = InferredDataType.UnhandledSP17Type; resultBitSize = ParentDiagService.RequestBytes.Length * 8; } } else { Console.WriteLine($"0x410 : sys param: 17 for qualifier {Qualifier} could not find referenced DiagService with index {ParentDiagService.InputRefNameMaybe}"); // throw new NotImplementedException } } else { throw new Exception($"Invalid system parameter for {Qualifier}"); } } else if (modeH == 0x420) { if (modeL > 6) { throw new Exception("nImplType <= 6; trying to map a data type that cannot exist"); } FieldType = InferredDataType.IntegerType; resultBitSize = IntegerSizeMapping[modeL]; } else if (modeH == 0x430) { // mode 0x430 is nonstandard and doesn't seem to exist in the function that I was disassembling /* AlternativeBitWidth : 128 SystemParam : 37 See 0x320 vs 0x330, seems to be similar */ resultBitSize = AlternativeBitWidth; // inPres + 20 FieldType = InferredDataType.BitDumpType; } else { FieldType = InferredDataType.UnhandledType; Console.WriteLine($"Unhandled type: {modeH} for {Qualifier}"); PrintDebug(); throw new Exception($"Attempted to load an unknown special param type for {Qualifier}"); //Console.WriteLine($"{qualifier} ({poolThing}/{ParentECU.ecuInfoPool_tableEntryCount})\n{BitUtility.BytesToHex(presentationStruct)}\n\n"); } } } /* if (modeH == 0x430) { // guessed if (verbose) { Console.WriteLine($"Unsupported 0x{modeH:X} behavior for {qualifier} (L: {modeL}) (BitWidth: {AlternativeBitWidth} ByteWidth: {SystemParam})"); } //PrintDebug(); resultBitSize = AlternativeBitWidth; // alternate bit width is 128 which should be a nice 16 bytes } else if (modeH > 0x430) { // guessed from varcoding behavior if ((PresPool == 0) && (AvailableBitWidth_PoolThing == 0)) { return 0; } else { //Console.WriteLine($"No idea how to handle Pres 0x750 from {qualifier} : {PresPool}"); } Console.WriteLine($"No idea how to handle 0x{modeH:X} from {qualifier} ({PresPool}, {AvailableBitWidth_PoolThing})"); } */ return resultBitSize; } 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("---------------"); } } } ================================================ FILE: Caesar/Caesar/DiagPresentation.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class DiagPresentation { public string Qualifier; public int Description_CTF; public int ScaleTableOffset; public int ScaleCountMaybe; public int Unk5; public int Unk6; public int Unk7; public int Unk8; public int Unk9; public int UnkA; public int UnkB; public int UnkC; public int UnkD; public int UnkE; public int UnkF; public int DisplayedUnit_CTF; public int Unk11; public int Unk12; public int EnumMaxValue; public int Unk14; public int Unk15; public int Description2_CTF; public int Unk17; public int Unk18; public int Unk19; public int TypeLength_1A; public int InternalDataType; // discovered by @prj : #37 public int Type_1C; public int Unk1d; public int SignBit; // discovered by @prj : #37 public int ByteOrder; // discovered by @prj : #37 ; Unset = HiLo, 1 = LoHi public int Unk20; public int TypeLengthBytesMaybe_21; public int Unk22; public int Unk23; public int Unk24; public int Unk25; public int Unk26; // public string DescriptionString; // public string DisplayedUnitString; // public string DescriptionString2; private long BaseAddress; public int PresentationIndex; [Newtonsoft.Json.JsonIgnore] public string DescriptionString { get { return Language.GetString(Description_CTF); } } [Newtonsoft.Json.JsonIgnore] public string DisplayedUnitString { get { return Language.GetString(DisplayedUnit_CTF); } } [Newtonsoft.Json.JsonIgnore] public string DescriptionString2 { get { return Language.GetString(Description2_CTF); } } [Newtonsoft.Json.JsonIgnore] public CTFLanguage Language; public List Scales = new List(); public void Restore(CTFLanguage language) { Language = language; foreach (Scale s in Scales) { s.Restore(language); } } public DiagPresentation() { } // 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; Language = language; 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); EnumMaxValue = 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); InternalDataType = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); Type_1C = CaesarReader.ReadBitflagInt8(ref bitflags, reader, -1); Unk1d = CaesarReader.ReadBitflagInt8(ref bitflags, reader); SignBit = CaesarReader.ReadBitflagInt8(ref bitflags, reader); ByteOrder = CaesarReader.ReadBitflagInt8(ref bitflags, reader); Unk20 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); bitflags = extendedBitflags; TypeLengthBytesMaybe_21 = 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); long scaleTableBase = BaseAddress + ScaleTableOffset; Scales = new List(); 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, language); 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 = (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 // 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 == 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 == 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"; } 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 int GetDataType() { // see DIDiagServiceRealPresType int result = -1; if (Unk14 != -1) { return 20; } // does the value have scale structures attached to it? // supposed to parse scale struct and check if we can return 20 if (ScaleTableOffset != -1) { return 20; // scaled value } else { if (Unk5 != -1) { return 18; // hexdump raw } if (Unk17 != -1) { return 18; // hexdump raw } if (Unk19 != -1) { return 18; // hexdump raw } if (Unk22 != -1) { return 18; // hexdump raw } if (InternalDataType != -1) { if (InternalDataType == 6) { return 17; // ascii dump } else if (InternalDataType == 7) { return 22; // ?? haven't seen this one around } else if (InternalDataType == 8) { result = 6; // IEEE754 float, discovered by @prj in https://github.com/jglim/CaesarSuite/issues/37 } 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 // see DT_STO_Zaehler_Programmierversuche_Reprogramming and DT_STO_ID_Aktive_Diagnose_Information_Version result = 6; } } else { if ((TypeLength_1A == -1) || (Type_1C == -1)) { Console.WriteLine("typelength and type must be valid"); // might be good to throw an exception here } if ((SignBit == 1) || (SignBit == 2)) { result = 5; // ?? haven't seen this one around } else { result = 2; // ?? haven't seen this one around } } return result; } } public void PrintDebug() { Console.WriteLine("Presentation: "); Console.WriteLine($"{nameof(Qualifier)}: {Qualifier}"); //Console.WriteLine($"{nameof(Description_CTF)}: {Description_CTF}"); Console.WriteLine($"{nameof(ScaleTableOffset)}: {ScaleTableOffset}"); Console.WriteLine($"{nameof(ScaleCountMaybe)}: {ScaleCountMaybe}"); Console.WriteLine($"{nameof(Unk5)}: {Unk5}"); Console.WriteLine($"{nameof(Unk6)}: {Unk6}"); Console.WriteLine($"{nameof(Unk7)}: {Unk7}"); Console.WriteLine($"{nameof(Unk8)}: {Unk8}"); Console.WriteLine($"{nameof(Unk9)}: {Unk9}"); Console.WriteLine($"{nameof(UnkA)}: {UnkA}"); Console.WriteLine($"{nameof(UnkB)}: {UnkB}"); Console.WriteLine($"{nameof(UnkC)}: {UnkC}"); Console.WriteLine($"{nameof(UnkD)}: {UnkD}"); Console.WriteLine($"{nameof(UnkE)}: {UnkE}"); Console.WriteLine($"{nameof(UnkF)}: {UnkF}"); //Console.WriteLine($"{nameof(DisplayedUnit_CTF)}: {DisplayedUnit_CTF}"); Console.WriteLine($"{nameof(Unk11)}: {Unk11}"); Console.WriteLine($"{nameof(Unk12)}: {Unk12}"); Console.WriteLine($"{nameof(EnumMaxValue)}: {EnumMaxValue}"); Console.WriteLine($"{nameof(Unk14)}: {Unk14}"); Console.WriteLine($"{nameof(Unk15)}: {Unk15}"); // Console.WriteLine($"{nameof(Description2_CTF)}: {Description2_CTF}"); Console.WriteLine($"{nameof(Unk17)}: {Unk17}"); Console.WriteLine($"{nameof(Unk18)}: {Unk18}"); Console.WriteLine($"{nameof(Unk19)}: {Unk19}"); Console.WriteLine($"{nameof(InternalDataType)}: {InternalDataType}"); Console.WriteLine($"{nameof(Unk1d)}: {Unk1d}"); Console.WriteLine($"{nameof(SignBit)}: {SignBit}"); Console.WriteLine($"{nameof(ByteOrder)}: {ByteOrder}"); Console.WriteLine($"{nameof(Unk20)}: {Unk20}"); Console.WriteLine($"{nameof(TypeLengthBytesMaybe_21)}: {TypeLengthBytesMaybe_21}"); Console.WriteLine($"{nameof(Unk22)}: {Unk22}"); Console.WriteLine($"{nameof(Unk23)}: {Unk23}"); Console.WriteLine($"{nameof(Unk24)}: {Unk24}"); Console.WriteLine($"{nameof(Unk25)}: {Unk25}"); Console.WriteLine($"{nameof(Unk26)}: {Unk26}"); /**/ Console.WriteLine($"{nameof(DescriptionString)}: {DescriptionString}"); Console.WriteLine($"{nameof(DisplayedUnitString)}: {DisplayedUnitString}"); Console.WriteLine($"{nameof(DescriptionString2)}: {DescriptionString2}"); Console.WriteLine($"Type: {GetDataType()}"); Console.WriteLine($"{nameof(Type_1C)}: {Type_1C}"); Console.WriteLine($"{nameof(TypeLength_1A)}: {TypeLength_1A}"); Console.WriteLine($"ScaleOffset: 0x{(ScaleTableOffset + BaseAddress):X}, base of pres @ 0x{BaseAddress:X}"); foreach (Scale s in Scales) { Console.WriteLine("Scale: "); s.PrintDebug(); } Console.WriteLine("Presentation end"); } public string CopyMinDebug() { StringBuilder sb = new StringBuilder(); sb.Append("PRES: "); sb.Append($" {nameof(Unk5)}: {Unk5}"); sb.Append($" {nameof(Unk6)}: {Unk6}"); sb.Append($" {nameof(Unk7)}: {Unk7}"); sb.Append($" {nameof(Unk8)}: {Unk8}"); sb.Append($" {nameof(Unk9)}: {Unk9}"); sb.Append($" {nameof(UnkA)}: {UnkA}"); sb.Append($" {nameof(UnkB)}: {UnkB}"); sb.Append($" {nameof(UnkC)}: {UnkC}"); sb.Append($" {nameof(UnkD)}: {UnkD}"); sb.Append($" {nameof(UnkE)}: {UnkE}"); sb.Append($" {nameof(UnkF)}: {UnkF}"); sb.Append($" {nameof(Unk11)}: {Unk11}"); sb.Append($" {nameof(Unk12)}: {Unk12}"); sb.Append($" {nameof(EnumMaxValue)}: {EnumMaxValue}"); sb.Append($" {nameof(Unk14)}: {Unk14}"); sb.Append($" {nameof(Unk15)}: {Unk15}"); sb.Append($" {nameof(Unk17)}: {Unk17}"); sb.Append($" {nameof(Unk18)}: {Unk18}"); sb.Append($" {nameof(Unk19)}: {Unk19}"); sb.Append($" {nameof(InternalDataType)}: {InternalDataType}"); sb.Append($" {nameof(Unk1d)}: {Unk1d}"); sb.Append($" {nameof(SignBit)}: {SignBit}"); sb.Append($" {nameof(ByteOrder)}: {ByteOrder}"); sb.Append($" {nameof(Unk20)}: {Unk20}"); sb.Append($" {nameof(TypeLengthBytesMaybe_21)}: {TypeLengthBytesMaybe_21}"); sb.Append($" {nameof(Unk22)}: {Unk22}"); sb.Append($" {nameof(Unk23)}: {Unk23}"); sb.Append($" {nameof(Unk24)}: {Unk24}"); sb.Append($" {nameof(Unk25)}: {Unk25}"); sb.Append($" {nameof(Unk26)}: {Unk26}"); sb.Append($" {nameof(BaseAddress)}: 0x{BaseAddress:X8}"); sb.Append($" {nameof(Type_1C)}: {Type_1C}"); sb.Append($" {nameof(TypeLength_1A)}: {TypeLength_1A}"); sb.Append($" Type: {GetDataType()}"); sb.Append($" {nameof(ScaleTableOffset)}: {ScaleTableOffset}"); sb.Append($" {nameof(Qualifier)}: {Qualifier}"); sb.Append($" {nameof(ScaleCountMaybe)}: {ScaleCountMaybe}"); if (ScaleCountMaybe > 0) { sb.Append($" {Language.GetString(Scales[0].EnumDescription)}"); } return sb.ToString(); } } } ================================================ FILE: Caesar/Caesar/DiagService.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { // DIAGJOB *__cdecl DIOpenDiagService(DI_ECUINFO *ecuHandle, char *serviceName, int ecuErrors) public class DiagService { /* 5 DT DATA 7 DL DOWNLOAD 10 FN|DNU DIAGNOSTIC_U, FN 19 DJ DIAGNOSTIC_JOB 21 SES SESSION 22 DT_STO STORED DATA 23 RT ROUTINE 24 IOC IO CONTROL 26 WVC VARIANTCODING WRITE 27 WVC VARIANTCODING READ */ public enum ServiceType { Data = 5, Download = 7, DiagnosticFunction = 10, DiagnosticJob = 19, Session = 21, StoredData = 22, Routine = 23, IoControl = 24, VariantCodingWrite = 26, VariantCodingRead = 27, } public string Qualifier; public int Name_CTF; public int Description_CTF; public ushort DataClass_ServiceType; public int DataClass_ServiceTypeShifted; public ushort IsExecutable; public ushort ClientAccessLevel; public ushort SecurityAccessLevel; private int T_ComParam_Count; private int T_ComParam_Offset; private int Q_Count; private int Q_Offset; private int R_Count; private int R_Offset; public string InputRefNameMaybe; private int U_prep_Count; private int U_prep_Offset; private int V_Count; private int V_Offset; private int RequestBytes_Count; private int RequestBytes_Offset; private int W_OutPres_Count; private int W_OutPres_Offset; public ushort Field50; public string NegativeResponseName; public string UnkStr3; public string UnkStr4; public int P_Count; // global vars? public int P_Offset; private int DiagServiceCodeCount; private int DiagServiceCodeOffset; private int S_Count; private int S_Offset; private int X_Count; private int X_Offset; private int Y_Count; private int Y_Offset; private int Z_Count; private int Z_Offset; public byte[] RequestBytes; private long BaseAddress; public int PoolIndex; // these are inlined preparations public List InputPreparations = new List(); public List> OutputPreparations = new List>(); public List DiagComParameters = new List(); [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; private CTFLanguage Language; public void Restore(CTFLanguage language, ECU parentEcu) { Language = language; ParentECU = parentEcu; foreach (DiagPreparation dp in InputPreparations) { dp.Restore(language, parentEcu, this); } foreach (List dpl in OutputPreparations) { foreach (DiagPreparation dp in dpl) { dp.Restore(language, parentEcu, this); } } /* // nothing in comparam to restore foreach (ComParameter cp in DiagComParameters) { } */ } public DiagService() { } public DiagService(BinaryReader reader, CTFLanguage language, long baseAddress, int poolIndex, ECU parentEcu) { ParentECU = parentEcu; Language = language; PoolIndex = poolIndex; BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); ulong bitflagExtended = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); DataClass_ServiceType = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); DataClass_ServiceTypeShifted = 1 << (DataClass_ServiceType - 1); IsExecutable = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); ; ClientAccessLevel = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); ; SecurityAccessLevel = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); ; T_ComParam_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); T_ComParam_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Q_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Q_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); R_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); R_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); InputRefNameMaybe = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); U_prep_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); U_prep_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); // array of DWORDs, probably reference to elsewhere V_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); V_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); RequestBytes_Count = CaesarReader.ReadBitflagInt16(ref bitflags, reader); RequestBytes_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); W_OutPres_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); W_OutPres_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Field50 = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); NegativeResponseName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); // negative response name UnkStr3 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); UnkStr4 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); P_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); P_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DiagServiceCodeCount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DiagServiceCodeOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); S_Count = CaesarReader.ReadBitflagInt16(ref bitflags, reader); S_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); bitflags = bitflagExtended; X_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); X_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Y_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Y_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Z_Count = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Z_Offset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); if (RequestBytes_Count > 0) { reader.BaseStream.Seek(baseAddress + RequestBytes_Offset, SeekOrigin.Begin); RequestBytes = reader.ReadBytes(RequestBytes_Count); } else { RequestBytes = new byte[] { }; } // u_table to u_entries InputPreparations = new List(); for (int prepIndex = 0; prepIndex < U_prep_Count; prepIndex++) { long presentationTableOffset = baseAddress + U_prep_Offset; reader.BaseStream.Seek(presentationTableOffset + (prepIndex * 10), SeekOrigin.Begin); // DIOpenDiagService (reads 4, 4, 2 then calls DiagServiceReadPresentation) to build a presentation int prepEntryOffset = reader.ReadInt32(); // file: 0 (DW) int prepEntryBitPos = reader.ReadInt32(); // file: 4 (DW) ushort prepEntryMode = reader.ReadUInt16(); // file: 8 (W) DiagPreparation preparation = new DiagPreparation(reader, language, presentationTableOffset + prepEntryOffset, prepEntryBitPos, prepEntryMode, parentEcu, this); //preparation.PrintDebug(); InputPreparations.Add(preparation); } OutputPreparations = new List>(); long outPresBaseAddress = BaseAddress + W_OutPres_Offset; // FIXME: run it through the entire dbr cbf directory, check if any file actually has more than 1 item in ResultPresentationSet for (int presIndex = 0; presIndex < W_OutPres_Count; presIndex++) { reader.BaseStream.Seek(outPresBaseAddress + (presIndex * 8), SeekOrigin.Begin); // FIXME int resultPresentationCount = reader.ReadInt32(); // index? if true, will fix the "wtf" list> int resultPresentationOffset = reader.ReadInt32(); List ResultPresentationSet = new List(); for (int presInnerIndex = 0; presInnerIndex < resultPresentationCount; presInnerIndex++) { long presentationTableOffset = outPresBaseAddress + resultPresentationOffset; reader.BaseStream.Seek(presentationTableOffset + (presIndex * 10), SeekOrigin.Begin); int prepEntryOffset = reader.ReadInt32(); // file: 0 (DW) int prepEntryBitPos = reader.ReadInt32(); // file: 4 (DW) ushort prepEntryMode = reader.ReadUInt16(); // file: 8 (W) DiagPreparation preparation = new DiagPreparation(reader, language, presentationTableOffset + prepEntryOffset, prepEntryBitPos, prepEntryMode, parentEcu, this); ResultPresentationSet.Add(preparation); } OutputPreparations.Add(ResultPresentationSet); } DiagComParameters = new List(); long comParamTableBaseAddress = BaseAddress + T_ComParam_Offset; for (int cpIndex = 0; cpIndex < T_ComParam_Count; cpIndex++) { reader.BaseStream.Seek(comParamTableBaseAddress + (cpIndex * 4), SeekOrigin.Begin); int resultCpOffset = reader.ReadInt32(); long cpEntryBaseAddress = comParamTableBaseAddress + resultCpOffset; ComParameter cp = new ComParameter(reader, cpEntryBaseAddress, parentEcu.ECUInterfaces, language); DiagComParameters.Add(cp); } // DJ_Zugriffsberechtigung_Abgleich // DJ_Zugriffsberechtigung // DT_Abgasklappe_kontinuierlich // FN_HardReset // WVC_Implizite_Variantenkodierung_Write // NR_Disable_Resp_required noexec // DT_Laufzeiten_Resetzaehler_nicht_implementiert exec /* if (false && qualifierName.Contains("RVC_SCN_Variantencodierung_VGS_73_Lesen")) { Console.WriteLine($"{nameof(field50)} : {field50}"); Console.WriteLine($"{nameof(IsExecutable)} : {IsExecutable} {IsExecutable != 0}"); Console.WriteLine($"{nameof(AccessLevel)} : {AccessLevel}"); Console.WriteLine($"{nameof(SecurityAccessLevel)} : {SecurityAccessLevel}"); Console.WriteLine($"{nameof(DataClass)} : {DataClass}"); Console.WriteLine($"{qualifierName} - ReqBytes: {RequestBytes_Count}, P: {P_Count}, Q: {Q_Count}, R: {R_Count}, S: {S_Count}, T: {T_Count}, Preparation: {U_prep_Count}, V: {V_Count}, W: {W_Count}, X: {X_Count}, Y: {Y_Count}, Z: {Z_Count}, DSC {DiagServiceCodeCount}"); Console.WriteLine($"at 0x{baseAddress:X}, W @ 0x{W_Offset:X}, DSC @ 0x{DiagServiceCodeOffset:X}"); Console.WriteLine($"ReqBytes: {BitUtility.BytesToHex(RequestBytes)}"); } */ //Console.WriteLine($"{qualifierName} - O: {RequestBytes_Count}, P: {P_Count}, Q: {Q_Count}, R: {R_Count}, S: {S_Count}, T: {T_Count}, U: {U_Count}, V: {V_Count}, W: {W_Count}, X: {X_Count}, Y: {Y_Count}, Z: {Z_Count}, DSC {DiagServiceCodeCount}"); byte[] dscPool = parentEcu.ParentContainer.CaesarCFFHeader.DSCPool; long dscTableBaseAddress = BaseAddress + DiagServiceCodeOffset; using (BinaryReader dscPoolReader = new BinaryReader(new MemoryStream(dscPool))) { for (int dscIndex = 0; dscIndex < DiagServiceCodeCount; dscIndex++) { reader.BaseStream.Seek(dscTableBaseAddress + (4 * dscIndex), SeekOrigin.Begin); long dscEntryBaseAddress = reader.ReadInt32() + dscTableBaseAddress; reader.BaseStream.Seek(dscEntryBaseAddress, SeekOrigin.Begin); ulong dscEntryBitflags = reader.ReadUInt16(); uint idk1 = CaesarReader.ReadBitflagUInt8(ref dscEntryBitflags, reader); uint idk2 = CaesarReader.ReadBitflagUInt8(ref dscEntryBitflags, reader); int dscPoolOffset = CaesarReader.ReadBitflagInt32(ref dscEntryBitflags, reader); string dscQualifier = CaesarReader.ReadBitflagStringWithReader(ref dscEntryBitflags, reader, dscEntryBaseAddress); dscPoolReader.BaseStream.Seek(dscPoolOffset * 8, SeekOrigin.Begin); long dscRecordOffset = dscPoolReader.ReadInt32() + parentEcu.ParentContainer.CaesarCFFHeader.DscBlockOffset; int dscRecordSize = dscPoolReader.ReadInt32(); reader.BaseStream.Seek(dscRecordOffset, SeekOrigin.Begin); // Console.WriteLine($"DSC {qualifierName} @ 0x{dscTableBaseAddress:X8} {idk1}/{idk2} pool @ 0x{dscPoolOffset:X}, name: {dscQualifier}"); byte[] dscBytes = reader.ReadBytes(dscRecordSize); #if DEBUG //string dscName = $"{parentEcu.Qualifier}_{Qualifier}_{dscIndex}.pal"; //Console.WriteLine($"Exporting DSC: {dscName}"); //File.WriteAllBytes(dscName, dscBytes); #endif // at this point, the DSC binary is available in dscBytes, intended for use in DSCContext (but is currently unimplemented) // Console.WriteLine($"DSC actual at 0x{dscRecordOffset:X}, size=0x{dscRecordSize:X}\n"); } } } public string GetDescription() { return Language.GetString(Description_CTF); } public string GetName() { return Language.GetString(Name_CTF); } public long GetCALInt16Offset(BinaryReader reader) { reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); ulong bitflagExtended = reader.ReadUInt32(); CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); // Qualifier CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); // Name CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); // Description CaesarReader.ReadBitflagUInt16(ref bitflags, reader); // Type CaesarReader.ReadBitflagUInt16(ref bitflags, reader); // IsExecutable if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags)) { return reader.BaseStream.Position; } else { return -1; } } public void PrintDebug() { Console.WriteLine($"{Qualifier} - ReqBytes: {RequestBytes_Count}, P: {P_Count}, Q: {Q_Count}, R: {R_Count}, S: {S_Count}, ComParams: {T_ComParam_Count}, Preparation: {U_prep_Count}, V: {V_Count}, OutPres: {W_OutPres_Count}, X: {X_Count}, Y: {Y_Count}, Z: {Z_Count}, DSC {DiagServiceCodeCount}, field50: {Field50}"); Console.WriteLine($"BaseAddress @ 0x{BaseAddress:X}, NR: {NegativeResponseName}"); Console.WriteLine($"V @ 0x{BaseAddress + V_Offset:X}, count: {V_Count}"); } } } /* // originally EnvironmentContext, removed because of overlap using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class EnvironmentContext { // see : const char *__cdecl DIGetComfortErrorCode(DI_ECUINFO *ecuh, unsigned int dtcIndex) public string Qualifier; public long BaseAddress; public int PoolIndex; public int Name_CTF; public int Description_CTF; public int ServiceTypeMaybe; public int AccessLevelType_Maybe; public int AccessLevelType_Maybe2; public int PresentationTableCount; public int PresentationTableOffset; public int PresentationTableRowSize_Maybe; // see diagservice for similar layout, seems unused (uint16) public ECU ParentECU; CTFLanguage Language; public EnvironmentContext(BinaryReader reader, CTFLanguage language, long baseAddress, int poolIndex, ECU parentEcu) { ParentECU = parentEcu; PoolIndex = poolIndex; BaseAddress = baseAddress; Language = language; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); // layout seems very similar to DiagService ulong bitflags = reader.ReadUInt32(); ulong bitflagsExtended = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); ServiceTypeMaybe = CaesarReader.ReadBitflagInt16(ref bitflags, reader); AccessLevelType_Maybe = CaesarReader.ReadBitflagInt16(ref bitflags, reader); AccessLevelType_Maybe2 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); // doesn't seem to be set for any files in my library for (int i = 0; i < 14; i++) { if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags)) { throw new Exception("Sorry, The parser for EnvironmentContext has encountered an unknown bitflag; please open an issue and indicate your CBF file name."); } } // these describe the table to the presentation PresentationTableCount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); PresentationTableOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); PresentationTableRowSize_Maybe = CaesarReader.ReadBitflagInt16(ref bitflags, reader); // ... looks like DiagService?! } public void PrintDebug() { Console.WriteLine(Qualifier); } } } */ ================================================ FILE: Caesar/Caesar/ECU.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class ECU { public string Qualifier; public int EcuName_CTF; public int EcuDescription_CTF; public string EcuXmlVersion; public int InterfaceBlockCount; public int InterfaceTableOffset; public int SubinterfacesCount; public int SubinterfacesOffset; public string EcuClassName; public string UnkStr7; public string UnkStr8; public int IgnitionRequired; public int Unk2; public int UnkBlockCount; public int UnkBlockOffset; public int EcuSgmlSource; public int Unk6RelativeOffset; private int EcuVariant_BlockOffset; // 1 private int EcuVariant_EntryCount; private int EcuVariant_EntrySize; private int EcuVariant_BlockSize; private int DiagJob_BlockOffset; // 2 private int DiagJob_EntryCount; private int DiagJob_EntrySize; private int DiagJob_BlockSize; private int Dtc_BlockOffset; // 3 private int Dtc_EntryCount; private int Dtc_EntrySize; private int Dtc_BlockSize; private int Env_BlockOffset; // 4 private int Env_EntryCount; private int Env_EntrySize; private int Env_BlockSize; private int VcDomain_BlockOffset; // 5 , 0x15716 private int VcDomain_EntryCount; // [1], 43 0x2B private int VcDomain_EntrySize; // [2], 12 0xC (multiply with [1] for size), 43*12=516 = 0x204 private int VcDomain_BlockSize; // [3] unused private int Presentations_BlockOffset; private int Presentations_EntryCount; private int Presentations_EntrySize; private int Presentations_BlockSize; private int InternalPresentations_BlockOffset; // 31 (formerly InfoPool) private int InternalPresentations_EntryCount; // 32 private int InternalPresentations_EntrySize; // 33 private int InternalPresentations_BlockSize; // 34 private int Unk_BlockOffset; private int Unk_EntryCount; private int Unk_EntrySize; private int Unk_BlockSize; public int Unk39; public List ECUInterfaces = new List(); public List ECUInterfaceSubtypes = new List(); public List ECUVariants = new List(); public List GlobalVCDs = new List(); public List GlobalDTCs = new List(); public List GlobalEnvironmentContexts = new List(); public List GlobalDiagServices = new List(); public List GlobalPresentations = new List(); public List GlobalInternalPresentations = new List(); private long BaseAddress; [Newtonsoft.Json.JsonIgnore] public CTFLanguage Language; [Newtonsoft.Json.JsonIgnore] public CaesarContainer ParentContainer; byte[] cachedVarcodingPool = new byte[] { }; byte[] cachedVariantPool = new byte[] { }; byte[] cachedDiagjobPool = new byte[] { }; byte[] cachedEcuInfoPool = new byte[] { }; byte[] cachedPresentationsPool = new byte[] { }; byte[] cachedInternalPresentationsPool = new byte[] { }; byte[] cachedEnvPool = new byte[] { }; byte[] cachedDtcPool = new byte[] { }; byte[] cachedUnkPool = new byte[] { }; [Newtonsoft.Json.JsonIgnore] public string ECUDescription { get { return Language.GetString(EcuDescription_CTF); } } public void Restore(CTFLanguage language, CaesarContainer parentContainer) { Language = language; ParentContainer = parentContainer; foreach (VCDomain vc in GlobalVCDs) { vc.Restore(language, this); } foreach (DTC dtc in GlobalDTCs) { dtc.Restore(language, this); } foreach (DiagService ds in GlobalDiagServices) { ds.Restore(language, this); } foreach (DiagService ds in GlobalEnvironmentContexts) { ds.Restore(language, this); } foreach (DiagPresentation pres in GlobalPresentations) { pres.Restore(language); } foreach (DiagPresentation pres in GlobalInternalPresentations) { pres.Restore(language); } foreach (ECUInterface iface in ECUInterfaces) { iface.Restore(language); } foreach (ECUInterfaceSubtype iface in ECUInterfaceSubtypes) { iface.Restore(language); } foreach (ECUVariant variant in ECUVariants) { variant.Restore(language, this); } } public byte[] ReadDiagjobPool(BinaryReader reader) { if (cachedDiagjobPool.Length == 0) { cachedDiagjobPool = ReadEcuPool(reader, DiagJob_BlockOffset, DiagJob_EntryCount, DiagJob_EntrySize); } return cachedDiagjobPool; } public byte[] ReadVariantPool(BinaryReader reader) { if (cachedVariantPool.Length == 0) { cachedVariantPool = ReadEcuPool(reader, EcuVariant_BlockOffset, EcuVariant_EntryCount, EcuVariant_EntrySize); } return cachedVariantPool; } public byte[] ReadVarcodingPool(BinaryReader reader) { if (cachedVarcodingPool.Length == 0) { cachedVarcodingPool = ReadEcuPool(reader, VcDomain_BlockOffset, VcDomain_EntryCount, VcDomain_EntrySize); } return cachedVarcodingPool; } // don't actually know what the proper name is, using "ECUInfo" for now public byte[] ReadECUInfoPool(BinaryReader reader) { if (cachedEcuInfoPool.Length == 0) { cachedEcuInfoPool = ReadEcuPool(reader, InternalPresentations_BlockOffset, InternalPresentations_EntryCount, InternalPresentations_EntrySize); } return cachedEcuInfoPool; } public byte[] ReadECUPresentationsPool(BinaryReader reader) { if (cachedPresentationsPool.Length == 0) { cachedPresentationsPool = ReadEcuPool(reader, Presentations_BlockOffset, Presentations_EntryCount, Presentations_EntrySize); } return cachedPresentationsPool; } public byte[] ReadECUInternalPresentationsPool(BinaryReader reader) { if (cachedInternalPresentationsPool.Length == 0) { cachedInternalPresentationsPool = ReadEcuPool(reader, InternalPresentations_BlockOffset, InternalPresentations_EntryCount, InternalPresentations_EntrySize); } return cachedInternalPresentationsPool; } public byte[] ReadECUEnvPool(BinaryReader reader) { if (cachedEnvPool.Length == 0) { cachedEnvPool = ReadEcuPool(reader, Env_BlockOffset, Env_EntryCount, Env_EntrySize); } return cachedEnvPool; } public byte[] ReadECUUnkPool (BinaryReader reader) { if (cachedUnkPool.Length == 0) { cachedUnkPool = ReadEcuPool(reader, Unk_BlockOffset, Unk_EntryCount, Unk_EntrySize); } return cachedUnkPool; } public byte[] ReadECUDtcPool(BinaryReader reader) { if (cachedDtcPool.Length == 0) { cachedDtcPool = ReadEcuPool(reader, Dtc_BlockOffset, Dtc_EntryCount, Dtc_EntrySize); } return cachedDtcPool; } public byte[] ReadEcuPool(BinaryReader reader, long addressToReadFrom, int multiplier1, int multiplier2) { reader.BaseStream.Seek(addressToReadFrom, SeekOrigin.Begin); return reader.ReadBytes(multiplier1 * multiplier2); } public ECU() { } public ECU(BinaryReader reader, CTFLanguage language, CFFHeader header, long baseAddress, CaesarContainer parentContainer) { ParentContainer = parentContainer; BaseAddress = baseAddress; Language = language; // 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); // 10 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); // 14 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); // 12 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); // 8 // 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); // 12 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); // 8 Presentations_BlockSize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); InternalPresentations_BlockOffset = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader) + dataBufferOffsetRelativeToFile; InternalPresentations_EntryCount = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); InternalPresentations_EntrySize = CaesarReader.ReadBitflagInt32(ref ecuBitFlags, reader); // 8 InternalPresentations_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(); 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(); 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, language); ECUInterfaceSubtypes.Add(ecuInterfaceSubtype); } // dependency of variants CreatePresentations(reader, language); CreateInternalPresentations(reader, language); // requires presentations CreateEnvironments(reader, language); CreateDiagServices(reader, language); // dtc has xrefs to envs CreateDTCs(reader, language); CreateVCDomains(reader, language); CreateEcuVariants(reader, language); //PrintDebug(); } public void CreateDiagServices(BinaryReader reader, CTFLanguage language) { byte[] diagjobPool = ReadDiagjobPool(reader); // arrays since list has become too expensive DiagService[] globalDiagServices = new DiagService[DiagJob_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(diagjobPool))) { for (int diagjobIndex = 0; diagjobIndex < DiagJob_EntryCount; diagjobIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); uint crc = poolReader.ReadUInt32(); uint config = poolReader.ReadUInt16(); long diagjobBaseAddress = offset + DiagJob_BlockOffset; // Console.WriteLine($"DJ @ {offset:X} with size {size:X}"); DiagService dj = new DiagService(reader, language, diagjobBaseAddress, diagjobIndex, this); // GlobalDiagServices.Add(dj); globalDiagServices[diagjobIndex] = dj; } } GlobalDiagServices = new List(globalDiagServices); } public void CreateDTCs(BinaryReader reader, CTFLanguage language) { byte[] dtcPool = ReadECUDtcPool(reader); DTC[] globalDtcs = new DTC[Dtc_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(dtcPool))) { for (int dtcIndex = 0; dtcIndex < Dtc_EntryCount; dtcIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); uint crc = poolReader.ReadUInt32(); long dtcBaseAddress = offset + Dtc_BlockOffset; DTC dtc = new DTC(reader, language, dtcBaseAddress, dtcIndex, this); globalDtcs[dtcIndex] = dtc; } } GlobalDTCs = new List(globalDtcs); } public void CreateVCDomains(BinaryReader reader, CTFLanguage language) { byte[] vcPool = ReadVarcodingPool(reader); VCDomain[] globalVCDs = new VCDomain[VcDomain_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(vcPool))) { for (int vcdIndex = 0; vcdIndex < VcDomain_EntryCount; vcdIndex++) { int entryOffset = poolReader.ReadInt32(); int entrySize = poolReader.ReadInt32(); uint entryCrc = poolReader.ReadUInt32(); long vcdBlockAddress = entryOffset + VcDomain_BlockOffset; VCDomain vcd = new VCDomain(reader, language, vcdBlockAddress, vcdIndex, this); globalVCDs[vcdIndex] = vcd; } } GlobalVCDs = new List(globalVCDs); } public void CreateEnvironments(BinaryReader reader, CTFLanguage language) { /* byte[] envPool = ReadECUEnvPool(reader); EnvironmentContext[] globalEnvs = new EnvironmentContext[Env_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(envPool))) { for (int envIndex = 0; envIndex < Env_EntryCount; envIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); long envBaseAddress = offset + Env_BlockOffset; // Console.WriteLine($"0x{envBaseAddress:X}"); EnvironmentContext env = new EnvironmentContext(reader, language, envBaseAddress, envIndex, this); globalEnvs[envIndex] = env; } } GlobalEnvironmentContexts = new List(globalEnvs); */ byte[] envPool = ReadECUEnvPool(reader); DiagService[] globalEnvs = new DiagService[Env_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(envPool))) { for (int envIndex = 0; envIndex < Env_EntryCount; envIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); long envBaseAddress = offset + Env_BlockOffset; // Console.WriteLine($"0x{envBaseAddress:X}"); DiagService env = new DiagService(reader, language, envBaseAddress, envIndex, this); globalEnvs[envIndex] = env; } } GlobalEnvironmentContexts = new List(globalEnvs); } public void CreateUnk(BinaryReader reader, CTFLanguage language) { byte[] unkPool = ReadECUUnkPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(unkPool))) { for (int unkIndex = 0; unkIndex < Unk_EntryCount; unkIndex++) { } } } public void CreatePresentations(BinaryReader reader, CTFLanguage language) { byte[] presentationsPool = ReadECUPresentationsPool(reader); // arrays since list has become too expensive // DiagService[] globalDiagServices = new DiagService[DiagJob_EntryCount]; DiagPresentation[] globalPresentations = new DiagPresentation[Presentations_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(presentationsPool))) { for (int presentationsIndex = 0; presentationsIndex < Presentations_EntryCount; presentationsIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); long presentationsBaseAddress = offset + Presentations_BlockOffset; // string offsetLog = $"Pres @ 0x{offset:X} with size 0x{size:X} base 0x{presentationsBaseAddress:X}"; DiagPresentation pres = new DiagPresentation(reader, presentationsBaseAddress, presentationsIndex, language); globalPresentations[presentationsIndex] = pres; } // Console.WriteLine($"Entry count/size for presentations : {Presentations_EntryCount}, {Presentations_EntrySize}"); } GlobalPresentations = new List(globalPresentations); } public void CreateInternalPresentations(BinaryReader reader, CTFLanguage language) { byte[] internalPresentationsPool = ReadECUInternalPresentationsPool(reader); DiagPresentation[] globalInternalPresentations = new DiagPresentation[InternalPresentations_EntryCount]; using (BinaryReader poolReader = new BinaryReader(new MemoryStream(internalPresentationsPool))) { for (int internalPresentationsIndex = 0; internalPresentationsIndex < InternalPresentations_EntryCount; internalPresentationsIndex++) { int offset = poolReader.ReadInt32(); int size = poolReader.ReadInt32(); long internalPresentationsBaseAddress = offset + InternalPresentations_BlockOffset; DiagPresentation pres = new DiagPresentation(reader, internalPresentationsBaseAddress, internalPresentationsIndex, language); globalInternalPresentations[internalPresentationsIndex] = pres; } } GlobalInternalPresentations = new List(globalInternalPresentations); } public void CreateEcuVariants(BinaryReader reader, CTFLanguage language) { ECUVariants.Clear(); byte[] ecuVariantPool = ReadVariantPool(reader); using (BinaryReader poolReader = new BinaryReader(new MemoryStream(ecuVariantPool))) { for (int ecuVariantIndex = 0; ecuVariantIndex < EcuVariant_EntryCount; ecuVariantIndex++) { poolReader.BaseStream.Seek(ecuVariantIndex * EcuVariant_EntrySize, SeekOrigin.Begin); int entryOffset = poolReader.ReadInt32(); int entrySize = poolReader.ReadInt32(); ushort poolEntryAttributes = poolReader.ReadUInt16(); long variantBlockAddress = entryOffset + EcuVariant_BlockOffset; ECUVariant variant = new ECUVariant(reader, this, language, variantBlockAddress, entrySize); ECUVariants.Add(variant); // Console.WriteLine($"Variant Entry @ 0x{entryOffset:X} with size 0x{entrySize:X} and CRC {poolEntryAttributes:X8}, abs addr {variantBlockAddress:X8}"); #if DEBUG int resultLimit = 1999; if (ecuVariantIndex >= resultLimit) { Console.WriteLine($"Breaking prematurely to create only {resultLimit} variant(s) (debug)"); break; } #endif } } } public void PrintDebug() { Console.WriteLine($"ECU Name: {Qualifier}"); Console.WriteLine($"{nameof(EcuName_CTF)} : {EcuName_CTF}"); Console.WriteLine($"{nameof(EcuDescription_CTF)} : {EcuDescription_CTF}"); Console.WriteLine($"ECU ecuXmlVersion: {EcuXmlVersion}"); Console.WriteLine($"{nameof(InterfaceBlockCount)} : {InterfaceBlockCount}"); Console.WriteLine($"{nameof(InterfaceTableOffset)} : 0x{InterfaceTableOffset:X}"); Console.WriteLine($"{nameof(SubinterfacesCount)} : {SubinterfacesCount}"); Console.WriteLine($"{nameof(SubinterfacesOffset)} : {SubinterfacesOffset}"); Console.WriteLine($"ECU ecuClassName: {EcuClassName}"); Console.WriteLine($"ECU ecuIdk7: {UnkStr7}"); Console.WriteLine($"ECU ecuIdk8: {UnkStr8}"); Console.WriteLine($"{nameof(IgnitionRequired)} : {IgnitionRequired}"); Console.WriteLine($"{nameof(Unk2)} : {Unk2}"); Console.WriteLine($"{nameof(UnkBlockCount)} : {UnkBlockCount}"); Console.WriteLine($"{nameof(UnkBlockOffset)} : {UnkBlockOffset}"); Console.WriteLine($"{nameof(EcuSgmlSource)} : {EcuSgmlSource}"); Console.WriteLine($"{nameof(Unk6RelativeOffset)} : 0x{Unk6RelativeOffset:X}"); Console.WriteLine($"{nameof(EcuVariant_BlockOffset)} : 0x{EcuVariant_BlockOffset:X}"); Console.WriteLine($"{nameof(EcuVariant_EntryCount)} : {EcuVariant_EntryCount}"); Console.WriteLine($"{nameof(EcuVariant_EntrySize)} : {EcuVariant_EntrySize}"); Console.WriteLine($"{nameof(EcuVariant_BlockSize)} : 0x{EcuVariant_BlockSize:X}"); Console.WriteLine($"{nameof(DiagJob_BlockOffset)} : 0x{DiagJob_BlockOffset:X}"); Console.WriteLine($"{nameof(DiagJob_EntryCount)} : {DiagJob_EntryCount}"); Console.WriteLine($"{nameof(DiagJob_EntrySize)} : {DiagJob_EntrySize}"); Console.WriteLine($"{nameof(DiagJob_BlockSize)} : 0x{DiagJob_BlockSize:X}"); Console.WriteLine($"{nameof(Dtc_BlockOffset)} : 0x{Dtc_BlockOffset:X}"); Console.WriteLine($"{nameof(Dtc_EntryCount)} : {Dtc_EntryCount}"); Console.WriteLine($"{nameof(Dtc_EntrySize)} : {Dtc_EntrySize}"); Console.WriteLine($"{nameof(Dtc_BlockSize)} : 0x{Dtc_BlockSize:X}"); Console.WriteLine($"{nameof(Env_BlockOffset)} : 0x{Env_BlockOffset:X}"); Console.WriteLine($"{nameof(Env_EntryCount)} : {Env_EntryCount}"); Console.WriteLine($"{nameof(Env_EntrySize)} : {Env_EntrySize}"); // Console.WriteLine("--- bitflag load 2 ---"); Console.WriteLine($"{nameof(Env_BlockSize)} : 0x{Env_BlockSize:X}"); Console.WriteLine($"{nameof(VcDomain_BlockOffset)} : 0x{VcDomain_BlockOffset:X}"); Console.WriteLine($"{nameof(VcDomain_EntryCount)} : {VcDomain_EntryCount}"); Console.WriteLine($"{nameof(VcDomain_EntrySize)} : {VcDomain_EntrySize}"); Console.WriteLine($"{nameof(VcDomain_BlockSize)} : 0x{VcDomain_BlockSize:X}"); Console.WriteLine($"{nameof(Presentations_BlockOffset)} : 0x{Presentations_BlockOffset:X}"); Console.WriteLine($"{nameof(Presentations_EntryCount)} : {Presentations_EntryCount}"); Console.WriteLine($"{nameof(Presentations_EntrySize)} : {Presentations_EntrySize}"); Console.WriteLine($"{nameof(Presentations_BlockSize)} : 0x{Presentations_BlockSize:X}"); Console.WriteLine($"{nameof(InternalPresentations_BlockOffset)} : 0x{InternalPresentations_BlockOffset:X}"); Console.WriteLine($"{nameof(InternalPresentations_EntryCount)} : {InternalPresentations_EntryCount}"); Console.WriteLine($"{nameof(InternalPresentations_EntrySize)} : {InternalPresentations_EntrySize}"); Console.WriteLine($"{nameof(InternalPresentations_BlockSize)} : 0x{InternalPresentations_BlockSize:X}"); Console.WriteLine($"{nameof(Unk_BlockOffset)} : 0x{Unk_BlockOffset:X}"); Console.WriteLine($"{nameof(Unk_EntryCount)} : {Unk_EntryCount}"); Console.WriteLine($"{nameof(Unk_EntrySize)} : {Unk_EntrySize}"); Console.WriteLine($"{nameof(Unk_BlockSize)} : {Unk_BlockSize}"); Console.WriteLine($"{nameof(Unk39)} : {Unk39}"); } } } /* example env records ENV_48_Data_Record_1_StdEnvData ENV_56_StdEnv_OccurenceFlag ENV_64_StdEnv_OriginalOdometerValue ENV_80_StdEnv_MostRecentOdometerValue ENV_96_StdEnv_FrequencyCounter ENV_104_StdEnv_OperationCycleCounter ENV_112_Data_Record_2_CommonEnvData ENV_120_CommonEnv_StorageSequence ENV_128_Data_Record_3_First_Occurrence ENV_136_First_SIGNALS_xSet1 ENV_136_First_SIGNALS_xSet2 */ ================================================ FILE: Caesar/Caesar/ECUInterface.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class ECUInterface { public string Qualifier; public int Name_CTF; public int Description_CTF; public string VersionString; public int Version; private int ComParamCount; private int ComParamListOffset; public int Unk6; public List ComParameterNames = new List(); private CTFLanguage Language; private long BaseAddress; public void Restore(CTFLanguage language) { Language = language; } public ECUInterface() { } public ECUInterface(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); // we can now properly operate on the interface block ulong interfaceBitflags = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref interfaceBitflags, reader, BaseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader, -1); VersionString = CaesarReader.ReadBitflagStringWithReader(ref interfaceBitflags, reader, BaseAddress); Version = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader); ComParamCount = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader); ComParamListOffset = CaesarReader.ReadBitflagInt32(ref interfaceBitflags, reader); Unk6 = CaesarReader.ReadBitflagInt16(ref interfaceBitflags, reader); long comparamFileOffset = ComParamListOffset + BaseAddress; // Console.WriteLine($"interface string table offset from definition block : {interfaceStringTableOffset_fromDefinitionBlock:X}"); for (int interfaceStringIndex = 0; interfaceStringIndex < ComParamCount; interfaceStringIndex++) { // seek to string pointer reader.BaseStream.Seek(comparamFileOffset + (interfaceStringIndex * 4), SeekOrigin.Begin); // from pointer, seek to string long interfaceStringReadoutPtr = reader.ReadInt32() + comparamFileOffset; reader.BaseStream.Seek(interfaceStringReadoutPtr, SeekOrigin.Begin); string comParameter = CaesarReader.ReadStringFromBinaryReader(reader); ComParameterNames.Add(comParameter); } } public void PrintDebug() { Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Description_CTF)} : {Description_CTF}"); Console.WriteLine($"{nameof(VersionString)} : {VersionString}"); Console.WriteLine($"{nameof(Version)} : {Version}"); Console.WriteLine($"{nameof(ComParamCount)} : {ComParamCount}"); Console.WriteLine($"{nameof(ComParamListOffset)} : 0x{ComParamListOffset:X}"); Console.WriteLine($"{nameof(Unk6)} : {Unk6}"); foreach (string comParameter in ComParameterNames) { Console.WriteLine($"InterfaceComParameter: {comParameter}"); } } } } ================================================ FILE: Caesar/Caesar/ECUInterfaceSubtype.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class ECUInterfaceSubtype { public enum ParamName { CP_BAUDRATE, CP_GLOBAL_REQUEST_CANIDENTIFIER, CP_FUNCTIONAL_REQUEST_CANIDENTIFIER, CP_REQUEST_CANIDENTIFIER, CP_RESPONSE_CANIDENTIFIER, CP_PARTNUMBERID, CP_PARTBLOCK, CP_HWVERSIONID, CP_SWVERSIONID, CP_SWVERSIONBLOCK, CP_SUPPLIERID, CP_SWSUPPLIERBLOCK, CP_ADDRESSMODE, CP_ADDRESSEXTENSION, CP_ROE_RESPONSE_CANIDENTIFIER, CP_USE_TIMING_RECEIVED_FROM_ECU, CP_STMIN_SUG, CP_BLOCKSIZE_SUG, CP_P2_TIMEOUT, CP_S3_TP_PHYS_TIMER, CP_S3_TP_FUNC_TIMER, CP_BR_SUG, CP_CAN_TRANSMIT, CP_BS_MAX, CP_CS_MAX, CPI_ROUTINECOUNTER, CP_REQREPCOUNT, // looks like outliers? CP_P2_EXT_TIMEOUT_7F_78, CP_P2_EXT_TIMEOUT_7F_21, } public string Qualifier; public int Name_CTF; public int Description_CTF; public int Unk3; public int Unk4; public int Unk5; public int Unk6; public int Unk7; public int Unk8; public int Unk9; public int Unk10; // might be signed private long BaseAddress; private int Index; public List CommunicationParameters = new List(); private CTFLanguage Language; public void Restore(CTFLanguage language) { Language = language; foreach (ComParameter cp in CommunicationParameters) { cp.Restore(language); } } public ECUInterfaceSubtype() { } public ECUInterfaceSubtype(BinaryReader reader, long baseAddress, int index, CTFLanguage language) { Index = index; BaseAddress = baseAddress; Language = language; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); // we can now properly operate on the interface block ulong ctBitflags = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref ctBitflags, reader, BaseAddress); Name_CTF = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader, -1); Unk3 = CaesarReader.ReadBitflagInt16(ref ctBitflags, reader); Unk4 = CaesarReader.ReadBitflagInt16(ref ctBitflags, reader); Unk5 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader); Unk6 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader); Unk7 = CaesarReader.ReadBitflagInt32(ref ctBitflags, reader); Unk8 = CaesarReader.ReadBitflagUInt8(ref ctBitflags, reader); Unk9 = CaesarReader.ReadBitflagUInt8(ref ctBitflags, reader); Unk10 = CaesarReader.ReadBitflagInt8(ref ctBitflags, reader); // might be signed } public ComParameter GetComParameterByName(string paramName) { return CommunicationParameters.Find(x => x.ParamName == paramName); } public int GetComParameterValue(ParamName name) { return GetComParameterByName(name.ToString()).ComParamValue; } public bool GetComParameterValue(ParamName name, out int result) { ComParameter param = GetComParameterByName(name.ToString()); if (param is null) { result = 0; return false; } else { result = param.ComParamValue; return true; } } public void PrintDebug() { Console.WriteLine($"iface subtype: @ 0x{BaseAddress:X}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Description_CTF)} : {Description_CTF}"); Console.WriteLine($"{nameof(Unk3)} : {Unk3}"); Console.WriteLine($"{nameof(Unk4)} : {Unk4}"); Console.WriteLine($"{nameof(Unk5)} : {Unk5}"); Console.WriteLine($"{nameof(Unk6)} : {Unk6}"); Console.WriteLine($"{nameof(Unk7)} : {Unk7}"); Console.WriteLine($"{nameof(Unk8)} : {Unk8}"); Console.WriteLine($"{nameof(Unk9)} : {Unk9}"); Console.WriteLine($"{nameof(Unk10)} : {Unk10}"); Console.WriteLine($"CT: {Qualifier}"); } } } ================================================ FILE: Caesar/Caesar/ECUVariant.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class ECUVariant { public string Qualifier; public int Name_CTF; public int Description_CTF; public string UnkStr1; public string UnkStr2; public int Unk1; private int MatchingPatternCount; // A private int MatchingPatternOffset; private int SubsectionB_Count; // B private int SubsectionB_Offset; private int ComParamsCount; // C private int ComParamsOffset; private int DiagServiceCode_Count; // D : DSC private int DiagServiceCode_Offset; private int DiagServicesCount; // E private int DiagServicesOffset; private int DTC_Count; // F private int DTC_Offset; private int EnvironmentCtx_Count; // G private int EnvironmentCtx_Offset; private int Xref_Count; // H private int Xref_Offset; private int VCDomainsCount; // I private int VCDomainsOffset; public string NegativeResponseName; public int UnkByte; public List VCDomainPoolOffsets = new List(); public List DiagServicesPoolOffsets = new List(); public List> DTCsPoolOffsetsWithBounds = new List>(); public List EnvironmentContextsPoolOffsets = new List(); public List VariantPatterns = new List(); public int[] Xrefs = new int[] { }; // these should be manually deserialized by creating references back to the parent ECU [Newtonsoft.Json.JsonIgnore] public List VCDomains = new List(); [Newtonsoft.Json.JsonIgnore] public DiagService[] DiagServices = new DiagService[] { }; [Newtonsoft.Json.JsonIgnore] public DTC[] DTCs = new DTC[] { }; [Newtonsoft.Json.JsonIgnore] public DiagService[] EnvironmentContexts = new DiagService[] { }; public long BaseAddress; [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; [Newtonsoft.Json.JsonIgnore] private CTFLanguage Language; public void Restore(CTFLanguage language, ECU parentEcu) { Language = language; ParentECU = parentEcu; CreateVCDomains(parentEcu, language); CreateDiagServices(parentEcu, language); CreateDTCs(parentEcu, language); CreateEnvironmentContexts(parentEcu, language); /* // no restoring required foreach (ECUVariantPattern vp in VariantPatterns) { vp.Restore(); } */ // CreateComParameters(reader, parentEcu); // already serialized in json } public ECUVariant() { } public ECUVariant(BinaryReader reader, ECU parentEcu, CTFLanguage language, long baseAddress, int blockSize) { // int __usercall DIIFindVariantByECUID@(ECU_VARIANT *a1@, _DWORD *a2, int a3, __int16 a4, int a5) BaseAddress = baseAddress; ParentECU = parentEcu; Language = language; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); byte[] variantBytes = reader.ReadBytes(blockSize); using (BinaryReader variantReader = new BinaryReader(new MemoryStream(variantBytes, 0, variantBytes.Length, false, true))) { ulong bitFlags = variantReader.ReadUInt32(); int skip = variantReader.ReadInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader); Name_CTF = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader, -1); UnkStr1 = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader); UnkStr2 = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader); Unk1 = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 1 MatchingPatternCount = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 2 MatchingPatternOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 3 SubsectionB_Count = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 4 SubsectionB_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 5 ComParamsCount = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 6 ComParamsOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 7 DiagServiceCode_Count = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 8 DiagServiceCode_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 9 DiagServicesCount = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 10 DiagServicesOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 11 DTC_Count = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 12 DTC_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 13 EnvironmentCtx_Count = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 14 EnvironmentCtx_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 15 Xref_Count = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 16 Xref_Offset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 17 VCDomainsCount = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 18 VCDomainsOffset = CaesarReader.ReadBitflagInt32(ref bitFlags, variantReader); // 19 NegativeResponseName = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, variantReader); UnkByte = CaesarReader.ReadBitflagInt8(ref bitFlags, variantReader); // 20 byte // vcdomain VCDomainPoolOffsets = new List(); variantReader.BaseStream.Seek(VCDomainsOffset, SeekOrigin.Begin); for (int variantCodingIndex = 0; variantCodingIndex < VCDomainsCount; variantCodingIndex++) { VCDomainPoolOffsets.Add(variantReader.ReadInt32()); } // diagnostic services DiagServicesPoolOffsets = new List(); variantReader.BaseStream.Seek(DiagServicesOffset, SeekOrigin.Begin); for (int diagIndex = 0; diagIndex < DiagServicesCount; diagIndex++) { DiagServicesPoolOffsets.Add(variantReader.ReadInt32()); } // DTCs //DTCsPoolOffsets = new List(); DTCsPoolOffsetsWithBounds = new List>(); variantReader.BaseStream.Seek(DTC_Offset, SeekOrigin.Begin); for (int dtcIndex = 0; dtcIndex < DTC_Count; dtcIndex++) { int actualIndex = variantReader.ReadInt32(); int xrefStart = variantReader.ReadInt32(); int xrefCount = variantReader.ReadInt32(); // stitch with table H : int __cdecl DIECUGetNumberOfEnvForAllErrors(DI_ECUINFO *ecuh, int a2, int a3) //DTCsPoolOffsets.Add(actualIndex); // todo: depreciate this DTCsPoolOffsetsWithBounds.Add(new Tuple(actualIndex, xrefStart, xrefCount)); } // EnvCtxs EnvironmentContextsPoolOffsets = new List(); variantReader.BaseStream.Seek(EnvironmentCtx_Offset, SeekOrigin.Begin); for (int envIndex = 0; envIndex < EnvironmentCtx_Count; envIndex++) { EnvironmentContextsPoolOffsets.Add(variantReader.ReadInt32()); } } CreateVCDomains(parentEcu, language); CreateDiagServices(parentEcu, language); CreateVariantPatterns(reader); CreateComParameters(reader, parentEcu); CreateDTCs(parentEcu, language); CreateEnvironmentContexts(parentEcu, language); CreateXrefs(reader, parentEcu, language); //PrintDebug(); } // this function is parked here since the values are drawn from EnvironmentContexts // Xref_Count and Xref_Offset; public List GetEnvironmentContextsForDTC(DTC inDtc) { List ctxList = new List(); for (int i = inDtc.XrefStart; i < (inDtc.XrefStart + inDtc.XrefCount); i++) { foreach (DiagService envToTest in EnvironmentContexts) { int xref = Xrefs[i]; if (envToTest.PoolIndex == xref) { ctxList.Add(envToTest); break; } } } return ctxList; } public void CreateComParameters(BinaryReader reader, ECU parentEcu) { // this is unusual as it doesn't use the usual caesar-style bitflag reads // for reasons unknown the comparam is attached to the basevariant long comparamBaseAddress = BaseAddress + ComParamsOffset; // Console.WriteLine($"Comparam base: 0x{comparamBaseAddress:X} : number of comparams: {ComParamsCount} "); reader.BaseStream.Seek(comparamBaseAddress, SeekOrigin.Begin); List comparameterOffsets = new List(); for (int comIndex = 0; comIndex < ComParamsCount; comIndex++) { comparameterOffsets.Add(reader.ReadInt32() + comparamBaseAddress); } if (parentEcu.ECUInterfaces.Count == 0) { throw new Exception("Invalid communication parameter : no parent interface"); } foreach (long comparamOffset in comparameterOffsets) { ComParameter param = new ComParameter(reader, comparamOffset, parentEcu.ECUInterfaces, Language); // KW2C3PE uses a different parent addressing style int parentIndex = param.ParentInterfaceIndex > 0 ? param.ParentInterfaceIndex : param.SubinterfaceIndex; if (param.ParentInterfaceIndex >= parentEcu.ECUInterfaceSubtypes.Count) { throw new Exception("ComParam: tried to assign to nonexistent interface"); } else { parentEcu.ECUInterfaceSubtypes[parentIndex].CommunicationParameters.Add(param); } } } public void CreateVariantPatterns(BinaryReader reader) { long tableOffset = BaseAddress + MatchingPatternOffset; reader.BaseStream.Seek(tableOffset, SeekOrigin.Begin); VariantPatterns.Clear(); for (int patternIndex = 0; patternIndex < MatchingPatternCount; patternIndex++) { reader.BaseStream.Seek(tableOffset + (patternIndex * 4), SeekOrigin.Begin); int patternOffset = reader.ReadInt32(); long patternAddress = patternOffset + tableOffset; ECUVariantPattern pattern = new ECUVariantPattern(reader, patternAddress); VariantPatterns.Add(pattern); } } public VCDomain GetVCDomainByName(string name) { foreach (VCDomain domain in VCDomains) { if (domain.Qualifier == name) { return domain; } } return null; } public DiagService GetDiagServiceByName(string name) { foreach (DiagService diag in DiagServices) { if (diag.Qualifier == name) { return diag; } } return null; } public string[] GetVCDomainNames() { List result = new List(); foreach (VCDomain domain in VCDomains) { result.Add(domain.Qualifier); } return result.ToArray(); } private void CreateVCDomains(ECU parentEcu, CTFLanguage language) { VCDomains = new List(); foreach (int variantCodingDomainEntry in VCDomainPoolOffsets) { /* VCDomain vcDomain = new VCDomain(reader, parentEcu, language, variantCodingDomainEntry); VCDomains.Add(vcDomain); */ VCDomains.Add(ParentECU.GlobalVCDs[variantCodingDomainEntry]); } } private void CreateDiagServices(ECU parentEcu, CTFLanguage language) { // unlike variant domains, storing references to the parent objects in the ecu is preferable since this is relatively larger //DiagServices = new List(); DiagServices = new DiagService[DiagServicesPoolOffsets.Count]; /* // computationally expensive, 40ish % runtime is spent here // easier to read, below optimization essentially accomplishes this in a shorter period foreach (DiagService diagSvc in parentEcu.GlobalDiagServices) { for (int i = 0; i < DiagServicesPoolOffsets.Count; i++) { if (diagSvc.PoolIndex == DiagServicesPoolOffsets[i]) { DiagServices[i] = diagSvc; } } } */ // optimization hack int poolSize = DiagServicesPoolOffsets.Count; for (int i = 0; i < poolSize; i++) { if (i == DiagServicesPoolOffsets[i]) { DiagServices[i] = parentEcu.GlobalDiagServices[i]; } } DiagServicesPoolOffsets.Sort(); int lowestIndex = 0; int loopMax = parentEcu.GlobalDiagServices.Count; for (int i = 0; i < poolSize; i++) { if (DiagServices[i] != null) { continue; } for (int globalIndex = lowestIndex; globalIndex < loopMax; globalIndex++) { if (parentEcu.GlobalDiagServices[globalIndex].PoolIndex == DiagServicesPoolOffsets[i]) { DiagServices[i] = parentEcu.GlobalDiagServices[globalIndex]; lowestIndex = globalIndex; break; } } } } private void CreateDTCs(ECU parentEcu, CTFLanguage language) { int dtcPoolSize = DTCsPoolOffsetsWithBounds.Count; DTCs = new DTC[dtcPoolSize]; for (int i = 0; i < dtcPoolSize; i++) { if (i == DTCsPoolOffsetsWithBounds[i].Item1) { DTCs[i] = parentEcu.GlobalDTCs[i]; DTCs[i].XrefStart = DTCsPoolOffsetsWithBounds[i].Item2; DTCs[i].XrefCount = DTCsPoolOffsetsWithBounds[i].Item3; } } DTCsPoolOffsetsWithBounds.Sort((x, y) => x.Item1.CompareTo(y.Item1)); int lowestIndex = 0; int loopMax = ParentECU.GlobalDTCs.Count; for (int i = 0; i < dtcPoolSize; i++) { if (DTCs[i] != null) { continue; } for (int globalIndex = lowestIndex; globalIndex < loopMax; globalIndex++) { if (ParentECU.GlobalDTCs[globalIndex].PoolIndex == DTCsPoolOffsetsWithBounds[i].Item1) { DTCs[i] = parentEcu.GlobalDTCs[globalIndex]; DTCs[i].XrefStart = DTCsPoolOffsetsWithBounds[i].Item2; DTCs[i].XrefCount = DTCsPoolOffsetsWithBounds[i].Item3; lowestIndex = globalIndex; break; } } } /* // same thing as above, just more readable and slower foreach (DTC dtc in parentEcu.GlobalDTCs) { for (int i = 0; i < DTCsPoolOffsetsWithBounds.Count; i++) { if (dtc.PoolIndex == DTCsPoolOffsetsWithBounds[i].Item1) { // this is only valid on the assumption that DTC instances are unique (e.g. not shared from a base variant) dtc.XrefStart = DTCsPoolOffsetsWithBounds[i].Item2; dtc.XrefCount = DTCsPoolOffsetsWithBounds[i].Item3; DTCs[i] = dtc; } } } */ } private void CreateXrefs(BinaryReader reader, ECU parentEcu, CTFLanguage language) { Xrefs = new int[Xref_Count]; reader.BaseStream.Seek(BaseAddress + Xref_Offset, SeekOrigin.Begin); for (int i = 0; i < Xref_Count; i++) { Xrefs[i] = reader.ReadInt32(); } } private void CreateEnvironmentContexts(ECU parentEcu, CTFLanguage language) { int envPoolSize = EnvironmentContextsPoolOffsets.Count; EnvironmentContexts = new DiagService[envPoolSize]; for (int i = 0; i < envPoolSize; i++) { if (i == EnvironmentContextsPoolOffsets[i]) { EnvironmentContexts[i] = parentEcu.GlobalEnvironmentContexts[i]; } } EnvironmentContextsPoolOffsets.Sort(); int lowestIndex = 0; int loopMax = parentEcu.GlobalEnvironmentContexts.Count; for (int i = 0; i < envPoolSize; i++) { if (EnvironmentContexts[i] != null) { continue; } for (int globalIndex = lowestIndex; globalIndex < loopMax; globalIndex++) { if (parentEcu.GlobalEnvironmentContexts[globalIndex].PoolIndex == EnvironmentContextsPoolOffsets[i]) { EnvironmentContexts[i] = parentEcu.GlobalEnvironmentContexts[globalIndex]; lowestIndex = globalIndex; break; } } } /* // same thing, more readable, much slower foreach (DiagService env in parentEcu.GlobalEnvironmentContexts) { for (int i = 0; i < EnvironmentContextsPoolOffsets.Count; i++) { if (env.PoolIndex == EnvironmentContextsPoolOffsets[i]) { EnvironmentContexts[i] = env; } } } */ } public void PrintDebug() { Console.WriteLine($"---------------- {BaseAddress:X} ----------------"); Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Description_CTF)} : {Description_CTF}"); Console.WriteLine($"{nameof(UnkStr1)} : {UnkStr1}"); Console.WriteLine($"{nameof(UnkStr2)} : {UnkStr2}"); Console.WriteLine($"{nameof(VCDomainsCount)} : {VCDomainsCount}"); Console.WriteLine($"{nameof(VCDomainsOffset)} : {VCDomainsOffset}"); Console.WriteLine($"{nameof(NegativeResponseName)} : {NegativeResponseName}"); Console.WriteLine($"{nameof(Unk1)} : {Unk1}"); Console.WriteLine($"{nameof(MatchingPatternCount)} : {MatchingPatternCount}"); Console.WriteLine($"{nameof(MatchingPatternOffset)} : {MatchingPatternOffset}"); Console.WriteLine($"{nameof(SubsectionB_Count)} : {SubsectionB_Count}"); Console.WriteLine($"{nameof(SubsectionB_Offset)} : {SubsectionB_Offset}"); Console.WriteLine($"{nameof(ComParamsCount)} : {ComParamsCount}"); Console.WriteLine($"{nameof(ComParamsOffset)} : {ComParamsOffset}"); Console.WriteLine($"{nameof(DiagServiceCode_Count)} : {DiagServiceCode_Count}"); Console.WriteLine($"{nameof(DiagServiceCode_Offset)} : {DiagServiceCode_Offset}"); Console.WriteLine($"{nameof(DiagServicesCount)} : {DiagServicesCount}"); Console.WriteLine($"{nameof(DiagServicesOffset)} : {DiagServicesOffset}"); Console.WriteLine($"{nameof(DTC_Count)} : {DTC_Count}"); Console.WriteLine($"{nameof(DTC_Offset)} : {DTC_Offset}"); Console.WriteLine($"{nameof(EnvironmentCtx_Count)} : {EnvironmentCtx_Count}"); Console.WriteLine($"{nameof(EnvironmentCtx_Offset)} : {EnvironmentCtx_Offset}"); Console.WriteLine($"{nameof(Xref_Count)} : {Xref_Count}"); Console.WriteLine($"{nameof(Xref_Offset)} : {Xref_Offset}"); Console.WriteLine($"{nameof(VCDomainsCount)} : {VCDomainsCount}"); Console.WriteLine($"{nameof(VCDomainsOffset)} : {VCDomainsOffset}"); } } } ================================================ FILE: Caesar/Caesar/ECUVariantPattern.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Diagnostics; namespace Caesar { public class ECUVariantPattern { public int UnkBufferSize; public byte[] UnkBuffer; public int Unk3; public int Unk4; public int Unk5; public string VendorName; public int KwpVendorID; public int Unk8; public int Unk9; public int Unk10; public int Unk11; public int Unk12; public int Unk13; public int Unk14; public int Unk15; public byte[] EcuId; public int Unk17; public int Unk18; public int Unk19; public int Unk20; public string Unk21; public int Unk22; public int Unk23; public int UdsVendorID; public int PatternType; public int VariantID; private readonly long BaseAddress; public void Restore() { } public ECUVariantPattern() { } public ECUVariantPattern(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); UnkBufferSize = CaesarReader.ReadBitflagInt32(ref bitflags, reader); UnkBuffer = CaesarReader.ReadBitflagDumpWithReader(ref bitflags, reader, UnkBufferSize, baseAddress); Unk3 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Unk4 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Unk5 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); VendorName = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); KwpVendorID = CaesarReader.ReadBitflagUInt16(ref bitflags, reader); Unk8 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); Unk9 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); Unk10 = CaesarReader.ReadBitflagInt16(ref bitflags, reader); Unk11 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk12 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk13 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk14 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk15 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); EcuId = CaesarReader.ReadBitflagRawBytes(ref bitflags, reader, 4); Unk17 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk18 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk19 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk20 = CaesarReader.ReadBitflagUInt8(ref bitflags, reader); Unk21 = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, baseAddress); Unk22 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Unk23 = CaesarReader.ReadBitflagInt32(ref bitflags, reader); UdsVendorID = CaesarReader.ReadBitflagInt32(ref bitflags, reader); PatternType = CaesarReader.ReadBitflagInt32(ref bitflags, reader); VariantID = UdsVendorID == 0 ? KwpVendorID : UdsVendorID; // type 3 contains a vendor name } public void PrintDebug() { Console.WriteLine($"UnkBufferSize : {UnkBufferSize}"); Console.WriteLine($"UnkBuffer : {UnkBuffer}"); Console.WriteLine($"Unk3 : {Unk3}"); Console.WriteLine($"Unk4 : {Unk4}"); Console.WriteLine($"Unk5 : {Unk5}"); Console.WriteLine($"VendorName : {VendorName}"); Console.WriteLine($"Unk7 : {KwpVendorID}"); Console.WriteLine($"Unk8 : {Unk8}"); Console.WriteLine($"Unk9 : {Unk9}"); Console.WriteLine($"Unk10 : {Unk10}"); Console.WriteLine($"Unk11 : {Unk11}"); Console.WriteLine($"Unk12 : {Unk12}"); Console.WriteLine($"Unk13 : {Unk13}"); Console.WriteLine($"Unk14 : {Unk14}"); Console.WriteLine($"Unk15 : {Unk15}"); Console.WriteLine($"EcuId : {EcuId}"); Console.WriteLine($"Unk17 : {Unk17}"); Console.WriteLine($"Unk18 : {Unk18}"); Console.WriteLine($"Unk19 : {Unk19}"); Console.WriteLine($"Unk20 : {Unk20}"); Console.WriteLine($"Unk21 : {Unk21}"); Console.WriteLine($"Unk22 : {Unk22}"); Console.WriteLine($"Unk23 : {Unk23}"); Console.WriteLine($"VariantID : {VariantID}"); Console.WriteLine($"PatternType : {PatternType}"); } } } ================================================ FILE: Caesar/Caesar/Flash/CaesarFlashContainer.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class CaesarFlashContainer { public FlashHeader CaesarFlashHeader; public CTFHeader CaesarCTFHeader; public byte[] FileBytes = new byte[] { }; public CaesarFlashContainer(byte[] fileBytes) { FileBytes = fileBytes; // from DIOpenCFF using (BinaryReader reader = new BinaryReader(new MemoryStream(fileBytes, 0, FileBytes.Length, false, true))) { byte[] header = reader.ReadBytes(StubHeader.StubHeaderSize); int cffHeaderSize = reader.ReadInt32(); byte[] cffHeaderData = reader.ReadBytes(cffHeaderSize); uint computedChecksum = CaesarReader.ComputeFileChecksumLazy(fileBytes); uint providedChecksum = ReadFileChecksum(fileBytes); if (computedChecksum != providedChecksum) { Console.WriteLine($"WARNING: Checksum mismatch : computed/provided: {computedChecksum:X8}/{providedChecksum:X8}"); } ReadFlashCFF(reader); // fix this ReadCTF(reader); } } void ReadCTF(BinaryReader fileReader) { if (CaesarFlashHeader.CTFHeaderTable == 0) { throw new NotImplementedException("No idea how to handle nonexistent ctf header"); } long ctfOffset = CaesarFlashHeader.BaseAddress + CaesarFlashHeader.CTFHeaderTable; CaesarCTFHeader = new CTFHeader(fileReader, ctfOffset, CaesarFlashHeader.CffHeaderSize); } public uint ReadFileChecksum(byte[] fileBytes) { return BitConverter.ToUInt32(fileBytes, fileBytes.Length - 4); } void ReadFlashCFF(BinaryReader fileReader) { CaesarFlashHeader = new FlashHeader(fileReader); } public static void ExportCFFMemorySegments(string filePath) { string directory = Path.GetDirectoryName(filePath); Console.WriteLine($"Starting CFF segment export. Assumes that segments are embedded and unprotected."); byte[] flashContainer = File.ReadAllBytes(filePath); CaesarFlashContainer container = new CaesarFlashContainer(flashContainer); // mini-feature: if a binary with enough space exists, the image's data will be written to it (for some CFFs with many segments, this saves time) string mergePath = @"merge.bin"; bool useMergeFeature = File.Exists(mergePath); byte[] mergeBytes = new byte[] { }; if (useMergeFeature) { mergeBytes = File.ReadAllBytes(mergePath); } using (BinaryReader reader = new BinaryReader(new MemoryStream(flashContainer))) { foreach (FlashDataBlock db in container.CaesarFlashHeader.DataBlocks) { Console.WriteLine($"FlashDataBlock: {db.Qualifier}"); long fileCursor = 0; foreach (FlashSegment seg in db.FlashSegments) { long offset = db.FlashData + container.CaesarFlashHeader.CffHeaderSize + container.CaesarFlashHeader.LanguageBlockLength + fileCursor + 0x414; fileCursor += seg.SegmentLength; Console.WriteLine($"Segment: {seg.SegmentName} mapped to 0x{seg.FromAddress:X} with size 0x{seg.SegmentLength:X}"); reader.BaseStream.Seek(offset, SeekOrigin.Begin); byte[] fileBytes = reader.ReadBytes(seg.SegmentLength); File.WriteAllBytes($"{directory}\\{db.Qualifier}_{seg.FromAddress:X}.bin", fileBytes); if (useMergeFeature) { if ((mergeBytes.Length >= (seg.FromAddress + fileBytes.Length))) { for (int i = 0; i < fileBytes.Length; i++) { mergeBytes[i + seg.FromAddress] |= fileBytes[i]; } } else { Console.WriteLine($"Out-of-bound merge, skipping {seg.SegmentName} mapped to 0x{seg.FromAddress:X} with size 0x{seg.SegmentLength:X}"); } } } } } Console.WriteLine($"Exported segments can be found at {directory}"); if (useMergeFeature) { File.WriteAllBytes(mergePath, mergeBytes); } } public void SpliceCFFFile(string filePath) { string directory = Path.GetDirectoryName(filePath); Console.WriteLine($"Starting CFF splicer.."); byte[] flashContainer = File.ReadAllBytes(filePath); CaesarFlashContainer container = new CaesarFlashContainer(flashContainer); using (BinaryReader reader = new BinaryReader(new MemoryStream(flashContainer))) { foreach (FlashDataBlock db in container.CaesarFlashHeader.DataBlocks) { Console.WriteLine($"FlashDataBlock: {db.Qualifier}"); long fileCursor = 0; foreach (FlashSegment seg in db.FlashSegments) { // check: which fields are mutable when splicing long offset = db.FlashData + // somewhat mutable : probably if there's more than 1 datablock, this value will be nonzero container.CaesarFlashHeader.CffHeaderSize + // constant container.CaesarFlashHeader.LanguageBlockLength + // constant fileCursor + // mutable, see below 0x414; // constant fileCursor += seg.SegmentLength; // mutable because of segment length Console.WriteLine($"Segment: {seg.SegmentName} mapped to 0x{seg.FromAddress:X} with size 0x{seg.SegmentLength:X}"); reader.BaseStream.Seek(offset, SeekOrigin.Begin); byte[] fileBytes = reader.ReadBytes(seg.SegmentLength); File.WriteAllBytes($"{directory}\\{db.Qualifier}_{seg.FromAddress:X}.bin", fileBytes); } } } Console.WriteLine($"Exported segments can be found at {directory}"); } } } ================================================ FILE: Caesar/Caesar/Flash/FlashDataBlock.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class FlashDataBlock { // 0x16 [6, 4,4,4,4, 4,4,4,4, 4,4,4,2, 4,4,4,4, 4,4,4,4, 4,4,4,4,4], public string Qualifier; public int LongName; public int Description; public int FlashData; public int BlockLength; public int DataFormat; public int FileName; public int NumberOfFilters; public int FiltersOffset; public int NumberOfSegments; public int SegmentOffset; public int EncryptionMode; public int KeyLength; public int KeyBuffer; public int NumberOfOwnIdents; public int IdentsOffset; public int NumberOfSecurities; public int SecuritiesOffset; public string DataBlockType; public int UniqueObjectId; public string FlashDataInfoQualifier; public int FlashDataInfoLongName; public int FlashDataInfoDescription; public int FlashDataInfoUniqueObjectId; public long BaseAddress; public List FlashSegments = new List(); public List FlashSecurities = new List(); public FlashDataBlock(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); reader.ReadUInt16(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); LongName = CaesarReader.ReadBitflagInt32(ref bitflags, reader); Description = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FlashData = CaesarReader.ReadBitflagInt32(ref bitflags, reader); BlockLength = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DataFormat = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FileName = CaesarReader.ReadBitflagInt32(ref bitflags, reader); NumberOfFilters = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FiltersOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); NumberOfSegments = CaesarReader.ReadBitflagInt32(ref bitflags, reader); SegmentOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); EncryptionMode = CaesarReader.ReadBitflagInt16(ref bitflags, reader); KeyLength = CaesarReader.ReadBitflagInt32(ref bitflags, reader); KeyBuffer = CaesarReader.ReadBitflagInt32(ref bitflags, reader); NumberOfOwnIdents = CaesarReader.ReadBitflagInt32(ref bitflags, reader); IdentsOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); NumberOfSecurities = CaesarReader.ReadBitflagInt32(ref bitflags, reader); SecuritiesOffset = CaesarReader.ReadBitflagInt32(ref bitflags, reader); DataBlockType = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); UniqueObjectId = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FlashDataInfoQualifier = CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); FlashDataInfoLongName = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FlashDataInfoDescription = CaesarReader.ReadBitflagInt32(ref bitflags, reader); FlashDataInfoUniqueObjectId = CaesarReader.ReadBitflagInt32(ref bitflags, reader); // CtfUnk1 = CaesarReader.ReadBitflagInt32(ref ctfBitflags, reader); FlashSegments = new List(); for (int segmentIndex = 0; segmentIndex < NumberOfSegments; segmentIndex++) { long segmentEntryAddress = SegmentOffset + BaseAddress + (segmentIndex * 4); reader.BaseStream.Seek(segmentEntryAddress, SeekOrigin.Begin); long segmentBaseAddress = SegmentOffset + BaseAddress + reader.ReadInt32(); FlashSegment segment = new FlashSegment(reader, segmentBaseAddress); FlashSegments.Add(segment); } FlashSecurities = new List(); for (int securitiesIndex = 0; securitiesIndex < NumberOfSecurities; securitiesIndex++) { long securitiesEntryAddress = SecuritiesOffset + BaseAddress + (securitiesIndex * 4); reader.BaseStream.Seek(securitiesEntryAddress, SeekOrigin.Begin); long securitiesBaseAddress = SecuritiesOffset + BaseAddress + reader.ReadInt32(); FlashSecurity security = new FlashSecurity(reader, securitiesBaseAddress); FlashSecurities.Add(security); } } public long GetBlockLengthOffset(BinaryReader reader) { reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); reader.ReadUInt16(); CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); // Qualifier CaesarReader.ReadBitflagInt32(ref bitflags, reader); // LongName CaesarReader.ReadBitflagInt32(ref bitflags, reader); // Description CaesarReader.ReadBitflagInt32(ref bitflags, reader); // FlashData if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags)) { return reader.BaseStream.Position; } else { return -1; } } public long GetFlashDataOffset(BinaryReader reader) { reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt32(); reader.ReadUInt16(); CaesarReader.ReadBitflagStringWithReader(ref bitflags, reader, BaseAddress); // Qualifier CaesarReader.ReadBitflagInt32(ref bitflags, reader); // LongName CaesarReader.ReadBitflagInt32(ref bitflags, reader); // Description if (CaesarReader.CheckAndAdvanceBitflag(ref bitflags)) { return reader.BaseStream.Position; } else { return -1; } } public void PrintDebug() { Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(LongName)} : {LongName}"); Console.WriteLine($"{nameof(Description)} : {Description}"); Console.WriteLine($"{nameof(FlashData)} : {FlashData}"); Console.WriteLine($"{nameof(BlockLength)} : 0x{BlockLength:X}"); Console.WriteLine($"{nameof(DataFormat)} : {DataFormat}"); Console.WriteLine($"{nameof(FileName)} : {FileName}"); Console.WriteLine($"{nameof(NumberOfFilters)} : {NumberOfFilters}"); Console.WriteLine($"{nameof(FiltersOffset)} : {FiltersOffset}"); Console.WriteLine($"{nameof(NumberOfSegments)} : {NumberOfSegments}"); Console.WriteLine($"{nameof(SegmentOffset)} : {SegmentOffset}"); Console.WriteLine($"{nameof(EncryptionMode)} : {EncryptionMode}"); Console.WriteLine($"{nameof(KeyLength)} : {KeyLength}"); Console.WriteLine($"{nameof(KeyBuffer)} : {KeyBuffer}"); Console.WriteLine($"{nameof(NumberOfOwnIdents)} : {NumberOfOwnIdents}"); Console.WriteLine($"{nameof(IdentsOffset)} : {IdentsOffset}"); Console.WriteLine($"{nameof(NumberOfSecurities)} : {NumberOfSecurities}"); Console.WriteLine($"{nameof(SecuritiesOffset)} : {SecuritiesOffset}"); Console.WriteLine($"{nameof(DataBlockType)} : {DataBlockType}"); Console.WriteLine($"{nameof(UniqueObjectId)} : {UniqueObjectId}"); Console.WriteLine($"{nameof(FlashDataInfoQualifier)} : {FlashDataInfoQualifier}"); Console.WriteLine($"{nameof(FlashDataInfoLongName)} : {FlashDataInfoLongName}"); Console.WriteLine($"{nameof(FlashDataInfoDescription)} : {FlashDataInfoDescription}"); Console.WriteLine($"{nameof(FlashDataInfoUniqueObjectId)} : {FlashDataInfoUniqueObjectId}"); } } } ================================================ FILE: Caesar/Caesar/Flash/FlashDescriptionHeader.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { // FLASH_DESCRIPTION_HEADER // 0x10: 4 : 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 public class FlashDescriptionHeader { public string Qualifier; public int Description; public int FlashAreaName; public int FlashTableStructureCount; public int FlashTableStructureOffset; public int NumberOfUploads; public int UploadTableRefTable; public int NumberOfIdentServices; public int IdentServicesOffset; public int UniqueObjectID; public int unkb; public int unkc; public long BaseAddress; public FlashDescriptionHeader(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong flashBitFlags = reader.ReadUInt32(); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref flashBitFlags, reader, baseAddress); Description = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); FlashAreaName = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); FlashTableStructureCount = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); FlashTableStructureOffset = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); NumberOfUploads = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); UploadTableRefTable = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); NumberOfIdentServices = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); IdentServicesOffset = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); UniqueObjectID = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); unkb = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); unkc = CaesarReader.ReadBitflagInt32(ref flashBitFlags, reader); } public void PrintDebug() { Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); Console.WriteLine($"{nameof(Description)} : {Description}"); Console.WriteLine($"{nameof(FlashAreaName)} : {FlashAreaName}"); Console.WriteLine($"{nameof(FlashTableStructureCount)} : {FlashTableStructureCount}"); Console.WriteLine($"{nameof(FlashTableStructureOffset)} : 0x{FlashTableStructureOffset:X}"); Console.WriteLine($"{nameof(NumberOfUploads)} : {NumberOfUploads}"); Console.WriteLine($"{nameof(UploadTableRefTable)} : {UploadTableRefTable}"); Console.WriteLine($"{nameof(NumberOfIdentServices)} : {NumberOfIdentServices}"); Console.WriteLine($"{nameof(IdentServicesOffset)} : {IdentServicesOffset}"); Console.WriteLine($"{nameof(UniqueObjectID)} : {UniqueObjectID}"); Console.WriteLine($"{nameof(unkb)} : {unkb}"); Console.WriteLine($"{nameof(unkc)} : {unkc}"); } } } ================================================ FILE: Caesar/Caesar/Flash/FlashHeader.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class FlashHeader { public int CffHeaderSize; public long BaseAddress; public string FlashName; public string FlashGenerationParams; public int Unk3; public int Unk4; public string FileAuthor; public string FileCreationTime; public string AuthoringToolVersion; public string FTRAFOVersionString; public int FTRAFOVersionNumber; public string CFFVersionString; public int NumberOfFlashAreas; public int FlashDescriptionTable; public int DataBlockTableCountProbably; public int DataBlockRefTable; public int CTFHeaderTable; public int LanguageBlockLength; public int NumberOfECURefs; public int ECURefTable; public int UnkTableCount; public int UnkTableProbably; public int Unk15; public List DataBlocks = new List(); public List DescriptionHeaders = new List(); // DIIAddCBFFile /* 21 bits active f [6, 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4, 1], */ public FlashHeader(BinaryReader reader) { reader.BaseStream.Seek(StubHeader.StubHeaderSize, SeekOrigin.Begin); CffHeaderSize = reader.ReadInt32(); BaseAddress = reader.BaseStream.Position; ulong bitFlags = reader.ReadUInt32(); reader.ReadUInt16(); // unused FlashName = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); FlashGenerationParams = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); Unk3 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); Unk4 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); FileAuthor = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); FileCreationTime = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); AuthoringToolVersion = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); FTRAFOVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); FTRAFOVersionNumber = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); CFFVersionString = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); NumberOfFlashAreas = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); FlashDescriptionTable = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); DataBlockTableCountProbably = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); DataBlockRefTable = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); CTFHeaderTable = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); LanguageBlockLength = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); NumberOfECURefs = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); ECURefTable = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); UnkTableCount = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); UnkTableProbably = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); Unk15 = CaesarReader.ReadBitflagUInt8(ref bitFlags, reader); DescriptionHeaders = new List(); for (int flashDescIndex = 0; flashDescIndex < NumberOfFlashAreas; flashDescIndex++) { long flashTableEntryAddress = FlashDescriptionTable + BaseAddress + (flashDescIndex * 4); reader.BaseStream.Seek(flashTableEntryAddress, SeekOrigin.Begin); long flashEntryBaseAddress = FlashDescriptionTable + BaseAddress + reader.ReadInt32(); FlashDescriptionHeader fdh = new FlashDescriptionHeader(reader, flashEntryBaseAddress); DescriptionHeaders.Add(fdh); } DataBlocks = new List(); for (int dataBlockIndex = 0; dataBlockIndex < DataBlockTableCountProbably; dataBlockIndex++) { long datablockEntryAddress = DataBlockRefTable + BaseAddress + (dataBlockIndex * 4); reader.BaseStream.Seek(datablockEntryAddress, SeekOrigin.Begin); long datablockBaseAddress = DataBlockRefTable + BaseAddress + reader.ReadInt32(); FlashDataBlock fdb = new FlashDataBlock(reader, datablockBaseAddress); DataBlocks.Add(fdb); } } public void PrintDebug() { Console.WriteLine($"{nameof(FlashName)} : {FlashName}"); Console.WriteLine($"{nameof(FlashGenerationParams)} : {FlashGenerationParams}"); Console.WriteLine($"{nameof(Unk3)} : {Unk3}"); Console.WriteLine($"{nameof(Unk4)} : {Unk4}"); Console.WriteLine($"{nameof(FileAuthor)} : {FileAuthor}"); Console.WriteLine($"{nameof(FileCreationTime)} : {FileCreationTime}"); Console.WriteLine($"{nameof(AuthoringToolVersion)} : {AuthoringToolVersion}"); Console.WriteLine($"{nameof(FTRAFOVersionString)} : {FTRAFOVersionString}"); Console.WriteLine($"{nameof(FTRAFOVersionNumber)} : {FTRAFOVersionNumber}"); Console.WriteLine($"{nameof(CFFVersionString)} : {CFFVersionString}"); Console.WriteLine($"{nameof(NumberOfFlashAreas)} : {NumberOfFlashAreas}"); Console.WriteLine($"{nameof(FlashDescriptionTable)} : 0x{FlashDescriptionTable:X}"); Console.WriteLine($"{nameof(DataBlockTableCountProbably)} : {DataBlockTableCountProbably}"); Console.WriteLine($"{nameof(DataBlockRefTable)} : {DataBlockRefTable}"); Console.WriteLine($"{nameof(CTFHeaderTable)} : {CTFHeaderTable}"); Console.WriteLine($"{nameof(LanguageBlockLength)} : {LanguageBlockLength}"); Console.WriteLine($"{nameof(NumberOfECURefs)} : {NumberOfECURefs}"); Console.WriteLine($"{nameof(ECURefTable)} : {ECURefTable}"); Console.WriteLine($"{nameof(UnkTableCount)} : {UnkTableCount}"); Console.WriteLine($"{nameof(UnkTableProbably)} : 0x{UnkTableProbably:X}"); Console.WriteLine($"{nameof(Unk15)} : {Unk15}"); } } } ================================================ FILE: Caesar/Caesar/Flash/FlashSecurity.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class FlashSecurity { public int MethodValueType; public int MethodSize; public byte[] MethodValue; public int SignatureValueType; public int SignatureSize; public byte[] SignatureValue; public int ChecksumValueType; public int ChecksumSize; public byte[] ChecksumValue; public int EcuKeyValueType; public int EcuKeySize; public byte[] EcuKeyValue; public long BaseAddress; public FlashSecurity(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitFlags = reader.ReadUInt16(); MethodValueType = CaesarReader.ReadBitflagInt16(ref bitFlags, reader); MethodSize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); MethodValue = CaesarReader.ReadBitflagDumpWithReader(ref bitFlags, reader, MethodSize, baseAddress); SignatureValueType = CaesarReader.ReadBitflagInt16(ref bitFlags, reader); SignatureSize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); SignatureValue = CaesarReader.ReadBitflagDumpWithReader(ref bitFlags, reader, SignatureSize, baseAddress); ChecksumValueType = CaesarReader.ReadBitflagInt16(ref bitFlags, reader); ChecksumSize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); ChecksumValue = CaesarReader.ReadBitflagDumpWithReader(ref bitFlags, reader, ChecksumSize, baseAddress); EcuKeyValueType = CaesarReader.ReadBitflagInt16(ref bitFlags, reader); EcuKeySize = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); EcuKeyValue = CaesarReader.ReadBitflagDumpWithReader(ref bitFlags, reader, EcuKeySize, baseAddress); } public void PrintDebug() { Console.WriteLine($"{nameof(MethodValueType)} : 0x{MethodValueType:X}"); Console.WriteLine($"{nameof(MethodSize)} : 0x{MethodSize:X}"); Console.WriteLine($"{nameof(MethodValue)} : {BitUtility.BytesToHex(MethodValue)}"); Console.WriteLine($"{nameof(SignatureValueType)} : 0x{SignatureValueType:X}"); Console.WriteLine($"{nameof(SignatureSize)} : 0x{SignatureSize:X}"); Console.WriteLine($"{nameof(SignatureValue)} : {BitUtility.BytesToHex(SignatureValue)}"); Console.WriteLine($"{nameof(ChecksumValueType)} : 0x{ChecksumValueType:X}"); Console.WriteLine($"{nameof(ChecksumSize)} : 0x{ChecksumSize:X}"); Console.WriteLine($"{nameof(ChecksumValue)} : {BitUtility.BytesToHex(ChecksumValue)}"); Console.WriteLine($"{nameof(EcuKeyValueType)} : 0x{EcuKeyValueType:X}"); Console.WriteLine($"{nameof(EcuKeySize)} : 0x{EcuKeySize:X}"); Console.WriteLine($"{nameof(EcuKeyValue)} : {BitUtility.BytesToHex(EcuKeyValue)}"); } } } ================================================ FILE: Caesar/Caesar/Flash/FlashSegment.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { public class FlashSegment { public int FromAddress; public int SegmentLength; public int Unk3; public string SegmentName; public int Unk5; public int Unk6; public int Unk7; /* 0x1b [2, 4,4,4,4, 4,4,4], */ public long BaseAddress; public FlashSegment(BinaryReader reader, long baseAddress) { BaseAddress = baseAddress; reader.BaseStream.Seek(baseAddress, SeekOrigin.Begin); ulong bitFlags = reader.ReadUInt16(); // start reading FromAddress = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); SegmentLength = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); Unk3 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); SegmentName = CaesarReader.ReadBitflagStringWithReader(ref bitFlags, reader, BaseAddress); Unk5 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); Unk6 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); Unk7 = CaesarReader.ReadBitflagInt32(ref bitFlags, reader); } public long GetMappedAddressFileOffset(BinaryReader reader) { reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitFlags = reader.ReadUInt16(); if (CaesarReader.CheckAndAdvanceBitflag(ref bitFlags)) { return reader.BaseStream.Position; } else { return -1; } } public long GetSegmentLengthFileOffset(BinaryReader reader) { reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitFlags = reader.ReadUInt16(); CaesarReader.ReadBitflagInt32(ref bitFlags, reader); // skip FromAddress if (CaesarReader.CheckAndAdvanceBitflag(ref bitFlags)) { return reader.BaseStream.Position; } else { return -1; } } public void PrintDebug() { Console.WriteLine($"{nameof(FromAddress)} : 0x{FromAddress:X}"); Console.WriteLine($"{nameof(SegmentLength)} : 0x{SegmentLength:X}"); Console.WriteLine($"{nameof(Unk3)} : {Unk3}"); Console.WriteLine($"{nameof(SegmentName)} : {SegmentName}"); Console.WriteLine($"{nameof(Unk5)} : {Unk5}"); Console.WriteLine($"{nameof(Unk6)} : {Unk6}"); Console.WriteLine($"{nameof(Unk7)} : {Unk7}"); } } } ================================================ FILE: Caesar/Caesar/Program.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { class Program { // During normal operation, this class is completely ignored // The project can be temporarily switched from class library to console application to run as a standalone binary static void Main(string[] args) { Console.WriteLine("Caesar (running as console application)"); // RunLibraryTest(); Console.WriteLine("Done, press any key to exit"); Console.ReadKey(); } static void RunLibraryTest() { // debug: step through files to observe potential faults, missing bitflags etc. List paths = new List(); string basePath = @""; LoadFilePaths(basePath + @"Data05.00.00\", paths); LoadFilePaths(basePath + @"CBF VAN\", paths); foreach (string file in paths) { Console.WriteLine(file); CaesarContainer container = new CaesarContainer(File.ReadAllBytes(file)); //Console.ReadKey(); } } static void LoadFilePaths(string path, List result) { foreach (string file in Directory.GetFiles(path)) { if (Path.GetExtension(file).ToLower() == ".cbf") { result.Add(file); } } } } } ================================================ FILE: Caesar/Caesar/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Caesar")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Caesar")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("71c43c61-7dc7-4d47-9947-1dd73e559911")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.5.2.0")] [assembly: AssemblyFileVersion("1.5.2.0")] ================================================ FILE: Caesar/Caesar/Scale.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class Scale { public long BaseAddress; // 0x0b [2, 4,4,4,4, 4,4,4,4, 4,4,4], public int EnumLowBound; public int EnumUpBound; public int PrepLowBound; public int PrepUpBound; public float MultiplyFactor; public float AddConstOffset; public int SICount; public int OffsetSI; public int USCount; public int OffsetUS; public int EnumDescription; public int UnkC; [Newtonsoft.Json.JsonIgnore] private CTFLanguage Language; public void Restore(CTFLanguage language) { Language = language; } public Scale() { } public Scale(BinaryReader reader, long baseAddress, CTFLanguage language) { BaseAddress = baseAddress; Language = language; reader.BaseStream.Seek(BaseAddress, SeekOrigin.Begin); ulong bitflags = reader.ReadUInt16(); EnumLowBound = CaesarReader.ReadBitflagInt32(ref bitflags, reader); EnumUpBound = CaesarReader.ReadBitflagInt32(ref bitflags, reader); PrepLowBound = CaesarReader.ReadBitflagInt32(ref bitflags, reader); // could be float PrepUpBound = CaesarReader.ReadBitflagInt32(ref bitflags, reader); // could be float MultiplyFactor = CaesarReader.ReadBitflagFloat(ref bitflags, reader); AddConstOffset = CaesarReader.ReadBitflagFloat(ref bitflags, reader); SICount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); OffsetSI = CaesarReader.ReadBitflagInt32(ref bitflags, reader); USCount = CaesarReader.ReadBitflagInt32(ref bitflags, reader); OffsetUS = CaesarReader.ReadBitflagInt32(ref bitflags, reader); EnumDescription = CaesarReader.ReadBitflagInt32(ref bitflags, reader, -1); UnkC = CaesarReader.ReadBitflagInt32(ref bitflags, reader); } public void PrintDebug() { Console.WriteLine($"{nameof(EnumLowBound)} : {EnumLowBound}"); Console.WriteLine($"{nameof(EnumUpBound)} : {EnumUpBound}"); Console.WriteLine($"{nameof(PrepLowBound)} : {PrepLowBound}"); Console.WriteLine($"{nameof(PrepUpBound)} : {PrepUpBound}"); Console.WriteLine($"{nameof(MultiplyFactor)} : {MultiplyFactor}"); Console.WriteLine($"{nameof(AddConstOffset)} : {AddConstOffset}"); Console.WriteLine($"{nameof(SICount)} : {SICount}"); Console.WriteLine($"{nameof(OffsetSI)} : {OffsetSI}"); Console.WriteLine($"{nameof(USCount)} : {USCount}"); Console.WriteLine($"{nameof(OffsetUS)} : {OffsetUS}"); Console.WriteLine($"{nameof(EnumDescription)} : {EnumDescription}"); Console.WriteLine($"{nameof(UnkC)} : {UnkC}"); } } } ================================================ FILE: Caesar/Caesar/StubHeader.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caesar { class StubHeader { public const int StubHeaderSize = 0x410; private static readonly byte[] FileHeader = Encoding.ASCII.GetBytes("CBF-TRANSLATOR-VERSION:04.00"); public static void ReadHeader(byte[] header) { // file checksum first, but we are skipping that // last 4 bytes of cbf is for checksum if (!header.Take(FileHeader.Length).SequenceEqual(FileHeader)) { Console.WriteLine("Unknown CBF version"); } int cbfHeaderIdentifier = header[0x401]; if (cbfHeaderIdentifier != 3) { Console.WriteLine($"Unrecognized magic 2 : {cbfHeaderIdentifier}"); } } } } ================================================ FILE: Caesar/Caesar/VCDomain.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class VCDomain { public string Qualifier; public int Name_CTF; public int Description_CTF; public string ReadServiceName; public string WriteServiceName; private int FragmentCount; private int FragmentTableOffset; public int DumpSize; private int DefaultStringCount; // exposed as DefaultData.Count private int StringTableOffset; // exposed as DefaultData public int Unk1; public List VCFragments = new List(); [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; public List> DefaultData = new List>(); public long BaseAddress; public int Index; public void Restore(CTFLanguage language, ECU parentEcu) { ParentECU = parentEcu; foreach (VCFragment fragment in VCFragments) { fragment.Restore(parentEcu, this, language); } } public VCDomain() { } // VCDomain(reader, language, vcdBlockAddress, vcdIndex, this); public VCDomain(BinaryReader reader, CTFLanguage language, long baseAddress, int variantCodingDomainEntry, ECU parentEcu) { ParentECU = parentEcu; BaseAddress = baseAddress; Index = variantCodingDomainEntry; /* 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(); for (int fragmentIndex = 0; fragmentIndex < FragmentCount; fragmentIndex++) { VCFragment fragment = new VCFragment(reader, this, FragmentTableOffset, fragmentIndex, language, parentEcu); VCFragments.Add(fragment); } // ValidateFragmentCoverage(); if (DefaultStringCount > 0) { DefaultData = new List>(); 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); // this value is almost always "default"; can probably let the hardcoded string pass DefaultData.Add(new Tuple(valueType, blob)); //Console.WriteLine($"Blob: {BitUtility.BytesToHex(blob)} @ {valueType}"); //Console.WriteLine($"String base address: 0x{stringBaseAddress:X}"); } } } private void ValidateFragmentCoverage() { // apparently gaps are okay, there isn't a 100% way to find out if parsing errors have snuck through int bitCursor = 0; int expectedLengthInBits = DumpSize * 8; List fragments = new List(VCFragments); List bitGapPositions = new List(); while (fragments.Count > 0) { VCFragment result = fragments.Find(x => x.ByteBitPos == bitCursor); if (result is null) { bitGapPositions.Add(bitCursor); bitCursor++; if (bitCursor > expectedLengthInBits) { throw new Exception("wtf"); } } else { bitCursor += result.BitLength; fragments.Remove(result); } } } public void PrintDebug() { Console.WriteLine($"VCD Name: {Qualifier}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Description_CTF)} : {Description_CTF}"); Console.WriteLine($"{nameof(ReadServiceName)} : {ReadServiceName}"); Console.WriteLine($"{nameof(WriteServiceName)} : {WriteServiceName}"); Console.WriteLine($"{nameof(FragmentCount)} : {FragmentCount}"); Console.WriteLine($"{nameof(FragmentTableOffset)} : 0x{FragmentTableOffset:X}"); Console.WriteLine($"{nameof(DumpSize)} : {DumpSize}"); Console.WriteLine($"{nameof(DefaultStringCount)} : {DefaultStringCount}"); Console.WriteLine($"{nameof(StringTableOffset)} : {StringTableOffset}"); Console.WriteLine($"{nameof(Unk1)} : {Unk1}"); } } } ================================================ FILE: Caesar/Caesar/VCFragment.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class VCFragment { public int ByteBitPos; public ushort ImplementationType; public int Name_CTF; public int Description_CTF; public int ReadAccessLevel; public int WriteAccessLevel; public int ByteOrder; public int RawBitLength; public int IttOffset; public int InfoPoolIndex; public int MeaningB; public int MeaningC; public int CCFHandle; public int VarcodeDumpSize; public byte[] VarcodeDump; private int SubfragmentCount; // exposed as Subfragments.Count private long SubfragmentFileOffset; // exposed as Subfragments public string Qualifier; public int ImplementationUpper; public int ImplementationLower; public int BitLength; public List Subfragments = new List(); [Newtonsoft.Json.JsonIgnore] private static readonly byte[] FragmentLengthTable = new byte[] { 0, 1, 4, 8, 0x10, 0x20, 0x40 }; [Newtonsoft.Json.JsonIgnore] public VCDomain ParentDomain; [Newtonsoft.Json.JsonIgnore] public ECU ParentECU; public void Restore(ECU parentEcu, VCDomain parentDomain, CTFLanguage language) { ParentECU = parentEcu; ParentDomain = parentDomain; foreach (VCSubfragment subfragment in Subfragments) { subfragment.Restore(language); } } public VCFragment() { } public VCFragment(BinaryReader reader, VCDomain parentDomain, long fragmentTable, int fragmentIndex, CTFLanguage language, ECU parentEcu) { // see DIOpenVarCodeFrag ParentDomain = parentDomain; ParentECU = parentEcu; long fragmentTableEntry = fragmentTable + (10 * fragmentIndex); reader.BaseStream.Seek(fragmentTableEntry, SeekOrigin.Begin); // no bitflag required for 10-byte table entry since it is mandatory int fragmentNewBaseOffset = reader.ReadInt32(); ByteBitPos = reader.ReadInt32(); ImplementationType = reader.ReadUInt16(); // Console.WriteLine($"Fragment new base @ 0x{fragmentNewBaseOffset:X}, byteBitPos 0x{fragmentByteBitPos:X}, implementationType: 0x{implementationType:X}"); long fragmentBaseAddress = fragmentTable + fragmentNewBaseOffset; reader.BaseStream.Seek(fragmentBaseAddress, SeekOrigin.Begin); ulong fragmentBitflags = reader.ReadUInt32(); // Console.WriteLine($"Fragment new bitflag @ 0x{fragmentBitflags:X}"); Name_CTF = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1); Description_CTF = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1); ReadAccessLevel = CaesarReader.ReadBitflagUInt8(ref fragmentBitflags, reader); WriteAccessLevel = CaesarReader.ReadBitflagUInt8(ref fragmentBitflags, reader); ByteOrder = CaesarReader.ReadBitflagUInt16(ref fragmentBitflags, reader); RawBitLength = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader); IttOffset = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader); InfoPoolIndex = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1); MeaningB = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1); MeaningC = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader, -1); CCFHandle = CaesarReader.ReadBitflagInt16(ref fragmentBitflags, reader, -1); VarcodeDumpSize = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader); VarcodeDump = CaesarReader.ReadBitflagDumpWithReader(ref fragmentBitflags, reader, VarcodeDumpSize, fragmentBaseAddress); SubfragmentCount = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader); SubfragmentFileOffset = CaesarReader.ReadBitflagInt32(ref fragmentBitflags, reader); Qualifier = CaesarReader.ReadBitflagStringWithReader(ref fragmentBitflags, reader, fragmentBaseAddress); // Console.WriteLine($"{nameof(fragmentName)} : {fragmentName}, child {fragmentNoOfSubFragments} @ 0x{fragmentSubfragmentFileOffset:X} base {fragmentBaseAddress:X}"); if ((ByteOrder != 0) && (BitLength > 0)) { //throw new Exception("Currently assumes everything is little-endian"); Console.WriteLine($"WARNING: {Qualifier} (Size: {BitLength}) has an unsupported byte order. Please proceed with caution"); //PrintDebug(true); } long subfragmentTableAddress = SubfragmentFileOffset + fragmentBaseAddress; Subfragments.Clear(); for (int subfragmentIndex = 0; subfragmentIndex < SubfragmentCount; subfragmentIndex++) { reader.BaseStream.Seek(subfragmentTableAddress + (subfragmentIndex * 4), SeekOrigin.Begin); long subfragmentAddress = reader.ReadInt32() + subfragmentTableAddress; VCSubfragment subfragment = new VCSubfragment(reader, this, language, subfragmentAddress); Subfragments.Add(subfragment); } // PrintDebug(); // Console.WriteLine($"implementation-default : {implementationType:X4} upper: {(implementationType & 0xFF0):X4} lower: {(implementationType & 0xF):X4}"); FindFragmentSize(reader); } public VCSubfragment GetSubfragmentConfiguration(byte[] variantCodingValue) { byte[] variantBits = BitUtility.ByteArrayToBitArray(variantCodingValue); byte[] affectedBits = variantBits.Skip(ByteBitPos).Take(BitLength).ToArray(); foreach (VCSubfragment subfragment in Subfragments) { byte[] sfToCompare = BitUtility.ByteArrayToBitArray(subfragment.Dump).Take(BitLength).ToArray(); if (sfToCompare.SequenceEqual(affectedBits)) { return subfragment; } } return null; } public byte[] SetSubfragmentConfiguration(byte[] variantCodingValue, string subfragmentName) { foreach (VCSubfragment subfragment in Subfragments) { if (subfragment.NameResolved == subfragmentName) { return SetSubfragmentConfiguration(variantCodingValue, subfragment); } } throw new FormatException($"Requested subfragment {subfragmentName} could not be found in {Qualifier}"); } public byte[] SetSubfragmentConfiguration(byte[] variantCodingValue, VCSubfragment subfragment) { byte[] variantBits = BitUtility.ByteArrayToBitArray(variantCodingValue); List result = new List(variantBits.Take(ByteBitPos)); variantBits = variantBits.Skip(BitLength + ByteBitPos).ToArray(); byte[] sfToSet = BitUtility.ByteArrayToBitArray(subfragment.Dump).Take(BitLength).ToArray(); result.AddRange(sfToSet); result.AddRange(variantBits); return BitUtility.BitArrayToByteArray(result.ToArray()); } private void FindFragmentSize(BinaryReader reader) { ImplementationUpper = ImplementationType & 0xFF0; ImplementationLower = ImplementationType & 0xF; BitLength = 0; // fixup the bit length if (ImplementationLower > 6) { throw new NotImplementedException("The disassembly throws an exception when fragmentImplementationLower > 6, copying verbatim"); } if (ImplementationUpper > 0x420) { // Console.WriteLine($"fragment value upper: {fragmentImplementationUpper:X}"); ECU ecu = ParentDomain.ParentECU; byte[] infoPool = ecu.ReadECUInfoPool(reader); // int infoEntryWidth = ecu.ecuInfoPool_tableEntrySize; // Console.WriteLine($"Info entry width: {infoEntryWidth}"); // 8 using (BinaryReader poolReader = new BinaryReader(new MemoryStream(infoPool))) { DiagPresentation pres = ParentECU.GlobalInternalPresentations[InfoPoolIndex]; /* // depreciate use of ReadCBFWithOffset poolReader.BaseStream.Seek(ecu.Info_EntrySize * InfoPoolIndex, SeekOrigin.Begin); int presentationStructOffset = poolReader.ReadInt32(); int presentationStructSize = poolReader.ReadInt32(); //Console.WriteLine($"struct offset: 0x{presentationStructOffset:X} , size: {presentationStructSize} , meaningA 0x{fragmentMeaningA_Presentation:X} infoBase 0x{ecu.ecuInfoPool_fileoffset_7:X}\n"); reader.BaseStream.Seek(presentationStructOffset + ecu.Info_BlockOffset, SeekOrigin.Begin); byte[] presentationStruct = reader.ReadBytes(presentationStructSize); int presentationMode = CaesarStructure.ReadCBFWithOffset(0x1C, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_Type int presentationLength = CaesarStructure.ReadCBFWithOffset(0x1A, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // PRESS_TypeLength if (presentationLength > 0) { BitLength = presentationLength; } else { BitLength = CaesarStructure.ReadCBFWithOffset(0x21, CaesarStructure.StructureName.PRESENTATION_STRUCTURE, presentationStruct); // ??? } */ BitLength = pres.TypeLength_1A > 0 ? pres.TypeLength_1A : pres.TypeLengthBytesMaybe_21; // if value was specified in bytes, convert to bits if (pres.Type_1C == 0) { BitLength *= 8; } } } else { if (ImplementationUpper == 0x420) { BitLength = FragmentLengthTable[ImplementationLower]; } else if (ImplementationUpper == 0x320) { BitLength = FragmentLengthTable[ImplementationLower]; } else if (ImplementationUpper == 0x330) { BitLength = RawBitLength; } else if (ImplementationUpper == 0x340) { //throw new NotImplementedException("Requires implementation of ITT handle"); Console.WriteLine($"[!] Warning: Please avoid {ParentDomain.Qualifier} -> {Qualifier} as it could not be parsed (requires ITT)."); } else { throw new NotImplementedException($"No known fragment length format. Fragment upper: 0x{ImplementationUpper:X}"); } } if (BitLength == 0) { // not sure if there are dummy entries that might trip below exception // throw new NotImplementedException("Fragment length cannot be zero"); } } public void PrintDebug(bool verbose=false) { if (verbose) { Console.WriteLine($"{nameof(ByteBitPos)} : {ByteBitPos}"); Console.WriteLine($"{nameof(BitLength)} : {BitLength}"); Console.WriteLine($"{nameof(ImplementationType)} : {ImplementationType}"); Console.WriteLine($"{nameof(ImplementationUpper)} : 0x{ImplementationUpper:X}"); Console.WriteLine($"{nameof(Name_CTF)} : {Name_CTF}"); Console.WriteLine($"{nameof(Description_CTF)} : {Description_CTF}"); Console.WriteLine($"{nameof(ReadAccessLevel)} : {ReadAccessLevel}"); Console.WriteLine($"{nameof(WriteAccessLevel)} : {WriteAccessLevel}"); Console.WriteLine($"{nameof(ByteOrder)} : {ByteOrder}"); Console.WriteLine($"{nameof(RawBitLength)} : {RawBitLength}"); Console.WriteLine($"{nameof(IttOffset)} : {IttOffset}"); Console.WriteLine($"{nameof(InfoPoolIndex)} : {InfoPoolIndex}"); Console.WriteLine($"{nameof(MeaningB)} : {MeaningB}"); Console.WriteLine($"{nameof(MeaningC)} : {MeaningC}"); Console.WriteLine($"{nameof(CCFHandle)} : {CCFHandle}"); Console.WriteLine($"{nameof(VarcodeDumpSize)} : {VarcodeDumpSize}"); Console.WriteLine($"{nameof(VarcodeDump)} : {BitUtility.BytesToHex(VarcodeDump)}"); Console.WriteLine($"{nameof(SubfragmentCount)} : {SubfragmentCount}"); Console.WriteLine($"{nameof(SubfragmentFileOffset)} : 0x{SubfragmentFileOffset:X}"); Console.WriteLine($"{nameof(Qualifier)} : {Qualifier}"); } else { Console.WriteLine($"{Qualifier}%{ByteBitPos}%{BitLength}%[{ImplementationUpper:X}/{ImplementationLower:X}]"); } } } } ================================================ FILE: Caesar/Caesar/VCSubfragment.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Caesar { public class VCSubfragment { public int Name_CTF; public byte[] Dump; public int Description_CTF; public string QualifierUsuallyDisabled; public int Unk3; public int Unk4; public string SupplementKey; [Newtonsoft.Json.JsonIgnore] public string NameResolved { get { return Language.GetString(Description_CTF); } } [Newtonsoft.Json.JsonIgnore] CTFLanguage Language; public void Restore(CTFLanguage language) { Language = language; } public VCSubfragment() { } public VCSubfragment(BinaryReader reader, VCFragment parentFragment, CTFLanguage language, long baseAddress) { // see DIOpenCBF_FragValHandle Language = language; 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); //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(); } private void PrintDebug(bool verbose = false) { if (verbose) { Console.WriteLine("------------- subfragment ------------- "); Console.WriteLine($"{nameof(Name_CTF)}, {Name_CTF}"); Console.WriteLine($"{nameof(Dump)}, {BitUtility.BytesToHex(Dump)}"); Console.WriteLine($"{nameof(Description_CTF)}, {Description_CTF}"); Console.WriteLine($"{nameof(NameResolved)}, {NameResolved}"); Console.WriteLine($"{nameof(QualifierUsuallyDisabled)}, {QualifierUsuallyDisabled}"); Console.WriteLine($"{nameof(Unk3)}, {Unk3}"); Console.WriteLine($"{nameof(Unk4)}, {Unk4}"); Console.WriteLine($"{nameof(SupplementKey)}, {SupplementKey}"); } else { Console.WriteLine($">> {BitUtility.BytesToHex(Dump)} : {NameResolved}"); } } } } ================================================ FILE: Caesar/Caesar/packages.config ================================================  ================================================ FILE: Caesar/Caesar.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30309.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Caesar", "Caesar\Caesar.csproj", "{71C43C61-7DC7-4D47-9947-1DD73E559911}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Trafo", "Trafo\Trafo.csproj", "{42A6F1FD-82CC-4721-BF0C-1658AE902875}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diogenes", "Diogenes\Diogenes.csproj", "{2216DB99-EAAC-46A8-B99A-28D659907DE7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {71C43C61-7DC7-4D47-9947-1DD73E559911}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {71C43C61-7DC7-4D47-9947-1DD73E559911}.Debug|Any CPU.Build.0 = Debug|Any CPU {71C43C61-7DC7-4D47-9947-1DD73E559911}.Release|Any CPU.ActiveCfg = Release|Any CPU {71C43C61-7DC7-4D47-9947-1DD73E559911}.Release|Any CPU.Build.0 = Release|Any CPU {42A6F1FD-82CC-4721-BF0C-1658AE902875}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42A6F1FD-82CC-4721-BF0C-1658AE902875}.Debug|Any CPU.Build.0 = Debug|Any CPU {42A6F1FD-82CC-4721-BF0C-1658AE902875}.Release|Any CPU.ActiveCfg = Release|Any CPU {42A6F1FD-82CC-4721-BF0C-1658AE902875}.Release|Any CPU.Build.0 = Release|Any CPU {2216DB99-EAAC-46A8-B99A-28D659907DE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2216DB99-EAAC-46A8-B99A-28D659907DE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {2216DB99-EAAC-46A8-B99A-28D659907DE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {2216DB99-EAAC-46A8-B99A-28D659907DE7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5BE4FB05-511E-4470-8F3E-9BEC3256EB69} EndGlobalSection EndGlobal ================================================ FILE: Caesar/Diogenes/App.config ================================================  ================================================ FILE: Caesar/Diogenes/DiagnosticProtocol/BaseProtocol.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes.DiagnosticProtocol { public class BaseProtocol { public virtual void ConnectionEstablishedHandler(ECUConnection connection) { } public virtual void ConnectionClosingHandler(ECUConnection connection) { } public virtual void SendTesterPresent(ECUConnection connection) { } public virtual bool IsResponseToTesterPresent(byte[] inBuffer) { return false; } public virtual string GetProtocolName() { return "UninitializedProtocol"; } public virtual bool SupportsUnlocking() { return false; } public virtual ECUMetadata QueryECUMetadata(ECUConnection connection) { return new ECUMetadata() { }; } public virtual List ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { return new List(); } public virtual bool GetDtcSnapshot(DTC dtc, ECUConnection connection, out byte[] snapshotBytes) { snapshotBytes = new byte[] { }; return false; } public static BaseProtocol GetProtocol(string profileName) { // fixme: this depends on the cbf author's consistency and so far it's been reliable BUT there should be a better way of specifying the protocol? if (profileName.Contains("_UDS_")) { return new UDS(); } else if (profileName.Contains("_KW2C3PE_")) { return new KW2C3PE(); } return new UnsupportedProtocol(); } } } ================================================ FILE: Caesar/Diogenes/DiagnosticProtocol/KW2C3PE.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes.DiagnosticProtocol { public class KW2C3PE : BaseProtocol { private static bool EnterDiagnosticSession(ECUConnection connection) { Console.WriteLine("KW2C3PE: Switching session states"); byte[] sessionSwitchResponse = connection.SendMessage(new byte[] { 0x10, 0x92 }); byte[] sessionExpectedResponse = new byte[] { 0x50, 0x92 }; if (!sessionSwitchResponse.Take(2).SequenceEqual(sessionExpectedResponse)) { Console.WriteLine($"Failed to switch session : target responded with [{BitUtility.BytesToHex(sessionSwitchResponse, true)}]"); return false; } return true; } private static bool ExitDiagnosticSession(ECUConnection connection) { Console.WriteLine("KW2C3PE: Switching session states"); byte[] sessionSwitchResponse = connection.SendMessage(new byte[] { 0x10, 0x81 }); byte[] sessionExpectedResponse = new byte[] { 0x50, 0x81 }; if (!sessionSwitchResponse.Take(2).SequenceEqual(sessionExpectedResponse)) { Console.WriteLine($"Failed to switch session : target responded with [{BitUtility.BytesToHex(sessionSwitchResponse, true)}]"); return false; } return true; } private static bool GetVariantID_1A86(ECUConnection connection, out int variantId) { byte[] variantQueryResponse = connection.SendMessage(new byte[] { 0x1A, 0x86 }); byte[] variantExpectedResponse = new byte[] { 0x5A, 0x86 }; if (!variantQueryResponse.Take(2).SequenceEqual(variantExpectedResponse)) { variantId = 0; return false; } else { variantId = (variantQueryResponse[12] << 8) | variantQueryResponse[13]; return true; } } private static bool GetVariantID_1A87(ECUConnection connection, out int variantId) { byte[] variantQueryResponse = connection.SendMessage(new byte[] { 0x1A, 0x87 }); byte[] variantExpectedResponse = new byte[] { 0x5A, 0x87 }; if (!variantQueryResponse.Take(2).SequenceEqual(variantExpectedResponse)) { variantId = 0; return false; } else { variantId = (variantQueryResponse[4] << 8) | variantQueryResponse[5]; return true; } } private static bool GetVariantID(ECUConnection connection, out int variantId) { if (GetVariantID_1A86(connection, out int idFor1A86)) { variantId = idFor1A86; return true; } if (GetVariantID_1A87(connection, out int idFor1A87)) { variantId = idFor1A87; return true; } variantId = 0; return false; } public override List ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { // FIXME : KW2C3PE probably uses a different set of commands at 0x18 return base.ReportDtcsByStatusMask(connection, variant, inMask); } public override bool GetDtcSnapshot(DTC dtc, ECUConnection connection, out byte[] snapshotBytes) { // FIXME return base.GetDtcSnapshot(dtc, connection, out snapshotBytes); } public override void ConnectionEstablishedHandler(ECUConnection connection) { if (!EnterDiagnosticSession(connection)) { return; } if (GetVariantID(connection, out int variantId)) { connection.VariantIsAvailable = true; connection.ECUVariantID = variantId; Console.WriteLine($"Variant has been successfully configured as {(variantId & 0xFFFF):X4}"); } else { Console.WriteLine("KW2C3PE: Could not identify variant (1A86, 1A87)"); return; } } public override void SendTesterPresent(ECUConnection connection) { // looks like 3E 01 for KW2C3PE connection.SendMessage(new byte[] { 0x3E, 0x01 }, true); } public override bool IsResponseToTesterPresent(byte[] inBuffer) { return inBuffer.SequenceEqual(new byte[] { 0x7E, 0x01 }); } public override void ConnectionClosingHandler(ECUConnection connection) { ExitDiagnosticSession(connection); } public override string GetProtocolName() { return "KW2C3PE"; } public override bool SupportsUnlocking() { return true; } } } ================================================ FILE: Caesar/Diogenes/DiagnosticProtocol/UDS.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static Caesar.DTC; namespace Diogenes.DiagnosticProtocol { public class UDS : BaseProtocol { private static string[] NegativeResponseDescriptions = new string[] { }; private static Dictionary MessageDescriptions = new Dictionary(); private static string[] GetNegativeResponseDescriptions() { if (NegativeResponseDescriptions.Length == 0) { NegativeResponseDescriptions = new string[0xFF]; for (int i = 0; i < 0xFF; i++) { NegativeResponseDescriptions[i] = "ISO SAE Reserved"; } for (int i = 0x38; i <= 0x4F; i++) { NegativeResponseDescriptions[i] = "Reserved By Extended Data Link Security Document"; } for (int i = 0x94; i <= 0xEF; i++) { NegativeResponseDescriptions[i] = "Reserved For Specific Conditions Not Correct"; } for (int i = 0xF0; i <= 0xFE; i++) { NegativeResponseDescriptions[i] = "Vehicle Manufacturer Specific Conditions Not Correct"; } NegativeResponseDescriptions[0x00] = "Positive Response"; NegativeResponseDescriptions[0x10] = "General Reject"; NegativeResponseDescriptions[0x11] = "Service Not Supported"; NegativeResponseDescriptions[0x12] = "Sub-function Not Supported"; NegativeResponseDescriptions[0x13] = "Incorrect Message Length Or Invalid Format"; NegativeResponseDescriptions[0x14] = "Response Too Long"; NegativeResponseDescriptions[0x21] = "Busy Repeat Request"; NegativeResponseDescriptions[0x22] = "Conditions Not Correct"; NegativeResponseDescriptions[0x24] = "Request Sequence Error"; NegativeResponseDescriptions[0x25] = "No Response From Sub-net Component"; NegativeResponseDescriptions[0x26] = "Failure Prevents Execution Of Requested Action"; NegativeResponseDescriptions[0x31] = "Request Out Of Range"; NegativeResponseDescriptions[0x33] = "Security Access Denied"; NegativeResponseDescriptions[0x35] = "Invalid Key"; NegativeResponseDescriptions[0x36] = "Exceed Number Of Attempts"; NegativeResponseDescriptions[0x37] = "Required Time Delay Not Expired"; NegativeResponseDescriptions[0x70] = "Upload Download Not Accepted"; NegativeResponseDescriptions[0x71] = "Transfer Data Suspended"; NegativeResponseDescriptions[0x72] = "General Programming Failure"; NegativeResponseDescriptions[0x73] = "Wrong Block Sequence Counter"; NegativeResponseDescriptions[0x78] = "Request Correctly Received-Response Pending"; NegativeResponseDescriptions[0x7E] = "Sub-function Not Supported In Active Session"; NegativeResponseDescriptions[0x7F] = "Service Not Supported In Active Session"; NegativeResponseDescriptions[0x81] = "Rpm Too High"; NegativeResponseDescriptions[0x82] = "Rpm Too Low"; NegativeResponseDescriptions[0x83] = "Engine Is Running"; NegativeResponseDescriptions[0x84] = "Engine Is Not Running"; NegativeResponseDescriptions[0x85] = "Engine Run Time Too Low"; NegativeResponseDescriptions[0x86] = "Temperature is Too High"; NegativeResponseDescriptions[0x87] = "Temperature is Too Low"; NegativeResponseDescriptions[0x88] = "Vehicle Speed is Too High"; NegativeResponseDescriptions[0x89] = "Vehicle Speed is Too Low"; NegativeResponseDescriptions[0x8A] = "Throttle/Pedal is Too High"; NegativeResponseDescriptions[0X8B] = "Throttle/Pedal IS Too Low"; NegativeResponseDescriptions[0X8C] = "Transmission Range Is Not In Neutral"; NegativeResponseDescriptions[0x8D] = "Transmission Range is Not In Gear"; NegativeResponseDescriptions[0x8F] = "Brake Switch(es) Not Closed (Brake Pedal not pressed or not applied)"; NegativeResponseDescriptions[0x90] = "Shifter Lever Not In Park"; NegativeResponseDescriptions[0x91] = "Torque Converter Clutch is Locked"; NegativeResponseDescriptions[0x92] = "Voltage is Too High"; NegativeResponseDescriptions[0x93] = "Voltage Too Low"; } return NegativeResponseDescriptions; } private static Dictionary GetMessageDescriptions() { if (MessageDescriptions.Count == 0) { MessageDescriptions.Add(0x10, "Diagnostic Session Control"); MessageDescriptions.Add(0x11, "ECU Reset"); MessageDescriptions.Add(0x27, "Security Access"); MessageDescriptions.Add(0x28, "Communication Control"); MessageDescriptions.Add(0x29, "Authentication"); MessageDescriptions.Add(0x3E, "Tester Present"); MessageDescriptions.Add(0x83, "Access Timing Parameters"); MessageDescriptions.Add(0x84, "Secured Data Transmission"); MessageDescriptions.Add(0x85, "Control DTC Settings"); MessageDescriptions.Add(0x86, "Response On Event"); MessageDescriptions.Add(0x87, "Link Control"); MessageDescriptions.Add(0x22, "Read Data By Identifier"); MessageDescriptions.Add(0x23, "Read Memory By Address"); MessageDescriptions.Add(0x24, "Read Scaling Data By Identifier"); MessageDescriptions.Add(0x2A, "Read Data By Identifier Periodic"); MessageDescriptions.Add(0x2C, "Dynamically Define Data Identifier"); MessageDescriptions.Add(0x2E, "Write Data By Identifier"); MessageDescriptions.Add(0x3D, "Write Memory By Address"); MessageDescriptions.Add(0x14, "Clear Diagnostic Information"); MessageDescriptions.Add(0x19, "Read DTC Information"); MessageDescriptions.Add(0x2F, "Input Output Control By Identifier"); MessageDescriptions.Add(0x31, "Routine Control"); MessageDescriptions.Add(0x34, "Request Download"); MessageDescriptions.Add(0x35, "Request Upload"); MessageDescriptions.Add(0x36, "Transfer Data"); MessageDescriptions.Add(0x37, "Request Transfer Exit"); MessageDescriptions.Add(0x38, "Request File Transfer"); } return MessageDescriptions; } public static string GetCommandDescription(byte[] command) { if (command.Length == 0) { return "Internal error: command buffer is empty"; } // handle NR first if (command[0] == 0x7F) { string response = "Negative Response"; if (command.Length > 1) { response = $"{response}: {GetNegativeResponseDescriptions()[command[1]]}"; } return response; } Dictionary descriptions = GetMessageDescriptions(); if (descriptions.ContainsKey(command[0])) { return $"Request: {descriptions[command[0]]}"; } int tryAsResponse = command[0] - 0x40; if (descriptions.ContainsKey(tryAsResponse)) { return $"Response: {descriptions[tryAsResponse]}"; } return "Unknown"; } private static bool IsNegativeResponse(byte[] command) { return ((command.Length > 0) && (command[0] == 0x7F)); } private static bool EnterDiagnosticSession(ECUConnection connection) { Console.WriteLine("UDS: Switching session states"); byte[] sessionSwitchResponse = connection.SendMessage(new byte[] { 0x10, 0x03 }); byte[] sessionExpectedResponse = new byte[] { 0x50, 0x03 }; if (!sessionSwitchResponse.Take(2).SequenceEqual(sessionExpectedResponse)) { Console.WriteLine($"Failed to switch session : target responded with [{BitUtility.BytesToHex(sessionSwitchResponse, true)}]"); return false; } return true; } private static bool ExitDiagnosticSession(ECUConnection connection) { Console.WriteLine("UDS: Switching session states"); byte[] sessionSwitchResponse = connection.SendMessage(new byte[] { 0x10, 0x01 }); byte[] sessionExpectedResponse = new byte[] { 0x50, 0x01 }; if (!sessionSwitchResponse.Take(2).SequenceEqual(sessionExpectedResponse)) { Console.WriteLine($"Failed to switch session : target responded with [{BitUtility.BytesToHex(sessionSwitchResponse, true)}]"); return false; } return true; } private static bool GetVariantID(ECUConnection connection, out int variantId) { byte[] variantQueryResponse = connection.SendMessage(new byte[] { 0x22, 0xF1, 0x00 }); byte[] variantExpectedResponse = new byte[] { 0x62, 0xF1 }; if (!variantQueryResponse.Take(2).SequenceEqual(variantExpectedResponse)) { Console.WriteLine($"Failed to identify variant (unexpected response) : target responded with [{BitUtility.BytesToHex(variantQueryResponse, true)}]"); variantId = 0; return false; } else { // found a variant id, check loaded ecus if any of them have a match variantId = (variantQueryResponse[3] << 16) | (variantQueryResponse[4] << 8) | variantQueryResponse[5]; return true; } } public override List ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { List dtcCtx = new List(); byte mask = (byte)(DTCStatusByte.TestFailedAtRequestTime | DTCStatusByte.TestFailedAtCurrentCycle | DTCStatusByte.PendingDTC | DTCStatusByte.ConfirmedDTC | DTCStatusByte.TestFailedSinceLastClear); byte[] request = new byte[] { 0x19, 0x02, inMask == 0 ? mask : inMask }; byte[] expectedResponse = new byte[] { 0x59, 0x02 }; byte[] response = connection.SendMessage(request); if (!response.Take(expectedResponse.Length).SequenceEqual(expectedResponse)) { return new List(); } for (int i = 3; i < response.Length; i += 4) { byte[] dtcRow = new byte[4]; Array.ConstrainedCopy(response, i, dtcRow, 0, 4); byte statusMask = dtcRow[3]; long dtcIdRaw = ((dtcRow[0] << 16) | (dtcRow[1] << 8) | dtcRow[2]); // fixup DTC prefix in https://github.com/jglim/CaesarSuite/issues/36 int dtcId = (int)dtcIdRaw & 0x3FFFFF; // id is the lowest 22 bits int dtcPrefix = (int)(dtcIdRaw >> 22) & 3; // prefix is the next 2 bits string[] prefixTable = new string[] { "P", // powertrain "C", // chassis "B", // body "U" // network }; string dtcIdentifier = $"{prefixTable[dtcPrefix]}{dtcId:X6}"; DTC foundDtc = FindDTCById(dtcIdentifier, variant); if (foundDtc is null) { Console.WriteLine($"DTC: No matching DTC available for {dtcIdentifier}"); } else { dtcCtx.Add(new DTCContext() { DTC = foundDtc, StatusByte = statusMask, EnvironmentContext = new List() }); } } return dtcCtx; } public override bool GetDtcSnapshot(DTC dtc, ECUConnection connection, out byte[] snapshotBytes) { byte[] identifier = BitUtility.BytesFromHex(dtc.Qualifier.Substring(1)); // apparently the existing dtc's mask should be ignored, use FF instead byte[] request = new byte[] { 0x19, 0x06, identifier[0], identifier[1], identifier[2], 0xFF }; byte[] expectedResponse = new byte[] { 0x59, 0x06 }; byte[] response = connection.SendMessage(request); if (response.Take(expectedResponse.Length).SequenceEqual(expectedResponse)) { snapshotBytes = response; return true; } else { snapshotBytes = new byte[] { }; return false; } } public override ECUMetadata QueryECUMetadata(ECUConnection connection) { ECUMetadata metadata = new ECUMetadata(); if (ReadDataByIdentifier(connection, 0xF100, out byte[] diagInfoRaw)) { byte session = diagInfoRaw[3]; byte gateway = diagInfoRaw[0]; uint variant = (uint)((diagInfoRaw[1] << 8) | diagInfoRaw[2]); metadata.GatewayMode = gateway == 2; metadata.VariantID = variant; } if (ReadDataByIdentifier(connection, 0xF111, out byte[] hardwareId)) { metadata.HardwarePartNumber = Encoding.ASCII.GetString(hardwareId); } if (ReadDataByIdentifier(connection, 0xF150, out byte[] hardwareVersion)) { metadata.HardwareVersion = $"{hardwareVersion[0]:D2}/{hardwareVersion[1]:D2}.{hardwareVersion[2]:D2}"; } if (ReadDataByIdentifier(connection, 0xF154, out byte[] hardwareVendor)) { metadata.VendorID = hardwareVendor[1]; // first byte for vendor is usually discarded; value does not fit BE } if (ReadDataByIdentifier(connection, 0xF153, out byte[] bootVersion)) { metadata.BootVersion = $"{bootVersion[0]:D2}/{bootVersion[1]:D2}.{bootVersion[2]:D2}"; } if (ReadDataByIdentifier(connection, 0xF18C, out byte[] serialNumber)) { metadata.SerialNumber = Encoding.ASCII.GetString(serialNumber); } if (ReadDataByIdentifier(connection, 0xF190, out byte[] vinOriginal)) { metadata.ChassisNumberOriginal = Encoding.ASCII.GetString(vinOriginal); } if (ReadDataByIdentifier(connection, 0xF1A0, out byte[] vinCurrent)) { metadata.ChassisNumberCurrent = Encoding.ASCII.GetString(vinCurrent); } // read flash blocks, normally code/data/flash if (ReadDataByIdentifier(connection, 0xF121, out byte[] fwIdentifier)) { ReadDataByIdentifier(connection, 0xF151, out byte[] aggregateFwVersion); ReadDataByIdentifier(connection, 0xF155, out byte[] aggregateSupplierIdent); ReadDataByIdentifier(connection, 0xF15B, out byte[] aggregateFingerprint); int versionWidth = 3; int vendorWidth = 2; int fingerprintWidth = 10; int pnWidth = 10; if (fwIdentifier.Length % pnWidth != 0) { Console.WriteLine("[!] Block PartNumber is not boundary aligned"); } int blockCount = fwIdentifier.Length / pnWidth; metadata.FlashMetadata = new List(); for (int i = 0; i < blockCount; i++) { byte[] localPn = fwIdentifier.Skip(i * pnWidth).Take(pnWidth).ToArray(); byte[] localFwVersion = aggregateFwVersion.Skip(i * versionWidth).Take(versionWidth).ToArray(); byte[] localSupplierIdent = aggregateSupplierIdent.Skip(i * vendorWidth).Take(vendorWidth).ToArray(); byte[] localFingerprint = aggregateFingerprint.Skip(i * fingerprintWidth).Take(fingerprintWidth).ToArray(); ECUFlashMetadata flashMetadata = new ECUFlashMetadata(); flashMetadata.Index = i; flashMetadata.PartNumber = Encoding.ASCII.GetString(localPn); flashMetadata.Version = $"{localFwVersion[0]:D2}/{localFwVersion[1]:D2}.{localFwVersion[2]:D2}"; flashMetadata.VendorID = localSupplierIdent[1]; flashMetadata.StatusID = localFingerprint[0]; flashMetadata.LastFlashVendor = localFingerprint[2]; flashMetadata.FlashDate = $"{localFingerprint[3]:D2}-{localFingerprint[4]:D2}-{localFingerprint[5]:D2}"; // no idea what sort of date format; all 3 fields can hold values above 12 flashMetadata.FlashFingerprint = BitUtility.BytesToHex(localFingerprint.Skip(6).ToArray()); metadata.FlashMetadata.Add(flashMetadata); } } return metadata; } private static bool ReadDataByIdentifier(ECUConnection connection, ushort identifier, out byte[] buffer) { buffer = new byte[] { }; byte identifierMsb = (byte)((identifier >> 8) & 0xFF); byte identifierLsb = (byte)(identifier & 0xFF); byte[] response = connection.SendMessage(new byte[] { 0x22, identifierMsb, identifierLsb }); if (response.Length < 3) { return false; } if (response[0] != 0x62) { return false; } buffer = response.Skip(3).ToArray(); return true; } public override void ConnectionEstablishedHandler(ECUConnection connection) { if (!EnterDiagnosticSession(connection)) { return; } if (GetVariantID(connection, out int variantId)) { connection.VariantIsAvailable = true; connection.ECUVariantID = variantId; Console.WriteLine($"Variant has been successfully configured as {(variantId & 0xFFFF):X4}"); } else { return; } } public override void SendTesterPresent(ECUConnection connection) { connection.SendMessage(new byte[] { 0x3E, 0x00 }, true); } public override bool IsResponseToTesterPresent(byte[] inBuffer) { return inBuffer.SequenceEqual(new byte[] { 0x7E, 0x00 }); } public override void ConnectionClosingHandler(ECUConnection connection) { ExitDiagnosticSession(connection); } public override string GetProtocolName() { return "UDS"; } public override bool SupportsUnlocking() { return true; } } } ================================================ FILE: Caesar/Diogenes/DiagnosticProtocol/UnsupportedProtocol.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes.DiagnosticProtocol { public class UnsupportedProtocol : BaseProtocol { public override void ConnectionEstablishedHandler(ECUConnection connection) { //Console.WriteLine("The current protocol is unsupported. Most functions will not be available."); } public override string GetProtocolName() { return "UnsupportedProtocol"; } public override bool SupportsUnlocking() { return false; } } } ================================================ FILE: Caesar/Diogenes/Diogenes.csproj ================================================  Debug AnyCPU {2216DB99-EAAC-46A8-B99A-28D659907DE7} WinExe Diogenes Diogenes v4.6 512 true true false publish\ true Disk false Foreground 7 Days false false true 0 1.1.0.%2a false true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 diogenes-256.ico ..\packages\Be.Windows.Forms.HexBox.1.6.1\lib\net40\Be.Windows.Forms.HexBox.dll ..\packages\J2534-Sharp.1.0.0-CI00026\lib\net46\J2534-Sharp.dll Form BlockDownload.cs Form AboutForm.cs Form DTCForm.cs Form FlashSplicer.cs Form GenericLoader.cs Form GenericPicker.cs Form PickDiagForm.cs Form RunDiagForm.cs Form MainForm.cs Form SecurityLevelForm.cs Form TraceForm.cs Form UDSHexEditor.cs Form VCForm.cs AboutForm.cs BlockDownload.cs DTCForm.cs FlashSplicer.cs GenericLoader.cs GenericPicker.cs MainForm.cs PickDiagForm.cs ResXFileCodeGenerator Resources.Designer.cs Designer True Resources.resx True RunDiagForm.cs SecurityLevelForm.cs TraceForm.cs VCForm.cs UDSHexEditor.cs SettingsSingleFileGenerator Settings.Designer.cs True Settings.settings True {71c43c61-7dc7-4d47-9947-1dd73e559911} Caesar False Microsoft .NET Framework 4.6 %28x86 and x64%29 true False .NET Framework 3.5 SP1 false ================================================ FILE: Caesar/Diogenes/ECUConnection.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SAE.J2534; using Caesar; using System.Timers; using System.Diagnostics; using Diogenes.DiagnosticProtocol; using Diogenes.SecurityAccess; namespace Diogenes { /* example communication params: HSCAN_UDS_500 CP_BAUDRATE : 500000 (0x7A120) CP_GLOBAL_REQUEST_CANIDENTIFIER : 1089 (0x441) CP_FUNCTIONAL_REQUEST_CANIDENTIFIER : 1089 (0x441) CP_REQUEST_CANIDENTIFIER : 2016 (0x7E0) CP_RESPONSE_CANIDENTIFIER : 2024 (0x7E8) CP_PARTNUMBERID : 0 (0x0) CP_PARTBLOCK : 1 (0x1) CP_HWVERSIONID : 0 (0x0) CP_SWVERSIONID : 0 (0x0) CP_SWVERSIONBLOCK : 1 (0x1) CP_SUPPLIERID : 61780 (0xF154) CP_SWSUPPLIERBLOCK : 1 (0x1) CP_ADDRESSMODE : 0 (0x0) CP_ADDRESSEXTENSION : 0 (0x0) CP_ROE_RESPONSE_CANIDENTIFIER : 0 (0x0) CP_USE_TIMING_RECEIVED_FROM_ECU : 0 (0x0) CP_STMIN_SUG : 0 (0x0) CP_BLOCKSIZE_SUG : 8 (0x8) CP_P2_TIMEOUT : 2100 (0x834) CP_P2_EXT_TIMEOUT_7F_78 : 4500 (0x1194) CP_S3_TP_PHYS_TIMER : 2000 (0x7D0) CP_S3_TP_FUNC_TIMER : 2000 (0x7D0) CP_BR_SUG : 0 (0x0) CP_CAN_TRANSMIT : 0 (0x0) CP_BS_MAX : 2000 (0x7D0) CP_CS_MAX : 2000 (0x7D0) CP_P2_EXT_TIMEOUT_7F_21 : 200 (0xC8) CPI_ROUTINECOUNTER : 30 (0x1E) CP_REQREPCOUNT : 3 (0x3) */ public class ECUConnection { public API ConnectionAPI; public Device ConnectionDevice; public Channel ConnectionChannel; public Simulation.SimulatedDevice SimulationChannel; public string DriverPath = ""; public delegate void ConnectionStateChanged(string newStateDescription); public ConnectionStateChanged ConnectionStateChangeEvent; public string FriendlyName = "Simulation"; public string FriendlyProfileName = "SIMULATION_PROFILE"; public ConnectionState State; public byte[] CanIdentifier = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }; public byte[] RxCanIdentifier = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }; public int InternalTimeout = 2000; public ECU EcuContext; public int ECUVariantID = 0; public bool VariantIsAvailable = false; public BaseProtocol ConnectionProtocol = null; // this should really go into a dedicated logger public StringBuilder CommunicationsLogHighLevel = new StringBuilder(); public readonly object WriteLock = new object(); // constant 2000 ms as recomended by the ISO 15765-3 standard (§6.3.3). public Timer TesterPresentTimer = new Timer(2000); // holds out-of-order, non testerpresent bytes since packets (apparently) can be received in any order Queue OutOfOrderBytesList = new Queue(); public enum ConnectionState { PendingDeviceSelection, DeviceSelectedPendingChannelConnection, ChannelConnectedPendingEcuContact, EcuContacted } public enum ConnectResponse { OK, NoValidInterface, UnsupportedProtocol, FailedWithException } public ECUConnection() { // create a dummy connection FriendlyName = "Simulation"; FriendlyProfileName = "SIMULATION_PROFILE"; State = ConnectionState.PendingDeviceSelection; ConnectionUpdateState(); } public ECUConnection(string fileName, string friendlyName) { DriverPath = fileName; InternalTimeout = 2000; if (!IsSimulation()) { // apparently AVDI embeds their hardware identifier in the device's name and path, which might be regarded as sensitive when sharing // this redacts it (somewhat) to help save some time for testers if (DriverIsAVDI()) { FriendlyName = "AVDI-PT"; Console.WriteLine($"Initializing new connection to {friendlyName}"); } else { FriendlyName = friendlyName; Console.WriteLine($"Initializing new connection to {friendlyName} using {fileName}"); } ConnectionAPI = APIFactory.GetAPI(fileName); } else { FriendlyName = "Simulation"; ConnectionAPI = null; } SetConnectionDefaults(); State = ConnectionState.PendingDeviceSelection; ConnectionUpdateState(); TesterPresentTimer.Elapsed += TesterPresentTimer_Elapsed; TesterPresentTimer.Start(); } public bool IsSimulation() { return DriverPath == "SIMULATION"; } public static List> GetAvailableJ2534NamesAndDrivers() { List> result = new List>(); foreach (APIInfo apiInfo in APIFactory.GetAPIList()) { result.Add(new Tuple(apiInfo.Name, apiInfo.Filename)); } #if DEBUG result.Add(new Tuple("Simulation", "SIMULATION")); #endif return result; } private void TesterPresentTimer_Elapsed(object sender, ElapsedEventArgs e) { // normally we would wait until the session was switched to extended, but we don't know for sure. seems to be probably OK to send this as-is? if (State > ConnectionState.DeviceSelectedPendingChannelConnection) { // TesterPresent, expects 0x7E, 0x00 if (ConnectionProtocol != null) { ConnectionProtocol.SendTesterPresent(this); } } } public void OpenDevice() { if (!IsSimulation()) { try { ConnectionDevice = ConnectionAPI.GetDevice(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } State = ConnectionState.DeviceSelectedPendingChannelConnection; ConnectionUpdateState(); } private void ConnectionUpdateState() { if (IsSimulation()) { ConnectionStateChangeEvent?.Invoke($"Operating in simulation mode"); return; } string connectionState = "No interface selected (disconnected)"; if (ConnectionDevice != null) { connectionState = $"Device: {FriendlyName} online"; if (ConnectionChannel != null) { connectionState = $"{connectionState}, connected with profile '{FriendlyProfileName}'"; } else { connectionState = $"{connectionState}, disconnected"; } } ConnectionStateChangeEvent?.Invoke(connectionState); } public void SetConnectionDefaults() { ECUVariantID = 0; VariantIsAvailable = false; ConnectionProtocol = null; } public ConnectResponse Connect(ECUInterfaceSubtype profile, ECU ecuContext) { State = ConnectionState.PendingDeviceSelection; EcuContext = ecuContext; if (!IsSimulation()) { if (ConnectionDevice is null) { Console.WriteLine("No interfaces available : please select a J2534 interface from the Connection menu"); return ConnectResponse.NoValidInterface; } } if (!profile.Qualifier.StartsWith("HSCAN")) { Console.WriteLine("Profile not supported: only HSCAN interfaces are supported."); return ConnectResponse.UnsupportedProtocol; } ConnectionProtocol = BaseProtocol.GetProtocol(profile.Qualifier); // actually start fixing up the connection if (ConnectionChannel != null) { ConnectionChannel.Dispose(); ConnectionChannel = null; } FriendlyProfileName = profile.Qualifier; if (IsSimulation()) { SimulationChannel = new Simulation.Simulated_CRD3(); Console.WriteLine("Connected (Simulation)"); } else { try { // only ISO15765 is supported // CAN_ID_BOTH : accepts 11-bit and 29-bit CAN messages // baudrate is specified by the ECU ConnectionChannel = ConnectionDevice.GetChannel(Protocol.ISO15765, (Baud)profile.GetComParameterValue(ECUInterfaceSubtype.ParamName.CP_BAUDRATE), ConnectFlag.CAN_ID_BOTH); Console.WriteLine($"Target voltage : {ConnectionChannel.MeasureBatteryVoltage()} mV"); ConnectionChannel.DefaultTxFlag = TxFlag.ISO15765_FRAME_PAD; SetCANIdentifiers(profile); J2534SetFilters(); J2534SetConfig(profile); J2534FlushBuffers(); } catch (Exception e) { Console.WriteLine($"Connection failed with exception : {e.Message}"); return ConnectResponse.FailedWithException; } // this chunk is repeated for AVDI devices; OpenPort2 does not care, Scanmatik refuses to continue if reconfigured without clearing prior filters // wrap the second attempt in a separate try block, so that we can suppress any potential filter errors if (DriverIsAVDI()) { try { ConnectionChannel.ClearMsgFilters(); SetCANIdentifiers(profile); J2534SetFilters(); J2534SetConfig(profile); J2534FlushBuffers(); } catch (Exception ex) { Console.WriteLine($"AVDI Second config exception suppressed: {ex.Message}"); } } } State = ConnectionState.ChannelConnectedPendingEcuContact; ConnectionUpdateState(); return ConnectResponse.OK; } public bool DriverIsAVDI() { return DriverPath.ToUpper().EndsWith("ABRPT32.DLL"); } // this (and the overloaded variant) will be an issue when operating in gateway mode; // gateway mode will likely require the two separate can ids to be defined public void SetCANIdentifiers(ECUInterfaceSubtype profile) { SetCANIdentifiers(profile.GetComParameterValue(ECUInterfaceSubtype.ParamName.CP_REQUEST_CANIDENTIFIER), profile.GetComParameterValue(ECUInterfaceSubtype.ParamName.CP_RESPONSE_CANIDENTIFIER)); } public void SetCANIdentifiers(int canIdentifier, int rxCanIdentifier) { // convert the CBF's identifier integers to byte arrays CanIdentifier = BitConverter.GetBytes(canIdentifier); RxCanIdentifier = BitConverter.GetBytes(rxCanIdentifier); // input byte data is in big-endian Array.Reverse(CanIdentifier); Array.Reverse(RxCanIdentifier); } public void J2534SetFilters() { // setup ecu filter (mimicking vediamo's behavior) MessageFilter filter = new MessageFilter(); // Apparently in the EIS series, the RX identifier is !! NOT !! CanIdentifier+8 per ISO15765, so the automatic config in J2534-Sharp will fail // manually configure a ISO15765 filter filter.FilterType = Filter.FLOW_CONTROL_FILTER; filter.Mask = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; filter.Pattern = RxCanIdentifier; // RX address, typically CanIdentifier+8, EXCEPT EIS filter.FlowControl = CanIdentifier; // TX address filter.TxFlags = TxFlag.ISO15765_FRAME_PAD; ConnectionChannel.ClearMsgFilters(); ConnectionChannel.StartMsgFilter(filter); } public void J2534SetConfig(ECUInterfaceSubtype profile) { List sconfigList = new List(); List> comPairs = new List>(); comPairs.Add(new Tuple(Parameter.STMIN_TX, ECUInterfaceSubtype.ParamName.CP_STMIN_SUG)); comPairs.Add(new Tuple(Parameter.ISO15765_STMIN, ECUInterfaceSubtype.ParamName.CP_STMIN_SUG)); comPairs.Add(new Tuple(Parameter.ISO15765_BS, ECUInterfaceSubtype.ParamName.CP_BLOCKSIZE_SUG)); foreach (Tuple comPair in comPairs) { // apparently some are optional so we have to check for the presence of known comparams to configure the target j2534 device if (profile.GetComParameterValue(comPair.Item2, out int comValue)) { sconfigList.Add(new SConfig(comPair.Item1, comValue)); } } ConnectionChannel.SetConfig(sconfigList.ToArray()); } public void J2534FlushBuffers() { ConnectionChannel.ClearRxBuffer(); ConnectionChannel.ClearTxBuffer(); } public byte[] SendDiagRequest(DiagService diag) { Console.WriteLine($"Running diagnostic request : {diag.Qualifier} ({BitUtility.BytesToHex(diag.RequestBytes, true)})"); byte[] response = SendMessage(diag.RequestBytes); return response; } public void ExecUserDiagJob(byte[] request, DiagService diagService) { Console.WriteLine($"\r\n{diagService.Qualifier}"); byte[] response = SendMessage(request); foreach (List wtf in diagService.OutputPreparations) { foreach (DiagPreparation outputPreparation in wtf) { //outputPreparation.PrintDebug(); DiagPresentation presentation = outputPreparation.ParentECU.GlobalPresentations[outputPreparation.PresPoolIndex]; // presentation.PrintDebug(); Console.WriteLine($"{presentation.InterpretData(response, outputPreparation)}"); } } // check if the response was an ECU seed if ((ConnectionProtocol?.SupportsUnlocking() ?? false) && (response.Length >= 2) && (response[0] == 0x67)) { SecurityAutoLogin.ReceiveSecurityResponse(response, diagService.ParentECU, this); } } public byte[] SendMessage(IEnumerable message, bool testerPresenceRequest = false) { LogWrite(message); if (IsSimulation()) { if (SimulationChannel is null) { throw new Exception("Simulation channel was not initialized"); } byte[] simResponse = SimulationChannel.ReceiveRequest(message); LogRead(simResponse); return simResponse; } byte[] response = Array.Empty(); // prepare data to send List packet = new List(CanIdentifier); packet.AddRange(message); string messageAsString = BitUtility.BytesToHex(message.ToArray(), true); if (!testerPresenceRequest) { // LogPacket(message, true); } if (ConnectionDevice is null) { Console.WriteLine($"[!] Attempted to write into an invalid device, data: {messageAsString}"); return response; } if (ConnectionChannel is null) { Console.WriteLine($"[!] Attempted to write into an invalid channel, data: {messageAsString}"); return response; } // try to send the message try { ConnectionChannel.SendMessage(packet); } catch (Exception ex) { Console.WriteLine($"[!] Exception while sending {messageAsString} : {ex.Message}"); return response; } // reset the heartbeat timer; I don't know the actual behavior per the spec TesterPresentTimer.Stop(); TesterPresentTimer.Start(); // this loop catches 7F xx 78 reqeuests from the ecu, where it needs more time to complete an action bool responseIsValid = false; while (!responseIsValid) { response = ReadResponse(messageAsString, testerPresenceRequest); responseIsValid = !IsECURequestingForWait(response); } return response; } public byte[] ReadResponse(string originalMessageAsStringForDebug, bool testerPresenceRequest) { byte[] response = Array.Empty(); // before reading from ecu, check if there were out-of-order responses that were stored if (OutOfOrderBytesList.Count > 0) { return OutOfOrderBytesList.Dequeue(); } // read response from ecu Stopwatch sw = new Stopwatch(); sw.Start(); bool waitingForPacket = true; while (waitingForPacket) { if (sw.ElapsedMilliseconds > 18500) // is this P2_TIMEOUT? initially picked 2000 since that is the minimum for tester presence { Console.WriteLine($"[!] Internally timed out"); // Console.WriteLine($"[!] Internally timed out: {originalMessageAsStringForDebug}"); sw.Stop(); break; } GetMessageResults readResult = ConnectionChannel.GetMessage(); if (readResult.Result == ResultCode.STATUS_NOERROR) { foreach (Message row in readResult.Messages) { if (row.Data.Length < 4) { Console.WriteLine($"[!] Discarding received message (invalid size): {BitUtility.BytesToHex(row.Data, true)}"); continue; } byte[] identifier = row.Data.Take(4).ToArray(); if (!identifier.SequenceEqual(RxCanIdentifier)) { if (identifier.SequenceEqual(CanIdentifier)) { // quietly ignore if it is our can id, usually empty packet continue; } Console.WriteLine($"[!] Discarding received message (unknown sender): {BitUtility.BytesToHex(row.Data, true)} expects {BitUtility.BytesToHex(RxCanIdentifier, true)}"); continue; } // skip can identifier byte[] rxMessageBody = row.Data.Skip(4).ToArray(); if (rxMessageBody.Length == 0) { continue; } response = rxMessageBody; LogRead(response); // if it's a tester presence response, skip it and retry for another packet if (ConnectionProtocol.IsResponseToTesterPresent(response)) { // if it is a TP request, we can exit now if (testerPresenceRequest) { return Array.Empty(); } else { // accidentally received an out-of-order TP response, silently discard it continue; } } else { // TP receiving someone else's valid command, push it back into the queue and exit if (testerPresenceRequest) { OutOfOrderBytesList.Enqueue(response); return Array.Empty(); } else { // received a packet normally, check in parent caller if the ECU was asking us to wait waitingForPacket = false; break; } } //Console.WriteLine($"ECU: {BitUtility.BytesToHex(messageBody, true)}"); } } else if (readResult.Result == ResultCode.BUFFER_EMPTY) { // nothing in the mailbox, try again // Console.WriteLine($"[!] Retrying: empty buffer: {readResult.Result}"); // Console.WriteLine($"[!] Retrying: empty buffer: {readResult.Result} for request {originalMessageAsStringForDebug}"); } else { Console.WriteLine($"[!] Error in receive result: {readResult.Result}"); break; } } return response; } public bool IsECURequestingForWait(byte[] response) { if ((response.Length == 3) && (response[0] == 0x7F) && (response[2] == 0x78)) { if ((ConnectionProtocol.GetProtocolName() == "UDS") || (ConnectionProtocol.GetProtocolName() == "KW2C3PE")) { // ecu requesting for more time return true; } else { Console.WriteLine("Received NR that looks like a wait request, but the current protocol does not seem to support it."); } } return false; } public void LogRead(IEnumerable inBuffer) { lock (WriteLock) { CommunicationsLogHighLevel.Append($"R {BitUtility.BytesToHex(inBuffer.ToArray(), true)}\r\n"); } } public void LogWrite(IEnumerable inBuffer) { lock (WriteLock) { CommunicationsLogHighLevel.Append($"W {BitUtility.BytesToHex(inBuffer.ToArray(), true)}\r\n"); } } public void TryCleanup() { try { if (FriendlyProfileName != "SIMULATION_PROFILE") { Console.WriteLine("Cleaning up existing connection"); } if (ConnectionChannel != null) { if (ConnectionProtocol != null) { ConnectionProtocol?.ConnectionClosingHandler(this); } ConnectionChannel.Dispose(); ConnectionChannel = null; } if (ConnectionDevice != null) { ConnectionDevice.Dispose(); ConnectionDevice = null; } if (ConnectionAPI != null) { ConnectionAPI.Dispose(); ConnectionAPI = null; } TesterPresentTimer.Stop(); TesterPresentTimer.Enabled = false; } catch (Exception ex) { Console.WriteLine($"Cleanup issues: {ex.Message}"); } } } } ================================================ FILE: Caesar/Diogenes/ECUFlashMetadata.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes { public class ECUFlashMetadata { public int Index = 0; public string PartNumber = "Unspecified"; public string Version = "Unspecified"; public byte VendorID = 0; public byte StatusID = 0; public string FlashDate; // string bc i don't know what sort of datetime format they're on public byte LastFlashVendor = 0; public string FlashFingerprint = "Unspecified"; } } ================================================ FILE: Caesar/Diogenes/ECUIdentification.cs ================================================ using Caesar; using SAE.J2534; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes { // this whole class makes the assumption that MB is consistent with their request identifiers (which thankfully seems generally true) public class ECUIdentification { // FIN = Fahrzeug-Identifizierungs-Nummer // VIN = Vehicle Identification Number public static bool TryReadChassisNumber(ECUConnection connection, out string chassisNumber) { chassisNumber = ""; // we need a existing hardware connection to a J2534 device if (connection is null) { return false; } if (connection.IsSimulation()) { return false; } if (connection.ConnectionDevice is null) { // no valid j2534 device initialized yet, can't do anything return false; } bool connectionWasEstablished = connection.ConnectionProtocol != null; // if the connection is already open, we can use the protocol's vin query int[] baudratesToTest = new int[] { 500000, 800000 }; foreach (int baudrateToTest in baudratesToTest) { // if there is an established connection (i.e. already connected and identified a target, do not reconfigure the connection if (!connectionWasEstablished) { SetupConnectionForBaud(connection, baudrateToTest); } // try KW2C3PE first, since it is a legacy protocol; UDS seems to be somewhat aware, and deliberately avoids known KW2C3PE identifiers if (TryReadKW2C3PEChassisNumber(connection, out string KW2C3PEChassisNumber)) { chassisNumber = KW2C3PEChassisNumber; return true; } if (TryReadUDSChassisNumber(connection, out string udsChassisNumber)) { chassisNumber = udsChassisNumber; return true; } // if there's an established connection that failed both UDS/KW2C3PE, the loop is no longer required if (connection.ConnectionProtocol != null) { return false; } } // if a connection was unavailable, it would have been established earlier on; clean it up if (!connectionWasEstablished) { connection.TryCleanup(); connection = null; } return false; } public static bool TryReadUDSChassisNumber(ECUConnection connection, out string chassisNumber) { chassisNumber = ""; byte[] response = connection.SendMessage(new byte[] { 0x22, 0xF1, 0xA0 }); if (response.Length != 20) // 62 F1 A0 + 17byte vin { return false; } if (response[0] != 0x62) { return false; } chassisNumber = Encoding.ASCII.GetString(response.Skip(3).ToArray()); return true; } public static bool TryReadKW2C3PEChassisNumber(ECUConnection connection, out string chassisNumber) { chassisNumber = ""; byte[] response = connection.SendMessage(new byte[] { 0x1A, 0x90 }); // VIN current if (response.Length != 19) // 5A 90 + 17byte vin { return false; } if (response[0] != 0x5A) { return false; } chassisNumber = Encoding.ASCII.GetString(response.Skip(2).ToArray()); return true; } // eventually move this to ecuconnection, since it touches J2534Sharp and this should be kept local public static void SetupConnectionForBaud(ECUConnection connection, int baud) { if (connection.ConnectionChannel != null) { connection.ConnectionChannel.ClearMsgFilters(); // this bit here for good luck since there are some misbehaving j2534 devices connection.ConnectionChannel.Dispose(); connection.ConnectionChannel = null; } try { // create a new channel; the protocol is almost always ISO15765 connection.ConnectionChannel = connection.ConnectionDevice.GetChannel(Protocol.ISO15765, (Baud)baud, ConnectFlag.CAN_ID_BOTH); connection.ConnectionProtocol = new DiagnosticProtocol.UnsupportedProtocol(); connection.ConnectionChannel.DefaultTxFlag = TxFlag.ISO15765_FRAME_PAD; connection.InternalTimeout = 100; // setup filters connection.SetCANIdentifiers(0x7E0, 0x7E8); connection.J2534SetFilters(); // setup config with some sane defaults since we are guessing our target List sconfigList = new List(); sconfigList.Add(new SConfig(Parameter.STMIN_TX, 0)); sconfigList.Add(new SConfig(Parameter.ISO15765_STMIN, 0)); sconfigList.Add(new SConfig(Parameter.ISO15765_BS, 8)); connection.ConnectionChannel.SetConfig(sconfigList.ToArray()); // flush the buffer connection.ConnectionChannel.ClearRxBuffer(); connection.ConnectionChannel.ClearTxBuffer(); } catch (Exception e) { Console.WriteLine($"[!] ECUIdentification exception in SetupConnectionForBaud: {e.Message}"); } } } } ================================================ FILE: Caesar/Diogenes/ECUMetadata.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes { public class ECUMetadata { public bool GatewayMode = false; public string BootVersion = "Unspecified"; public string SerialNumber = "Unspecified"; public string ChassisNumberOriginal = "Unspecified"; public string ChassisNumberCurrent = "Unspecified"; public string HardwarePartNumber = "Unspecified"; public string HardwareVersion = "Unspecified"; public uint VariantID = 0; public byte VendorID = 0; public List FlashMetadata = new List(); public string GetHtmlTable(ECUConnection connection) { ECUMetadata metadata = connection.ConnectionProtocol.QueryECUMetadata(connection); string[][] rows = new string[][] { new string[]{ "Variant ID", metadata.VariantID.ToString("X4") }, new string[]{ "Gateway Mode", metadata.GatewayMode.ToString() }, new string[]{ "Boot Version", metadata.BootVersion }, new string[]{ "Serial Number", metadata.SerialNumber }, new string[]{ "Chassis Number (Current)", metadata.ChassisNumberCurrent }, new string[]{ "Chassis Number (Original)", metadata.ChassisNumberOriginal }, new string[]{ "Hardware Part Number", metadata.HardwarePartNumber }, new string[]{ "Hardware Version", metadata.HardwareVersion }, new string[]{ "Hardware Supplier", ECUMetadata.GetVendorName(metadata.VendorID) }, }; StringBuilder ecuTableRows = new StringBuilder(); foreach (string[] row in rows) { ecuTableRows.AppendLine($"{row[0]}{row[1]}"); } StringBuilder swBlockRows = new StringBuilder(); foreach (ECUFlashMetadata flash in metadata.FlashMetadata) { string flashStatus = flash.StatusID == 1 ? "Valid" : "Invalid"; swBlockRows.AppendLine($@"

SW Block #{flash.Index}

Part Number{flash.PartNumber}
Version{flash.Version}
Vendor{ECUMetadata.GetVendorName(flash.VendorID)}
Status{flashStatus}
Last Flash Vendor{ECUMetadata.GetVendorName(flash.LastFlashVendor)}
Last Flash Date{flash.FlashDate}
Flash Fingerprint{flash.FlashFingerprint}
"); } return $@"

Hardware

{ecuTableRows}
{swBlockRows} "; } public static string GetVendorName(byte vendorId) { string vendorName = "Undefined"; if (Enum.IsDefined(typeof(Vendor), vendorId)) { vendorName = ((Vendor)vendorId).ToString().Replace("VENDOR_", "").Replace("_", " "); } return vendorName; } public static void ShowMetadataModal(ECUConnection connection) { if (connection.ConnectionProtocol is null) { Console.WriteLine("Please initiate contact with a target first."); return; } ECUMetadata metadata = connection.ConnectionProtocol.QueryECUMetadata(connection); string[][] rows = new string[][] { new string[]{ "Variant ID", metadata.VariantID.ToString("X4") }, new string[]{ "Gateway Mode", metadata.GatewayMode.ToString() }, new string[]{ "Boot Version", metadata.BootVersion }, new string[]{ "Serial Number", metadata.SerialNumber }, new string[]{ "Chassis Number (Current)", metadata.ChassisNumberCurrent }, new string[]{ "Chassis Number (Original)", metadata.ChassisNumberOriginal }, new string[]{ "Hardware Part Number", metadata.HardwarePartNumber }, new string[]{ "Hardware Version", metadata.HardwareVersion }, new string[]{ "Hardware Supplier", ECUMetadata.GetVendorName(metadata.VendorID) }, }; List rowsAsList = new List(rows); foreach (ECUFlashMetadata flash in metadata.FlashMetadata) { string blockPrefix = $"SW Block #{flash.Index} : "; string flashStatus = flash.StatusID == 1 ? "Valid" : "Invalid"; rowsAsList.Add(new string[] { $"{blockPrefix}Descriptor", $"{flash.PartNumber} [Version {flash.Version} from {ECUMetadata.GetVendorName(flash.VendorID)}]" }); rowsAsList.Add(new string[] { $"{blockPrefix}Status", $"{flashStatus}, Last flashed by {ECUMetadata.GetVendorName(flash.LastFlashVendor)} on {flash.FlashDate} (Fingerprint: {flash.FlashFingerprint})" }); } GenericPicker picker = new GenericPicker(rowsAsList.ToArray(), new string[] { "Attribute", "Value" }); picker.Text = "ECU Metadata"; picker.ShowDialog(); } public enum Vendor : byte { VENDOR_Unspecified = 0, VENDOR_Becker = 1, VENDOR_Blaupunkt = 2, VENDOR_Bosch = 3, VENDOR_MB = 4, VENDOR_HuF = 5, VENDOR_Kammerer = 6, VENDOR_Kostal = 7, VENDOR_Siemens = 8, VENDOR_Stribel = 9, VENDOR_MicroHeat = 10, VENDOR_JATCO = 11, VENDOR_SWF = 16, VENDOR_VDO = 17, VENDOR_Webasto = 18, VENDOR_Dornier = 19, VENDOR_TEG = 20, VENDOR_Hella = 21, VENDOR_Lucas = 22, VENDOR_GKR = 23, VENDOR_MBB = 24, VENDOR_Motometer = 25, VENDOR_Borg = 32, VENDOR_Temic = 33, VENDOR_Teves = 34, VENDOR_Borg_Warner = 35, VENDOR_MED_SPA = 36, VENDOR_DENSO = 37, VENDOR_ZF = 38, VENDOR_TRW = 39, VENDOR_Dunlop = 40, VENDOR_LUK = 41, VENDOR_Magneti_Marelli = 48, VENDOR_DODUCO = 49, VENDOR_Alpine = 50, VENDOR_AMC_AEG_Mobile = 51, VENDOR_Bose = 52, VENDOR_Dasa = 53, VENDOR_Motorola = 54, VENDOR_Nokia = 55, VENDOR_Panasonic = 56, VENDOR_APAG = 57, VENDOR_Rialtosoft = 58, VENDOR_Applicom = 59, VENDOR_Conti_Temic = 60, VENDOR_Cherry = 61, VENDOR_TI_Automotive = 62, VENDOR_Kongsberg_Company = 63, VENDOR_Delphi = 64, VENDOR_Alfmeier = 65, VENDOR_Sidler = 66, VENDOR_Marquardt = 67, VENDOR_Wehrle = 68, VENDOR_megamos = 69, VENDOR_ADC = 70, VENDOR_BERU = 71, VENDOR_Valeo = 72, VENDOR_Magna = 73, VENDOR_Allison = 74, VENDOR_Isringhausen = 75, VENDOR_Grammer = 76, VENDOR_Funkwerk_Dabendorf = 77, VENDOR_Hella_Behr = 78, VENDOR_Pollak = 79, VENDOR_AKG = 80, VENDOR_Automotive_Lighting = 81, VENDOR_TAG = 82, VENDOR_UNITED_PARTS = 83, VENDOR_catem = 84, VENDOR_Alge = 85, VENDOR_Pierburg = 86, VENDOR_Brusa = 87, VENDOR_Ecostar = 88, VENDOR_Xcellsis = 89, VENDOR_Wabco_Automotive = 90, VENDOR_Voith = 91, VENDOR_Knorr = 92, VENDOR_TVI = 93, VENDOR_Stoneridge = 94, VENDOR_Telma = 95, VENDOR_STW = 96, VENDOR_Koyo = 97, VENDOR_Eberspacher = 98, VENDOR_ADVICS = 99, VENDOR_OMRON = 100, VENDOR_Mitsubishi_Heavy_Industry = 101, VENDOR_Methode = 102, VENDOR_UNISIAJECS = 103, VENDOR_UNISIA_JKC_Steering_Systems = 104, VENDOR_AISIN = 105, VENDOR_Zexel_Valeo = 106, VENDOR_Schrader = 107, VENDOR_Ballard = 108, VENDOR_SFT = 112, VENDOR_Kieckert_AG = 113, VENDOR_Behr = 114, VENDOR_MB_Lenkungen = 115, VENDOR_Sachs_Automotive = 116, VENDOR_Peiker = 117, VENDOR_Petri = 118, VENDOR_Autoliv = 119, VENDOR_Thien_Electronic = 120, VENDOR_Siemens_VDO = 121, VENDOR_Dornier_Consulting_GmbH = 122, VENDOR_Alps = 123, VENDOR_PREH = 124, VENDOR_Hitachi_Unisia = 125, VENDOR_Hitachi = 126, VENDOR_Reserved_127 = 127, VENDOR_Huntsville = 128, VENDOR_Yazaki = 129, VENDOR_Lear = 130, VENDOR_Johnson_Controls = 131, VENDOR_HarmanBecker = 132, VENDOR_Mitsubishi_Electric = 133, VENDOR_Tokico_USA_Inc = 134, VENDOR_Nippon_Seiki_International = 135, VENDOR_Inalfa = 136, VENDOR_Nippon_Seiki_UK = 137, VENDOR_GHSP = 138, VENDOR_Vector = 139, VENDOR_Gentex = 140, VENDOR_Visteon = 141, VENDOR_Tochigi_Fuji = 142, VENDOR_DCA = 143, VENDOR_May_and_Scofield = 144, VENDOR_DaimlerChrysler_Hamburg_Plant = 145, VENDOR_AISIN_AW = 146, VENDOR_TOYODA_MACHINE_WORKS = 147, VENDOR_Solectron_Invotronics = 148, VENDOR_Kicker = 149, VENDOR_American_Axle_Company = 150, VENDOR_GETRAG = 151, VENDOR_Promate = 152, VENDOR_ArvinMeritor = 153, VENDOR_Reserved_MMC = 160, VENDOR_Reserved_MMC_SMART = 161, VENDOR_Reserved_162 = 162, VENDOR_After_Market_Supplier = 254, VENDOR_Unidentified = 255, } } } ================================================ FILE: Caesar/Diogenes/Forms/AboutForm.Designer.cs ================================================  namespace Diogenes { partial class AboutForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.pbLogo = new System.Windows.Forms.PictureBox(); this.lblDescName = new System.Windows.Forms.Label(); this.lblVersion = new System.Windows.Forms.Label(); this.linkLabel1 = new System.Windows.Forms.LinkLabel(); this.btnClose = new System.Windows.Forms.Button(); this.lbCredits = new System.Windows.Forms.ListBox(); ((System.ComponentModel.ISupportInitialize)(this.pbLogo)).BeginInit(); this.SuspendLayout(); // // pbLogo // this.pbLogo.Image = global::Diogenes.Properties.Resources.diogenes; this.pbLogo.Location = new System.Drawing.Point(20, 20); this.pbLogo.Name = "pbLogo"; this.pbLogo.Size = new System.Drawing.Size(80, 80); this.pbLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.pbLogo.TabIndex = 0; this.pbLogo.TabStop = false; // // lblDescName // this.lblDescName.AutoSize = true; this.lblDescName.Font = new System.Drawing.Font("Segoe UI Semilight", 36F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblDescName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), ((int)(((byte)(157)))), ((int)(((byte)(220))))); this.lblDescName.Location = new System.Drawing.Point(106, 24); this.lblDescName.Name = "lblDescName"; this.lblDescName.Size = new System.Drawing.Size(249, 65); this.lblDescName.TabIndex = 1; this.lblDescName.Text = "DIOGENES"; // // lblVersion // this.lblVersion.AutoSize = true; this.lblVersion.Font = new System.Drawing.Font("Segoe UI Semibold", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblVersion.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), ((int)(((byte)(157)))), ((int)(((byte)(220))))); this.lblVersion.Location = new System.Drawing.Point(16, 119); this.lblVersion.Name = "lblVersion"; this.lblVersion.Size = new System.Drawing.Size(167, 21); this.lblVersion.TabIndex = 2; this.lblVersion.Text = "v0.0.0 (Caesar: v0.0.0)"; // // linkLabel1 // this.linkLabel1.AutoSize = true; this.linkLabel1.Font = new System.Drawing.Font("Segoe UI Semibold", 12F, System.Drawing.FontStyle.Bold); this.linkLabel1.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), ((int)(((byte)(157)))), ((int)(((byte)(220))))); this.linkLabel1.Location = new System.Drawing.Point(16, 140); this.linkLabel1.Name = "linkLabel1"; this.linkLabel1.Size = new System.Drawing.Size(285, 21); this.linkLabel1.TabIndex = 3; this.linkLabel1.TabStop = true; this.linkLabel1.Text = "https://github.com/jglim/CaesarSuite"; this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); // // btnClose // 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, 361); this.btnClose.Name = "btnClose"; this.btnClose.Size = new System.Drawing.Size(75, 23); this.btnClose.TabIndex = 4; this.btnClose.Text = "Close"; this.btnClose.UseVisualStyleBackColor = true; this.btnClose.Click += new System.EventHandler(this.btnClose_Click); // // 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))); this.lbCredits.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(84)))), ((int)(((byte)(157)))), ((int)(((byte)(220))))); this.lbCredits.FormattingEnabled = true; 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)", "@prj (@prj)"}); this.lbCredits.Location = new System.Drawing.Point(20, 180); this.lbCredits.Name = "lbCredits"; this.lbCredits.Size = new System.Drawing.Size(548, 170); this.lbCredits.TabIndex = 5; // // AboutForm // 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, 396); this.Controls.Add(this.lbCredits); this.Controls.Add(this.btnClose); this.Controls.Add(this.linkLabel1); this.Controls.Add(this.lblVersion); this.Controls.Add(this.lblDescName); this.Controls.Add(this.pbLogo); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "AboutForm"; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "About"; ((System.ComponentModel.ISupportInitialize)(this.pbLogo)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.PictureBox pbLogo; private System.Windows.Forms.Label lblDescName; private System.Windows.Forms.Label lblVersion; private System.Windows.Forms.LinkLabel linkLabel1; private System.Windows.Forms.Button btnClose; private System.Windows.Forms.ListBox lbCredits; } } ================================================ FILE: Caesar/Diogenes/Forms/AboutForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public partial class AboutForm : Form { public AboutForm(string displayedVersion) { InitializeComponent(); lblVersion.Text = displayedVersion; } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { System.Diagnostics.Process.Start(((LinkLabel)sender).Text); } } } ================================================ FILE: Caesar/Diogenes/Forms/AboutForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: Caesar/Diogenes/Forms/BlockDownload.Designer.cs ================================================  namespace Diogenes { partial class BlockDownload { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BlockDownload)); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.gbInputOutput = new System.Windows.Forms.GroupBox(); this.txtIOPrefixHex = new System.Windows.Forms.TextBox(); this.lblDescCmdRead = new System.Windows.Forms.Label(); this.nudPayloadWidth = new System.Windows.Forms.NumericUpDown(); this.lblDescIOWidth = new System.Windows.Forms.Label(); this.nudAddressWidth = new System.Windows.Forms.NumericUpDown(); this.lblDescPrefix = new System.Windows.Forms.Label(); this.gbOperation = new System.Windows.Forms.GroupBox(); this.btnExportAsMono = new System.Windows.Forms.Button(); this.btnDownload = new System.Windows.Forms.Button(); this.btnRemoveBlocks = new System.Windows.Forms.Button(); this.btnAddBlock = new System.Windows.Forms.Button(); this.gbMemo = new System.Windows.Forms.GroupBox(); this.lblWarning = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.gbInputOutput.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudPayloadWidth)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudAddressWidth)).BeginInit(); this.gbOperation.SuspendLayout(); this.gbMemo.SuspendLayout(); this.SuspendLayout(); // // groupBox1 // this.groupBox1.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.groupBox1.Controls.Add(this.dgvMain); this.groupBox1.Location = new System.Drawing.Point(282, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(506, 455); this.groupBox1.TabIndex = 2; this.groupBox1.TabStop = false; this.groupBox1.Text = "Flash Payload"; // // dgvMain // this.dgvMain.AllowDrop = true; this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.Dock = System.Windows.Forms.DockStyle.Fill; this.dgvMain.Location = new System.Drawing.Point(3, 16); this.dgvMain.MultiSelect = false; this.dgvMain.Name = "dgvMain"; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(500, 436); this.dgvMain.TabIndex = 1; this.dgvMain.DragDrop += new System.Windows.Forms.DragEventHandler(this.dgvMain_DragDrop); this.dgvMain.DragEnter += new System.Windows.Forms.DragEventHandler(this.dgvMain_DragEnter); // // gbInputOutput // this.gbInputOutput.Controls.Add(this.txtIOPrefixHex); this.gbInputOutput.Controls.Add(this.lblDescCmdRead); this.gbInputOutput.Controls.Add(this.nudPayloadWidth); this.gbInputOutput.Controls.Add(this.lblDescIOWidth); this.gbInputOutput.Controls.Add(this.nudAddressWidth); this.gbInputOutput.Controls.Add(this.lblDescPrefix); this.gbInputOutput.Location = new System.Drawing.Point(12, 12); this.gbInputOutput.Name = "gbInputOutput"; this.gbInputOutput.Size = new System.Drawing.Size(264, 214); this.gbInputOutput.TabIndex = 8; this.gbInputOutput.TabStop = false; this.gbInputOutput.Text = "I/O"; // // txtIOPrefixHex // this.txtIOPrefixHex.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtIOPrefixHex.Font = new System.Drawing.Font("Consolas", 16F); this.txtIOPrefixHex.Location = new System.Drawing.Point(6, 37); this.txtIOPrefixHex.Name = "txtIOPrefixHex"; this.txtIOPrefixHex.Size = new System.Drawing.Size(250, 32); this.txtIOPrefixHex.TabIndex = 10; this.txtIOPrefixHex.Text = "34 00"; // // lblDescCmdRead // this.lblDescCmdRead.AutoSize = true; this.lblDescCmdRead.Location = new System.Drawing.Point(5, 149); this.lblDescCmdRead.Name = "lblDescCmdRead"; this.lblDescCmdRead.Size = new System.Drawing.Size(76, 13); this.lblDescCmdRead.TabIndex = 7; this.lblDescCmdRead.Text = "Payload Width"; // // nudPayloadWidth // this.nudPayloadWidth.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudPayloadWidth.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudPayloadWidth.Hexadecimal = true; this.nudPayloadWidth.Location = new System.Drawing.Point(6, 168); this.nudPayloadWidth.Maximum = new decimal(new int[] { 4, 0, 0, 0}); this.nudPayloadWidth.Minimum = new decimal(new int[] { 1, 0, 0, 0}); this.nudPayloadWidth.Name = "nudPayloadWidth"; this.nudPayloadWidth.Size = new System.Drawing.Size(250, 32); this.nudPayloadWidth.TabIndex = 6; this.nudPayloadWidth.Value = new decimal(new int[] { 4, 0, 0, 0}); // // lblDescIOWidth // this.lblDescIOWidth.AutoSize = true; this.lblDescIOWidth.Location = new System.Drawing.Point(5, 85); this.lblDescIOWidth.Name = "lblDescIOWidth"; this.lblDescIOWidth.Size = new System.Drawing.Size(76, 13); this.lblDescIOWidth.TabIndex = 5; this.lblDescIOWidth.Text = "Address Width"; // // nudAddressWidth // this.nudAddressWidth.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudAddressWidth.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudAddressWidth.Hexadecimal = true; this.nudAddressWidth.Location = new System.Drawing.Point(6, 104); this.nudAddressWidth.Maximum = new decimal(new int[] { 4, 0, 0, 0}); this.nudAddressWidth.Minimum = new decimal(new int[] { 1, 0, 0, 0}); this.nudAddressWidth.Name = "nudAddressWidth"; this.nudAddressWidth.Size = new System.Drawing.Size(250, 32); this.nudAddressWidth.TabIndex = 4; this.nudAddressWidth.Value = new decimal(new int[] { 4, 0, 0, 0}); // // lblDescPrefix // this.lblDescPrefix.AutoSize = true; this.lblDescPrefix.Location = new System.Drawing.Point(6, 21); this.lblDescPrefix.Name = "lblDescPrefix"; this.lblDescPrefix.Size = new System.Drawing.Size(61, 13); this.lblDescPrefix.TabIndex = 3; this.lblDescPrefix.Text = "Prefix (Hex)"; // // gbOperation // this.gbOperation.Controls.Add(this.btnExportAsMono); this.gbOperation.Controls.Add(this.btnDownload); this.gbOperation.Controls.Add(this.btnRemoveBlocks); this.gbOperation.Controls.Add(this.btnAddBlock); this.gbOperation.Location = new System.Drawing.Point(12, 232); this.gbOperation.Name = "gbOperation"; this.gbOperation.Size = new System.Drawing.Size(264, 139); this.gbOperation.TabIndex = 9; this.gbOperation.TabStop = false; this.gbOperation.Text = "Operation"; // // btnExportAsMono // this.btnExportAsMono.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnExportAsMono.Location = new System.Drawing.Point(9, 106); this.btnExportAsMono.Name = "btnExportAsMono"; this.btnExportAsMono.Size = new System.Drawing.Size(250, 23); this.btnExportAsMono.TabIndex = 3; this.btnExportAsMono.Text = "Save as monolithic binary"; this.btnExportAsMono.UseVisualStyleBackColor = true; this.btnExportAsMono.Visible = false; this.btnExportAsMono.Click += new System.EventHandler(this.btnExportAsMono_Click); // // btnDownload // this.btnDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnDownload.Location = new System.Drawing.Point(8, 77); this.btnDownload.Name = "btnDownload"; this.btnDownload.Size = new System.Drawing.Size(250, 23); this.btnDownload.TabIndex = 2; this.btnDownload.Text = "Download"; this.btnDownload.UseVisualStyleBackColor = true; this.btnDownload.Click += new System.EventHandler(this.btnDownload_Click); // // btnRemoveBlocks // this.btnRemoveBlocks.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnRemoveBlocks.Location = new System.Drawing.Point(8, 48); this.btnRemoveBlocks.Name = "btnRemoveBlocks"; this.btnRemoveBlocks.Size = new System.Drawing.Size(250, 23); this.btnRemoveBlocks.TabIndex = 1; this.btnRemoveBlocks.Text = "Clear All Blocks"; this.btnRemoveBlocks.UseVisualStyleBackColor = true; this.btnRemoveBlocks.Click += new System.EventHandler(this.btnRemoveBlocks_Click); // // btnAddBlock // this.btnAddBlock.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnAddBlock.Location = new System.Drawing.Point(8, 19); this.btnAddBlock.Name = "btnAddBlock"; this.btnAddBlock.Size = new System.Drawing.Size(250, 23); this.btnAddBlock.TabIndex = 0; this.btnAddBlock.Text = "Add Block"; this.btnAddBlock.UseVisualStyleBackColor = true; this.btnAddBlock.Click += new System.EventHandler(this.btnAddBlock_Click); // // gbMemo // this.gbMemo.Controls.Add(this.lblWarning); this.gbMemo.Location = new System.Drawing.Point(12, 377); this.gbMemo.Name = "gbMemo"; this.gbMemo.Size = new System.Drawing.Size(264, 88); this.gbMemo.TabIndex = 10; this.gbMemo.TabStop = false; this.gbMemo.Text = "Warning"; // // lblWarning // this.lblWarning.AutoSize = true; this.lblWarning.Location = new System.Drawing.Point(6, 16); this.lblWarning.Name = "lblWarning"; this.lblWarning.Size = new System.Drawing.Size(252, 65); this.lblWarning.TabIndex = 0; this.lblWarning.Text = "This feature is intended for developers only.\r\nThe target must be in a state that" + " is ready to receive\r\nflash blocks to use this feature.\r\n\r\nPlease check the docs" + " for more information"; // // BlockDownload // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 479); this.Controls.Add(this.gbMemo); this.Controls.Add(this.gbOperation); this.Controls.Add(this.gbInputOutput); this.Controls.Add(this.groupBox1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "BlockDownload"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Block Download"; this.Load += new System.EventHandler(this.BlockDownload_Load); this.groupBox1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.gbInputOutput.ResumeLayout(false); this.gbInputOutput.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudPayloadWidth)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudAddressWidth)).EndInit(); this.gbOperation.ResumeLayout(false); this.gbMemo.ResumeLayout(false); this.gbMemo.PerformLayout(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.GroupBox gbInputOutput; private System.Windows.Forms.Label lblDescCmdRead; private System.Windows.Forms.NumericUpDown nudPayloadWidth; private System.Windows.Forms.Label lblDescIOWidth; private System.Windows.Forms.NumericUpDown nudAddressWidth; private System.Windows.Forms.Label lblDescPrefix; private System.Windows.Forms.TextBox txtIOPrefixHex; private System.Windows.Forms.GroupBox gbOperation; private System.Windows.Forms.Button btnDownload; private System.Windows.Forms.Button btnRemoveBlocks; private System.Windows.Forms.Button btnAddBlock; private System.Windows.Forms.GroupBox gbMemo; private System.Windows.Forms.Label lblWarning; private System.Windows.Forms.Button btnExportAsMono; } } ================================================ FILE: Caesar/Diogenes/Forms/BlockDownload.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; using SAE.J2534; namespace Diogenes { public partial class BlockDownload : Form { List FlashBlocks = new List(); ECUConnection connection; public BlockDownload(ECUConnection connection) { this.connection = connection; InitializeComponent(); } private void BlockDownload_Load(object sender, EventArgs e) { } private void dgvMain_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } } private void dgvMain_DragDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach (string file in files) { TryLoadBlock(file); } FlashBlocks = FlashBlocks.OrderBy(x => x.Address).ToList(); PresentRows(); } private void TryLoadBlock(string fileName) { string[] fileNameChunks = Path.GetFileNameWithoutExtension(fileName).Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); if (fileNameChunks.Length > 0) { if (uint.TryParse(fileNameChunks[fileNameChunks.Length - 1], System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out uint result)) { if (FlashBlocks.FindAll(x => x.Path == fileName).Count > 0) { MessageBox.Show($"Skipping repeated block : {fileName}"); } else { FlashBlocks.Add(new FlashBlock { Address = result, Payload = File.ReadAllBytes(fileName), Path = fileName }); } } else { MessageBox.Show($"Could not load {fileName} : unable to parse destination address. Please append a valid hex-value to the filename to specify the address (e.g. file_1FFFFF.bin)"); } } else { MessageBox.Show($"Could not load {fileName} : unable to parse name. Please append a valid hex-value to the filename to specify the address (e.g. file_1FFFFF.bin)"); } } private void PresentRows() { if (FlashBlocks is null) { return; } DataTable dt = new DataTable(); foreach (string header in new string[] { "Block #", "Name", "Address" }) { dt.Columns.Add(header, typeof(string)); } dgvMain.DataSource = dt; for (int i = 0; i < FlashBlocks.Count; i++) { dt.Rows.Add( i.ToString(), Path.GetFileNameWithoutExtension(FlashBlocks[i].Path), $"{FlashBlocks[i].Address:X}" ); } dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[0].ReadOnly = true; dgvMain.Columns[1].ReadOnly = true; dgvMain.Columns[2].ReadOnly = true; dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; } private void btnDownload_Click(object sender, EventArgs e) { if (MessageBox.Show("Please note that the STMin and BS values are hardcoded. This process will also take some time. Continue?", "Download", MessageBoxButtons.YesNo) == DialogResult.Yes) { StartDownload(); } } private void StartDownload() { int sumBytesTransferred = 0; int sumBytes = 0; foreach (FlashBlock block in FlashBlocks) { sumBytes += block.Payload.Length; } GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.TopMost = true; loader.Show(); Application.DoEvents(); foreach (FlashBlock block in FlashBlocks) { byte[] startDownloadCmd = CreateDownloadRequest(block.Address, (uint)block.Payload.Length); byte[] response = connection.SendMessage(startDownloadCmd); // comment this, uncomment below if dryrun //byte[] response = BitUtility.BytesFromHex("74 20 00 03"); if (response.Length < 2) { MessageBox.Show($"Error: ECU sent an incorrectly sized response when initiating download for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } if (response[0] != startDownloadCmd[0] + 0x40) { MessageBox.Show($"Error: ECU sent a non-positive response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // read alfid to know memory size description's width byte rxAlfid = response[1]; // we are only expecting a size value if ((rxAlfid & 0xF) > 0) { MessageBox.Show($"Error: Could not understand ECU ALFID response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // find out how wide the memory size description is int memSize = rxAlfid >> 4; List memBytes = response.Skip(2).Take(memSize).ToList(); if (memBytes.Count != memSize) { MessageBox.Show($"Error: Could not understand ECU ALFID response (size mismatch) ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // parse the memory size desc as a BE integer uint messageSize = 0; for (int i = 0; i < memBytes.Count; i++) { messageSize <<= 8; messageSize |= memBytes[i]; } // debug: uncomment to cap msg size at 0x100, normally 0xF02, blocksize = 0xF00 // messageSize = 0x102; int blockSize = (int)messageSize - 2; int totalBlockCount = (int)(block.Payload.Length / blockSize); int remainderBytes = block.Payload.Length % blockSize; if (remainderBytes != 0) { totalBlockCount++; } // reconfigure connection for block transfer connection.TesterPresentTimer.Enabled = false; RaiseSTMin(); byte[] dataBlock = new byte[messageSize]; loader.SetProgressMax(totalBlockCount); for (int blockCounter = 0; blockCounter < totalBlockCount; blockCounter++) { dataBlock[0] = 0x36; dataBlock[1] = (byte)((blockCounter + 1) & 0xFF); // if this is the last block, and there is a remainder block, write only the remainder if (((blockCounter + 1) == totalBlockCount) && (remainderBytes != 0)) { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, remainderBytes); dataBlock = dataBlock.Take(2 + remainderBytes).ToArray(); } else { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, blockSize); } byte[] transferResponse = connection.SendMessage(dataBlock); // comment this, uncomment below if dryrun //byte[] transferResponse = new byte[] { 0x76, 0x00 }; if ((transferResponse.Length > 0) && (transferResponse[0] == 0x76)) { // no need to check block index, if the ecu accepts it, continue } else { MessageBox.Show($"Error: Data transfer rejected by ECU ({BitUtility.BytesToHex(transferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // update progress sumBytesTransferred += dataBlock.Length - 2; // loader.Text = $"Writing to ECU : 0x{sumBytesTransferred:X8} of 0x{sumBytes:X8}"; loader.Text = $"Writing to ECU : block {blockCounter} of 0x{totalBlockCount}"; loader.SetProgressValue(blockCounter); Application.DoEvents(); // fixme: show two progressbars, one for the block# and another for the individual block's % } byte[] exitTransferResponse = connection.SendMessage(new byte[] { 0x37 });// ------------------ patch if debugging if (!((exitTransferResponse.Length > 0) && (exitTransferResponse[0] == 0x77))) { MessageBox.Show($"Error: Exit transfer rejected by ECU ({BitUtility.BytesToHex(exitTransferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } } // restore prior connection status connection.TesterPresentTimer.Enabled = true; ResetSTMin(); loader.Close(); MessageBox.Show("Download completed"); } // WARNING: this bit here is hardcoded; should pull the correct values from the connection private void RaiseSTMin() { List sconfigList = new List(); sconfigList.Add(new SConfig(Parameter.STMIN_TX, 65535)); // todo: check if only STMIN_TX can be raised without affecting the other values sconfigList.Add(new SConfig(Parameter.ISO15765_STMIN, 20)); sconfigList.Add(new SConfig(Parameter.ISO15765_BS, 8)); connection.ConnectionChannel.SetConfig(sconfigList.ToArray()); } private void ResetSTMin() { List sconfigList = new List(); sconfigList.Add(new SConfig(Parameter.STMIN_TX, 20)); sconfigList.Add(new SConfig(Parameter.ISO15765_STMIN, 20)); sconfigList.Add(new SConfig(Parameter.ISO15765_BS, 8)); connection.ConnectionChannel.SetConfig(sconfigList.ToArray()); } private byte[] CreateDownloadRequest(uint address, uint size) { byte[] prefix = BitUtility.BytesFromHex(txtIOPrefixHex.Text.ToUpper().Replace(" ", "")); int addressWidth = (int)nudAddressWidth.Value; int payloadWidth = (int)nudPayloadWidth.Value; byte alfid = GetAddressAndLengthFormatIdentifier(addressWidth, payloadWidth); List command = new List(prefix); command.Add(alfid); command.AddRange(ValueToBEByteArrayConstrained(address, addressWidth)); command.AddRange(ValueToBEByteArrayConstrained(size, payloadWidth)); return command.ToArray(); } // alfid generation copied fro UDS hex editor, (temporarily) preferring to duplicate to avoid coupling private static byte GetAddressAndLengthFormatIdentifier(int addressSizeInBytes, int memorySizeInBytes) { /* address map in bits: 8 bits : 1 16 bits : 2 24 bits : 3 32 bits : 4 40 bits : 5 memory size map in bits: 8 bits : 1 16 bits : 2 24 bits : 3 32 bits : 4 */ if ((addressSizeInBytes < 1) || (addressSizeInBytes > 5)) { throw new ArgumentOutOfRangeException("Invalid address size for ALFID"); } if ((memorySizeInBytes < 1) || (memorySizeInBytes > 5)) { throw new ArgumentOutOfRangeException("Invalid memory size for ALFID"); } return (byte)((memorySizeInBytes << 4) | addressSizeInBytes); } // also from uds hex editor private List ValueToBEByteArrayConstrained(long inValue, int size) { List result = new List(); for (int i = 0; i < size; i++) { byte row = (byte)(inValue & 0xFF); result.Insert(0, row); inValue >>= 8; } return result; } private void btnAddBlock_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a BIN File"; ofd.Filter = "BIN files (*.bin)|*.bin|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { TryLoadBlock(ofd.FileName); } FlashBlocks = FlashBlocks.OrderBy(x => x.Address).ToList(); PresentRows(); } private void btnRemoveBlocks_Click(object sender, EventArgs e) { FlashBlocks.Clear(); PresentRows(); } // debug stub, not intended for direct execution private void SetSessionStub(ECUConnection Connection) { return; Console.WriteLine("Entering bootmode"); Connection.SendMessage(BitUtility.BytesFromHex("1002")); Console.WriteLine("Requesting for seed"); byte[] seed = Connection.SendMessage(BitUtility.BytesFromHex("2705")); SecurityAccess.SecurityAutoLogin.QueryUnlockEcu(seed.Skip(2).ToArray(), "X_4", 5, out byte[] key); Console.Write("Authenticating for bootmode.. "); List keyResponse = new List(new byte[] { 0x27, 0x06 }); keyResponse.AddRange(key); byte[] authResponse = Connection.SendMessage(keyResponse); Console.WriteLine(BitUtility.BytesToHex(authResponse)); // remind myself to write fingerprint Console.WriteLine($"2EF15A 00 0004 150213 00000000\r\n2EF15A 01 0004 150213 00000000\r\n3101FF00"); /* int blockId = 1; // block0: CODE, block1: DATA Console.WriteLine($"Writing fingerprint"); // 2e f1 5a 00 00 04 15 02 16 00 00 00 00 Connection.SendMessage(BitUtility.BytesFromHex($"2EF15A {blockId:X2} 0004 150213 00000000")); // 2EF15A 00 0004 150213 00000000 // 2EF15A 01 0004 150213 00000000 Console.WriteLine($"Erasing block {blockId}"); Connection.SendMessage(BitUtility.BytesFromHex("3101FF00")); Console.WriteLine("Ready to accept flash data"); */ } private void btnExportAsMono_Click(object sender, EventArgs e) { // fixme: buffer allocation // on a good day, the base is 0, however if it's significantly offset, this won't work out of the box // button is currently set as invisible until this is properly fixed byte[] finalBuffer = new byte[0x200000]; foreach (FlashBlock b in FlashBlocks) { Array.ConstrainedCopy(b.Payload, 0, finalBuffer, (int)b.Address, b.Payload.Length); } SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your BIN file"; sfd.Filter = "BIN files (*.bin)|*.bin|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, finalBuffer); } } } public class FlashBlock { public string Path; public byte[] Payload; public uint Address; } } ================================================ FILE: Caesar/Diogenes/Forms/BlockDownload.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAnqNw3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAKaze1Sep3OklptsMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACuv3wwtrt//K6ve/yWm24oAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6/fz0+85/9Muub/Jqfc7SSk2xcAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArr9//hNPy/1W95/8uqt7/JKTbkAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALbLgwHDM7v+D0vL/fs7x/0q2 5P8kpdvxIqLaFwAAAAAAAAAAAAAAAAAAAAA4wufwNsDm+DW95fgzu+T4Mbjj+C+24viG1/P/L7br/0q8 7P+AzvH/Ubnm/yyo3f8jotqdAAAAAAAAAAAAAAAAOsTo6XXa8v+T5vj/keP3/43g9v+K3PX/itv1/4jX 9P+E0/L/f8/x/3zM8P96ye//SLTj/yOj2vUgntgjAAAAADvH6TdPzez/mOn5/0rV8/9Fz/H/QMrw/zjC 7v+J2fT/LrTh/iyx4Pgrrt/4Kaze+Cep3Pglptv4I6Pa6QAAAAAAAAAAO8fp9IDh9f+O5vj/Q9Lz/z/N 8f85x+//jNz1/1jG6v8utOF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3J6lRb1O//mer5/0fW 9P9C0PL/Pcvw/27V8/9/1/P/SsDn/y+04UoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPcrq+ZPp +f9y4ff/RdTz/0HO8v88yfD/itz1/3DQ7/89u+T/L7XhIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/M 64Nk2fH/muv6/0jY9P9E0/P/P87x/zrI8P+M3PX/Ysvt/zG44/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAP8zr/Zrt+v+Z6/n/l+j5/5Tl+P+R4vf/jt/2/4vb9f9Wx+v/Mbjj8wAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAEDO7KI/zOv/Psvq/zzJ6f87x+n/OsTo/zjC5/82wOb/Nb3l/zO75P8xuOPhAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA7/8AAOP/AADh/wAA8H8AAPg/AAD4DwAAAAcAAAABAAAAAQAAgD8AAIAfAADADwAAwA8AAOAH AADgAwAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/DTCForm.Designer.cs ================================================  namespace Diogenes { partial class DTCForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DTCForm)); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.dgvContext = new System.Windows.Forms.DataGridView(); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportDTCsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dTCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.clearSelectedDTCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.clearAllDTCsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.refreshDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.viewAllAvailableDTCsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.dgvContext)).BeginInit(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 24); this.splitContainer1.Name = "splitContainer1"; this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitContainer1.Panel1 // this.splitContainer1.Panel1.Controls.Add(this.dgvMain); // // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.dgvContext); this.splitContainer1.Size = new System.Drawing.Size(1490, 735); this.splitContainer1.SplitterDistance = 224; this.splitContainer1.TabIndex = 0; // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.Dock = System.Windows.Forms.DockStyle.Fill; this.dgvMain.Location = new System.Drawing.Point(0, 0); this.dgvMain.MultiSelect = false; this.dgvMain.Name = "dgvMain"; this.dgvMain.ReadOnly = true; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(1490, 224); this.dgvMain.TabIndex = 1; this.dgvMain.SelectionChanged += new System.EventHandler(this.dgvMain_SelectionChanged); // // dgvContext // this.dgvContext.AllowUserToAddRows = false; this.dgvContext.AllowUserToDeleteRows = false; this.dgvContext.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvContext.Dock = System.Windows.Forms.DockStyle.Fill; this.dgvContext.Location = new System.Drawing.Point(0, 0); this.dgvContext.Name = "dgvContext"; this.dgvContext.ReadOnly = true; this.dgvContext.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvContext.ShowEditingIcon = false; this.dgvContext.Size = new System.Drawing.Size(1490, 507); this.dgvContext.TabIndex = 2; // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.dTCToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; this.menuStrip1.Size = new System.Drawing.Size(1490, 24); this.menuStrip1.TabIndex = 1; this.menuStrip1.Text = "menuStrip1"; // // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.exportDTCsToolStripMenuItem, this.viewAllAvailableDTCsToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // // exportDTCsToolStripMenuItem // this.exportDTCsToolStripMenuItem.Name = "exportDTCsToolStripMenuItem"; this.exportDTCsToolStripMenuItem.Size = new System.Drawing.Size(192, 22); this.exportDTCsToolStripMenuItem.Text = "Export DTCs"; this.exportDTCsToolStripMenuItem.Click += new System.EventHandler(this.exportDTCsToolStripMenuItem_Click); // // dTCToolStripMenuItem // this.dTCToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.clearSelectedDTCToolStripMenuItem, this.clearAllDTCsToolStripMenuItem, this.refreshDataToolStripMenuItem}); this.dTCToolStripMenuItem.Name = "dTCToolStripMenuItem"; this.dTCToolStripMenuItem.Size = new System.Drawing.Size(40, 20); this.dTCToolStripMenuItem.Text = "DTC"; // // clearSelectedDTCToolStripMenuItem // this.clearSelectedDTCToolStripMenuItem.Name = "clearSelectedDTCToolStripMenuItem"; this.clearSelectedDTCToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.clearSelectedDTCToolStripMenuItem.Text = "Clear Selected DTC"; this.clearSelectedDTCToolStripMenuItem.Click += new System.EventHandler(this.clearSelectedDTCToolStripMenuItem_Click); // // clearAllDTCsToolStripMenuItem // this.clearAllDTCsToolStripMenuItem.Name = "clearAllDTCsToolStripMenuItem"; this.clearAllDTCsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.clearAllDTCsToolStripMenuItem.Text = "Clear All DTCs"; this.clearAllDTCsToolStripMenuItem.Click += new System.EventHandler(this.clearAllDTCsToolStripMenuItem_Click); // // refreshDataToolStripMenuItem // this.refreshDataToolStripMenuItem.Name = "refreshDataToolStripMenuItem"; this.refreshDataToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.refreshDataToolStripMenuItem.Text = "Refresh Data"; this.refreshDataToolStripMenuItem.Click += new System.EventHandler(this.refreshDataToolStripMenuItem_Click); // // viewAllAvailableDTCsToolStripMenuItem // this.viewAllAvailableDTCsToolStripMenuItem.Name = "viewAllAvailableDTCsToolStripMenuItem"; this.viewAllAvailableDTCsToolStripMenuItem.Size = new System.Drawing.Size(192, 22); this.viewAllAvailableDTCsToolStripMenuItem.Text = "View all available DTCs"; this.viewAllAvailableDTCsToolStripMenuItem.Click += new System.EventHandler(this.viewAllAvailableDTCsToolStripMenuItem_Click); // // DTCForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1490, 759); this.Controls.Add(this.splitContainer1); this.Controls.Add(this.menuStrip1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MainMenuStrip = this.menuStrip1; this.Name = "DTCForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Diagnostic Trouble Codes"; this.Load += new System.EventHandler(this.DTCForm_Load); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.dgvContext)).EndInit(); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportDTCsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem dTCToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem clearSelectedDTCToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem clearAllDTCsToolStripMenuItem; private System.Windows.Forms.DataGridView dgvContext; private System.Windows.Forms.ToolStripMenuItem refreshDataToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem viewAllAvailableDTCsToolStripMenuItem; } } ================================================ FILE: Caesar/Diogenes/Forms/DTCForm.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static Caesar.DTC; namespace Diogenes { public partial class DTCForm : Form { ECUConnection Connection; ECUVariant Variant; //List> DisplayedDTCs; List DTCContexts = new List(); public DTCForm(ECUConnection connection, ECUVariant variant) { Connection = connection; Variant = variant; InitializeComponent(); } private void DTCForm_Load(object sender, EventArgs e) { EnableDoubleBuffer(dgvMain, true); EnableDoubleBuffer(dgvContext, true); QueryDTC(); PresentDtcData(); } private void PresentDtcData() { if (DTCContexts.Count == 0) { MessageBox.Show("ECU reports zero Diagnostic Trouble Codes", "No DTCs"); } PresentDTCs(); PresentEnvironmentContext(); } private void QueryDTC() { GenericLoader loader = new GenericLoader(); loader.Text = "Querying DTCs"; loader.Show(); Application.DoEvents(); // fetch the base dtc value first DTCContexts = Connection.ConnectionProtocol.ReportDtcsByStatusMask(Connection, Variant); loader.SetProgressMax(DTCContexts.Count); Application.DoEvents(); // query individual dtcs to retrieve the environment context for (int j = 0; j < DTCContexts.Count; j++) { DTCContext dtcCtx = DTCContexts[j]; loader.Text = $"Querying DTC {dtcCtx.DTC.Qualifier} [{j + 1}/{DTCContexts.Count}]"; loader.SetProgressValue(j); Application.DoEvents(); if (!Connection.ConnectionProtocol.GetDtcSnapshot(dtcCtx.DTC, Connection, out byte[] snapshot)) { dtcCtx.EnvironmentContext = new List(); dtcCtx.EnvironmentContext.Add(new string[] { "N/A", "N/A" }); continue; } List dtcEnvs = Variant.GetEnvironmentContextsForDTC(dtcCtx.DTC); List envCtx = new List(); for (int i = 0; i < dtcEnvs.Count; i++) { DiagService currentService = dtcEnvs[i]; StringBuilder presentationOutput = new StringBuilder(); foreach (List wtf in currentService.OutputPreparations) { foreach (DiagPreparation outputPreparation in wtf) { /* // crd3: uncomment to find a misbehaving presentation; enum does not have the correct scales, maybe there's something shaped like a scale that needs parsing if (currentService.GetName().Contains("ufigkeitsz")) { Console.WriteLine("dbg"); } */ DiagPresentation presentation = outputPreparation.ParentECU.GlobalPresentations[outputPreparation.PresPoolIndex]; #if DEBUG // way too verbose /* if (false) { presentationOutput.Append($"Position: {outputPreparation.BitPosition}, BitWidth: {outputPreparation.SizeInBits}, "); presentationOutput.Append($"\r\n{ presentation.CopyMinDebug()}\r\n"); } */ #endif presentationOutput.Append(presentation.InterpretData(snapshot, outputPreparation, false)); } } envCtx.Add(new string[] { currentService.GetName(), presentationOutput.ToString() }); } dtcCtx.EnvironmentContext = envCtx; } loader.Close(); } private void PresentDTCs() { string[] Headers = new string[] { "Code", "Description", "Status", "Current", "Stored", "MIL On", "Failed: Request Time", "Failed: Current Cycle", "Failed: Last Clear", "Incomplete: Current Cycle", "Incomplete: Last Clear" }; DataTable dt = new DataTable(); dt.Columns.Add("Index", typeof(int)); foreach (string header in Headers) { dt.Columns.Add(header, typeof(String)); } dgvMain.DataSource = dt; for (int i = 0; i < DTCContexts.Count; i++) { List row = new List(); DTC currentDtc = DTCContexts[i].DTC; byte statusByte = DTCContexts[i].StatusByte; bool dtcStatusIsCurrent = (statusByte & (int)DTCStatusByte.PendingDTC) > 0; bool dtcStatusIsStored = (statusByte & (int)DTCStatusByte.ConfirmedDTC) > 0; bool dtcStatusIsMILActive = (statusByte & (int)DTCStatusByte.WarningIndicatorActive) > 0; bool dtcStatusFailedAtRequestTime = (statusByte & (int)DTCStatusByte.TestFailedAtRequestTime) > 0; bool dtcStatusFailedAtCurrentCycle = (statusByte & (int)DTCStatusByte.TestFailedAtCurrentCycle) > 0; bool dtcStatusFailedSinceLastClear = (statusByte & (int)DTCStatusByte.TestFailedSinceLastClear) > 0; bool dtcStatusIncompleteAtCurrentCycle = (statusByte & (int)DTCStatusByte.TestIncompleteAtCurrentCycle) > 0; bool dtcStatusIncompleteSinceLastClear = (statusByte & (int)DTCStatusByte.TestIncompleteSinceLastClear) > 0; row.Add(currentDtc.Qualifier); row.Add(currentDtc.Description); row.Add($"{statusByte:X2}"); row.Add($"{dtcStatusIsCurrent}"); row.Add($"{dtcStatusIsStored}"); row.Add($"{dtcStatusIsMILActive}"); row.Add($"{dtcStatusFailedAtRequestTime}"); row.Add($"{dtcStatusFailedAtCurrentCycle}"); row.Add($"{dtcStatusFailedSinceLastClear}"); row.Add($"{dtcStatusIncompleteAtCurrentCycle}"); row.Add($"{dtcStatusIncompleteSinceLastClear}"); row.Insert(0, i.ToString()); dt.Rows.Add(row.ToArray()); } for (int i = 3; i < Headers.Length; i++) { dgvMain.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; } dgvMain.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.None; dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // was Fill, dgvMain.Columns[0].Visible = false; } private void PresentEnvironmentContext() { if (dgvMain.SelectedRows.Count != 1) { return; } int selectedIndex = int.Parse(dgvMain.SelectedRows[0].Cells[0].Value.ToString()); List envCtx = DTCContexts[selectedIndex].EnvironmentContext; string[] Headers = new string[] { "Environment", "Description" }; DataTable dt = new DataTable(); dt.Columns.Add("Index", typeof(int)); foreach (string header in Headers) { dt.Columns.Add(header, typeof(String)); } dgvContext.DataSource = dt; for (int i = 0; i < envCtx.Count; i++) { List row = new List(); row.Insert(0, i.ToString()); row.AddRange(envCtx[i]); dt.Rows.Add(row.ToArray()); } dgvContext.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.None; dgvContext.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvContext.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvContext.Columns[2].DefaultCellStyle.WrapMode = DataGridViewTriState.True; dgvContext.AutoResizeRows(); dgvContext.Columns[0].Visible = false; } public static void EnableDoubleBuffer(DataGridView dgv, bool setting) { Type dgvType = dgv.GetType(); PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); pi.SetValue(dgv, setting, null); } private void clearAllDTCsToolStripMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show($"Clear all DTCs?", "Confirm DTC Clear", MessageBoxButtons.YesNo) == DialogResult.Yes) { ClearAllDTCs(); } } private void clearSelectedDTCToolStripMenuItem_Click(object sender, EventArgs e) { if (dgvMain.SelectedRows.Count == 1) { int selectedIndex = int.Parse(dgvMain.SelectedRows[0].Cells[0].Value.ToString()); DTC selectedDtc = DTCContexts[selectedIndex].DTC; if (MessageBox.Show($"Clear {selectedDtc.Qualifier}?", "Confirm DTC Clear", MessageBoxButtons.YesNo) == DialogResult.Yes) { ClearDTC(selectedDtc); } } } private void ClearAllDTCs() { byte[] request = new byte[] { 0x14, 0xFF, 0xFF, 0xFF }; // essentially ClearDTC a mask of FFFFFF byte[] expectedResponse = new byte[] { 0x59 }; byte[] response = Connection.SendMessage(request); if (!(response.Take(expectedResponse.Length).SequenceEqual(expectedResponse))) { MessageBox.Show($"Clear request (for all DTCs) was rejected", "Negative Response"); } else { QueryDTC(); PresentDtcData(); } } private void ClearDTC(DTC dtc) { if (dtc.Qualifier.Length != 7) { MessageBox.Show("Internal error: DTC qualifier is invalid, exiting prematurely."); return; } byte[] identifier = BitUtility.BytesFromHex(dtc.Qualifier.Substring(1)); byte[] request = new byte[] { 0x14, identifier[0], identifier[1], identifier[2] }; byte[] expectedResponse = new byte[] { 0x59 }; byte[] response = Connection.SendMessage(request); if (!(response.Take(expectedResponse.Length).SequenceEqual(expectedResponse))) { MessageBox.Show($"Clear request ({dtc.Qualifier}) was rejected", "Negative Response"); } else { QueryDTC(); PresentDtcData(); } } private void refreshDataToolStripMenuItem_Click(object sender, EventArgs e) { QueryDTC(); PresentDtcData(); } private void dgvMain_SelectionChanged(object sender, EventArgs e) { PresentEnvironmentContext(); } private void exportDTCsToolStripMenuItem_Click(object sender, EventArgs e) { DTCReport.CreateDTCReport(DTCContexts, Connection, Variant); } private void viewAllAvailableDTCsToolStripMenuItem_Click(object sender, EventArgs e) { List rows = new List(); foreach (DTC dtc in Variant.DTCs) { rows.Add(new string[] { dtc.Qualifier, dtc.Description }); } GenericPicker picker = new GenericPicker(rows.ToArray(), new string[] { "Identifier", "Description" }, 0, true); picker.Text = $"All DTCs for {Variant.Qualifier}"; picker.Show(); } } public class DTCContext { public DTC DTC; public byte StatusByte; public List EnvironmentContext; } } ================================================ FILE: Caesar/Diogenes/Forms/DTCForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAADKKxewwh8T2L4XD9i2DwvYrgcH2KX/A9ih9v/Yme772JXm99iN3 vfYidrzDAAAAAAAAAAAAAAAAAAAAAAAAAAA4kcnk3ez2/73u+f+s6vj/q+r4/6vq+P+r6vj/rer4/9Tz +/+kyOT/Jnu+qwAAAAAAAAAAAAAAAAAAAAAAAAAAP5nNa47C4f+X6Pn/Ydz2/1vb9f8yiML/W9v1/2re 9v+x5/b/LYPC6SuBwSqmpqa3oKCg/5qamv+Tk5P/jY2N/4SHiP9PmL//q9vv/3Tg9/9Y2vX/WNr1/13b 9f+Q5vj/ksHh/0dyj/9aWlq3rq6u/+np6f/T09P/0tLS/9HR0f/Q0ND/qMPP/3u93/+i6vn/Ydz2/zGH wv934ff/tt7w/1Gcyv/Z3uH/W1tb/7W1tf/W1tb/u7u7/7m5uf+2trb/tLS0/7Gysv9xrcj/rNns/4Lj +P8ziML/rO36/0Oez/+Go7T/yMjI/19fX/+8vLz/2dnZ/76+vv+7u7v/jo6O/4+Pj/+QkJD/hpWc/1Wt 0v+06/j/jub4/7Xd7v9mp8f/p6mq/8rKyv9kZGT/w8PD/93d3f/CwsL/vr6+/5GRkf+SkpL/lJSU/5SU lP91pLf/pNfr/9z0+/9VrdL/ma22/62trf/Pz8//aWlp/8nJyb3d3d3/yMjI/8HBwf/AwMD/vr6+/7u7 u/+5ubn/s7i6/2i51/+r2+3/f7TI/7CwsP+0tLT/wMDA/29vb73Pz8+96Ojo/+fn5//h4eH/4ODg/+Dg 4P/f39//39/f/97e3v+z097/eMTe/9HZ3P/b29v/4ODg/83Nzf91dXW909PTP9nZ2f/s7Oz/3t7e/9jY 2P/S0tL/zMzM/8jIyP/Hx8f/yMjI/8vLy//Q0ND/3d3d/+jo6P+goKD/fHx8QgAAAADU1NS96Ojo/9vb 2//i4uL/4uLi/+Hh4f/g4OD/4ODg/+Dg4P/f39//w8PD/9HR0f/S0tL/ioqKvQAAAAAAAAAA2NjYP97e 3v/z8/P/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7Ozs/+zs7P/x8fH/sbGx/5KSkkIAAAAAAAAAAAAA AADY2Ni91dXV/9LS0v/Ozs7/ycnJ/8TExP+/v7//ubm5/7Ozs/+tra3/pqam/6CgoL0AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAgAEAAMAD AAD//wAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/FlashSplicer.Designer.cs ================================================  namespace Diogenes { partial class FlashSplicer { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FlashSplicer)); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.openCFFFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportSplicedFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.txtLog = new System.Windows.Forms.TextBox(); this.menuStrip1.SuspendLayout(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.groupBox2.SuspendLayout(); this.SuspendLayout(); // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.Size = new System.Drawing.Size(991, 24); this.menuStrip1.TabIndex = 0; this.menuStrip1.Text = "menuStrip1"; // // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.openCFFFileToolStripMenuItem, this.exportSplicedFileToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // // openCFFFileToolStripMenuItem // this.openCFFFileToolStripMenuItem.Name = "openCFFFileToolStripMenuItem"; this.openCFFFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); this.openCFFFileToolStripMenuItem.Size = new System.Drawing.Size(209, 22); this.openCFFFileToolStripMenuItem.Text = "Open CFF File"; this.openCFFFileToolStripMenuItem.Click += new System.EventHandler(this.openCFFFileToolStripMenuItem_Click); // // exportSplicedFileToolStripMenuItem // this.exportSplicedFileToolStripMenuItem.Name = "exportSplicedFileToolStripMenuItem"; this.exportSplicedFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); this.exportSplicedFileToolStripMenuItem.Size = new System.Drawing.Size(209, 22); this.exportSplicedFileToolStripMenuItem.Text = "Export Spliced File"; this.exportSplicedFileToolStripMenuItem.Click += new System.EventHandler(this.exportSplicedFileToolStripMenuItem_Click); // // groupBox1 // this.groupBox1.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.groupBox1.Controls.Add(this.dgvMain); this.groupBox1.Location = new System.Drawing.Point(12, 288); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(967, 228); this.groupBox1.TabIndex = 1; this.groupBox1.TabStop = false; this.groupBox1.Text = "Flash Payload"; // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.Dock = System.Windows.Forms.DockStyle.Fill; this.dgvMain.Location = new System.Drawing.Point(3, 16); this.dgvMain.MultiSelect = false; this.dgvMain.Name = "dgvMain"; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(961, 209); this.dgvMain.TabIndex = 1; this.dgvMain.CellBeginEdit += new System.Windows.Forms.DataGridViewCellCancelEventHandler(this.dgvMain_CellBeginEdit); // // groupBox2 // this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupBox2.Controls.Add(this.txtLog); this.groupBox2.Location = new System.Drawing.Point(12, 27); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(964, 255); this.groupBox2.TabIndex = 2; this.groupBox2.TabStop = false; this.groupBox2.Text = "CFF Description"; // // txtLog // this.txtLog.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.txtLog.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtLog.Location = new System.Drawing.Point(6, 19); this.txtLog.Multiline = true; this.txtLog.Name = "txtLog"; this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtLog.Size = new System.Drawing.Size(952, 230); this.txtLog.TabIndex = 0; // // FlashSplicer // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(991, 528); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.menuStrip1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MainMenuStrip = this.menuStrip1; this.Name = "FlashSplicer"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Flash Splicer"; this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.groupBox1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem openCFFFileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportSplicedFileToolStripMenuItem; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.TextBox txtLog; } } ================================================ FILE: Caesar/Diogenes/Forms/FlashSplicer.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public partial class FlashSplicer : Form { List> FlashData = new List>(); CaesarFlashContainer FlashContainer = null; List> SplicePath = new List>(); List> MappedAddresses = new List>(); byte[] FlashBytes = new byte[] { }; public FlashSplicer() { InitializeComponent(); } private void openCFFFileToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a CFF File"; ofd.Filter = "CFF files (*.cff)|*.cff|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { LoadCFF(ofd.FileName); PresentRows(); } } public void LoadCFF(string filePath) { string directory = Path.GetDirectoryName(filePath); FlashBytes = File.ReadAllBytes(filePath); FlashContainer = new CaesarFlashContainer(FlashBytes); FlashData = new List>(); SplicePath = new List>(); MappedAddresses = new List>(); using (BinaryReader reader = new BinaryReader(new MemoryStream(FlashBytes))) { foreach (FlashDataBlock db in FlashContainer.CaesarFlashHeader.DataBlocks) { long fileCursor = 0; List segmentChunks = new List(); List spliceStub = new List(); List mapStub = new List(); foreach (FlashSegment seg in db.FlashSegments) { long offset = db.FlashData + FlashContainer.CaesarFlashHeader.CffHeaderSize + FlashContainer.CaesarFlashHeader.LanguageBlockLength + fileCursor + 0x414; fileCursor += seg.SegmentLength; reader.BaseStream.Seek(offset, SeekOrigin.Begin); byte[] fileBytes = reader.ReadBytes(seg.SegmentLength); segmentChunks.Add(fileBytes); spliceStub.Add(""); mapStub.Add(seg.FromAddress); } FlashData.Add(segmentChunks); SplicePath.Add(spliceStub); MappedAddresses.Add(mapStub); } } txtLog.Text = GetLog(); } private string GetLog() { FlashHeader header = FlashContainer.CaesarFlashHeader; StringBuilder response = new StringBuilder(); response.Append($"Name\t\t\t: {header.FlashName}\r\n" + $"Author\t\t\t: {header.FileAuthor}\r\n" + $"Creation Time\t\t: {header.FileCreationTime}\r\n" + $"Authoring Tool Version\t: {header.AuthoringToolVersion}\r\n" + $"Trafo Version\t\t: {header.FTRAFOVersionString}\r\n" + $"CFF Version\t\t: {header.CFFVersionString}\r\n" + $"Referenced ECU count\t: {header.NumberOfECURefs}\r\n" + $"Generation Parameter:\n {header.FlashGenerationParams}\r\n" + $"\r\n---------------------\r\n"); foreach (var blocks in FlashContainer.CaesarFlashHeader.DataBlocks) { response.Append($"\r\nFlash block: {blocks.Qualifier}"); for (int secIndex = 0; secIndex < blocks.FlashSecurities.Count; secIndex++) { var sec = blocks.FlashSecurities[secIndex]; response.Append($"\r\n\r\nSecurity [{secIndex}]"); if (sec.MethodValue.Length > 0) { response.Append($"\r\n - Method : {BitUtility.BytesToHex(sec.MethodValue)}"); } if (sec.SignatureValue.Length > 0) { response.Append($"\r\n - Signature : {BitUtility.BytesToHex(sec.SignatureValue)}"); } if (sec.ChecksumValue.Length > 0) { response.Append($"\r\n - Checksum : {BitUtility.BytesToHex(sec.ChecksumValue)}"); } if (sec.EcuKeyValue.Length > 0) { response.Append($"\r\n - ECU : {BitUtility.BytesToHex(sec.EcuKeyValue)}"); } } } return response.ToString(); } private void PresentRows() { if (FlashContainer is null) { return; } DataTable dt = new DataTable(); foreach (string header in new string[] { "Block #", "Block Name", "Block Description", "Segment #", "Segment Name", "ECU Target Address (Editable)", "Original Length", "Original Offset", "Splice Mode"}) { dt.Columns.Add(header, typeof(string)); } dgvMain.DataSource = dt; for (int i = 0; i < FlashContainer.CaesarFlashHeader.DataBlocks.Count; i++) { FlashDataBlock db = FlashContainer.CaesarFlashHeader.DataBlocks[i]; long fileCursor = 0; for (int j = 0; j < db.FlashSegments.Count; j++) { FlashSegment seg = db.FlashSegments[j]; long offset = db.FlashData + FlashContainer.CaesarFlashHeader.CffHeaderSize + FlashContainer.CaesarFlashHeader.LanguageBlockLength + fileCursor + 0x414; fileCursor += seg.SegmentLength; // Console.WriteLine($"Segment: {seg.SegmentName} mapped to 0x{seg.FromAddress:X} with size 0x{seg.SegmentLength:X}"); string spliceModeForRow = SplicePath[i][j].Length == 0 ? "Inherit Original" : SplicePath[i][j]; dt.Rows.Add( i.ToString(), db.Qualifier, FlashContainer.CaesarCTFHeader.CtfLanguages[0].GetString(db.Description), j.ToString(), seg.SegmentName, seg.FromAddress.ToString("X"), seg.SegmentLength.ToString("X"), offset.ToString("X"), spliceModeForRow ); } } dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[0].ReadOnly = true; dgvMain.Columns[1].ReadOnly = true; dgvMain.Columns[2].ReadOnly = true; dgvMain.Columns[3].ReadOnly = true; dgvMain.Columns[4].ReadOnly = true; dgvMain.Columns[5].ReadOnly = false; dgvMain.Columns[6].ReadOnly = true; dgvMain.Columns[7].ReadOnly = true; dgvMain.Columns[8].ReadOnly = false; dgvMain.Columns[dgvMain.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; } private void GenericPicker_Load(object sender, EventArgs e) { PresentRows(); } private void dgvMain_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) { if ((e.RowIndex < 0) || (e.RowIndex > dgvMain.Rows.Count)) { return; } if (e.ColumnIndex == (dgvMain.Columns.Count - 1)) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a replacement binary file"; ofd.Filter = "BIN files (*.bin)|*.bin|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { int blockIndex = int.Parse(dgvMain.Rows[e.RowIndex].Cells[0].Value.ToString()); int segmentIndex = int.Parse(dgvMain.Rows[e.RowIndex].Cells[3].Value.ToString()); SplicePath[blockIndex][segmentIndex] = ofd.FileName; PresentRows(); } e.Cancel = true; } } private void exportSplicedFileToolStripMenuItem_Click(object sender, EventArgs e) { if (FlashContainer is null) { return; } if (!LoadMappedAddresses()) { return; } /* we need to.. - get the fileoffsets of the segment sizes - get the fileoffsets of the segment addresses - get the fileoffset of the flash start address - patch all the fileoffsets (size+address) with the new value */ int flashDataFileOffset = FlashContainer.CaesarFlashHeader.CffHeaderSize + FlashContainer.CaesarFlashHeader.LanguageBlockLength + 0x414; byte[] nonFlashData = FlashBytes.Take(flashDataFileOffset).ToArray(); using (BinaryReader reader = new BinaryReader(new MemoryStream(FlashBytes, 0, FlashBytes.Length, false, true))) using (BinaryWriter nonFlashWriter = new BinaryWriter(new MemoryStream(nonFlashData))) using (BinaryWriter flashPayloadWriter = new BinaryWriter(new MemoryStream())) { int segmentCursor = 0; for (int i = 0; i < FlashContainer.CaesarFlashHeader.DataBlocks.Count; i++) { FlashDataBlock db = FlashContainer.CaesarFlashHeader.DataBlocks[i]; // read block offset fileoffset long blockOffsetFileOffset = db.GetFlashDataOffset(reader); // patch segment length on filebytes nonFlashWriter.BaseStream.Seek(blockOffsetFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentCursor); int localBlockLength = 0; for (int j = 0; j < db.FlashSegments.Count; j++) { FlashSegment seg = db.FlashSegments[j]; // check: which fields are mutable when splicing long offset = db.FlashData + // somewhat mutable : probably if there's more than 1 datablock, this value will be nonzero FlashContainer.CaesarFlashHeader.CffHeaderSize + // constant FlashContainer.CaesarFlashHeader.LanguageBlockLength + // constant segmentCursor + // mutable, see below 0x414; // constant byte[] segmentPayload = FlashData[i][j]; if (SplicePath[i][j].Length > 0) { segmentPayload = File.ReadAllBytes(SplicePath[i][j]); } int segmentMappedAddress = MappedAddresses[i][j]; // read segment length's offset long segmentLengthFileOffset = seg.GetSegmentLengthFileOffset(reader); // read segment's mapped address long segmentMappedAddressFileOffset = seg.GetMappedAddressFileOffset(reader); // patch segment length on filebytes nonFlashWriter.BaseStream.Seek(segmentLengthFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentPayload.Length); // patch segment's mapped address nonFlashWriter.BaseStream.Seek(segmentMappedAddressFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(segmentMappedAddress); // increment segment offset for db.flashdata segmentCursor += segmentPayload.Length; localBlockLength += segmentPayload.Length; // append flash payload to temp buffer flashPayloadWriter.Write(segmentPayload); } // refresh the block size // read block size fileoffset long blockSizeFileOffset = db.GetBlockLengthOffset(reader); // patch block length nonFlashWriter.BaseStream.Seek(blockSizeFileOffset, SeekOrigin.Begin); nonFlashWriter.Write(localBlockLength); } // take the non-flash part of the bytes that we patched... // .. then merge it with the flash section that we rebuilt byte[] flashPayload = ((MemoryStream)flashPayloadWriter.BaseStream).ToArray(); byte[] nonFlashPrefix = ((MemoryStream)nonFlashWriter.BaseStream).ToArray(); byte[] result = new byte[flashPayload.Length + nonFlashPrefix.Length + 4]; Array.ConstrainedCopy(nonFlashPrefix, 0, result, 0, nonFlashPrefix.Length); Array.ConstrainedCopy(flashPayload, 0, result, nonFlashPrefix.Length, flashPayload.Length); // restore the checksum uint checksum = CaesarReader.ComputeFileChecksumLazy(result); result[result.Length - 4] = (byte)((checksum >> 0) & 0xFF); result[result.Length - 3] = (byte)((checksum >> 8) & 0xFF); result[result.Length - 2] = (byte)((checksum >> 16) & 0xFF); result[result.Length - 1] = (byte)((checksum >> 24) & 0xFF); // save the result SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new CFF file"; sfd.Filter = "CFF files (*.cff)|*.cff|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, result); } } } private bool LoadMappedAddresses() { for (int i = 0; i < dgvMain.Rows.Count; i++) { int blockIndex = int.Parse(dgvMain.Rows[i].Cells[0].Value.ToString()); int segmentIndex = int.Parse(dgvMain.Rows[i].Cells[3].Value.ToString()); string inHexString = dgvMain.Rows[i].Cells[5].Value.ToString(); if (int.TryParse(inHexString, System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.InvariantCulture, out int result)) { MappedAddresses[blockIndex][segmentIndex] = result; } else { MessageBox.Show($"Failed to parse a hex value: {inHexString}"); return false; } } return true; } } } ================================================ FILE: Caesar/Diogenes/Forms/FlashSplicer.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAJabbLiKh2SwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACir3UklptvfIqLaUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAKlxUanDjmj/wItm/76IZP+7hWH/TqG8/0O14/9Tla//qH1g/655V/+tdlb/q3VU/6lz U/+pcVH/qXFRqQAAAADIkmz///////////////////////P7/f8xr9//Ubrm/zut3v+r2fD///////// /////////////6lyUf8AAAAAypRu//////+k4/T/kNvw/5La7/+M1u7/Pbfi/33Q8P9tx+z/RLLi/3PB 5P/f7/X//Pz5//////+qc1P/AAAAAMyXb///////Y9Hs/27Y8P9o0+//Zs/t/4TZ8/+I1/T/fc/x/1i8 6P9St+X/Ip3X/6XT6f/1+v3/rHVU/wAAAADRnHP//////9Tz+P9Jyer/kOb4/43j9/9g0vL/hNf0/zy3 4v+Gz+r/i8/p/4LK5/+QzOb/5fP6/7B6WP8AAAAA1J51///////6/fz/muLy/2vZ8f+W5/j/R8/y/4nc 9P84ueP/pNvs//v49P/79/L/+/Xy//////+yfFr/AAAAANWgdv///////f38/+X3+f9HzOv/k+f4/1/Y 9P+Q4Pb/fdby/1LD6f+q2+v/+vPv//jy7P//////tX5c/wAAAADYonn///////39+v/6+/r/jeDx/3Te 8/+J4/b/hd71/4HZ9P940/H/UMLo/67a5//07Oj//////7eBXv8AAAAA2aN5///////8+/n//Pv4/8ru 9P9d1Oz/WdHr/1fO6v9Vyuj/U8fn/07C5P9YwuP/3OHe//////+6hWD/AAAAANukev////////////// ////////////////////////////////////////////////////////vYdj/wAAAADcp3v/3Kd7/9yn e//cp3v/3Kd7/9yne//cp3v/3Kd7/9yne//cp3v/3Kd7/9yne//cp3v/3Kd7/8CLZv8AAAAA3ayF/ei5 kv/ouZL/6LmS/+i5kv/ouZL/6LmS/+i5kv/ouZL/6LmS/+i5kv/ouZL/6LmS/+i5kv/BkG/9AAAAAKlx UWvdsY303Kd7/9ymev/apHr/2KJ5/9Wgdv/UnnX/0p1z/8+acv/OmXD/y5Zv/8mUbP/Emnr0qXFRawAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA8/8AAPH/AAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAB AAAAAQAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/GenericLoader.Designer.cs ================================================  namespace Diogenes { partial class GenericLoader { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.SuspendLayout(); // // progressBar1 // this.progressBar1.Dock = System.Windows.Forms.DockStyle.Fill; this.progressBar1.Location = new System.Drawing.Point(0, 0); this.progressBar1.Name = "progressBar1"; this.progressBar1.Size = new System.Drawing.Size(658, 51); this.progressBar1.TabIndex = 0; // // GenericLoader // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(658, 51); this.ControlBox = false; this.Controls.Add(this.progressBar1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.Name = "GenericLoader"; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Loading.."; this.ResumeLayout(false); } #endregion private System.Windows.Forms.ProgressBar progressBar1; } } ================================================ FILE: Caesar/Diogenes/Forms/GenericLoader.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public partial class GenericLoader : Form { public GenericLoader() { InitializeComponent(); } public void SetProgressValue(int value) { progressBar1.Value = value; } public void SetProgressMax(int value) { progressBar1.Maximum = value; } } } ================================================ FILE: Caesar/Diogenes/Forms/GenericLoader.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: Caesar/Diogenes/Forms/GenericPicker.Designer.cs ================================================  namespace Diogenes { partial class GenericPicker { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.dgvMain = new System.Windows.Forms.DataGridView(); this.txtFilter = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.SuspendLayout(); // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.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.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.Location = new System.Drawing.Point(0, 20); this.dgvMain.MultiSelect = false; this.dgvMain.Name = "dgvMain"; this.dgvMain.ReadOnly = true; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(800, 430); this.dgvMain.TabIndex = 0; this.dgvMain.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvMain_CellDoubleClick); // // txtFilter // this.txtFilter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtFilter.Location = new System.Drawing.Point(0, 0); this.txtFilter.Name = "txtFilter"; this.txtFilter.Size = new System.Drawing.Size(800, 20); this.txtFilter.TabIndex = 3; this.txtFilter.TextChanged += new System.EventHandler(this.txtFilter_TextChanged); // // GenericPicker // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.txtFilter); this.Controls.Add(this.dgvMain); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; this.Name = "GenericPicker"; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Select an item.."; this.Load += new System.EventHandler(this.GenericPicker_Load); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.TextBox txtFilter; } } ================================================ FILE: Caesar/Diogenes/Forms/GenericPicker.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public partial class GenericPicker : Form { private string[][] Table; private string[] Headers; public string[] SelectedResult; public int SelectedRowIndex = -1; public int FilterColumnIndex; public GenericPicker(string[][] table, string[] headers, int filterColumn = 0, bool allowMultiSelect = false) { InitializeComponent(); Table = table; Headers = headers; FilterColumnIndex = filterColumn; dgvMain.MultiSelect = allowMultiSelect; } private void PresentRows() { DataTable dt = new DataTable(); string namePartialMatch = txtFilter.Text.ToLower(); dt.Columns.Add("Index", typeof(int)); foreach (string header in Headers) { dt.Columns.Add(header, typeof(String)); } dgvMain.DataSource = dt; for (int i = 0; i < Table.Length; i++) { if (Table[i][FilterColumnIndex].ToLower().Contains(namePartialMatch)) { List row = new List(Table[i]); row.Insert(0, i.ToString()); dt.Rows.Add(row.ToArray()); } } for (int i = 1; i < Headers.Length; i++) { dgvMain.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; } dgvMain.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.None; dgvMain.Columns[Headers.Length].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgvMain.Columns[0].Visible = false; } private void GenericPicker_Load(object sender, EventArgs e) { UnmanagedUtility.SendMessage(txtFilter.Handle, UnmanagedUtility.EM_SETCUEBANNER, 0, "Type here to filter results"); PresentRows(); } private void dgvMain_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (dgvMain.SelectedRows.Count == 1) { int selectedRowIndex = int.Parse(dgvMain.SelectedRows[0].Cells[0].Value.ToString()); SelectedResult = Table[selectedRowIndex]; SelectedRowIndex = selectedRowIndex; this.DialogResult = DialogResult.OK; this.Close(); } } private void txtFilter_TextChanged(object sender, EventArgs e) { PresentRows(); } } } ================================================ FILE: Caesar/Diogenes/Forms/GenericPicker.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: Caesar/Diogenes/Forms/MainForm.Designer.cs ================================================ namespace Diogenes { partial class MainForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.lblConnectionType = new System.Windows.Forms.ToolStripStatusLabel(); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.loadCBFFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.unloadExistingFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.loadCompressedJsonToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportContainerAsCompressedJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.loadJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportContainerAsJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.connectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.j2534InterfacesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.defaultJ2534InterfaceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.disconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.eCUToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.setSecurityLevelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.fixClientAccessPermissionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.cFFFlashSplicerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.cFFExportFlashSegmentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.uDSHexEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.diagnosticTroubleCodesDTCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.viewECUMetadataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); this.showTraceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.copyConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.clearConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.identifyECUToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dSCDebugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.genericDebugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.listVariantIDsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.downloadBlocksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.preferencesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.fingerprintModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.useLastFingerprintToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.customValueToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.sCNModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.useLastSCNToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.writeZerosVediamoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.allowWriteVariantCodingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.tvMain = new System.Windows.Forms.TreeView(); this.txtLog = new System.Windows.Forms.TextBox(); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.pbResourcePlaceholder = new System.Windows.Forms.PictureBox(); this.txtJ2534Input = new System.Windows.Forms.TextBox(); this.tmrBlinkConnectionMenu = new System.Windows.Forms.Timer(this.components); this.fixCBFChecksumToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.statusStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pbResourcePlaceholder)).BeginInit(); this.SuspendLayout(); // // statusStrip1 // this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.lblConnectionType}); this.statusStrip1.Location = new System.Drawing.Point(0, 706); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Size = new System.Drawing.Size(1123, 22); this.statusStrip1.TabIndex = 0; this.statusStrip1.Text = "statusStrip1"; // // lblConnectionType // this.lblConnectionType.Name = "lblConnectionType"; this.lblConnectionType.Size = new System.Drawing.Size(201, 17); this.lblConnectionType.Text = "No interface selected (Disconnected)"; // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.connectionToolStripMenuItem, this.eCUToolStripMenuItem, this.preferencesToolStripMenuItem1}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; this.menuStrip1.Size = new System.Drawing.Size(1123, 24); this.menuStrip1.TabIndex = 1; this.menuStrip1.Text = "menuStrip1"; // // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.loadCBFFilesToolStripMenuItem, this.unloadExistingFilesToolStripMenuItem, this.toolStripSeparator1, this.loadCompressedJsonToolStripMenuItem, this.exportContainerAsCompressedJSONToolStripMenuItem, this.loadJSONToolStripMenuItem, this.exportContainerAsJSONToolStripMenuItem, this.toolStripSeparator6, this.aboutToolStripMenuItem, this.toolStripSeparator2, this.exitToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // // loadCBFFilesToolStripMenuItem // this.loadCBFFilesToolStripMenuItem.Name = "loadCBFFilesToolStripMenuItem"; this.loadCBFFilesToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); this.loadCBFFilesToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.loadCBFFilesToolStripMenuItem.Text = "Load CBF Files"; this.loadCBFFilesToolStripMenuItem.Click += new System.EventHandler(this.loadCBFFilesToolStripMenuItem_Click); // // unloadExistingFilesToolStripMenuItem // this.unloadExistingFilesToolStripMenuItem.Name = "unloadExistingFilesToolStripMenuItem"; this.unloadExistingFilesToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.U))); this.unloadExistingFilesToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.unloadExistingFilesToolStripMenuItem.Text = "Unload Existing Files"; this.unloadExistingFilesToolStripMenuItem.Click += new System.EventHandler(this.unloadExistingFilesToolStripMenuItem_Click); // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; this.toolStripSeparator1.Size = new System.Drawing.Size(274, 6); // // loadCompressedJsonToolStripMenuItem // this.loadCompressedJsonToolStripMenuItem.Name = "loadCompressedJsonToolStripMenuItem"; this.loadCompressedJsonToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.loadCompressedJsonToolStripMenuItem.Text = "Load Compressed JSON"; this.loadCompressedJsonToolStripMenuItem.Click += new System.EventHandler(this.loadCompressedJsonToolStripMenuItem_Click); // // exportContainerAsCompressedJSONToolStripMenuItem // this.exportContainerAsCompressedJSONToolStripMenuItem.Name = "exportContainerAsCompressedJSONToolStripMenuItem"; this.exportContainerAsCompressedJSONToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.exportContainerAsCompressedJSONToolStripMenuItem.Text = "Export Container as Compressed JSON"; this.exportContainerAsCompressedJSONToolStripMenuItem.Click += new System.EventHandler(this.exportContainerAsCompressedJSONToolStripMenuItem_Click); // // loadJSONToolStripMenuItem // this.loadJSONToolStripMenuItem.Name = "loadJSONToolStripMenuItem"; this.loadJSONToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.loadJSONToolStripMenuItem.Text = "Load JSON"; this.loadJSONToolStripMenuItem.Click += new System.EventHandler(this.loadJSONToolStripMenuItem_Click); // // exportContainerAsJSONToolStripMenuItem // this.exportContainerAsJSONToolStripMenuItem.Name = "exportContainerAsJSONToolStripMenuItem"; this.exportContainerAsJSONToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.exportContainerAsJSONToolStripMenuItem.Text = "Export Container as JSON"; this.exportContainerAsJSONToolStripMenuItem.Click += new System.EventHandler(this.exportContainerAsJSONToolStripMenuItem_Click); // // toolStripSeparator6 // this.toolStripSeparator6.Name = "toolStripSeparator6"; this.toolStripSeparator6.Size = new System.Drawing.Size(274, 6); // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; this.aboutToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.aboutToolStripMenuItem.Text = "About.."; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; this.toolStripSeparator2.Size = new System.Drawing.Size(274, 6); // // exitToolStripMenuItem // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; this.exitToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.exitToolStripMenuItem.Text = "Exit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); // // connectionToolStripMenuItem // this.connectionToolStripMenuItem.BackColor = System.Drawing.SystemColors.Control; this.connectionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.j2534InterfacesToolStripMenuItem, this.disconnectToolStripMenuItem}); this.connectionToolStripMenuItem.ForeColor = System.Drawing.SystemColors.ControlText; this.connectionToolStripMenuItem.Name = "connectionToolStripMenuItem"; this.connectionToolStripMenuItem.Size = new System.Drawing.Size(81, 20); this.connectionToolStripMenuItem.Text = "Connection"; this.connectionToolStripMenuItem.DropDownOpening += new System.EventHandler(this.connectionToolStripMenuItem_DropDownOpening); // // j2534InterfacesToolStripMenuItem // this.j2534InterfacesToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.defaultJ2534InterfaceToolStripMenuItem}); this.j2534InterfacesToolStripMenuItem.Name = "j2534InterfacesToolStripMenuItem"; this.j2534InterfacesToolStripMenuItem.Size = new System.Drawing.Size(156, 22); this.j2534InterfacesToolStripMenuItem.Text = "J2534 Interfaces"; this.j2534InterfacesToolStripMenuItem.DropDownOpening += new System.EventHandler(this.j2534InterfacesToolStripMenuItem_DropDownOpening); // // defaultJ2534InterfaceToolStripMenuItem // this.defaultJ2534InterfaceToolStripMenuItem.Name = "defaultJ2534InterfaceToolStripMenuItem"; this.defaultJ2534InterfaceToolStripMenuItem.Size = new System.Drawing.Size(192, 22); this.defaultJ2534InterfaceToolStripMenuItem.Text = "Default J2534 Interface"; // // disconnectToolStripMenuItem // this.disconnectToolStripMenuItem.Name = "disconnectToolStripMenuItem"; this.disconnectToolStripMenuItem.Size = new System.Drawing.Size(156, 22); this.disconnectToolStripMenuItem.Text = "Disconnect"; this.disconnectToolStripMenuItem.Click += new System.EventHandler(this.disconnectToolStripMenuItem_Click); // // eCUToolStripMenuItem // this.eCUToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.setSecurityLevelToolStripMenuItem, this.fixClientAccessPermissionsToolStripMenuItem, this.toolStripSeparator4, this.cFFFlashSplicerToolStripMenuItem, this.cFFExportFlashSegmentsToolStripMenuItem, this.toolStripSeparator3, this.uDSHexEditorToolStripMenuItem, this.diagnosticTroubleCodesDTCToolStripMenuItem, this.viewECUMetadataToolStripMenuItem, this.toolStripSeparator5, this.showTraceToolStripMenuItem, this.copyConsoleToolStripMenuItem, this.clearConsoleToolStripMenuItem, this.identifyECUToolStripMenuItem, this.dSCDebugToolStripMenuItem, this.genericDebugToolStripMenuItem, this.listVariantIDsToolStripMenuItem, this.downloadBlocksToolStripMenuItem, this.fixCBFChecksumToolStripMenuItem}); this.eCUToolStripMenuItem.Name = "eCUToolStripMenuItem"; this.eCUToolStripMenuItem.Size = new System.Drawing.Size(46, 20); this.eCUToolStripMenuItem.Text = "Tools"; // // setSecurityLevelToolStripMenuItem // this.setSecurityLevelToolStripMenuItem.Name = "setSecurityLevelToolStripMenuItem"; this.setSecurityLevelToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.setSecurityLevelToolStripMenuItem.Text = "Set Security Level (DLL)"; this.setSecurityLevelToolStripMenuItem.Click += new System.EventHandler(this.setSecurityLevelToolStripMenuItem_Click); // // fixClientAccessPermissionsToolStripMenuItem // this.fixClientAccessPermissionsToolStripMenuItem.Name = "fixClientAccessPermissionsToolStripMenuItem"; this.fixClientAccessPermissionsToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.fixClientAccessPermissionsToolStripMenuItem.Text = "Fix Client Access Permissions"; this.fixClientAccessPermissionsToolStripMenuItem.Click += new System.EventHandler(this.fixClientAccessPermissionsToolStripMenuItem_Click); // // toolStripSeparator4 // this.toolStripSeparator4.Name = "toolStripSeparator4"; this.toolStripSeparator4.Size = new System.Drawing.Size(236, 6); // // cFFFlashSplicerToolStripMenuItem // this.cFFFlashSplicerToolStripMenuItem.Name = "cFFFlashSplicerToolStripMenuItem"; this.cFFFlashSplicerToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.cFFFlashSplicerToolStripMenuItem.Text = "CFF: Flash Splicer"; this.cFFFlashSplicerToolStripMenuItem.Click += new System.EventHandler(this.cFFFlashSplicerToolStripMenuItem_Click); // // cFFExportFlashSegmentsToolStripMenuItem // this.cFFExportFlashSegmentsToolStripMenuItem.Name = "cFFExportFlashSegmentsToolStripMenuItem"; this.cFFExportFlashSegmentsToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.cFFExportFlashSegmentsToolStripMenuItem.Text = "CFF: Export Flash Segments"; this.cFFExportFlashSegmentsToolStripMenuItem.Click += new System.EventHandler(this.cFFExportFlashSegmentsToolStripMenuItem_Click); // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; this.toolStripSeparator3.Size = new System.Drawing.Size(236, 6); // // uDSHexEditorToolStripMenuItem // this.uDSHexEditorToolStripMenuItem.Name = "uDSHexEditorToolStripMenuItem"; this.uDSHexEditorToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.uDSHexEditorToolStripMenuItem.Text = "UDS Hex Editor"; this.uDSHexEditorToolStripMenuItem.Click += new System.EventHandler(this.uDSHexEditorToolStripMenuItem_Click); // // diagnosticTroubleCodesDTCToolStripMenuItem // this.diagnosticTroubleCodesDTCToolStripMenuItem.Name = "diagnosticTroubleCodesDTCToolStripMenuItem"; this.diagnosticTroubleCodesDTCToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.diagnosticTroubleCodesDTCToolStripMenuItem.Text = "Diagnostic Trouble Codes (DTC)"; this.diagnosticTroubleCodesDTCToolStripMenuItem.Click += new System.EventHandler(this.diagnosticTroubleCodesDTCToolStripMenuItem_Click); // // viewECUMetadataToolStripMenuItem // this.viewECUMetadataToolStripMenuItem.Name = "viewECUMetadataToolStripMenuItem"; this.viewECUMetadataToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.viewECUMetadataToolStripMenuItem.Text = "View ECU Metadata"; this.viewECUMetadataToolStripMenuItem.Click += new System.EventHandler(this.viewECUMetadataToolStripMenuItem_Click); // // toolStripSeparator5 // this.toolStripSeparator5.Name = "toolStripSeparator5"; this.toolStripSeparator5.Size = new System.Drawing.Size(236, 6); // // showTraceToolStripMenuItem // this.showTraceToolStripMenuItem.Name = "showTraceToolStripMenuItem"; this.showTraceToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.Q))); this.showTraceToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.showTraceToolStripMenuItem.Text = "Show Trace"; this.showTraceToolStripMenuItem.Click += new System.EventHandler(this.showTraceToolStripMenuItem_Click); // // copyConsoleToolStripMenuItem // this.copyConsoleToolStripMenuItem.Name = "copyConsoleToolStripMenuItem"; this.copyConsoleToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.copyConsoleToolStripMenuItem.Text = "Copy Console"; this.copyConsoleToolStripMenuItem.Click += new System.EventHandler(this.copyConsoleToolStripMenuItem_Click); // // clearConsoleToolStripMenuItem // this.clearConsoleToolStripMenuItem.Name = "clearConsoleToolStripMenuItem"; this.clearConsoleToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.clearConsoleToolStripMenuItem.Text = "Clear Console"; this.clearConsoleToolStripMenuItem.Click += new System.EventHandler(this.clearConsoleToolStripMenuItem_Click); // // identifyECUToolStripMenuItem // this.identifyECUToolStripMenuItem.Name = "identifyECUToolStripMenuItem"; this.identifyECUToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.identifyECUToolStripMenuItem.Text = "Identify ECU"; this.identifyECUToolStripMenuItem.Visible = false; this.identifyECUToolStripMenuItem.Click += new System.EventHandler(this.identifyECUToolStripMenuItem_Click); // // dSCDebugToolStripMenuItem // this.dSCDebugToolStripMenuItem.Name = "dSCDebugToolStripMenuItem"; this.dSCDebugToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.dSCDebugToolStripMenuItem.Text = "DSC Debug"; this.dSCDebugToolStripMenuItem.Visible = false; this.dSCDebugToolStripMenuItem.Click += new System.EventHandler(this.dSCDebugToolStripMenuItem_Click); // // genericDebugToolStripMenuItem // this.genericDebugToolStripMenuItem.Name = "genericDebugToolStripMenuItem"; this.genericDebugToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.genericDebugToolStripMenuItem.Text = "Generic Debug Button"; this.genericDebugToolStripMenuItem.Click += new System.EventHandler(this.genericDebugToolStripMenuItem_Click); // // listVariantIDsToolStripMenuItem // this.listVariantIDsToolStripMenuItem.Name = "listVariantIDsToolStripMenuItem"; this.listVariantIDsToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.listVariantIDsToolStripMenuItem.Text = "List Variant IDs"; this.listVariantIDsToolStripMenuItem.Click += new System.EventHandler(this.listVariantIDsToolStripMenuItem_Click); // // downloadBlocksToolStripMenuItem // this.downloadBlocksToolStripMenuItem.Name = "downloadBlocksToolStripMenuItem"; this.downloadBlocksToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.downloadBlocksToolStripMenuItem.Text = "Download Blocks"; this.downloadBlocksToolStripMenuItem.Click += new System.EventHandler(this.downloadBlocksToolStripMenuItem_Click); // // preferencesToolStripMenuItem1 // this.preferencesToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fingerprintModeToolStripMenuItem, this.sCNModeToolStripMenuItem, this.allowWriteVariantCodingToolStripMenuItem}); this.preferencesToolStripMenuItem1.Name = "preferencesToolStripMenuItem1"; this.preferencesToolStripMenuItem1.Size = new System.Drawing.Size(80, 20); this.preferencesToolStripMenuItem1.Text = "Preferences"; this.preferencesToolStripMenuItem1.DropDownOpening += new System.EventHandler(this.preferencesToolStripMenuItem1_DropDownOpening); // // fingerprintModeToolStripMenuItem // this.fingerprintModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.useLastFingerprintToolStripMenuItem, this.customValueToolStripMenuItem}); this.fingerprintModeToolStripMenuItem.Name = "fingerprintModeToolStripMenuItem"; this.fingerprintModeToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.fingerprintModeToolStripMenuItem.Text = "Fingerprint Mode"; // // useLastFingerprintToolStripMenuItem // this.useLastFingerprintToolStripMenuItem.Name = "useLastFingerprintToolStripMenuItem"; this.useLastFingerprintToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.useLastFingerprintToolStripMenuItem.Text = "Use Last Fingerprint"; this.useLastFingerprintToolStripMenuItem.Click += new System.EventHandler(this.useLastFingerprintToolStripMenuItem_Click); // // customValueToolStripMenuItem // this.customValueToolStripMenuItem.Name = "customValueToolStripMenuItem"; this.customValueToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.customValueToolStripMenuItem.Text = "Custom Value"; this.customValueToolStripMenuItem.Click += new System.EventHandler(this.customValueToolStripMenuItem_Click); // // sCNModeToolStripMenuItem // this.sCNModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.useLastSCNToolStripMenuItem, this.writeZerosVediamoToolStripMenuItem}); this.sCNModeToolStripMenuItem.Name = "sCNModeToolStripMenuItem"; this.sCNModeToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.sCNModeToolStripMenuItem.Text = "SCN Mode"; // // useLastSCNToolStripMenuItem // this.useLastSCNToolStripMenuItem.Name = "useLastSCNToolStripMenuItem"; this.useLastSCNToolStripMenuItem.Size = new System.Drawing.Size(191, 22); this.useLastSCNToolStripMenuItem.Text = "Use Last SCN"; this.useLastSCNToolStripMenuItem.Click += new System.EventHandler(this.useLastSCNToolStripMenuItem_Click); // // writeZerosVediamoToolStripMenuItem // this.writeZerosVediamoToolStripMenuItem.Name = "writeZerosVediamoToolStripMenuItem"; this.writeZerosVediamoToolStripMenuItem.Size = new System.Drawing.Size(191, 22); this.writeZerosVediamoToolStripMenuItem.Text = "Write Zeros (Vediamo)"; this.writeZerosVediamoToolStripMenuItem.Click += new System.EventHandler(this.writeZerosVediamoToolStripMenuItem_Click); // // allowWriteVariantCodingToolStripMenuItem // this.allowWriteVariantCodingToolStripMenuItem.Name = "allowWriteVariantCodingToolStripMenuItem"; this.allowWriteVariantCodingToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.allowWriteVariantCodingToolStripMenuItem.Text = "Allow Write Variant Coding"; this.allowWriteVariantCodingToolStripMenuItem.Click += new System.EventHandler(this.allowWriteVariantCodingToolStripMenuItem_Click); // // tvMain // this.tvMain.AllowDrop = true; this.tvMain.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.tvMain.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.tvMain.Location = new System.Drawing.Point(3, 3); this.tvMain.Name = "tvMain"; this.tvMain.Size = new System.Drawing.Size(1117, 480); this.tvMain.TabIndex = 2; this.tvMain.DragDrop += new System.Windows.Forms.DragEventHandler(this.tvMain_DragDrop); this.tvMain.DragEnter += new System.Windows.Forms.DragEventHandler(this.tvMain_DragEnter); this.tvMain.DoubleClick += new System.EventHandler(this.tvMain_DoubleClick); // // txtLog // this.txtLog.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.txtLog.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtLog.Location = new System.Drawing.Point(3, 3); this.txtLog.Multiline = true; this.txtLog.Name = "txtLog"; this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtLog.Size = new System.Drawing.Size(1117, 160); this.txtLog.TabIndex = 3; // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 24); this.splitContainer1.Name = "splitContainer1"; this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitContainer1.Panel1 // this.splitContainer1.Panel1.Controls.Add(this.tvMain); this.splitContainer1.Panel1.Controls.Add(this.pbResourcePlaceholder); // // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.txtJ2534Input); this.splitContainer1.Panel2.Controls.Add(this.txtLog); this.splitContainer1.Size = new System.Drawing.Size(1123, 682); this.splitContainer1.SplitterDistance = 486; this.splitContainer1.TabIndex = 5; // // pbResourcePlaceholder // this.pbResourcePlaceholder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.pbResourcePlaceholder.Image = global::Diogenes.Properties.Resources.report; this.pbResourcePlaceholder.Location = new System.Drawing.Point(1070, 3); this.pbResourcePlaceholder.Name = "pbResourcePlaceholder"; this.pbResourcePlaceholder.Size = new System.Drawing.Size(50, 50); this.pbResourcePlaceholder.TabIndex = 4; this.pbResourcePlaceholder.TabStop = false; this.pbResourcePlaceholder.Visible = false; // // txtJ2534Input // this.txtJ2534Input.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtJ2534Input.Enabled = false; this.txtJ2534Input.Location = new System.Drawing.Point(3, 169); this.txtJ2534Input.Name = "txtJ2534Input"; this.txtJ2534Input.Size = new System.Drawing.Size(1117, 20); this.txtJ2534Input.TabIndex = 4; this.txtJ2534Input.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtJ2534Input_KeyDown); // // tmrBlinkConnectionMenu // this.tmrBlinkConnectionMenu.Interval = 60; this.tmrBlinkConnectionMenu.Tick += new System.EventHandler(this.tmrBlinkConnectionMenu_Tick); // // fixCBFChecksumToolStripMenuItem // this.fixCBFChecksumToolStripMenuItem.Name = "fixCBFChecksumToolStripMenuItem"; this.fixCBFChecksumToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.fixCBFChecksumToolStripMenuItem.Text = "Fix CBF Checksum"; this.fixCBFChecksumToolStripMenuItem.Click += new System.EventHandler(this.fixCBFChecksumToolStripMenuItem_Click); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1123, 728); this.Controls.Add(this.splitContainer1); this.Controls.Add(this.statusStrip1); this.Controls.Add(this.menuStrip1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MainMenuStrip = this.menuStrip1; this.Name = "MainForm"; this.Text = "Diogenes"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); this.Load += new System.EventHandler(this.MainForm_Load); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); this.splitContainer1.Panel2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.pbResourcePlaceholder)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripStatusLabel lblConnectionType; private System.Windows.Forms.TreeView tvMain; private System.Windows.Forms.TextBox txtLog; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem loadCBFFilesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem unloadExistingFilesToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem connectionToolStripMenuItem; private System.Windows.Forms.PictureBox pbResourcePlaceholder; private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem eCUToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem setSecurityLevelToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem j2534InterfacesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem defaultJ2534InterfaceToolStripMenuItem; private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.TextBox txtJ2534Input; private System.Windows.Forms.ToolStripMenuItem cFFExportFlashSegmentsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem fixClientAccessPermissionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem cFFFlashSplicerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem showTraceToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripMenuItem clearConsoleToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; private System.Windows.Forms.Timer tmrBlinkConnectionMenu; private System.Windows.Forms.ToolStripMenuItem disconnectToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem copyConsoleToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem uDSHexEditorToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; private System.Windows.Forms.ToolStripMenuItem preferencesToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem fingerprintModeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem useLastFingerprintToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem customValueToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem sCNModeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem useLastSCNToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem writeZerosVediamoToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem allowWriteVariantCodingToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem diagnosticTroubleCodesDTCToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem viewECUMetadataToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem identifyECUToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem loadCompressedJsonToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportContainerAsCompressedJSONToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; private System.Windows.Forms.ToolStripMenuItem dSCDebugToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem loadJSONToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportContainerAsJSONToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem genericDebugToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem listVariantIDsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem downloadBlocksToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem fixCBFChecksumToolStripMenuItem; } } ================================================ FILE: Caesar/Diogenes/Forms/MainForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; using System.IO; using Diogenes.Properties; using System.Runtime.InteropServices; using Diogenes.SecurityAccess; namespace Diogenes { public partial class MainForm : Form { public ECUConnection Connection = null; public MainForm() { InitializeComponent(); } TraceForm TraceFormSingleInstance; List Containers = new List(); ImageList treeImages = null; TextboxWriter LogTextbox; private void MainForm_Load(object sender, EventArgs e) { RedirectConsole(); LoadContainers(); UnmanagedUtility.SendMessage(txtJ2534Input.Handle, UnmanagedUtility.EM_SETCUEBANNER, 0, "J2534 Console : Enter hex values (01 23 45 57) and press enter to send a raw J2534 command"); #if (!DEBUG) genericDebugToolStripMenuItem.Visible = false; downloadBlocksToolStripMenuItem.Visible = false; #endif SetDisconnectedState(false); } private void RedirectConsole() { LogTextbox = new TextboxWriter(txtLog); Console.SetOut(LogTextbox); } private void LoadContainers() { Containers.Clear(); foreach (string file in Directory.GetFiles(Application.StartupPath)) { if (Path.GetExtension(file).ToLower() == ".cbf") { CaesarContainer cbfContainer = new CaesarContainer(File.ReadAllBytes(file)); Containers.Add(cbfContainer); //PostInitDebug(cbfContainer); } } LoadTree(); } private void PostInitDebug(CaesarContainer cbfContainer) { } private void InitializeTree() { if (treeImages is null) { treeImages = new ImageList(); treeImages.Images.Add(Resources.blank); // 0 treeImages.Images.Add(Resources.box); treeImages.Images.Add(Resources.brick); treeImages.Images.Add(Resources.cog); treeImages.Images.Add(Resources.house); treeImages.Images.Add(Resources.connect); treeImages.Images.Add(Resources.information); // 6 treeImages.Images.Add(Resources.bullet_go); // 7 treeImages.Images.Add(Resources.bullet_star); treeImages.Images.Add(Resources.bullet_black); // 9 treeImages.Images.Add(Resources.bullet_blue); treeImages.Images.Add(Resources.bullet_green); treeImages.Images.Add(Resources.bullet_orange); treeImages.Images.Add(Resources.bullet_pink); treeImages.Images.Add(Resources.bullet_purple); treeImages.Images.Add(Resources.bullet_red); treeImages.Images.Add(Resources.bullet_white); treeImages.Images.Add(Resources.bullet_yellow); // 17 treeImages.Images.Add(Resources.computer_go); // 18 treeImages.Images.Add(Resources.lock_edit); // 19 treeImages.Images.Add(Resources.key); // 20 treeImages.Images.Add(Resources.application_xp_terminal); // 21 treeImages.Images.Add(Resources.page_white_edit); // 22 treeImages.Images.Add(Resources.asterisk_orange); // 23 treeImages.Images.Add(Resources.folder); // 24 treeImages.Images.Add(Resources.accept); // 25 treeImages.Images.Add(Resources.report); // 26 tvMain.ImageList = treeImages; UnmanagedUtility.SendMessage(tvMain.Handle, UnmanagedUtility.TVM_SETEXTENDEDSTYLE, (IntPtr)UnmanagedUtility.TVS_EX_DOUBLEBUFFER, (IntPtr)UnmanagedUtility.TVS_EX_DOUBLEBUFFER); } } private void AddDiagServicesToNode(TreeNode parentNode, ECUVariant variant) { string newTag = $"Exec{nameof(DiagService)}:{variant.Qualifier}"; TreeNode diagUnlockingOptions = new TreeNode($"Security Access", 19, 19); diagUnlockingOptions.Tag = newTag; TreeNode diagStoredData = new TreeNode($"Diagnostics: Stored Data", 24, 24); diagStoredData.Tag = newTag; TreeNode diagData = new TreeNode($"Diagnostics: Data", 24, 24); diagData.Tag = newTag; TreeNode diagFunction = new TreeNode($"Diagnostics: Function", 24, 24); diagFunction.Tag = newTag; TreeNode diagRoutine = new TreeNode($"Diagnostics: Routine", 24, 24); diagRoutine.Tag = newTag; TreeNode diagIO = new TreeNode($"Diagnostics: IO", 24, 24); diagIO.Tag = newTag; TreeNode diagDownload = new TreeNode($"Diagnostics: Download", 24, 24); diagDownload.Tag = newTag; for (int i = 0; i < variant.DiagServices.Length; i++) { DiagService currentDiagService = variant.DiagServices[i]; TreeNode diagNode = new TreeNode(currentDiagService.Qualifier, 9, 9); diagNode.Tag = i.ToString(); if ((currentDiagService.RequestBytes.Length > 1) && (currentDiagService.RequestBytes[0] == 0x27)) { diagUnlockingOptions.Nodes.Add(diagNode); continue; } if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.StoredData) { diagStoredData.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.DiagnosticFunction) { diagFunction.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Data) { diagData.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Routine) { diagRoutine.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.IoControl) { diagIO.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Download) { diagDownload.Nodes.Add(diagNode); } } parentNode.Nodes.Add(diagUnlockingOptions); parentNode.Nodes.Add(diagStoredData); parentNode.Nodes.Add(diagData); parentNode.Nodes.Add(diagFunction); parentNode.Nodes.Add(diagRoutine); parentNode.Nodes.Add(diagIO); parentNode.Nodes.Add(diagDownload); } private void AddEcuMetadataToNode(TreeNode parentNode, CaesarContainer container, ECU ecu) { TreeNode rootMetadata = new TreeNode("Metadata", 26, 26); rootMetadata.Tag = $"RootMetadata"; TreeNode metadataRowNode; metadataRowNode = new TreeNode($"Container File Size: {container.GetFileSize()}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); metadataRowNode = new TreeNode($"Container Checksum: {container.FileChecksum:X8}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); metadataRowNode = new TreeNode($"CBF Version: {container.CaesarCFFHeader.CbfVersionString}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); metadataRowNode = new TreeNode($"GPD Version: {container.CaesarCFFHeader.GpdVersionString}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); metadataRowNode = new TreeNode($"ECU Version: {ecu.EcuXmlVersion}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); metadataRowNode = new TreeNode($"ECU Ignition Required: {ecu.IgnitionRequired}", 9, 9); metadataRowNode.Tag = "RootMetadataEntry"; rootMetadata.Nodes.Add(metadataRowNode); parentNode.Nodes.Add(rootMetadata); } private void LoadTree() { InitializeTree(); tvMain.Nodes.Clear(); foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { TreeNode ecuNode = new TreeNode(ecu.Qualifier, 1, 1); ecuNode.Tag = nameof(ECU); TreeNode execDiagAtRoot = new TreeNode("Execute Diagnostic Service (Root)", 21, 21); execDiagAtRoot.Tag = $"{nameof(DiagService)}:{nameof(ECU)}:{ecu.Qualifier}"; ecuNode.Nodes.Add(execDiagAtRoot); AddEcuMetadataToNode(ecuNode, container, ecu); foreach (ECUInterfaceSubtype subtype in ecu.ECUInterfaceSubtypes) { if (Connection?.VariantIsAvailable ?? false) { // interfaces don't matter anymore when we are connected break; } TreeNode interfaceNode = new TreeNode(subtype.Qualifier, 5, 5); interfaceNode.Tag = ""; TreeNode initiateContactNode = new TreeNode("Initiate Contact", 18, 18); initiateContactNode.Tag = $"{nameof(ECUInterfaceSubtype)}:{subtype.Qualifier}"; interfaceNode.Nodes.Add(initiateContactNode); TreeNode comparamParentNode = new TreeNode("Communications Parameters", 6, 6); comparamParentNode.Tag = $"ComParamParent"; foreach (ComParameter parameter in subtype.CommunicationParameters) { TreeNode comNode = new TreeNode($"{parameter.ParamName} : {parameter.ComParamValue} (0x{parameter.ComParamValue:X})", 9, 9); // Console.WriteLine(comNode.Text); comNode.Tag = nameof(ComParameter); comparamParentNode.Nodes.Add(comNode); } interfaceNode.Nodes.Add(comparamParentNode); ecuNode.Nodes.Add(interfaceNode); interfaceNode.Expand(); } // offer the ability to switch sessions at all times, in case user runs functions like FN_Reset TreeNode sessionContainer = new TreeNode("Session", 23, 23); sessionContainer.Tag = $"Session"; foreach (DiagService ds in ecu.GlobalDiagServices) { if (ds.DataClass_ServiceType == (ushort)DiagService.ServiceType.Session) { TreeNode dsNode = new TreeNode(ds.Qualifier, 12, 12); dsNode.Tag = ds.Qualifier; sessionContainer.Nodes.Add(dsNode); } } ecuNode.Nodes.Add(sessionContainer); foreach (ECUVariant variant in ecu.ECUVariants) { TreeNode ecuVariantNode = new TreeNode(variant.Qualifier, 2, 2); ecuVariantNode.Tag = nameof(ECUVariant); // check if variant should be filtered if (Connection?.VariantIsAvailable ?? false) { bool foundCorrectVariant = false; foreach (ECUVariantPattern pattern in variant.VariantPatterns) { if (pattern.VariantID == Connection.ECUVariantID) { foundCorrectVariant = true; break; } } if (!foundCorrectVariant) { continue; } ecuVariantNode.ImageIndex = 25; ecuVariantNode.SelectedImageIndex = 25; ecuVariantNode.Expand(); } // exec diag button TreeNode execDiagAtVariant = new TreeNode("Execute Diagnostic Service", 21, 21); execDiagAtVariant.Tag = $"{nameof(DiagService)}:{nameof(ECUVariant)}:{variant.Qualifier}"; ecuVariantNode.Nodes.Add(execDiagAtVariant); // metadata TreeNode metadataNode = new TreeNode($"Metadata", 6, 6); metadataNode.Tag = $"{nameof(ECUVariant)}Metadata"; foreach (ECUVariantPattern pattern in variant.VariantPatterns) { string vendorText = pattern.PatternType == 3 ? $", Vendor: {pattern.VendorName}" : ""; TreeNode patternNode = new TreeNode($"Variant ID: {pattern.VariantID} ({pattern.VariantID:X4}){vendorText}", 9, 9); patternNode.Tag = nameof(ECUVariantPattern); metadataNode.Nodes.Add(patternNode); } AddDiagServicesToNode(ecuVariantNode, variant); ecuVariantNode.Nodes.Add(metadataNode); // vc domains foreach (VCDomain domain in variant.VCDomains) { TreeNode vcDomainNode = new TreeNode(domain.Qualifier, 3, 3); vcDomainNode.Tag = nameof(VCDomain); ecuVariantNode.Nodes.Add(vcDomainNode); } TreeNode backupNode = new TreeNode("Backup Variant Strings", 3, 3); backupNode.Tag = "VCBackup"; ecuVariantNode.Nodes.Add(backupNode); ecuNode.Nodes.Add(ecuVariantNode); } tvMain.Nodes.Add(ecuNode); ecuNode.Expand(); } } } private void FixCALs(CaesarContainer container) { int newLevel = 1; byte[] newFile = new byte[container.FileBytes.Length]; Buffer.BlockCopy(container.FileBytes, 0, newFile, 0, container.FileBytes.Length); Console.WriteLine($"Creating a new CBF with access level requirements set at {newLevel}"); List dsPendingFix = new List(); using (BinaryReader reader = new BinaryReader(new MemoryStream(container.FileBytes))) { foreach (ECU ecu in container.CaesarECUs) { foreach (DiagService ds in ecu.GlobalDiagServices) { if (ds.ClientAccessLevel > newLevel) { dsPendingFix.Add(ds); Console.WriteLine($"-> {ds.Qualifier} (Level {ds.ClientAccessLevel})"); long fileOffset = ds.GetCALInt16Offset(reader); if (fileOffset != -1) { newFile[fileOffset] = (byte)newLevel; newFile[fileOffset + 1] = (byte)(newLevel >> 8); } } } } uint checksum = CaesarReader.ComputeFileChecksum(newFile); byte[] checksumBytes = BitConverter.GetBytes(checksum); Array.ConstrainedCopy(checksumBytes, 0, newFile, newFile.Length - 4, checksumBytes.Length); } SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new CBF file"; sfd.Filter = "CBF files (*.cbf)|*.cbf|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, newFile); } } private void TreeViewDoubleClickCheckIfSession(TreeNode node) { if (node.Parent != null && node.Parent.Tag.ToString() == "Session") { string ecuName = node.Parent.Parent.Text; string serviceName = node.Tag.ToString(); foreach (CaesarContainer container in Containers) { ECU ecu = container.CaesarECUs.Find(x => x.Qualifier == ecuName); if (ecu != null) { DiagService ds = ecu.GlobalDiagServices.Find(x => x.Qualifier == serviceName); if (ds != null) { PresentRunDiagDialog(ds); break; } } } } } private void TreeViewDoubleClickCheckIfVariantDiag(TreeNode node) { string validNodePrefix = $"Exec{nameof(DiagService)}:"; if (node.Parent is null) { return; } if (node.Parent.Tag.ToString().StartsWith(validNodePrefix)) { string variantName = node.Parent.Tag.ToString().Substring(validNodePrefix.Length); ECUVariant foundVariant = null; foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { if (variant.Qualifier == variantName) { foundVariant = variant; } } } } // variant found, exec the diag service if (foundVariant != null) { DiagService ds = foundVariant.DiagServices[int.Parse(node.Tag.ToString())]; bool connectionSupportsUnlocking = Connection?.ConnectionProtocol?.SupportsUnlocking() ?? false; // can we help to skip the modal if the ds doesn't require additional user input? common for data, stored data if ((ds.DataClass_ServiceType == (int)DiagService.ServiceType.StoredData) || (ds.DataClass_ServiceType == (int)DiagService.ServiceType.Data)) { Connection?.ExecUserDiagJob(ds.RequestBytes, ds); } else if (connectionSupportsUnlocking && (ds.RequestBytes.Length == 2) && (ds.RequestBytes[0] == 0x27)) { // request seed, no need to prompt Connection?.ExecUserDiagJob(ds.RequestBytes, ds); } else { PresentRunDiagDialog(ds); } } } } private void PresentRunDiagDialog(DiagService ds) { RunDiagForm runDiagForm = new RunDiagForm(ds); if (runDiagForm.ShowDialog() == DialogResult.OK) { Connection.ExecUserDiagJob(runDiagForm.Result, ds); } } private void treeViewSelectVariantCoding(TreeNode node) { string domainName = node.Text; string variantName = node.Parent.Text; string ecuName = node.Parent.Parent.Text; Console.WriteLine($"Starting VC Dialog for {ecuName} ({variantName}) with domain as {domainName}"); CaesarContainer container = Containers.Find(x => x.GetECUVariantByName(variantName) != null); // prompt the user for vc changes via VCForm VCForm vcForm = new VCForm(container, ecuName, variantName, domainName, Connection); if (vcForm.ShowDialog() == DialogResult.OK) { VariantCoding.DoVariantCoding(Connection, vcForm, allowWriteVariantCodingToolStripMenuItem.Checked); } } private void tvMain_DoubleClick(object sender, EventArgs e) { TreeNode node = tvMain.SelectedNode; if (node is null) { return; } if (node.Tag.ToString() == nameof(VCDomain)) { // variant coding treeViewSelectVariantCoding(node); } else if (node.Tag.ToString() == "VCBackup") { // variant coding backup VCReport.treeViewSelectVariantCodingBackup(node, Connection, Containers); } else if (node.Tag.ToString().StartsWith(nameof(ECUInterfaceSubtype))) { // initiate contact string connectionProfileName = node.Tag.ToString().Substring(nameof(ECUInterfaceSubtype).Length + 1); string ecuName = node.Parent.Parent.Text; foreach (CaesarContainer container in Containers) { ECU ecu = container.CaesarECUs.Find(x => x.Qualifier == ecuName); if (ecu != null) { ECUInterfaceSubtype subtype = ecu.ECUInterfaceSubtypes.Find(x => x.Qualifier == connectionProfileName); if (subtype != null) { Console.WriteLine($"Attempting to open a connection to ({ecuName}) with profile '{connectionProfileName}'"); ECUConnection.ConnectResponse response = Connection.Connect(subtype, ecu); if (response == ECUConnection.ConnectResponse.OK) { ProtocolPostConnect(); } else if (response == ECUConnection.ConnectResponse.NoValidInterface) { BlinkConnectionMenu(); connectionToolStripMenuItem.ShowDropDown(); j2534InterfacesToolStripMenuItem.ShowDropDown(); } else { // uhoh Console.WriteLine($"ECU connection was unsuccessful : {response}"); } break; } } } } else if (node.Tag.ToString().StartsWith(nameof(DiagService))) { // execute diag service (modal) string diagOrigin = node.Tag.ToString().Substring(nameof(DiagService).Length + 1); string variantName = ""; string ecuName = ""; if (diagOrigin.StartsWith($"{nameof(ECUVariant)}:")) { variantName = node.Parent.Text; ecuName = node.Parent.Parent.Text; } else { ecuName = node.Parent.Text; } foreach (CaesarContainer container in Containers) { ECU ecu = container.CaesarECUs.Find(x => x.Qualifier == ecuName); if (ecu != null) { PickDiagForm picker; ECUVariant variant = ecu.ECUVariants.Find(x => x.Qualifier == variantName); if (variant != null) { //Console.WriteLine($"Starting Diagnostic Service picker modal for variant {variantName}"); picker = new PickDiagForm(variant.DiagServices); } else { //Console.WriteLine($"Starting Diagnostic Service picker modal for root {ecuName}"); picker = new PickDiagForm(ecu.GlobalDiagServices.ToArray()); } if (picker.ShowDialog() == DialogResult.OK) { PresentRunDiagDialog(picker.SelectedDiagService); } break; } } } TreeViewDoubleClickCheckIfSession(node); TreeViewDoubleClickCheckIfVariantDiag(node); } private void ProtocolPostConnect() { if (Connection.ConnectionProtocol != null) { Connection.ConnectionProtocol.ConnectionEstablishedHandler(Connection); LoadTree(); } } private void ShowAbout() { AboutForm about = new AboutForm($"Diogenes {GetVersion()} (Caesar {CaesarContainer.GetCaesarVersionString()})"); about.ShowDialog(); } public static string GetVersion() { System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); return fvi.FileVersion; } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { ShowAbout(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } private void unloadExistingFilesToolStripMenuItem_Click(object sender, EventArgs e) { Containers.Clear(); LoadTree(); } private void loadCBFFilesToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a CBF File"; ofd.Filter = "CBF files (*.cbf)|*.cbf|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { TryLoadFile(ofd.FileName); } } private void TryLoadFile(string fileName) { byte[] fileBytes = File.ReadAllBytes(fileName); if (CaesarContainer.VerifyChecksum(fileBytes, out uint checksum)) { Containers.Add(new CaesarContainer(fileBytes)); LoadTree(); } else { Console.WriteLine($"File {Path.GetFileName(fileName)} was not loaded as the checksum is invalid"); } } private void setSecurityLevelToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a Security DLL File"; ofd.Filter = "DLL files (*.dll)|*.dll|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { DllContext ctx = new DllContext(ofd.FileName); if (ctx.KeyGenerationCapability) { SecurityLevelForm slForm = new SecurityLevelForm(ctx); if (slForm.ShowDialog() == DialogResult.OK) { Console.WriteLine($"Authentication: Selected level {slForm.RequestedSecurityLevel} : {BitUtility.BytesToHex(slForm.KeyResponse)}"); } } else { MessageBox.Show("The selected DLL is not capable of configuring ECU security levels. Please try another file.", "Security Level Configuration"); } } } private void debugJ2534ToolStripMenuItem_Click(object sender, EventArgs e) { } private void j2534InterfacesToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { j2534InterfacesToolStripMenuItem.DropDownItems.Clear(); ToolStripItem defaultItem = j2534InterfacesToolStripMenuItem.DropDownItems.Add("(No devices found)"); defaultItem.Enabled = false; foreach (Tuple device in ECUConnection.GetAvailableJ2534NamesAndDrivers()) { defaultItem.Visible = false; ToolStripItem newItem = j2534InterfacesToolStripMenuItem.DropDownItems.Add(device.Item1); newItem.Tag = device.Item2; newItem.Click += J2534InterfaceItem_Click; } } private void J2534InterfaceItem_Click(object sender, EventArgs e) { ToolStripItem caller = (ToolStripItem)sender; if (Connection != null) { Connection.TryCleanup(); } Connection = new ECUConnection(caller.Tag.ToString(), caller.Text); Connection.ConnectionStateChangeEvent += ConnectionStateChangedHandler; Connection.OpenDevice(); // loadtree should not be necessary if the prior state was disconnected // LoadTree(); } private void disconnectToolStripMenuItem_Click(object sender, EventArgs e) { SetDisconnectedState(); } private void SetDisconnectedState(bool refresh = true) { // disconnected really means "running in simulation mode" if (Connection != null) { Connection.TryCleanup(); } Connection = new ECUConnection(); Connection.ConnectionStateChangeEvent += ConnectionStateChangedHandler; if (refresh) { LoadTree(); } } private void ConnectionStateChangedHandler(string newStateDescription) { lblConnectionType.Text = newStateDescription; txtJ2534Input.Enabled = Connection.State > ECUConnection.ConnectionState.DeviceSelectedPendingChannelConnection; } private void txtJ2534Input_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { e.Handled = true; string inText = txtJ2534Input.Text; txtJ2534Input.Text = ""; if (BitUtility.CheckHexValid(inText)) { byte[] requestData = BitUtility.BytesFromHex(inText.Replace(" ", "").ToUpper()); byte[] response = Connection.SendMessage(requestData); Console.WriteLine($"ECU: {BitUtility.BytesToHex(response, true)}"); } else { Console.WriteLine($"Could not understand provided hex input: '{inText}'"); } } } private void cFFExportFlashSegmentsToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a CFF File"; ofd.Filter = "CFF files (*.cff)|*.cff|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { try { CaesarFlashContainer.ExportCFFMemorySegments(ofd.FileName); } catch (Exception ex) { Console.WriteLine($"CFF Export failed: {ex.Message}"); } } } private void fixClientAccessPermissionsToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a CBF File to apply new permissions on"; ofd.Filter = "CBF files (*.cbf)|*.cbf|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { FixCALs(new CaesarContainer(File.ReadAllBytes(ofd.FileName))); } } private void cFFFlashSplicerToolStripMenuItem_Click(object sender, EventArgs e) { FlashSplicer splicer = new FlashSplicer(); splicer.Show(); } private void allowWriteVariantCodingToolStripMenuItem_Click(object sender, EventArgs e) { allowWriteVariantCodingToolStripMenuItem.Checked = !allowWriteVariantCodingToolStripMenuItem.Checked; Preferences.SetValue(Preferences.PreferenceKey.AllowVC, allowWriteVariantCodingToolStripMenuItem.Checked ? "true" : "false"); } private void showTraceToolStripMenuItem_Click(object sender, EventArgs e) { if (TraceFormSingleInstance is null || TraceFormSingleInstance.IsDisposed) { TraceFormSingleInstance = new TraceForm(this); } TraceFormSingleInstance.Show(); } private void clearConsoleToolStripMenuItem_Click(object sender, EventArgs e) { LogTextbox?.Clear(); } // originally this was intended to blink the menuitem, but this requires overriding the draw call private void tmrBlinkConnectionMenu_Tick(object sender, EventArgs e) { if (connectionToolStripMenuItem.ForeColor != SystemColors.ControlText) { connectionToolStripMenuItem.ForeColor = SystemColors.ControlText; ConnectionMenuBlinksRemaining--; if (ConnectionMenuBlinksRemaining <= 0) { ConnectionMenuBlinksRemaining = 0; tmrBlinkConnectionMenu.Enabled = false; } } else { if (ConnectionMenuBlinksRemaining > 0) { connectionToolStripMenuItem.ForeColor = SystemColors.Control; } } } private int ConnectionMenuBlinksRemaining = 0; private void BlinkConnectionMenu() { ConnectionMenuBlinksRemaining = 8; tmrBlinkConnectionMenu.Enabled = true; } private void connectionToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { disconnectToolStripMenuItem.Enabled = Connection?.ConnectionDevice != null; j2534InterfacesToolStripMenuItem.Enabled = Connection?.ConnectionDevice == null; } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { SetDisconnectedState(); } private void copyConsoleToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetText(txtLog.Text); } private void uDSHexEditorToolStripMenuItem_Click(object sender, EventArgs e) { if (Connection.ConnectionProtocol is null) { MessageBox.Show("Please initiate contact with a target first."); return; } string protocolName = Connection.ConnectionProtocol.GetProtocolName(); if (protocolName != "UDS") { MessageBox.Show($"Only UDS targets are officially supported (current protocol: {protocolName}). \r\n\r\n" + $"The editor will still open, however please ensure that the ECU accepts UDS-like read and write commands"); } UDSHexEditor editor = new UDSHexEditor(Connection); editor.ShowDialog(); } private void preferencesToolStripMenuItem1_DropDownOpening(object sender, EventArgs e) { RefreshPreferencesDropdown(); } private void RefreshPreferencesDropdown() { // VC safety switch allowWriteVariantCodingToolStripMenuItem.Checked = Preferences.GetValue(Preferences.PreferenceKey.AllowVC) == "true"; // scn mode bool scnZero = Preferences.GetValue(Preferences.PreferenceKey.EnableSCNZero) == "true"; writeZerosVediamoToolStripMenuItem.Checked = scnZero; useLastSCNToolStripMenuItem.Checked = !writeZerosVediamoToolStripMenuItem.Checked; // fingerprint mode bool fingerprintClone = Preferences.GetValue(Preferences.PreferenceKey.EnableFingerprintClone) == "true"; useLastFingerprintToolStripMenuItem.Checked = fingerprintClone; customValueToolStripMenuItem.Checked = !fingerprintClone; // fingerprint custom value uint customFingerprint = uint.Parse(Preferences.GetValue(Preferences.PreferenceKey.FingerprintValue)); customValueToolStripMenuItem.Text = $"Custom Value: {customFingerprint}"; } private void useLastSCNToolStripMenuItem_Click(object sender, EventArgs e) { Preferences.SetValue(Preferences.PreferenceKey.EnableSCNZero, "false"); RefreshPreferencesDropdown(); } private void writeZerosVediamoToolStripMenuItem_Click(object sender, EventArgs e) { Preferences.SetValue(Preferences.PreferenceKey.EnableSCNZero, "true"); RefreshPreferencesDropdown(); } private void useLastFingerprintToolStripMenuItem_Click(object sender, EventArgs e) { Preferences.SetValue(Preferences.PreferenceKey.EnableFingerprintClone, "true"); RefreshPreferencesDropdown(); } private void customValueToolStripMenuItem_Click(object sender, EventArgs e) { Preferences.SetValue(Preferences.PreferenceKey.EnableFingerprintClone, "false"); // prompt for new fingerprint value RefreshPreferencesDropdown(); } private void tvMain_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } } private void tvMain_DragDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach (string file in files) { TryLoadFile(file); } } // maybe this should belong in ECUConnection private ECUVariant GetCurrentVariantInstance() { if (!(Connection?.VariantIsAvailable ?? false)) { return null; } foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { foreach (ECUVariantPattern pattern in variant.VariantPatterns) { if (pattern.VariantID == Connection.ECUVariantID) { return variant; } } } } } return null; } private void diagnosticTroubleCodesDTCToolStripMenuItem_Click(object sender, EventArgs e) { if (Connection.ConnectionProtocol is null) { MessageBox.Show("Please initiate contact with a target first."); return; } if (Connection.ConnectionProtocol.GetProtocolName() != "UDS") { MessageBox.Show("Sorry, only UDS is supported at this time."); // return was removed from here, to allow for kw2c3pe debugging } if (!(Connection?.VariantIsAvailable ?? false)) { MessageBox.Show("DTCs require the variant to be identified first"); return; } ECUVariant currentVariant = GetCurrentVariantInstance(); DTCForm dtcForm = new DTCForm(Connection, currentVariant); dtcForm.ShowDialog(); } private void viewECUMetadataToolStripMenuItem_Click(object sender, EventArgs e) { ECUMetadata.ShowMetadataModal(Connection); } private void identifyECUToolStripMenuItem_Click(object sender, EventArgs e) { if (ECUIdentification.TryReadChassisNumber(Connection, out string vin)) { Console.WriteLine($"VIN: {vin}"); } else { Console.WriteLine($"Target could not be identified"); } } private void loadCompressedJsonToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a Compressed Caesar Binary (JSON) File"; ofd.Filter = "CCB files (*.ccb)|*.ccb|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { Containers.Add(CaesarContainer.DeserializeCompressedContainer(File.ReadAllBytes(ofd.FileName))); LoadTree(); } } private CaesarContainer PickContainer() { if (Containers.Count == 0) { MessageBox.Show("No containers have been loaded yet."); return null; } CaesarContainer targetContainer = Containers[0]; if (Containers.Count > 1) { // there isn't an embedded qualifier to identify containers easily; the ecu name is probably an easier name to identify with List table = new List(); foreach (CaesarContainer container in Containers) { if (container.CaesarECUs.Count > 0) { table.Add(new string[] { container.CaesarECUs[0].Qualifier }); } } GenericPicker picker = new GenericPicker(table.ToArray(), new string[] { "Container" }, 0); picker.Text = "Please select a container"; if (picker.ShowDialog() != DialogResult.OK) { return null; } string selectedEcuQualifier = picker.SelectedResult[0]; targetContainer = Containers.Find(x => ((x.CaesarECUs.Count > 0) && (x.CaesarECUs[0].Qualifier == selectedEcuQualifier))); } return targetContainer; } private void exportContainerAsCompressedJSONToolStripMenuItem_Click(object sender, EventArgs e) { CaesarContainer targetContainer = PickContainer(); if (targetContainer is null) { Console.WriteLine("Internal error: target container is null"); } else { SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new Compressed Caesar Binary (JSON) file"; sfd.Filter = "CCB files (*.ccb)|*.ccb|All files (*.*)|*.*"; sfd.FileName = targetContainer.CaesarECUs[0].Qualifier; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, CaesarContainer.SerializeCompressedContainer(targetContainer)); } } } private void dSCDebugToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a PAL File"; ofd.Filter = "PAL files (*.pal)|*.pal|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { DSCContext ctx = new DSCContext(File.ReadAllBytes(ofd.FileName)); } } private void loadJSONToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a Caesar JSON File"; ofd.Filter = "JSON files (*.json)|*.json|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { Containers.Add(CaesarContainer.DeserializeContainer(Encoding.UTF8.GetString(File.ReadAllBytes(ofd.FileName)))); LoadTree(); } } private void exportContainerAsJSONToolStripMenuItem_Click(object sender, EventArgs e) { CaesarContainer targetContainer = PickContainer(); if (targetContainer is null) { Console.WriteLine("Internal error: target container is null"); } else { SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new Caesar JSON file"; sfd.Filter = "JSON files (*.json)|*.json|All files (*.*)|*.*"; sfd.FileName = targetContainer.CaesarECUs[0].Qualifier; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, Encoding.UTF8.GetBytes(CaesarContainer.SerializeContainer(targetContainer))); } } } // this is normally not exposed to the user, the button has to be manually enabled in the Designer private void genericDebugToolStripMenuItem_Click(object sender, EventArgs e) { foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { foreach (DiagPresentation pres in ecu.GlobalPresentations) { Console.WriteLine($"Pres : {pres.Qualifier} : {pres.GetDataType()}"); if (pres.InternalDataType == 8) { throw new NotImplementedException("found a iee754 float!"); } } } } return; foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { foreach (DiagService ds in ecu.GlobalDiagServices) { if (ds.Qualifier != "DT_Istgang") { //continue; } foreach (List dpl in ds.OutputPreparations) { foreach (DiagPreparation prep in dpl) { DiagPresentation pres = ecu.GlobalPresentations[prep.PresPoolIndex]; if (pres.EnumMaxValue == 0) { continue; } foreach (Scale scale in pres.Scales) { if (scale.EnumUpBound >= 0) { string presOut = pres.InterpretData(BitUtility.BytesFromHex("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"), prep); Console.WriteLine($"{ds.Qualifier} : {prep.Qualifier} @ {presOut} = {pres.InternalDataType}, {pres.EnumMaxValue}"); } } if (pres.Qualifier == "PRES_ZIELGANG") { pres.PrintDebug(); } } } } } } Console.WriteLine("done"); } private void listVariantIDsToolStripMenuItem_Click(object sender, EventArgs e) { CaesarContainer targetContainer = PickContainer(); if (targetContainer is null) { Console.WriteLine("Internal error: target container is null"); } else { foreach (ECU ecu in targetContainer.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { foreach (ECUVariantPattern pattern in variant.VariantPatterns) { Console.WriteLine($"{variant.Qualifier}: {pattern.VariantID:X4}"); } } } } } private void downloadBlocksToolStripMenuItem_Click(object sender, EventArgs e) { if (Connection.ConnectionProtocol is null) { //MessageBox.Show("Please initiate contact with a target first."); //return; } BlockDownload blockDownload = new BlockDownload(Connection); blockDownload.ShowDialog(); } private void fixCBFChecksumToolStripMenuItem_Click(object sender, EventArgs e) { // repairs the checksum on a CBF that may have been modified, so that it can be loaded by c32s (e.g. Vediamo) again OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select a CBF File"; ofd.Filter = "CBF files (*.cbf)|*.cbf|All files (*.*)|*.*"; ofd.Multiselect = false; if (ofd.ShowDialog() == DialogResult.OK) { byte[] file = File.ReadAllBytes(ofd.FileName); Console.WriteLine($"Current checksum: {BitUtility.BytesToHex(file.Skip(file.Length - 4).Reverse().ToArray())}"); // restore the checksum uint checksum = CaesarReader.ComputeFileChecksumLazy(file); Console.WriteLine($"New checksum: {checksum:X8}"); file[file.Length - 4] = (byte)((checksum >> 0) & 0xFF); file[file.Length - 3] = (byte)((checksum >> 8) & 0xFF); file[file.Length - 2] = (byte)((checksum >> 16) & 0xFF); file[file.Length - 1] = (byte)((checksum >> 24) & 0xFF); File.WriteAllBytes(ofd.FileName, file); Console.WriteLine($"Fixed CBF file saved at {ofd.FileName}"); } } } } ================================================ FILE: Caesar/Diogenes/Forms/MainForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 133, 17 248, 17 AAABAAEAAAAAAAEAGAAoIAMAFgAAACgAAAAAAQAAAAIAAAEAGAAAAAAAACADAAAAAAAAAAAAAAAAAAAA AADLn2LTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvT nlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvTnlvLn2LcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnVTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTenlTe nlTenlTenlTenlTdnlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTXmlPmpFf7sVz3r1v3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3 rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv3rlv8slzp plfXmlPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTv qVmxgUpcSjVsVDltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlt VTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTltVTlYRzSkeUbxq1ncnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/tF2LaEAAABgHEyAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJ FCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAJFCAAABdzWTr/t13cnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKCgmJycjJCcpKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnJygyLiocICUNFiErKikpKSgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCghJCYvLCqleUdUQzMADB0gIyYrKikoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgmJigLFSHCjE7/vmFtVDkJFCEPGCIsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgGEiB5XTz/vmH/t166h0wrKikACx0jJScrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgKFCFgTTb0rFrg n1X/tl7hoFVjTjcFEiARGSIsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgTGyNDOS/lolbkolbYmlPyq1n/t16p fEgjJScADh4mJicqKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCghIyYgIya/i03yq1rcnVTam1Pfn1X/uF7cnVRTRDMCDx8X HSQsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgHEyCUbkP/tF3cnVTcnVTcnVTYm1P1rVr9s1yfdUUXHSQBDx8oKCgqKSgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgGEiB4XDz9s1zcnVTcnVTcnVTcnVTZm1PjoVb/uV/MklFJPjABDx4aHyUsKikoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgMFiFYRzTx q1nfn1XcnVTcnVTcnVTcnVTbnFTZm1P6sVv8slyMaUEQGCIIEyApKSgpKSgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgWHCQ8NS3dnlTmpFbcnVTcnVTc nVTcnVTcnVTcnVTZm1Pmo1b/uV7Ejk47NS0ADR4fIiYrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCggIyYiJCfDjU7xq1ncnVTcnVTcnVTcnVTcnVTcnVTc nVTbnFTbnFT9s1zzq1qCYz4JFCAKFSEqKSkpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgmJycRGSKmekf7sVzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYm1Pq p1f/uV+zgkozLysCDx8iJCYrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCFZT//tF3cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFTcnVT/tV3wqllv VjoCDx8QGSIrKikpKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgIEyBn UTj4r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYm1PuqVj/tl2pe0glJigRGSIs KikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgQGSJKPjHqplfioVXcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTam1Pfn1X/uF7hoFU/Ny4UGyMoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgdISYpKCjKkVDuqVjcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTam1P/vmGHZkACEB8oKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgLFSGddEX9slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVT9s1yddEUMFiEnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgGEiB/YT7+s13cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVT0rVq6h0wcICUjJCcoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgK FCBfTDb1rVrenlXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTpplfWmVM0 MCsZHiQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgTGyNDOS/joVbko1bc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVThoVXsp1hPQjIPGCIoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgeIiYoKCjJkVDvqVncnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnVT7slxuVjoGEiAoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCglJicVHCOtf0n5sFvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVT/tFyNakEIEyAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgHEyCNakH/tF3cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVT5sFutf0kUGyMlJicoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgGEiBuVjr7sVzdnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTuqVnK kVAnJygeISYoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgOFyJQQjLuqFng oFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVThoFXuqVlSRDIOFyIoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgaHyUxLivUmFLrp1jcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1x3XDwFESAoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgmJygQGSKne0f6sVvcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1yVb0MKFCEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgGEiCGZUD/tFzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT3rlqzg0oYHiQjJScoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgIEyBnUTj4sFvdnlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTs p1jQlVIuLCocICUoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgQGSJJPjHo pVfjolbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTjoVbnpFdIPTARGSMo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgcICUuLCrQlVHsp1jcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnlT4sFtnUjgIEyAoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgkJScZHiW0hEv2rlrcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/s12GZT8HEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgnKCgJFCCVb0P+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVT7sVumekcQGSImJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiB2Wzz9slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTxq1nBjE4gIyYgIyYoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgMFiFX RzTxq1nfn1XcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTjolbmpFdHPDAS GSMoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgXHSQ6NC3dnVTopFfcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s1xwVzkGESAoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgnKCgnJygoKCgoKCgoKCgkJicWHSSygUr3rlvcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/tFyOa0EIEyAoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnJygjJScX HSQIEyADEB8ZHiQtKykoKCgoKCgoKCgGEiCNakH/tF3cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVT5sFusfkkUGyMlJicoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCglJicfIiYVGyMKFSEGEiALFSEYHiQ3MixjTjeYc0VfTDYT GyMoKCgoKCgoKCgGEiBuVjr7sVzcnlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTuqVjKkVAoKCgeIiYoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgm JygiJCYTGiMGEiAHEyARGSMlJic+Ni1cSjV6Xjybc0S3hUvZm1T4r1v/zGWleUcFEiAnKCgoKCgoKCgO GCJQQzPtqFjhoFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTlo1bioVZB OC8UGyMoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKikjJCcIEyAFER8OFyIcISVCOS9sVDmK aECoe0jGj0/fn1XzrFr9s1z9slz1rVropFfdnlT1rVq3hUsbHyUjJCcoKCgoKCgZHiQ0MCvWmVPqplfc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTen1X1rVpgTDYKFCAoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCggIyYyLytnUTeCYz6ieEa+iU3ioVX8slz/s1z6sFvvqVnlo1bf n1XcnVTcnVTcnVTcnVTcnVTrp1jTl1IxLiobHyUoKCgoKCgiJCcdISa8iE30rVrcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1x+YD0GEiAoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgPGCJLPzH/tF3/uF77sVzzrFnkolbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTioVXrp1hNQDEPGCIoKCgoKCgnKCgMFiGddEX9slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVT9slyfdUYNFyInJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgc ICUtKyrQlVLtqFjcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnlT5sVtq UzkHEyAoKCgoKCgoKCgGEiB+YD7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVT0rVq6h0wbHyUjJScoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgkJicWHCSwgUn3r1vc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+tF2LaUEHEyAoKCgoKCgo KCgKFCFeSzb0rVrfnlXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFbe nlU8NS0WHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCCSbUL+s1zcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT6sFupfEgSGiMmJicoKCgoKCgTGyNCOS/lolbl olbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnVT5sFtnUTgIEyAoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiBxWDr8slzdnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTwqlnGj08jJScgIiYoKCgoKCghJCYeISa9iU3zrFrcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/tF2GZkAGEiAoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgNFyJURTPvqlngoFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTioVbppldLPzEQGSIoKCgoKCgpKCgIEyCUb0P/tFzcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVykeUcQGCImJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgZHyQ1MSzYmlPpplfcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+ tF11WjsFER8oKCgoKCgoKCgGEiB2Wzv9s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTxq1nDjU4iJCcgIyYoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCglJicUGyOtf0n4 r1vcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/s1yRbUIIFCAoKCgo KCgoKCgMFiFYRzTxqlngn1XcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTn pFfcnVQ7NC0WHSQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgFEh+IZ0D/tF3cnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT3r1uxgUoWHCQlJicoKCgoKCgXHSQ6NC3c nVTnpFfcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTgn1XxqllYSDUMFiEo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgHEiBrVDn6sVzdnlTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTtqFjMk1ErKSkdISUoKCgoKCggIyYiJCfDjU7xq1ncnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9slx3WzwGEiAoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgQGCJMPzHqplfioVXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTjolblo1dGOzASGiMoKCgoKCgmJygQGSKkeUb7sVzcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1yXcEQKFSEnKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgaHyUyLivTl1LqpljcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTe nlT2rltjTzcJFCAoKCgoKCgoKCgHEiCFZT/+tFzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVT3rluzgksXHSQkJScoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgjJScaHyW3 hUv1rlrcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/tFyDZD8GEiAo KCgoKCgoKCgIEyBlUDf4r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTqplfUmFIyLisZHyUoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnKCgLFSGackT9s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7slyieEYOGCInJygoKCgoKCgQGSJK PjHqpljioVbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTen1X0rVpdSzUL FSEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiB5XTz9s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTzrFq/ik0dISYiJCYoKCgoKCgeIiYmJyjIkE/vqlncnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnFT/t16HZkAFEh8oKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgLFSFbSTXyrFrfn1XcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTlo1bhoFVBOC4UGyMoKCgoKCgoKCgLFSGcdEX9slzcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTenlTjoVbwqln+s1z+s1z/v2GieEYNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgVHCM9Ni7hoFXmo1bcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVT8slxtVTkGEiAoKCgoKCgoKCgGESB9YD3+s13cnVTcnVTcnVTcnVTcnVTgoFXnpFfyq1n8sVz+ s1z2rlrnpFfFjk+YcUN7XjxdSjU9Ni0kJicnKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgiJCcb ICW4hkv0rVrcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/s1yJaEAH EyAoKCgoKCgoKCgKFCFfTDb1rVrhoFXlo1b0rFr/tF38slzuqVnanFO/ik2ieEaCYj5jTzdGPC8kJicJ FCAFER8IEyAaHyQrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgGEiCPa0L/tF3cnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT6sVupfEgSGiMmJycoKCgoKCgS GiNAOC/8slz/tF3hoFW6h0yQbEJ0WTtURTM4MywfIiYOFyIGEiAIEyASGSIfIiYoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiBzWTv8slzcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTwqlnGjk8lJigfIiYoKCgoKCgjJSctKyp0WTtlUDc/ Ny4cICUGEiAGEiANFiEXHSQhIyYmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgNFyFTRDPuqVngoFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTlo1bgoFU/Ny4UHCMoKCgoKCgrKiklJicIEyAJEyAVGyMiJCYoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgYHiQ4Mizam1TopVfcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTfn1XyrFpbSjULFSEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgi JCYfIia+ik3zrFrcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1x7 Xz0GEh8oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnJygOFyKhd0b8slzc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s1yac0QLFSEnKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCBYj7+s1zcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT1rVq4hUwZHiUjJScoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBiTjf2rlvenlXcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTopVfYmlQ2MSwYHSQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgSGiNFOzDnpFfjolbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTdnlT4r1tjTzcJFCAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgfIyYjJSfEjU7xqlncnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/ tFyCYz4GEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgIFCCXcET+ tFzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT8slyieEYOFyImJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgFEh96Xj3+s1zcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTyrFq/ik4gIiYhJCYoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgLFSFaSTXyrFrfn1XcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTopVfanFQ4MywXHSQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgVHCQ+Ni7fn1XmpFbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTgoFXuqVlURTMNFyIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCggIyYkJSfFjk/wqlncnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVT9slx0WjsGEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgmJicSGiOo fEj6sFvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1yTbkIJFCEo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgu LCobHyUBDx4GEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAG EiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAGEiAG EiAGEiAHEyAIEyAKFCELFSEPGCIWHCMcICUiJCcnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEyCIZ0D/tF3cnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT3r1qxgkoWHCQkJicoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgZHiRMPzGQbEKDYz6C Yz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6C Yz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6CYz6AYT58Xjx0WTpp UjhdSjVNQDE9Ni0sKikbICUNFiEFER8LFSEbICUmJycpKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgHEyBpUzn5sFzdnlTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTsqFjPlVItKykbICUoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgDEB58Xzz/yGX/tFz+s1z+s1z+s1z+s1z+ s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+ s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z+s1z9s1z8slz5sFv2rlryq1nppVfdnlTN k1C4hUuddEWCYj5cSjUsKikPGCIEER8NFiEeIiYoKCgpKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgPGCJMPzHrp1jhoVXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTfn1Xyq1pZSDQMFSEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnlTenlTfn1XioVbmpFbsqFj1rVr8slz/tF30 rFrRlVGoe0eAYT1QQjIlJicGEiAJFCEjJScqKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgdISUrKinOlFHtqFjcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVT/tFx7Xz0FESAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnVTen1Xsp1j7sVz/tV3v qlnLklCZcUNXRjMSGiIBDx8XHSQpKCgpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnJygN FiKhdkb8slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s1yac0UL FiEnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTgoFXvqVn/tl32rlq4 hUt2WzsxLioDEB8RGSIqKSgpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEh+BYz/+tFzcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT1rVq4hkwbHyUjJScoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFTfn1X4sFv/tl3dnVSbc0Q7 NCwADR4RGSIpKSgpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBiTjf2rlrenlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTqplfUmFIyLisaHyUoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTanFTqplj/uV/npFeTbkI4MywBDx8X HSQsKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgSGiNFOzDlo1fkolbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTioVXqplhNQDEPGCIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1PopVf/uF7ppVeVb0IhJCYADR4iJCcrKiko KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgdISUoKCjfn1X4r1vZm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTdnlT6sVtsVTkHEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1PppVf/ul/UmFJlTzcJFCEOFyIsKikpKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgm JygTGiOCYz7/t170rVrYmlPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT/tFyL aUEHEyAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTbnVTZm1P0rVr/t16zg0ovLSoADR4lJicqKSkoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgjJScKFCFLPzHc nVT/ul/goFXZm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT5sFurfUkSGiMlJicoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTanFPenlT/t17npFdbSTQCEB8aHyUsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgmJycADh8mJyeleUf/tV3yq1nY mlPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTvqlnHj08lJicfIiYoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTYmlPyq1n/tV2ackQNFiEMFiEsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKykRGSMBDx9fTDbkolb/t13enlTanFPcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVThoVbrp1hOQTIPGCIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1Pj olb/ul+3hUsfIiYKFSEsKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKikkJicADR4rKim1g0v/t17sp1jYmlPcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT+s1x1WjwFEh8oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTbnVT/t17fn1Uw LSoADh4rKikpKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgpKCgsKikOFyIIEyBqUzjvqln/tl3cnVTanFTcnVTcnVTcnVTcnVTcnVTcnVT+ s1yTbkMJFCEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1P+s13ioVU5MywFEiArKiko KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgrKikgIyYADB48NS2+ik3/t17ppVfYm1PcnVTcnVTcnVTcnVTcnVT3r1uxgUoXHSQkJico KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTXmlP6sVz0rFo7NS0ADR4rKikoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgp KSgrKikJFCEJFSF9Xz34r1v7sVzanFTbnFTcnVTcnVTcnVTsqFjOlFEsKykdICUoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYmlP6sVzlo1Y1MCsIFCAsKykoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikdISUA DR5EOi/Mk1D/uF7lo1bZm1PcnVTcnVTkolblo1dGOzASGiMoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTXmlP8slznpFcmJygIEyEsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgpKSgGEiAUGyOHZj/9 s1z5sFvZm1PbnFTenlT3r1tlTzgIEyAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTbnFTcnVTopVfrp1jqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfpplfopVfmo1bioVXfn1XdnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTYm1P/tV3EjU4UGyMVHSQrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKikZHiQADR5VRTPVmVP/tl7hoVXZ m1P+s1yDZD8GEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTdnVTcnVTUmFLSllLTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LV mFLZm1PenlTppVfzrFr7sVz+s1z3rlvppVfenlTbnFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFP/ uV+tfkgGEiAgIycpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgnKCgDEB8XHSSackT/t17yq1r5r1ujeEcPGCIm JygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTlpFfdnVRHOy8f IyYxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLio0MCs5MyxBOC5NQDFe SzV1WjuSbUKygkrWmVL1rVr/tV3sp1jbnFTbnFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTfn1X/uF9uVTkADB0q KikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikVGyMDEB9fTDbgoFX/xWPBjE4cICUiJCYoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTnpVfdnVQzLioGEiAaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUZHiQXHSQUGyMPGCILFSEGEiAIEyAWHCQy LypZSDSOakHVmFL/tl74r1ven1XanFPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFPsqFj0rVpCOC4IFCErKikoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgrKikkJScADh8kJSepfkn/vWBURTMOFyIoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgkJicZHiQIEyACDx8rKihy WDq6h0v7sVv5sFvanFTbnFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYmlP/tF3Hj08SGiMdISYpKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgrKikQGCIFEB+TbkNyWDoQGCIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKCgqKSgZHiQBDx4RGSJWRjPAik3/ uV7sp1jYm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTbnFT/uV95XDwACx0rKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr KikiJCYNFiEnKCgqKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSkiJCcBDx8SGSN+YD3rplj6sVzZm1Pb nFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTbnFTuqFnkolYzLyoSGiMqKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKCgmJyclJicp KSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKikdISUADB4vLCrHj0//ul/en1XanFPcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYmlP/ uF+oe0cFESAnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgqKSkHEyAVGyOoe0f/tV3ioVbanFTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTkolbyq1lHPDAMFiIp KSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgtKykTGyMADR6VbkL/uV/hoFXanFPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTam1P/tl6hd0YDEB8oKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgrKikZHyUEER+XcEP/tl3enlXbnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTkolbvqVlIPDAOFyIpKSgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKikZ HiQADh6uf0j/ul/Zm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTZm1P/t16jeEYGEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikRGSMZHyXNk1D5 sFvZm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTppVffn1Q1MCsWHSQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgtKykFEiA1MSvvqVnqpljbnFTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFT/tl12 WzoCEB8pKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgADR6EZD//uV/anFTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFT6sVyxgUkPGCImJigoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgpKSgcICUUGyPEjU74sFvanFPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTioVbtqFhKPjAPGCIoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgsKikBDx9XRjT8slzen1XcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTanFP/t16IZz8DEB8pKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgj JScPGCK4hUv6sFzbnFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT3r1u3hUsWHSQkJicoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSkCDx9tVDj/tl7b nFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTo pVfbnVQ4MiwXHiQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgdISYhIybKklDxqlncnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTenlT1rVpeSzUJFCEo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikADR+AYT3/tl3bnFTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+tFyBYj4GEiAoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgNFyJMPzHtqFjhoFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT8slyjeEYPGCInJycoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgeIiUmJyjJkVDvqlncnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVT0rFq9iE0dISUiJCYoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgnJygOFyKi d0b8slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVToplfYmlM2MSsYHiQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEh+AYj7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTfn1Xxq1lZRzQM FiIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBjTjf2rlrenlXcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTdnlT5sFtvVjkIEyAoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgPGCJOQDHqpljioVXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s1x9Xz0GEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgWHCQ+Ny3dnVTmpFbcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVT9s1yLaEAJEyAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgaHyUx LyrTl1LqpljcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVT7sVyUbkIMFiEnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgeIiYnJyjGj07vqVncnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyZckQO FyImJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgfIyYiIya+iUzyq1ncnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT6sVufdUUQGCImJycoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCggIyYgIyW9iUvyrFrcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT6sFugdkUQGCImJycoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgfIiYlJifCjE3wqlncnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVT6sVufdUUQGCImJycoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgcICUu KynOlFHsqFjcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVT7sVyZckQOFyImJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgXHiQ5NCzanFTnpVfcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyUbkIM FiEnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgSGiJIPTDlo1bjolbcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT+s1yKZ0AIEyAoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgLFSFbSTTyq1nfn1XcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s1x8Xz0GEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgpKCgFEiB2Wzv9slzdnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTdnVT5sFtuVjkIFCAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCGW b0P+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTgn1XwqllYRzQNFiIoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgiJSccICW8iE30rFrcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTpplfWmVMzLysZ HiUoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgUHCM8NS3goFXlo1bcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT0rVq8iEwdISYiJCYoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgqKSkBDx9rUzj/tF3cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT8slyhdkYOFyInJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCglJygPFyKsfkj7sVzbnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVT+tF2AYT4GEiAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgKFSFNQDH0rVrg oFXcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTf n1X0rVpaSTQLFSEoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgDEB+Vb0P/tl7anFTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVToplfanFQ2MSwYHiQo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgRGSMxLirkolbppVfcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT5sFuygkoUGyMlJicoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgpKCgADh6MaUD/tl7anFPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTanFP/t16GZT8DEB8pKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikGEiBH PC/3rlrlo1bbnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTlo1bnpFdCOS4SGiMoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKSgeIiYLFSG8iEz+tF3Zm1PcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFT8slyt fkgMFiEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpKCgoKCgACh19Xzz/t17cnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnVT/tF1uVTkDEB8pKSgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgrKikBDx9RQzL5sFvopVfanFPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTrp1janFQwLSoYHiQoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsKikA Dx4xLiruqFj0rVrYm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTZm1P/uV+YcUQDDx8pKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgrKikFESAtKynbnFT6sVzYmlPc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTnpFfqplc/Ny4QGCIpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgmJygACx02MSvnpFf9s1zYmlPcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1P/uF6TbkIADR4q KSkoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgsKykYHiQADB5YRzTppVf5sFvYmlPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTnpFftqFg9Ni0PGCIpKSgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSkkJScBDx4W HCSSbUL+s13zrFrXmlPcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTYm1P/ul+WcEMBDx4pKSkoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgqKSgmJycIEyAKFCFRQjLIkE//uV7kolbZm1Pc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTanFPyrFrbnFQnJygVHCMpKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0V HCQoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgpKSgnJygZHiQDEB8JEyBPQTKzg0r7sVz3r1vam1PbnFTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTenlT/t15k TzYADR4sKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTmpFfdnVQ/Ni0VHCQoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgmJygiJCYSGiMD EB8LFSEuLCpkTzerfUj0rVr/tFzgn1Xam1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTYmlP/tl63hUsLFSEhJCcoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTopVfdnVQmJicACBwMFiEMFiEMFiEMFiEMFiEMFiEMFiEM FiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiELFSEJFCEGEiAIEyAPGCIbICVBOS53WzuieEbWmVL8slz8 slzhoFXZm1PcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1P0rVrioFYpKCgQGSIrKikoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTjolbdnVRqUjhMPzFaSDRaSDRaSDRaSDRaSDRaSDRaSDRaSDRaSDRaSDRaSDRa SDRaSDRaSDRZSDRaSTRgTDZpUjh3WzuLaECid0a9iUzjolX/tF39slzqplfcnVTbnFTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTbnFTlo1b/tV1aSDQADR4sKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTbnFTcnVTuqVjzrFnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnx qlnzrFn2rlr7sVz+s1z6sVvzrFrkolbbnFTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTdnlT/ u2CNaUEADh4mJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTfn1Xg n1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1XenlTdnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFT/t16vf0kKFCEbICUqKSgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1P/uF7LklARGSISGiMsKikoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTZm1P/tF3Tl1IjJCcMFiEsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTZm1P/ t17Ym1MfISYIEyAtKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTcnVT/tl7Nk1AlJicJFCEsKyko KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTam1PhoFX/u1+7h0wUGyMJFCEsKykoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTYmlPtqFj/uF6bckQQGCIQGCIsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTbnFT+s1zy q1lqUzgDEB8XHSQsKykoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTZm1PnpFf/t17Nk1BAOC4ADB4iJScrKiko KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTanFPdnlT/tF35r1uCYj4TGiMJFCEqKSkpKSgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTb nFTanFT3r1v/tl23hUtJPTAADh4aHyUrKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnFTcnVT1rVr/ul/IkE9eSzUN FiEIEyApKCgqKSgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTanFTen1X7sVz/tF3HkE95XDwbICUADh4jJCcrKikoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgJFCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTbnFTenlTtqFj/tV36sFuzgkphTTYbICUADh4cISUsKikoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJ FCBvVjn3r1venlTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTbnVTdnlTuqFj/tV33r1vTl1GX cUNXRjQRGSIBDx8fIiYqKSkoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgJFCBvVjn3r1venlTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTenlXjolbuqVj6sFv/tF33r1vPlFGTbUJdSjUqKSgGEiAIFCAjJScrKiko KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgIFCBwVzn7slzhoFXfn1Xfn1Xfn1Xfn1Xf n1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xf n1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1Xfn1XgoFXhoFXjolblo1bopVfxq1n6sVv9 s1z9s1z0rFrkolbLkVCrfUiEYz5cSjUqKSgEEB8IEyAcICUoKCgpKSgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEh93Wzv/vmHyq1nwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnw qlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnw qlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnwqlnvqVjsp1jmo1bgn1XZm1PAi02leUaRbEJ7XjxgTDZFOy8p KCgSGSIFER8JFCEcICUpKSgpKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCggIyY7NCxfTDVYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRY RzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRYRzRY RzRYRzRYRzRYRzRYRzRWRjNSQzJLPzBCOS44MiwiJCYQGCIJFCAGEiAKFSESGiMdISUlJicoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgt KykdISUIEyAMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEM FiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEMFiEM FiENFiEOFyIRGSIUGyMYHSQgIyYmJycnJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCC Yz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7 sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT7sVyXcEMNFyEmJygoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCgoKCgoKCgoKCgGEiCCYz7+s1zcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVT9s12SbUIADR0YHiUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUaHyUa HyUaHyUaHyUABxx7Xjz/tV3cnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVT5sFybckQYHiQvLSoxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLiox LioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioxLioRGSOH Zj/8slzcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTe nlTYm1PRllHTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LT l1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LTl1LRllHXmlPenlTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTam1PhoFXsp1jqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplfq plfqplfqplfqplfqplfqplfqplfqplfqplfqplfqplftqFjjolbZm1PcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTT nlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTTnlvTnlvcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTcnVTc nVTcnVTcnVTcnVTTnlv/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/mzr/ mzp1paB4pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14 pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ14pJ11paAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== ================================================ FILE: Caesar/Diogenes/Forms/PickDiagForm.Designer.cs ================================================ namespace Diogenes { partial class PickDiagForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PickDiagForm)); this.dgvMain = new System.Windows.Forms.DataGridView(); this.txtFilter = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.SuspendLayout(); // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.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.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this.dgvMain.Location = new System.Drawing.Point(0, 21); this.dgvMain.Name = "dgvMain"; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.Size = new System.Drawing.Size(800, 429); this.dgvMain.TabIndex = 1; this.dgvMain.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvMain_CellDoubleClick); // // txtFilter // this.txtFilter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtFilter.Location = new System.Drawing.Point(0, 1); this.txtFilter.Name = "txtFilter"; this.txtFilter.Size = new System.Drawing.Size(800, 20); this.txtFilter.TabIndex = 2; this.txtFilter.TextChanged += new System.EventHandler(this.txtFilter_TextChanged); // // PickDiagForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.txtFilter); this.Controls.Add(this.dgvMain); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "PickDiagForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Select Diagnostic Service"; this.Load += new System.EventHandler(this.PickDiagForm_Load); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.TextBox txtFilter; } } ================================================ FILE: Caesar/Diogenes/Forms/PickDiagForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; namespace Diogenes { public partial class PickDiagForm : Form { public DiagService[] DiagServices = new DiagService[] { }; public DiagService SelectedDiagService = null; public PickDiagForm(DiagService[] diagServices) { DiagServices = diagServices; InitializeComponent(); } private void PickDiagForm_Load(object sender, EventArgs e) { UnmanagedUtility.SendMessage(txtFilter.Handle, UnmanagedUtility.EM_SETCUEBANNER, 0, "Search for a diagnostic service.."); EnableDoubleBuffer(dgvMain, true); PresentDiagServices(); } public static void EnableDoubleBuffer(DataGridView dgv, bool setting) { Type dgvType = dgv.GetType(); PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); pi.SetValue(dgv, setting, null); } private void PresentDiagServices() { DataTable dt = new DataTable(); dt.Columns.Add("Index", typeof(String)); dt.Columns.Add("Name", typeof(String)); dt.Columns.Add("Function Type", typeof(String)); dt.Columns.Add("Access Level", typeof(String)); dt.Columns.Add("Security Access Level", typeof(String)); dt.Columns.Add("Input Parameters", typeof(String)); dt.Columns.Add("Output Parameters", typeof(String)); dt.Columns.Add("Command", typeof(String)); string namePartialMatch = txtFilter.Text.ToLower(); for (int i = 0; i < DiagServices.Length; i++) { DiagService diag = DiagServices[i]; if (diag.Qualifier.ToLower().Contains(namePartialMatch)) { dt.Rows.Add(new string[] { i.ToString(), diag.Qualifier, diag.IsExecutable == 1 ? "User" : "System" , diag.ClientAccessLevel.ToString(), diag.SecurityAccessLevel.ToString(), diag.InputPreparations.Count.ToString(), diag.OutputPreparations.Count.ToString(), BitUtility.BytesToHex(diag.RequestBytes, true), }); } } dgvMain.DataSource = dt; // apparently resize+sort is really expensive if (dgvMain.Columns[dgvMain.Columns.Count - 1].AutoSizeMode != DataGridViewAutoSizeColumnMode.Fill) { dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[dgvMain.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgvMain.Columns[0].Visible = false; } /* int colIndex = 0; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.None; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; */ // dgvMain.Sort(dgvMain.Columns[0], ListSortDirection.Ascending); } private void txtFilter_TextChanged(object sender, EventArgs e) { PresentDiagServices(); } private void dgvMain_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (dgvMain.SelectedRows.Count == 1) { int selectedDiagIndex = int.Parse(dgvMain.SelectedRows[0].Cells[0].Value.ToString()); SelectedDiagService = DiagServices[selectedDiagIndex]; this.DialogResult = DialogResult.OK; this.Close(); } } } } ================================================ FILE: Caesar/Diogenes/Forms/PickDiagForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAw5Ftm8OOaP/Ai2b/vohk/7uFYf+5g1//toBe/7R+XP+yfFr/sXtY/655V/+tdlb/q3VU/6lz U/+pcVH/o3BRm8iSbP9SUlL/U1NT/1RUVP9VVVX/VlZW/1dXV/9XV1f/WFhY/1lZWf9aWlr/W1tb/1xc XP9cXFz/XV1d/6lyUf/KlG7/Tk5O/z09Pf89PT3/Pj4+/z8/P/9BQUH/QkJC/0NDQ/9ERET/RUVF/0ZG Rv9GRkb/SEhI/1paWv+qc1P/zJdv/0tLS/84ODj/OTk5/zo6Ov88PDz/PT09/z8/P/8/Pz//QUFB/0JC Qv9CQkL/RERE/0VFRf9XV1f/rHVU/8+acv9HR0f/MzMz/zQ0NP82Njb/Nzc3/zk5Of86Ojr/Ozs7/zw8 PP8+Pj7/Pz8//0BAQP9BQUH/VVVV/614Vv/RnHP/QkJC/y8vL/8wMDD/MTEx/zMzM/80NDT/NjY2/zY2 Nv84ODj/Ojo6/zs7O/89PT3/PT09/1JSUv+welj/1J51/z09Pf8pKSn/0dHR/62trf8uLi7/Ly8v/zEx Mf8yMjL/NDQ0/zY2Nv83Nzf/ODg4/zo6Ov9OTk7/snxa/9Wgdv85OTn/JSUl/yYmJv/e3t7/dHR0/yoq Kv8sLCz/LS0t/y8vL/8xMTH/MjIy/zQ0NP81NTX/S0tL/7V+XP/Yonn/NDQ0/yAgIP/Pz8//qKio/yQk JP8lJSX/JiYm/ygoKP8qKir/LCws/y0tLf8vLy//MTEx/0ZGRv+3gV7/2aN5/zQ0NP8gICD/ISEh/yIi Iv8kJCT/JSUl/yYmJv8oKCj/Kioq/ywsLP8tLS3/Ly8v/zExMf9GRkb/uoVg/9ukev8xMTH/MjIy/zMz M/80NDT/NTU1/zY2Nv83Nzf/OTk5/zs7O/88PDz/PT09/z8/P/9BQUH/Q0ND/72HY//cp3v/26R6/9qj ef/Yonn/16F4/9Wfdv/TnnT/0Zxz/8+acv/Nl3D/y5Vu/8mUbP/HkWv/xI9p/8ONZ//Ai2b/3ayF/fHc zv/qwaD/6LmS/+i5kv/ouZL/6LmS/+i5kv/ouZL/zcjF/+i5kv/NyMX/6LmS/0Rk///oxKf/wZBv/d2s hsLdsY303Kd7/9ymev/apHr/2KJ5/9ihef/VoHb/1J51/9Kdc//PmnL/zplw/8uWb//JlGz/xJp69MOT ccIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/RunDiagForm.Designer.cs ================================================ namespace Diogenes { partial class RunDiagForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RunDiagForm)); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.btnApply = new System.Windows.Forms.Button(); this.btnReinterpret = new System.Windows.Forms.Button(); this.btnCopy = new System.Windows.Forms.Button(); this.txtDiagCommand = new System.Windows.Forms.TextBox(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); // // groupBox2 // this.groupBox2.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.groupBox2.Controls.Add(this.dgvMain); this.groupBox2.Location = new System.Drawing.Point(12, 99); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(1225, 507); this.groupBox2.TabIndex = 3; this.groupBox2.TabStop = false; this.groupBox2.Text = "Diagnostics Parameters"; // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.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.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.Location = new System.Drawing.Point(6, 19); this.dgvMain.Name = "dgvMain"; this.dgvMain.ReadOnly = true; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(1213, 482); this.dgvMain.TabIndex = 0; // // groupBox1 // this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupBox1.Controls.Add(this.btnApply); this.groupBox1.Controls.Add(this.btnReinterpret); this.groupBox1.Controls.Add(this.btnCopy); this.groupBox1.Controls.Add(this.txtDiagCommand); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(1225, 81); this.groupBox1.TabIndex = 2; this.groupBox1.TabStop = false; this.groupBox1.Text = "Computed Command"; // // btnApply // this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnApply.Location = new System.Drawing.Point(1144, 51); this.btnApply.Name = "btnApply"; this.btnApply.Size = new System.Drawing.Size(75, 23); this.btnApply.TabIndex = 5; this.btnApply.Text = "Write"; this.btnApply.UseVisualStyleBackColor = true; this.btnApply.Click += new System.EventHandler(this.btnApply_Click); // // btnReinterpret // this.btnReinterpret.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnReinterpret.Location = new System.Drawing.Point(1063, 51); this.btnReinterpret.Name = "btnReinterpret"; this.btnReinterpret.Size = new System.Drawing.Size(75, 23); this.btnReinterpret.TabIndex = 4; this.btnReinterpret.Text = "Reinterpret"; this.btnReinterpret.UseVisualStyleBackColor = true; // // btnCopy // this.btnCopy.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnCopy.Location = new System.Drawing.Point(982, 51); this.btnCopy.Name = "btnCopy"; this.btnCopy.Size = new System.Drawing.Size(75, 23); this.btnCopy.TabIndex = 3; this.btnCopy.Text = "Copy"; this.btnCopy.UseVisualStyleBackColor = true; // // txtDiagCommand // this.txtDiagCommand.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtDiagCommand.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtDiagCommand.Location = new System.Drawing.Point(6, 19); this.txtDiagCommand.Name = "txtDiagCommand"; this.txtDiagCommand.Size = new System.Drawing.Size(1213, 26); this.txtDiagCommand.TabIndex = 0; // // RunDiagForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1249, 618); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "RunDiagForm"; this.Text = "Execute Diagnostic Service"; this.Load += new System.EventHandler(this.RunDiagForm_Load); this.groupBox2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Button btnApply; private System.Windows.Forms.Button btnReinterpret; private System.Windows.Forms.Button btnCopy; private System.Windows.Forms.TextBox txtDiagCommand; } } ================================================ FILE: Caesar/Diogenes/Forms/RunDiagForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; namespace Diogenes { public partial class RunDiagForm : Form { public DiagService CurrentDiagService; public byte[] Result = Array.Empty(); public RunDiagForm(DiagService diagService) { CurrentDiagService = diagService; Result = CurrentDiagService.RequestBytes; InitializeComponent(); } private void RunDiagForm_Load(object sender, EventArgs e) { this.Text = $"Run Diagnostics Service: {CurrentDiagService.Qualifier}"; TrimIntegerDumps(); txtDiagCommand.Text = BitUtility.BytesToHex(Result, true); if (!CheckBitAlignment()) { MessageBox.Show("One or more parameters are placed between byte boundaries. This isn't supported yet.", "Parameter misalignment"); this.Close(); return; } PresentDiagService(); } private void TrimIntegerDumps() { // integer dumps are always saved as LE int32, even if they are not int32 foreach (DiagPreparation prep in CurrentDiagService.InputPreparations) { if (prep.FieldType == DiagPreparation.InferredDataType.IntegerType) { int byteSize = prep.SizeInBits / 8; if (prep.Dump.Length > byteSize) { prep.Dump = prep.Dump.Take(byteSize).ToArray(); } } } } private bool CheckBitAlignment() { // example service that fails this check: /* MED40: IOC_Getriebeanwaermung_Absperrventil_Getriebeanwaermung_Absperrventil User 1 0 5 1 2F D1 05 03 00 */ foreach (DiagPreparation prep in CurrentDiagService.InputPreparations) { if (prep.BitPosition % 8 != 0) { return false; } if (prep.SizeInBits % 8 != 0) { return false; } } return true; } private void PresentDiagService() { DataTable dt = new DataTable(); dt.Columns.Add("Index", typeof(int)); dt.Columns.Add("Name", typeof(String)); dt.Columns.Add("Byte Position", typeof(int)); dt.Columns.Add("Data Size", typeof(int)); dt.Columns.Add("Data Type", typeof(String)); dt.Columns.Add("Inferred Type", typeof(String)); dt.Columns.Add("Direction", typeof(String)); dt.Columns.Add("Raw Data", typeof(String)); int listUniqueIndex = 0; for (int i = 0; i < CurrentDiagService.InputPreparations.Count; i++) { DiagPreparation prep = CurrentDiagService.InputPreparations[i]; dt.Rows.Add(new object[] { listUniqueIndex, prep.Qualifier, prep.BitPosition / 8, prep.SizeInBits / 8, prep.ModeConfig.ToString("X"), prep.FieldType.ToString(), "Input", BitUtility.BytesToHex(prep.Dump, true), }); listUniqueIndex++; } for (int i = 0; i < CurrentDiagService.OutputPreparations.Count; i++) { List currentDiagList = CurrentDiagService.OutputPreparations[i]; for (int j = 0; j < currentDiagList.Count; j++) { DiagPreparation prep = CurrentDiagService.OutputPreparations[i][j]; dt.Rows.Add(new object[] { listUniqueIndex, prep.Qualifier, prep.BitPosition / 8, prep.SizeInBits / 8, prep.ModeConfig.ToString("X"), prep.FieldType.ToString(), $"Output ({i})", BitUtility.BytesToHex(prep.Dump, true), }); listUniqueIndex++; } } dgvMain.DataSource = dt; int colIndex = 0; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.None; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[colIndex++].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgvMain.Columns[0].Visible = false; dgvMain.Columns[4].Visible = false; // dgvMain.Columns[6].Visible = false; dgvMain.Sort(dgvMain.Columns[0], ListSortDirection.Ascending); } private void btnApply_Click(object sender, EventArgs e) { string commandAsString = txtDiagCommand.Text; if (!BitUtility.CheckHexValid(commandAsString)) { MessageBox.Show("Hex data could not be parsed. Please check if there are any invalid values", "Write Variant Coding"); return; } Result = BitUtility.BytesFromHex(commandAsString); this.DialogResult = DialogResult.OK; this.Close(); } } } ================================================ FILE: Caesar/Diogenes/Forms/RunDiagForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAw5Ftm8OOaP/Ai2b/vohk/7uFYf+5g1//toBe/7R+XP+yfFr/sXtY/655V/+tdlb/q3VU/6lz U/+pcVH/o3BRm8iSbP9SUlL/U1NT/1RUVP9VVVX/VlZW/1dXV/9XV1f/WFhY/1lZWf9aWlr/W1tb/1xc XP9cXFz/XV1d/6lyUf/KlG7/Tk5O/z09Pf89PT3/Pj4+/z8/P/9BQUH/QkJC/0NDQ/9ERET/RUVF/0ZG Rv9GRkb/SEhI/1paWv+qc1P/zJdv/0tLS/84ODj/OTk5/zo6Ov88PDz/PT09/z8/P/8/Pz//QUFB/0JC Qv9CQkL/RERE/0VFRf9XV1f/rHVU/8+acv9HR0f/MzMz/zQ0NP82Njb/Nzc3/zk5Of86Ojr/Ozs7/zw8 PP8+Pj7/Pz8//0BAQP9BQUH/VVVV/614Vv/RnHP/QkJC/y8vL/8wMDD/MTEx/zMzM/80NDT/NjY2/zY2 Nv84ODj/Ojo6/zs7O/89PT3/PT09/1JSUv+welj/1J51/z09Pf8pKSn/0dHR/62trf8uLi7/Ly8v/zEx Mf8yMjL/NDQ0/zY2Nv83Nzf/ODg4/zo6Ov9OTk7/snxa/9Wgdv85OTn/JSUl/yYmJv/e3t7/dHR0/yoq Kv8sLCz/LS0t/y8vL/8xMTH/MjIy/zQ0NP81NTX/S0tL/7V+XP/Yonn/NDQ0/yAgIP/Pz8//qKio/yQk JP8lJSX/JiYm/ygoKP8qKir/LCws/y0tLf8vLy//MTEx/0ZGRv+3gV7/2aN5/zQ0NP8gICD/ISEh/yIi Iv8kJCT/JSUl/yYmJv8oKCj/Kioq/ywsLP8tLS3/Ly8v/zExMf9GRkb/uoVg/9ukev8xMTH/MjIy/zMz M/80NDT/NTU1/zY2Nv83Nzf/OTk5/zs7O/88PDz/PT09/z8/P/9BQUH/Q0ND/72HY//cp3v/26R6/9qj ef/Yonn/16F4/9Wfdv/TnnT/0Zxz/8+acv/Nl3D/y5Vu/8mUbP/HkWv/xI9p/8ONZ//Ai2b/3ayF/fHc zv/qwaD/6LmS/+i5kv/ouZL/6LmS/+i5kv/ouZL/zcjF/+i5kv/NyMX/6LmS/0Rk///oxKf/wZBv/d2s hsLdsY303Kd7/9ymev/apHr/2KJ5/9ihef/VoHb/1J51/9Kdc//PmnL/zplw/8uWb//JlGz/xJp69MOT ccIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/SecurityLevelForm.Designer.cs ================================================ namespace Diogenes { partial class SecurityLevelForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SecurityLevelForm)); this.txtChallenge = new System.Windows.Forms.TextBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.SuspendLayout(); // // txtChallenge // this.txtChallenge.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtChallenge.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtChallenge.Location = new System.Drawing.Point(6, 19); this.txtChallenge.Name = "txtChallenge"; this.txtChallenge.Size = new System.Drawing.Size(764, 26); this.txtChallenge.TabIndex = 1; this.txtChallenge.TextChanged += new System.EventHandler(this.txtCodingString_TextChanged); // // groupBox1 // this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupBox1.Controls.Add(this.txtChallenge); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(776, 54); this.groupBox1.TabIndex = 2; this.groupBox1.TabStop = false; this.groupBox1.Text = "Input Seed"; // // groupBox2 // this.groupBox2.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.groupBox2.Controls.Add(this.dgvMain); this.groupBox2.Location = new System.Drawing.Point(12, 72); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(776, 366); this.groupBox2.TabIndex = 3; this.groupBox2.TabStop = false; this.groupBox2.Text = "Available Key Responses"; // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.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.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this.dgvMain.Location = new System.Drawing.Point(6, 19); this.dgvMain.Name = "dgvMain"; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.Size = new System.Drawing.Size(764, 341); this.dgvMain.TabIndex = 0; this.dgvMain.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvMain_CellDoubleClick); // // SecurityLevelForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "SecurityLevelForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Configure Security Level"; this.Load += new System.EventHandler(this.SecurityLevelForm_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.groupBox2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TextBox txtChallenge; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.DataGridView dgvMain; } } ================================================ FILE: Caesar/Diogenes/Forms/SecurityLevelForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; using Diogenes.SecurityAccess; namespace Diogenes { public partial class SecurityLevelForm : Form { public int RequestedSecurityLevel = -1; public byte[] InputChallenge = new byte[] { }; public byte[] KeyResponse = new byte[] { }; DllContext Context; private const string invalidSeedPrompt = "(double-click to request for seed)"; public SecurityLevelForm(DllContext context) { InitializeComponent(); Context = context; } private void PresentKeys(byte[] seed) { DataTable dt = new DataTable(); dt.Columns.Add("Access Level", typeof(String)); dt.Columns.Add("Key", typeof(String)); for (int i = 0; i < Context.AccessLevels.Count; i++) { if (Context.AccessLevels[i].Item3 == seed.Length) { DataRow row = dt.Rows.Add(new string[] { Context.AccessLevels[i].Item1.ToString(), Context.GenerateKeyAuto(Context.AccessLevels[i].Item1, seed) }); } else { dt.Rows.Add(new string[] { Context.AccessLevels[i].Item1.ToString(), invalidSeedPrompt }); } } dgvMain.DataSource = dt; dgvMain.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgvMain.Sort(dgvMain.Columns[0], ListSortDirection.Ascending); } private void SecurityLevelForm_Load(object sender, EventArgs e) { // dj_zugriffsberechtigung this.Text = $"Configure Security Level - {Context.ECUName}"; txtChallenge.Text = BitUtility.BytesToHex(InputChallenge, true); PresentKeys(new byte[] { }); } private void txtCodingString_TextChanged(object sender, EventArgs e) { TryRefreshKey(); } public void TryRefreshKey() { bool validHex = true; string cleanedText = txtChallenge.Text.Replace(" ", "").Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("-", "").ToUpper(); if (cleanedText.Length % 2 != 0) { validHex = false; } if (!System.Text.RegularExpressions.Regex.IsMatch(cleanedText, @"\A\b[0-9a-fA-F]+\b\Z")) { validHex = false; } if (validHex) { byte[] seed = BitUtility.BytesFromHex(cleanedText); txtChallenge.BackColor = System.Drawing.SystemColors.Window; PresentKeys(seed); } else { if (cleanedText.Length == 0) { PresentKeys(new byte[] { }); } txtChallenge.BackColor = System.Drawing.Color.LavenderBlush; } } private void dgvMain_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (dgvMain.SelectedRows.Count == 1) { int selectedLevel = int.Parse(dgvMain.SelectedRows[0].Cells[0].Value.ToString()); string selectedValue = dgvMain.SelectedRows[0].Cells[1].Value.ToString(); if (selectedValue == invalidSeedPrompt) { Console.WriteLine($"Security Access: Requesting seed for level {selectedLevel}"); RequestSeed(selectedLevel); } else { KeyResponse = BitUtility.BytesFromHex(selectedValue); RequestedSecurityLevel = selectedLevel; DialogResult = DialogResult.OK; this.Close(); } } } private void RequestSeed(int accessLevel) { // since we have no connection at the moment, feed in a dummy value int seedSize = Context.AccessLevels.Find(x => x.Item1 == accessLevel).Item3; txtChallenge.Text = BitUtility.BytesToHex(new byte[seedSize]); } } } ================================================ FILE: Caesar/Diogenes/Forms/SecurityLevelForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAA2ndn/MZnY/yyU1/8okNb/I4zV/x6I1P8ahNP/FYDS/xF80f8OedH/CnbQ/wdzz/8EcM//AW7O/wAA AAAAAAAAPaPa/7zr+v+86/z/v+7+/8b0///O+P//0/r//9D4///H8v//uun8/7Pk+f+w4vj/sOL4/wVx z/8AAAAAAAAAAEOo2/+/7Pv/Wc/1/0Gw7P8TQVr/KWGJ/0mJvv9Imsj/SK7n/zel5v8qmuH/OLju/7Hj +P8JddD/AAAAAAAAAABJrdz/we77/1/T9/9s2/z/LGeF/5TH+f+Ryfn/QYXJ/yFqrv9Tvez/Rr7v/zy6 7v+z4/n/DnnR/wAAAAAAAAAATrLd/8Pv+/9l1vj/TLbs/0OJqv/g8v//VJrY/xp6vv9JmMX/NYbF/zOb 3v9Cvu//tOX5/xN+0v8AAAAAAAAAAFO33v/G8Pz/atn4/3zi/f9jt9n/erbV/5C30f9VyeT/W9/1/3jQ 7f9CmNz/RLrt/7bn+f8Yg9P/AAAAAAAAAABYu9//x/H8/2/c+f9Wu+3/Yb3v/3HG5/9yuNb/wvb9/2Pf 9/9d4vj/edPw/0OX3P+o3PX/HojU/wAAAAAAAAAAXL/g/8jz/P913/n/ieb9/5Xn//+a5f//ecrn/3fL 5//H9/3/Xtz1/1rh9/971PH/SJne/yiN1v8AAAAAAAAAAGDC4f/J8/z/y/P9/9T2/v/X9v//2PT//+D4 //+p4/X/edPu/8f3/f9f3PX/W+L3/3rW8v8+mN7/RI3NMAAAAABhw+H/iKCo/5GRkf+Ojo7/Wrnc/1W4 3/9Rtd7/TbHd/z+w3v981O7/xPb9/2zd9v9tyu3/Y6PX/12b0uxRksomAAAAAJmZmcPGxsb/lJSU/wAA AAgAAAAAAAAAAAAAAAAAAAAAJ7LdWn7T6/+y4/n/i8Dn/67T9v/E4Pz/Zp/T9wAAAACdnZ2uxMTE/6Gh of+Tk5MpAAAAAAAAAAAAAAAAAAAAAIKCgilkman/d77n/7TS8P/l8///rNLv/0iMx+gAAAAAoaGhdbq6 uv+/v7//mJiY3ZSUlB8AAAAFAAAABYqKih+Hh4flqKio/3uks/9Ypdj/hbHb/0ad0P8rldFeAAAAAKSk pAyhoaHbxMTE/76+vv+hoaH/lpaW/5OTk/+Xl5f/rq6u/66urv+EhITbAAAACQAAAAAAAAAAAAAAAAAA AAAAAAAApKSkMKKiot68vLz/ysrK/8zMzP/Kysr/wsLC/62trf+MjIzeiYmJMAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAClpaUMo6OjgaCgoLqdnZ3MmpqazJeXl7qUlJSBkJCQDAAAAAAAAAAAAAAAAAAA AAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAQAAAAAAAI+AAACHgAAAgwAAAIAP AADADwAA4B8AAA== ================================================ FILE: Caesar/Diogenes/Forms/TraceForm.Designer.cs ================================================  namespace Diogenes { partial class TraceForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TraceForm)); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.copyAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveToFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.txtTrace = new System.Windows.Forms.TextBox(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; this.menuStrip1.Size = new System.Drawing.Size(800, 24); this.menuStrip1.TabIndex = 0; this.menuStrip1.Text = "menuStrip1"; // // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.copyAllToolStripMenuItem, this.saveToFileToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // // copyAllToolStripMenuItem // this.copyAllToolStripMenuItem.Name = "copyAllToolStripMenuItem"; this.copyAllToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.C))); this.copyAllToolStripMenuItem.Size = new System.Drawing.Size(193, 22); this.copyAllToolStripMenuItem.Text = "Copy All"; this.copyAllToolStripMenuItem.Click += new System.EventHandler(this.copyAllToolStripMenuItem_Click); // // saveToFileToolStripMenuItem // this.saveToFileToolStripMenuItem.Name = "saveToFileToolStripMenuItem"; this.saveToFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); this.saveToFileToolStripMenuItem.Size = new System.Drawing.Size(193, 22); this.saveToFileToolStripMenuItem.Text = "Save to file"; this.saveToFileToolStripMenuItem.Click += new System.EventHandler(this.saveToFileToolStripMenuItem_Click); // // txtTrace // this.txtTrace.Dock = System.Windows.Forms.DockStyle.Fill; this.txtTrace.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtTrace.Location = new System.Drawing.Point(0, 24); this.txtTrace.Multiline = true; this.txtTrace.Name = "txtTrace"; this.txtTrace.ReadOnly = true; this.txtTrace.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtTrace.Size = new System.Drawing.Size(800, 426); this.txtTrace.TabIndex = 1; // // TraceForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.txtTrace); this.Controls.Add(this.menuStrip1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MainMenuStrip = this.menuStrip1; this.Name = "TraceForm"; this.Text = "Trace"; this.Load += new System.EventHandler(this.TraceForm_Load); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem copyAllToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveToFileToolStripMenuItem; private System.Windows.Forms.TextBox txtTrace; } } ================================================ FILE: Caesar/Diogenes/Forms/TraceForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { // trace is generally quite hacky since I did not plan for this early public partial class TraceForm : Form { MainForm ParentMainForm = new MainForm(); Timer RefreshTimer = new Timer(); public TraceForm(MainForm parentMainForm) { ParentMainForm = parentMainForm; InitializeComponent(); } private void TraceForm_Load(object sender, EventArgs e) { RefreshTimer.Interval = 50; RefreshTimer.Tick += RefreshTimer_Tick; RefreshTimer.Start(); } private void RefreshTimer_Tick(object sender, EventArgs e) { if ((ParentMainForm is null) || (ParentMainForm.Connection is null)) { return; } if (txtTrace.Text.Length != ParentMainForm.Connection.CommunicationsLogHighLevel.Length) { lock (ParentMainForm.Connection.WriteLock) { txtTrace.Text = ParentMainForm.Connection.CommunicationsLogHighLevel.ToString(); } txtTrace.SelectionStart = txtTrace.TextLength; txtTrace.ScrollToCaret(); } } private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetText(txtTrace.Text); } private void saveToFileToolStripMenuItem_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your trace"; sfd.Filter = "txt file (*.txt)|*.txt|All files (*.*)|*.*"; sfd.FileName = $"Trace_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.txt"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllText(sfd.FileName, txtTrace.Text); } } } } ================================================ FILE: Caesar/Diogenes/Forms/TraceForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuIdYHLiHWK64h1gsAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiHWAy4h1jxuIdY97iHWDIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuIdY2eLOuv+4h1j4uIdYMQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuIdYVbiHWPH59vH/4s25/7iH WP64h1jcuIdY07iHWJG4h1gPAAAAAAAAAAC4h1gVuIdYgbiHWCEAAAAAuIdYh8+ujv/r3tH//fz6//38 +v/9+/j/9Ovj//Hn3f/YvqP/uIdY9riHWHIAAAAAAAAACbiHWLO4h1i3uIdYJbiHWOj48ez//fv4//jw 5//37+b/9+7k//jw6P/48er//fv5//Lp4P+4h1jYAAAAAAAAAAC4h1ih4s66vbiHWLi4h1jz+vfy//rz 7P/48en/+PDn//fv5v/37uT/9uzi//fv5//07OX/uIdY3wAAAAC4h1g8uIdYqvbw6b3izbm9uIdY+/r2 8f/69O7/+fLq//jx6f/48Oj/9+/m//fu5P/48en/8+ri/7iHWNq4h1hkzqyMverczr39/Pq9/fz6vbqL Xfv69vL/+vXv//r07v/68+3/+fPr//ny6//48en/+vXv//Pq4v+4h1jauIdYrPjx7L39+/m9+PDnvffv 5r3FnHXw5NG+//r28v/69vH/+vbx//r18f/69fH/+vXw//bw6f/cxK3/uIdYrbiHWLP69/K9+vPsvfjx 6b348Oe95tPAy8Sbc+67jF77u4xf+7uMXvu4h1j5uIdY77iHWO+4h1jkuIdYhriHWCi4h1iy+vbxvfr0 7r358uq9+PHpvfjw6L337+a99+7kvfjx6b3z6uK9uIdYogAAAAAAAAAAAAAAAAAAAAAAAAAAuIdYsvr2 8r369e+9+vTuvfrz7b358+u9+fLrvfjx6b369e+98+rivbiHWKIAAAAAAAAAAAAAAAAAAAAAAAAAALiH WJHk0b69+vbyvfr28b369vG9+vXxvfr18b369fC99vDpvdzErb24h1iAAAAAAAAAAAAAAAAAAAAAAAAA AAC4h1gouIdYjriHWLG4h1ixuIdYsbiHWLG4h1ixuIdYsbiHWKm4h1hjuIdYHgAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAPx/AAD8PwAA/h8AAPwBAACIAAAAwAAAAMAAAACAAAAAAAAAAAAAAAAAAAAAAB8AAAAf AAAAHwAAAB8AAA== ================================================ FILE: Caesar/Diogenes/Forms/UDSHexEditor.Designer.cs ================================================  namespace Diogenes { partial class UDSHexEditor { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UDSHexEditor)); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.gbInputOutput = new System.Windows.Forms.GroupBox(); this.chkSendAlfid = new System.Windows.Forms.CheckBox(); this.lblDescCmdWrite = new System.Windows.Forms.Label(); this.nudWriteCmd = new System.Windows.Forms.NumericUpDown(); this.lblDescCmdRead = new System.Windows.Forms.Label(); this.nudReadCmd = new System.Windows.Forms.NumericUpDown(); this.lblDescIOWidth = new System.Windows.Forms.Label(); this.nudIOWidth = new System.Windows.Forms.NumericUpDown(); this.lblDescWidth = new System.Windows.Forms.Label(); this.nudAddressWidth = new System.Windows.Forms.NumericUpDown(); this.gbOperation = new System.Windows.Forms.GroupBox(); this.btnSaveToFile = new System.Windows.Forms.Button(); this.btnWrite = new System.Windows.Forms.Button(); this.btnRead = new System.Windows.Forms.Button(); this.gbDestination = new System.Windows.Forms.GroupBox(); this.txtDestination = new System.Windows.Forms.TextBox(); this.rbSize = new System.Windows.Forms.RadioButton(); this.rbAddress = new System.Windows.Forms.RadioButton(); this.gbSource = new System.Windows.Forms.GroupBox(); this.txtSource = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.SuspendLayout(); this.gbInputOutput.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudWriteCmd)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudReadCmd)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudIOWidth)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudAddressWidth)).BeginInit(); this.gbOperation.SuspendLayout(); this.gbDestination.SuspendLayout(); this.gbSource.SuspendLayout(); this.SuspendLayout(); // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 0); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 // this.splitContainer1.Panel1.Controls.Add(this.gbInputOutput); this.splitContainer1.Panel1.Controls.Add(this.gbOperation); this.splitContainer1.Panel1.Controls.Add(this.gbDestination); this.splitContainer1.Panel1.Controls.Add(this.gbSource); this.splitContainer1.Size = new System.Drawing.Size(929, 595); this.splitContainer1.SplitterDistance = 285; this.splitContainer1.TabIndex = 0; // // gbInputOutput // this.gbInputOutput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.gbInputOutput.Controls.Add(this.chkSendAlfid); this.gbInputOutput.Controls.Add(this.lblDescCmdWrite); this.gbInputOutput.Controls.Add(this.nudWriteCmd); this.gbInputOutput.Controls.Add(this.lblDescCmdRead); this.gbInputOutput.Controls.Add(this.nudReadCmd); this.gbInputOutput.Controls.Add(this.lblDescIOWidth); this.gbInputOutput.Controls.Add(this.nudIOWidth); this.gbInputOutput.Controls.Add(this.lblDescWidth); this.gbInputOutput.Controls.Add(this.nudAddressWidth); this.gbInputOutput.Location = new System.Drawing.Point(12, 289); this.gbInputOutput.Name = "gbInputOutput"; this.gbInputOutput.Size = new System.Drawing.Size(264, 295); this.gbInputOutput.TabIndex = 7; this.gbInputOutput.TabStop = false; this.gbInputOutput.Text = "I/O"; // // chkSendAlfid // this.chkSendAlfid.AutoSize = true; this.chkSendAlfid.Checked = true; this.chkSendAlfid.CheckState = System.Windows.Forms.CheckState.Checked; this.chkSendAlfid.Location = new System.Drawing.Point(9, 270); this.chkSendAlfid.Name = "chkSendAlfid"; this.chkSendAlfid.Size = new System.Drawing.Size(227, 17); this.chkSendAlfid.TabIndex = 10; this.chkSendAlfid.Text = "AddressAndLengthFormatID (KW: Disable)"; this.chkSendAlfid.UseVisualStyleBackColor = true; // // lblDescCmdWrite // this.lblDescCmdWrite.AutoSize = true; this.lblDescCmdWrite.Location = new System.Drawing.Point(5, 213); this.lblDescCmdWrite.Name = "lblDescCmdWrite"; this.lblDescCmdWrite.Size = new System.Drawing.Size(147, 13); this.lblDescCmdWrite.TabIndex = 9; this.lblDescCmdWrite.Text = "WriteMemoryByAddress (Hex)"; // // nudWriteCmd // this.nudWriteCmd.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudWriteCmd.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudWriteCmd.Hexadecimal = true; this.nudWriteCmd.Location = new System.Drawing.Point(6, 232); this.nudWriteCmd.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.nudWriteCmd.Name = "nudWriteCmd"; this.nudWriteCmd.Size = new System.Drawing.Size(250, 32); this.nudWriteCmd.TabIndex = 8; this.nudWriteCmd.Value = new decimal(new int[] { 61, 0, 0, 0}); // // lblDescCmdRead // this.lblDescCmdRead.AutoSize = true; this.lblDescCmdRead.Location = new System.Drawing.Point(5, 149); this.lblDescCmdRead.Name = "lblDescCmdRead"; this.lblDescCmdRead.Size = new System.Drawing.Size(148, 13); this.lblDescCmdRead.TabIndex = 7; this.lblDescCmdRead.Text = "ReadMemoryByAddress (Hex)"; // // nudReadCmd // this.nudReadCmd.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudReadCmd.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudReadCmd.Hexadecimal = true; this.nudReadCmd.Location = new System.Drawing.Point(6, 168); this.nudReadCmd.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.nudReadCmd.Name = "nudReadCmd"; this.nudReadCmd.Size = new System.Drawing.Size(250, 32); this.nudReadCmd.TabIndex = 6; this.nudReadCmd.Value = new decimal(new int[] { 35, 0, 0, 0}); // // lblDescIOWidth // this.lblDescIOWidth.AutoSize = true; this.lblDescIOWidth.Location = new System.Drawing.Point(5, 85); this.lblDescIOWidth.Name = "lblDescIOWidth"; this.lblDescIOWidth.Size = new System.Drawing.Size(82, 13); this.lblDescIOWidth.TabIndex = 5; this.lblDescIOWidth.Text = "I/O Width (Hex)"; // // nudIOWidth // this.nudIOWidth.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudIOWidth.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudIOWidth.Hexadecimal = true; this.nudIOWidth.Location = new System.Drawing.Point(6, 104); this.nudIOWidth.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.nudIOWidth.Minimum = new decimal(new int[] { 1, 0, 0, 0}); this.nudIOWidth.Name = "nudIOWidth"; this.nudIOWidth.Size = new System.Drawing.Size(250, 32); this.nudIOWidth.TabIndex = 4; this.nudIOWidth.Value = new decimal(new int[] { 16, 0, 0, 0}); // // lblDescWidth // this.lblDescWidth.AutoSize = true; this.lblDescWidth.Location = new System.Drawing.Point(6, 21); this.lblDescWidth.Name = "lblDescWidth"; this.lblDescWidth.Size = new System.Drawing.Size(76, 13); this.lblDescWidth.TabIndex = 3; this.lblDescWidth.Text = "Address Width"; // // nudAddressWidth // this.nudAddressWidth.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.nudAddressWidth.Font = new System.Drawing.Font("Consolas", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudAddressWidth.Hexadecimal = true; this.nudAddressWidth.Location = new System.Drawing.Point(8, 40); this.nudAddressWidth.Maximum = new decimal(new int[] { 5, 0, 0, 0}); this.nudAddressWidth.Minimum = new decimal(new int[] { 1, 0, 0, 0}); this.nudAddressWidth.Name = "nudAddressWidth"; this.nudAddressWidth.Size = new System.Drawing.Size(250, 32); this.nudAddressWidth.TabIndex = 2; this.nudAddressWidth.Value = new decimal(new int[] { 4, 0, 0, 0}); // // gbOperation // this.gbOperation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.gbOperation.Controls.Add(this.btnSaveToFile); this.gbOperation.Controls.Add(this.btnWrite); this.gbOperation.Controls.Add(this.btnRead); this.gbOperation.Location = new System.Drawing.Point(12, 171); this.gbOperation.Name = "gbOperation"; this.gbOperation.Size = new System.Drawing.Size(264, 112); this.gbOperation.TabIndex = 6; this.gbOperation.TabStop = false; this.gbOperation.Text = "Operation"; // // btnSaveToFile // this.btnSaveToFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnSaveToFile.Location = new System.Drawing.Point(8, 77); this.btnSaveToFile.Name = "btnSaveToFile"; this.btnSaveToFile.Size = new System.Drawing.Size(250, 23); this.btnSaveToFile.TabIndex = 2; this.btnSaveToFile.Text = "Save Displayed Data"; this.btnSaveToFile.UseVisualStyleBackColor = true; this.btnSaveToFile.Click += new System.EventHandler(this.btnSaveToFile_Click); // // btnWrite // this.btnWrite.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnWrite.Location = new System.Drawing.Point(8, 48); this.btnWrite.Name = "btnWrite"; this.btnWrite.Size = new System.Drawing.Size(250, 23); this.btnWrite.TabIndex = 1; this.btnWrite.Text = "Write"; this.btnWrite.UseVisualStyleBackColor = true; this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click); // // btnRead // this.btnRead.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnRead.Location = new System.Drawing.Point(8, 19); this.btnRead.Name = "btnRead"; this.btnRead.Size = new System.Drawing.Size(250, 23); this.btnRead.TabIndex = 0; this.btnRead.Text = "Read"; this.btnRead.UseVisualStyleBackColor = true; this.btnRead.Click += new System.EventHandler(this.btnRead_Click); // // gbDestination // this.gbDestination.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.gbDestination.Controls.Add(this.txtDestination); this.gbDestination.Controls.Add(this.rbSize); this.gbDestination.Controls.Add(this.rbAddress); this.gbDestination.Location = new System.Drawing.Point(12, 78); this.gbDestination.Name = "gbDestination"; this.gbDestination.Size = new System.Drawing.Size(264, 87); this.gbDestination.TabIndex = 3; this.gbDestination.TabStop = false; this.gbDestination.Text = "Destination (Hex)"; // // txtDestination // this.txtDestination.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtDestination.Font = new System.Drawing.Font("Consolas", 16F); this.txtDestination.Location = new System.Drawing.Point(8, 19); this.txtDestination.Name = "txtDestination"; this.txtDestination.Size = new System.Drawing.Size(250, 32); this.txtDestination.TabIndex = 3; this.txtDestination.Text = "0"; // // rbSize // this.rbSize.AutoSize = true; this.rbSize.Location = new System.Drawing.Point(77, 57); this.rbSize.Name = "rbSize"; this.rbSize.Size = new System.Drawing.Size(45, 17); this.rbSize.TabIndex = 5; this.rbSize.Text = "Size"; this.rbSize.UseVisualStyleBackColor = true; // // rbAddress // this.rbAddress.AutoSize = true; this.rbAddress.Checked = true; this.rbAddress.Location = new System.Drawing.Point(8, 57); this.rbAddress.Name = "rbAddress"; this.rbAddress.Size = new System.Drawing.Size(63, 17); this.rbAddress.TabIndex = 4; this.rbAddress.TabStop = true; this.rbAddress.Text = "Address"; this.rbAddress.UseVisualStyleBackColor = true; // // gbSource // this.gbSource.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.gbSource.Controls.Add(this.txtSource); this.gbSource.Location = new System.Drawing.Point(12, 12); this.gbSource.Name = "gbSource"; this.gbSource.Size = new System.Drawing.Size(264, 60); this.gbSource.TabIndex = 2; this.gbSource.TabStop = false; this.gbSource.Text = "Source Address (Hex)"; // // txtSource // this.txtSource.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtSource.Font = new System.Drawing.Font("Consolas", 16F); this.txtSource.Location = new System.Drawing.Point(8, 19); this.txtSource.Name = "txtSource"; this.txtSource.Size = new System.Drawing.Size(250, 32); this.txtSource.TabIndex = 2; this.txtSource.Text = "0"; // // UDSHexEditor // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(929, 595); this.Controls.Add(this.splitContainer1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "UDSHexEditor"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "UDS Hex Editor"; this.Load += new System.EventHandler(this.UDSHexEditor_Load); this.splitContainer1.Panel1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); this.gbInputOutput.ResumeLayout(false); this.gbInputOutput.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudWriteCmd)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudReadCmd)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudIOWidth)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudAddressWidth)).EndInit(); this.gbOperation.ResumeLayout(false); this.gbDestination.ResumeLayout(false); this.gbDestination.PerformLayout(); this.gbSource.ResumeLayout(false); this.gbSource.PerformLayout(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.GroupBox gbOperation; private System.Windows.Forms.Button btnWrite; private System.Windows.Forms.Button btnRead; private System.Windows.Forms.GroupBox gbDestination; private System.Windows.Forms.RadioButton rbSize; private System.Windows.Forms.RadioButton rbAddress; private System.Windows.Forms.GroupBox gbSource; private System.Windows.Forms.GroupBox gbInputOutput; private System.Windows.Forms.Label lblDescWidth; private System.Windows.Forms.NumericUpDown nudAddressWidth; private System.Windows.Forms.Label lblDescCmdWrite; private System.Windows.Forms.NumericUpDown nudWriteCmd; private System.Windows.Forms.Label lblDescCmdRead; private System.Windows.Forms.NumericUpDown nudReadCmd; private System.Windows.Forms.Label lblDescIOWidth; private System.Windows.Forms.NumericUpDown nudIOWidth; private System.Windows.Forms.TextBox txtDestination; private System.Windows.Forms.TextBox txtSource; private System.Windows.Forms.Button btnSaveToFile; private System.Windows.Forms.CheckBox chkSendAlfid; } } ================================================ FILE: Caesar/Diogenes/Forms/UDSHexEditor.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using Be.Windows.Forms; using Caesar; using System.Globalization; namespace Diogenes { public partial class UDSHexEditor : Form { ECUConnection Connection; HexBox Hexbox; byte[] OriginalBuffer = new byte[] { }; public UDSHexEditor(ECUConnection connection) { InitializeComponent(); Connection = connection; // missing docs for HexBox : https://stackoverflow.com/questions/53410380/how-to-create-hex-editor-inside-of-winforms-app Hexbox = new HexBox() { /* UseFixedBytesPerLine = true, BytesPerLine = 16, */ ColumnInfoVisible = true, LineInfoVisible = true, StringViewVisible = true, VScrollBarVisible = true }; Hexbox.Dock = DockStyle.Fill; splitContainer1.Panel2.Controls.Add(Hexbox); Hexbox.LineInfoOffset = 0; Hexbox.ByteProvider = new DynamicByteProvider(new byte[] { }); } private void UDSHexEditor_Load(object sender, EventArgs e) { } private static void GatewayWait() { System.Threading.Thread.Sleep(150); Application.DoEvents(); } private void btnRead_Click(object sender, EventArgs e) { if (!FetchAndValidateInput(out uint sourceAddress, out uint destinationAddress, out uint bufferSize)) { return; } int strideWidth = decimal.ToInt32(nudIOWidth.Value); int addressWidth = decimal.ToInt32(nudAddressWidth.Value); int ioDigitCount = GetMemoryDigitCount(strideWidth); byte readCmd = decimal.ToByte(nudReadCmd.Value); byte positiveResponse = (byte)(readCmd + 0x40); byte alfid = GetAddressAndLengthFormatIdentifier( addressWidth, ioDigitCount ); GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.SetProgressMax((int)(destinationAddress - sourceAddress)); loader.SetProgressValue(0); loader.TopMost = true; loader.Show(); Application.DoEvents(); byte[] memoryBuffer = new byte[bufferSize]; uint readCursor = sourceAddress; int bufferCursor = 0; bool hasBadReads = false; while (readCursor < destinationAddress) { loader.Text = $"Reading from ECU : 0x{readCursor:X8}"; loader.SetProgressValue((int)(readCursor - sourceAddress)); Application.DoEvents(); uint remainder = destinationAddress - readCursor; int readSize = strideWidth; if (readSize > remainder) { readSize = (int)remainder; } List readCommand = CreateReadCommand(readCmd, alfid, readCursor, addressWidth, readSize, chkSendAlfid.Checked); byte[] response = Connection.SendMessage(readCommand); if (response[0] == positiveResponse) { Array.ConstrainedCopy(response, 1, memoryBuffer, bufferCursor, readSize); } else { hasBadReads = true; } readCursor += (uint)readSize; bufferCursor += readSize; // waiting for a moment here; if there is a gateway (e.g. 500k<->83.3k), let it take a breather GatewayWait(); } loader.Close(); Application.DoEvents(); OriginalBuffer = memoryBuffer; Hexbox.LineInfoOffset = sourceAddress; Hexbox.ByteProvider = new DynamicByteProvider(OriginalBuffer); if (hasBadReads) { MessageBox.Show("One or more read requests were rejected by the ECU, and the empty blocks were substituted with zeros. \r\n\r\n" + "Please check if the memory address is valid to the ECU, and if the ECU has been unlocked if required.\r\n\r\n" + "If the memory region has protected bytes, consider loading a smaller, more specific range with a I/O width of 1 to skip past the protected bytes.", "Warning: Invalid reads"); } } private List CreateReadCommand(byte readCmd, byte alfid, long sourceAddress, int addressWidth, int ioWidth, bool includeAlfid) { List readCommand = new List(); readCommand.Add(readCmd); // command if (includeAlfid) { readCommand.Add(alfid); // addressing and memory mode } readCommand.AddRange(ValueToBEByteArrayConstrained(sourceAddress, addressWidth)); // address, constrained to earlier specified width readCommand.AddRange(ValueToBEByteArray(ioWidth)); // should actually be constrained too, based on alfid return readCommand; } private List CreateWriteCommand(byte writeCmd, long destAddress, int addressWidth, byte[] payload, bool includeAlfid) { int ioDigitCount = GetMemoryDigitCount(payload.Length); byte alfid = GetAddressAndLengthFormatIdentifier( addressWidth, ioDigitCount ); List writeCommand = new List(); writeCommand.Add(writeCmd); // command if (includeAlfid) { writeCommand.Add(alfid); // addressing and memory mode } writeCommand.AddRange(ValueToBEByteArrayConstrained(destAddress, addressWidth)); // address, constrained to earlier specified width writeCommand.AddRange(ValueToBEByteArray(payload.Length)); // should actually be constrained too, based on alfid writeCommand.AddRange(payload); return writeCommand; } private List ValueToBEByteArrayConstrained(long inValue, int size) { List result = new List(); for (int i = 0; i < size; i++) { byte row = (byte)(inValue & 0xFF); result.Insert(0, row); inValue >>= 8; } return result; } // unconstrained size private List ValueToBEByteArray(long inValue) { List result = new List(); while (inValue > 0) { byte row = (byte)(inValue & 0xFF); result.Insert(0, row); inValue >>= 8; } return result; } private static int GetMemoryDigitCount(int value) { int count = 0; while (value > 0) { count++; value >>= 8; } return count; } private static byte GetAddressAndLengthFormatIdentifier(int addressSizeInBytes, int memorySizeInBytes) { /* address map in bits: 8 bits : 1 16 bits : 2 24 bits : 3 32 bits : 4 40 bits : 5 memory size map in bits: 8 bits : 1 16 bits : 2 24 bits : 3 32 bits : 4 */ if ((addressSizeInBytes < 1) || (addressSizeInBytes > 5)) { throw new ArgumentOutOfRangeException("Invalid address size for ALFID"); } if ((memorySizeInBytes < 1) || (memorySizeInBytes > 5)) { throw new ArgumentOutOfRangeException("Invalid memory size for ALFID"); } return (byte)((memorySizeInBytes << 4) | addressSizeInBytes); } private bool FetchAndValidateInput(out uint sourceAddress_, out uint destinationAddress_, out uint bufferSize) { sourceAddress_ = 0; destinationAddress_ = 0; bufferSize = 0; if (!uint.TryParse(txtSource.Text, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint sourceAddress)) { MessageBox.Show($"Please check the source address : could not parse '{txtSource.Text}'"); return false; } if (!uint.TryParse(txtDestination.Text, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint destinationAddress)) { MessageBox.Show($"Please check the destination address : could not parse '{txtDestination.Text}'"); return false; } if (rbSize.Checked) { destinationAddress += sourceAddress; } if (destinationAddress < sourceAddress) { MessageBox.Show($"Destination position cannot be lower than the source address."); return false; } sourceAddress_ = sourceAddress; destinationAddress_ = destinationAddress; bufferSize = destinationAddress - sourceAddress; const uint sizeLimitMB = 50; if (bufferSize > (sizeLimitMB * 1024 * 1024)) { MessageBox.Show($"Buffer size is above {sizeLimitMB}MB. Please read in smaller chunks."); return false; } return true; } private bool BytearrayEqual(byte[] a, byte[] b) { if (a.Length != b.Length) { return false; } for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { return false; } } return true; } private void btnWrite_Click(object sender, EventArgs e) { if (!FetchAndValidateInput(out uint sourceAddress, out uint destinationAddress, out uint bufferSize)) { return; } byte[] memoryBuffer = ((DynamicByteProvider)Hexbox.ByteProvider).Bytes.ToArray(); if (memoryBuffer.Length != OriginalBuffer.Length) { MessageBox.Show("Please read the memory region first, before attempting to write."); } int strideWidth = decimal.ToInt32(nudIOWidth.Value); int addressWidth = decimal.ToInt32(nudAddressWidth.Value); byte writeCmd = decimal.ToByte(nudWriteCmd.Value); byte positiveResponse = (byte)(writeCmd + 0x40); uint writeCursor = sourceAddress; int bufferCursor = 0; bool hasBadWrites = false; while (writeCursor < destinationAddress) { uint remainder = destinationAddress - writeCursor; int writeSizeChunk = strideWidth; if (writeSizeChunk > remainder) { writeSizeChunk = (int)remainder; } byte[] dataToWrite = new byte[writeSizeChunk]; byte[] originalData = new byte[writeSizeChunk]; Array.ConstrainedCopy(memoryBuffer, bufferCursor, dataToWrite, 0, writeSizeChunk); // consider checking in-place Array.ConstrainedCopy(OriginalBuffer, bufferCursor, originalData, 0, writeSizeChunk); // skip writes to unmodified chunks if (!BytearrayEqual(dataToWrite, originalData)) { List writeCommand = CreateWriteCommand(writeCmd, writeCursor, addressWidth, dataToWrite, chkSendAlfid.Checked); byte[] response = Connection.SendMessage(writeCommand); if (response[0] != positiveResponse) { hasBadWrites = true; } } writeCursor += (uint)writeSizeChunk; bufferCursor += writeSizeChunk; GatewayWait(); } if (hasBadWrites) { MessageBox.Show("One or more write requests were rejected by the ECU\r\n\r\n" + "Please check if the memory address is valid to the ECU, and if the ECU has been unlocked if required.\r\n\r\n", "Warning: Write command rejected"); } else { MessageBox.Show("Write complete"); } } private void btnSaveToFile_Click(object sender, EventArgs e) { byte[] memoryBuffer = ((DynamicByteProvider)Hexbox.ByteProvider).Bytes.ToArray(); SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your binary data"; sfd.Filter = "BIN files (*.bin)|*.bin|All files (*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(sfd.FileName, memoryBuffer); } } } } ================================================ FILE: Caesar/Diogenes/Forms/UDSHexEditor.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAANaecsTTmW700ZZo/86SY//Ljl7/yYpb/8eHVv/DhFL/w4RS/8OEUv/DhFL/w4RS/8OE Uv+7d0KwAAAAAAAAAADXoXX/+PLt//fw6v/27eb/9Ori//Pn3v/x5Nv/8OLY//Di2P/w4tj/8OLY//Di 2P/w4tj/xYpd/QAAAAAAAAAA2aR6//nz7v/r0r7//////+vTv//////////////////qx63///////// ////////8OLY/8aMX/8AAAAAAAAAAN2ofv/58+//69C6/+vQu//r0Lv/69C7/+vQu//r0b3/6s21/+rN tf/qzbX/6s21//Di2P/Gilz/AAAAAAAAAADfqoL/+fPv/+rOt///////69C7/////////////////+rP uv/79vL////////////w4tj/yI1f/wAAAAAAAAAA4a6H//r08P/qy7L/6syz/+rMs//qzLP/6syz/+rO t//ox6z/6Mes/+jIsP/oyK7/8OLY/8SGVP8AAAAAAAAAAOOxjP/69vH/6smu///////qybD///////// ////////6Mes//////////////////Hl2//GhlX/AAAAAAAAAADltI//+vby/+nGqv/pxqz/6ses/+nH rf/pya7/6cmw/+jHrP/pybD/6Miw/+jMtf/y597/yIpZ/wAAAAAAAAAA57eU//v39P/pw6b//////+jE qf/////////////////ox6z/////////////////9/Hr/8uPX/8AAAAAAAAAAOm6mP/79/T/6cOm/+nD pv/pw6b/6cOm/+nDpv/pw6b/6cOm/+nDpv/pw6b/6cOm//v39P/Ok2T/AAAAAAAAAADrvZv/+/f0//// ///////////////////////////////////////////////////79/T/0Zdq/wAAAAAAAAAA7L+e//v3 9P+c1aX/mNOh/5TQnf+Qzpj/i8uT/4fJjv+Cxon/fsOE/3rBgP92vnz/+/f0/9Sbb/8AAAAAAAAAAO7B oev79/T/+/f0//v39P/79/T/+/f0//v39P/79/T/+/f0//v39P/79/T/+/f0//v39P/XoHT4AAAAAAAA AADvwqN+78Gi4+3An//rvp3/67ya/+m6lv/nt5P/5rWQ/+SyjP/ir4j/4KyE/92pgP/cpX3/2qN6ygAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA//8AAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB AACAAQAA//8AAA== ================================================ FILE: Caesar/Diogenes/Forms/VCForm.Designer.cs ================================================ namespace Diogenes { partial class VCForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VCForm)); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.btnApply = new System.Windows.Forms.Button(); this.btnReinterpret = new System.Windows.Forms.Button(); this.btnCopy = new System.Windows.Forms.Button(); this.radioButton1 = new System.Windows.Forms.RadioButton(); this.rbHex = new System.Windows.Forms.RadioButton(); this.txtCodingString = new System.Windows.Forms.TextBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.dgvMain = new System.Windows.Forms.DataGridView(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).BeginInit(); this.SuspendLayout(); // // groupBox1 // this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupBox1.Controls.Add(this.btnApply); this.groupBox1.Controls.Add(this.btnReinterpret); this.groupBox1.Controls.Add(this.btnCopy); this.groupBox1.Controls.Add(this.radioButton1); this.groupBox1.Controls.Add(this.rbHex); this.groupBox1.Controls.Add(this.txtCodingString); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(1225, 81); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; this.groupBox1.Text = "Computed Values"; // // btnApply // this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnApply.Location = new System.Drawing.Point(1144, 51); this.btnApply.Name = "btnApply"; this.btnApply.Size = new System.Drawing.Size(75, 23); this.btnApply.TabIndex = 5; this.btnApply.Text = "Write"; this.btnApply.UseVisualStyleBackColor = true; this.btnApply.Click += new System.EventHandler(this.btnApply_Click); // // btnReinterpret // this.btnReinterpret.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnReinterpret.Location = new System.Drawing.Point(1063, 51); this.btnReinterpret.Name = "btnReinterpret"; this.btnReinterpret.Size = new System.Drawing.Size(75, 23); this.btnReinterpret.TabIndex = 4; this.btnReinterpret.Text = "Reinterpret"; this.btnReinterpret.UseVisualStyleBackColor = true; this.btnReinterpret.Click += new System.EventHandler(this.btnReinterpret_Click); // // btnCopy // this.btnCopy.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnCopy.Location = new System.Drawing.Point(982, 51); this.btnCopy.Name = "btnCopy"; this.btnCopy.Size = new System.Drawing.Size(75, 23); this.btnCopy.TabIndex = 3; this.btnCopy.Text = "Copy"; this.btnCopy.UseVisualStyleBackColor = true; this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click); // // radioButton1 // this.radioButton1.AutoSize = true; this.radioButton1.Location = new System.Drawing.Point(56, 54); this.radioButton1.Name = "radioButton1"; this.radioButton1.Size = new System.Drawing.Size(45, 17); this.radioButton1.TabIndex = 2; this.radioButton1.Text = "Dec"; this.radioButton1.UseVisualStyleBackColor = true; this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton1_CheckedChanged); // // rbHex // this.rbHex.AutoSize = true; this.rbHex.Checked = true; this.rbHex.Location = new System.Drawing.Point(6, 54); this.rbHex.Name = "rbHex"; this.rbHex.Size = new System.Drawing.Size(44, 17); this.rbHex.TabIndex = 1; this.rbHex.TabStop = true; this.rbHex.Text = "Hex"; this.rbHex.UseVisualStyleBackColor = true; this.rbHex.CheckedChanged += new System.EventHandler(this.rbHex_CheckedChanged); // // txtCodingString // this.txtCodingString.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtCodingString.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtCodingString.Location = new System.Drawing.Point(6, 19); this.txtCodingString.Name = "txtCodingString"; this.txtCodingString.Size = new System.Drawing.Size(1213, 26); this.txtCodingString.TabIndex = 0; // // groupBox2 // this.groupBox2.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.groupBox2.Controls.Add(this.dgvMain); this.groupBox2.Location = new System.Drawing.Point(12, 99); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(1225, 507); this.groupBox2.TabIndex = 1; this.groupBox2.TabStop = false; this.groupBox2.Text = "Variant Configuration"; // // dgvMain // this.dgvMain.AllowUserToAddRows = false; this.dgvMain.AllowUserToDeleteRows = false; this.dgvMain.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.dgvMain.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dgvMain.ContextMenuStrip = this.contextMenuStrip1; this.dgvMain.Location = new System.Drawing.Point(6, 19); this.dgvMain.Name = "dgvMain"; this.dgvMain.ReadOnly = true; this.dgvMain.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; this.dgvMain.ShowEditingIcon = false; this.dgvMain.Size = new System.Drawing.Size(1213, 482); this.dgvMain.TabIndex = 0; // // contextMenuStrip1 // this.contextMenuStrip1.Name = "contextMenuStrip1"; this.contextMenuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); // // VCForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1249, 618); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "VCForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Variant Coding"; this.Load += new System.EventHandler(this.VCForm_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.groupBox2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvMain)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Button btnReinterpret; private System.Windows.Forms.Button btnCopy; private System.Windows.Forms.RadioButton radioButton1; private System.Windows.Forms.RadioButton rbHex; private System.Windows.Forms.TextBox txtCodingString; private System.Windows.Forms.Button btnApply; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.DataGridView dgvMain; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; } } ================================================ FILE: Caesar/Diogenes/Forms/VCForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Caesar; namespace Diogenes { public partial class VCForm : Form { ECU SelectedECU; ECUVariant ECUVariant; VCDomain VariantCodingDomain; string ECUName; string VariantName; string VCDomainName; public byte[] VCValue; public byte[] UnfilteredReadValue; public DiagService ReadService; public DiagService WriteService; public VCForm(CaesarContainer container, string ecuName, string variantName, string vcDomain, ECUConnection connection) { InitializeComponent(); ECUName = ecuName; VariantName = variantName; VCDomainName = vcDomain; SelectedECU = container.GetECUByName(ecuName); ECUVariant = container.GetECUVariantByName(variantName); VariantCodingDomain = ECUVariant.GetVCDomainByName(VCDomainName); ReadService = ECUVariant.GetDiagServiceByName(VariantCodingDomain.ReadServiceName); WriteService = ECUVariant.GetDiagServiceByName(VariantCodingDomain.WriteServiceName); if ((ReadService is null) || (WriteService is null)) { Console.WriteLine("VC Dialog: Unable to proceed - could not find referenced diagnostic services"); this.Close(); } //Console.WriteLine(ReadService.Qualifier); //Console.WriteLine(WriteService.Qualifier); VCValue = new byte[VariantCodingDomain.DumpSize]; UnfilteredReadValue = new byte[] { }; foreach (Tuple row in VariantCodingDomain.DefaultData) { if (row.Item1.ToLower() == "default" && (row.Item2.Length == VariantCodingDomain.DumpSize)) { VCValue = row.Item2; Console.WriteLine("Default CBF variant coding data is available"); break; } } if (connection.State >= ECUConnection.ConnectionState.ChannelConnectedPendingEcuContact) { // Console.WriteLine($"Requesting variant coding read: {ReadService.Qualifier} : ({BitUtility.BytesToHex(ReadService.RequestBytes)})"); byte[] response = connection.SendDiagRequest(ReadService); DiagPreparation largestPrep = GetLargestPreparation(ReadService.OutputPreparations); if (largestPrep.PresPoolIndex > -1) { // DiagPresentation pres = SelectedECU.GlobalPresentations[largestPrep.PresPoolIndex]; // pres.PrintDebug(); } // Console.WriteLine($"Variant coding received: {BitUtility.BytesToHex(response)}"); VCValue = response.Skip(largestPrep.BitPosition / 8).Take(largestPrep.SizeInBits / 8).ToArray(); // store the received VC: when writing back, we might need the previous author's fingerprints UnfilteredReadValue = response; } else { Console.WriteLine("Please check for connectivity to the target ECU (could not read variant coding data)"); MessageBox.Show("Variant Coding dialog will operate as a simulation using default values.", "Unable to read ECU variant coding data", MessageBoxButtons.OK); btnApply.Enabled = false; } // VCSanityCheck(); IntepretVC(); PresentVC(); } // extremely unscientific way of figuring out the actual vc data public static DiagPreparation GetLargestPreparation(List> presSet) { int largestField = 0; foreach (List wtf in presSet) { foreach (DiagPreparation prep in wtf) { if (prep.SizeInBits > largestField) { largestField = prep.SizeInBits; } } } foreach (List wtf in presSet) { foreach (DiagPreparation prep in wtf) { if (prep.SizeInBits == largestField) { return prep; } } } return null; } public static DiagPreparation GetLargestPreparation(List presSet) { int largestField = 0; foreach (DiagPreparation prep in presSet) { if (prep.SizeInBits > largestField) { largestField = prep.SizeInBits; } } foreach (DiagPreparation prep in presSet) { if (prep.SizeInBits == largestField) { return prep; } } return null; } private void VCSanityCheck() { VariantCodingDomain.VCFragments.ForEach(x => Console.WriteLine($"Fragment: {x.Qualifier}, R:{x.ReadAccessLevel} W:{x.WriteAccessLevel}")); Console.WriteLine($"ReadSvc level {ReadService.ClientAccessLevel}/{ReadService.SecurityAccessLevel}, WriteSvc level {WriteService.ClientAccessLevel}/{WriteService.SecurityAccessLevel}"); Console.WriteLine($"ReadService: {ReadService.Qualifier} : {BitUtility.BytesToHex(ReadService.RequestBytes)} ({ReadService.RequestBytes.Length * 8})"); ReadService.InputPreparations.ForEach(x => Console.WriteLine($"{x.Qualifier} @ {x.BitPosition}, size: {x.SizeInBits}")); Console.WriteLine($"WriteService: {WriteService.Qualifier} : {BitUtility.BytesToHex(WriteService.RequestBytes)} ({WriteService.RequestBytes.Length * 8})"); WriteService.InputPreparations.ForEach(x => Console.WriteLine($"{x.Qualifier} @ {x.BitPosition}, size: {x.SizeInBits}")); } private void PresentVC() { txtCodingString.Text = rbHex.Checked ? BitUtility.BytesToHex(VCValue, true) : BitUtility.BytesToDecimalString(VCValue); txtCodingString.Select(0, 0); } private void ReinterpretVC() { VCValue = rbHex.Checked ? BitUtility.BytesFromHex(txtCodingString.Text) : BitUtility.BytesFromDecimalString(txtCodingString.Text); IntepretVC(); } private void IntepretVC() { // save view state int saveRow = 0; if (dgvMain.Rows.Count > 0 && dgvMain.FirstDisplayedCell != null) { saveRow = dgvMain.FirstDisplayedCell.RowIndex; } List saveSelectedIndices = new List(); foreach (DataGridViewRow row in dgvMain.SelectedRows) { saveSelectedIndices.Add(row.Index); } // actually interpret vc DataTable dt = new DataTable(); dt.Columns.Add("Fragment", typeof(String)); dt.Columns.Add("Value", typeof(String)); dt.Columns.Add("Bit Position", typeof(String)); dt.Columns.Add("Bit Length", typeof(String)); for (int i = 0; i < VariantCodingDomain.VCFragments.Count; i++) { VCFragment currentFragment = VariantCodingDomain.VCFragments[i]; VCSubfragment subfragment = currentFragment.GetSubfragmentConfiguration(VCValue); dt.Rows.Add(new string[] { currentFragment.Qualifier, subfragment is null ? "(warning: no matching subfragment)" : subfragment.NameResolved, currentFragment.ByteBitPos.ToString(), currentFragment.BitLength.ToString(), }); } dgvMain.DataSource = dt; dgvMain.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; dgvMain.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dgvMain.Sort(dgvMain.Columns[0], ListSortDirection.Ascending); // restore view state if (saveRow != 0 && saveRow < dgvMain.Rows.Count) { dgvMain.FirstDisplayedScrollingRowIndex = saveRow; } foreach (int rowIndex in saveSelectedIndices) { foreach (DataGridViewRow row in dgvMain.Rows) { row.Selected = row.Index == rowIndex; } } } private void VCForm_Load(object sender, EventArgs e) { SetDoubleBuffer(dgvMain, true); } static void SetDoubleBuffer(Control ctl, bool DoubleBuffered) { typeof(Control).InvokeMember("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, ctl, new object[] { DoubleBuffered }); } private void btnApply_Click(object sender, EventArgs e) { if (!BitUtility.CheckHexValid(txtCodingString.Text)) { MessageBox.Show("Hex data could not be parsed. Please check if there are any invalid values", "Write Variant Coding"); return; } VCValue = BitUtility.BytesFromHex(txtCodingString.Text); ReinterpretVC(); PresentVC(); if (MessageBox.Show("The SCN (Software Calibration Number) will be reset for some ECUs when the variant coding is modified. Continue?", "SCN Warning", MessageBoxButtons.YesNo) == DialogResult.Yes) { this.DialogResult = DialogResult.OK; this.Close(); } } private void btnReinterpret_Click(object sender, EventArgs e) { if (!BitUtility.CheckHexValid(txtCodingString.Text)) { MessageBox.Show("Hex data could not be parsed. Please check if there are any invalid values", "Reinterpret Variant Coding"); return; } ReinterpretVC(); } private void rbHex_CheckedChanged(object sender, EventArgs e) { PresentVC(); } private void radioButton1_CheckedChanged(object sender, EventArgs e) { PresentVC(); } private void btnCopy_Click(object sender, EventArgs e) { Clipboard.SetText(txtCodingString.Text); } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { if (dgvMain.SelectedRows.Count > 0) { string fragmentName = dgvMain.SelectedRows[0].Cells[0].Value.ToString(); string fragmentValue = dgvMain.SelectedRows[0].Cells[1].Value.ToString(); VCFragment fragment = VariantCodingDomain.VCFragments.Find(x => x.Qualifier == fragmentName); if (fragment is null) { return; } int contextMenuLimit = 30; contextMenuStrip1.Items.Clear(); ToolStripMenuItem tsHeader = new ToolStripMenuItem(); tsHeader.Text = fragmentName; if (fragment.Subfragments.Count > contextMenuLimit) { tsHeader.Text += " (Warning: too many entries to show)"; // build table for picker ShowPickerDialog(fragmentName, fragment); e.Cancel = true; return; } tsHeader.Enabled = false; contextMenuStrip1.Items.Add(tsHeader); contextMenuStrip1.Items.Add(new ToolStripSeparator()); foreach (VCSubfragment subfragment in fragment.Subfragments) { ToolStripMenuItem tsItem = new ToolStripMenuItem(); tsItem.Text = subfragment.NameResolved; tsItem.Tag = fragmentName; tsItem.Click += VCContextMenu_Click; if (fragmentValue == tsItem.Text) { tsItem.Checked = true; } contextMenuStrip1.Items.Add(tsItem); if (--contextMenuLimit == 0) { break; } } } // we *want* to show the context menu, this makes it happen e.Cancel = false; } private void ShowPickerDialog(string fragmentName, VCFragment fragment) { string[][] table = new string[fragment.Subfragments.Count][]; for (int i = 0; i < fragment.Subfragments.Count; i++) { table[i] = new string[] { fragment.Subfragments[i].NameResolved }; } GenericPicker picker = new GenericPicker(table, new string[] { "Name" }); picker.Text = $"Select an option for {fragmentName}"; if (picker.ShowDialog() == DialogResult.OK) { SelectVC(fragmentName, picker.SelectedResult[0]); } } private void VCContextMenu_Click(object sender, EventArgs e) { ToolStripMenuItem senderItem = (ToolStripMenuItem)sender; string fragmentName = senderItem.Tag.ToString(); string fragmentValue = senderItem.Text; SelectVC(fragmentName, fragmentValue); } private void SelectVC(string fragmentName, string fragmentValue) { VCFragment fragment = VariantCodingDomain.VCFragments.Find(x => x.Qualifier == fragmentName); if (fragment is null) { Console.WriteLine("Coding context menu: couldn't find a matching fragment"); return; } VCSubfragment subfragment = fragment.Subfragments.Find(x => x.NameResolved == fragmentValue); if (subfragment is null) { Console.WriteLine("Coding context menu: couldn't find a matching subfragment"); return; } VCValue = fragment.SetSubfragmentConfiguration(VCValue, subfragment); IntepretVC(); PresentVC(); } } } ================================================ FILE: Caesar/Diogenes/Forms/VCForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbW1jWFhYv1FRUb9SUlJjAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAb29vKWpqag4AAAACgYGB6r29vf+ysrL/W1tb6gAAAAJcXFwOTk5OKQAA AAAAAAAAAAAAAAAAAAAAAAAAgYGBm29vb/1kZGTndnZ2GYODg+fLy8v/x8fH/2JiYudaWloZWFhY505O Tv1JSUmbAAAAAAAAAAAAAAAApKSke7y8vP/e3t7/pqam/4ODg/SFhYX+xMTE/8LCwv9tbW3+bm5u9Kam pv/S0tL/gICA/1JSUnsAAAAAAAAAAKurq32mpqb+1dXV/8XFxf/Ly8v/0dHR/8nJyf/Hx8f/zMzM/8XF xf+9vb3/y8vL/25ubv5nZ2d9AAAAAAAAAAAAAAAArKyshcXFxf/BwcH/xcXF/8fHx/+qqqr/p6en/8HB wf++vr7/tbW1/6qqqv9paWmFAAAAAAAAAACjo6PNj4+P46CgoO7Pz8//xsbG/8zMzP+enp7GmZmZRJSU lESPj4/GwcHB/7y8vP+5ubn/ZGRk7lhYWONTU1PNv7+//eLi4v/S0tL/xsbG/83Nzf+xsbH/k5OTRAAA AAAAAAAAlZWVRKioqP/CwsL/t7e3/8DAwP/S0tL/YWFh/cTExP3p6en/1tbW/8nJyf/Ozs7/paWl/4SE hEQAAAAAAAAAAJqamkSsrKz/xMTE/7q6uv/Gxsb/3d3d/2tra/3IyMjNxMTE48DAwO7Y2Nj/zc3N/7y8 vP+CgoLGd3d3RH5+fkSPj4/Gw8PD/8LCwv/Nzc3/jIyM7oeHh+ODg4PNAAAAAAAAAADFxcWF1NTU/8zM zP/Jycn/urq6/5ycnP+hoaH/wsLC/8bGxv/BwcH/t7e3/4mJiYUAAAAAAAAAAAAAAADKysp9xMTE/tzc 3P/U1NT/2dnZ/9vb2//W1tb/1NTU/9nZ2f/S0tL/y8vL/8jIyP95eXn+cXFxfQAAAAAAAAAA0NDQe9zc 3P/t7e3/29vb/8LCwvS+vr7+1tbW/9TU1P+wsLD+rKys9MvLy//n5+f/t7e3/4uLi3sAAAAAAAAAAAAA AADR0dGbzs7O/crKyufGxsYZwsLC597e3v/d3d3/srKy57GxsRmsrKznp6en/aOjo5sAAAAAAAAAAAAA AAAAAAAAAAAAANHR0SnOzs4OAAAAAsfHx+rl5eX/5OTk/6ysrOoAAAACsrKyDq2trSkAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLy8tjx8fHv8TExL+/v79jAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA/D8AAOQnAADAAwAAgAEAAIABAADAAwAAAAAAAAGAAAABgAAAAAAAAMADAACAAQAAgAEAAMAD AADkJwAA/D8AAA== ================================================ FILE: Caesar/Diogenes/Preferences.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes { public class Preferences { public enum PreferenceKey { AllowVC, EnableSCNZero, EnableFingerprintClone, FingerprintValue, } private static Dictionary UserPreferences = null; public static void InitializePreferences() { // default values for first run / no config file UserPreferences = new Dictionary(); UserPreferences.Add((int)PreferenceKey.AllowVC, "false"); UserPreferences.Add((int)PreferenceKey.EnableSCNZero, "true"); UserPreferences.Add((int)PreferenceKey.FingerprintValue, "1"); UserPreferences.Add((int)PreferenceKey.EnableFingerprintClone, "true"); LoadAndDeserializePreferences(); } public static string GetValue(PreferenceKey key) { int keyIndex = (int)key; if (UserPreferences is null) { InitializePreferences(); } if (UserPreferences.ContainsKey(keyIndex)) { return UserPreferences[keyIndex]; } else { return ""; } } public static void SetValue(PreferenceKey key, string newValue, bool save = true) { int keyIndex = (int)key; if (UserPreferences is null) { InitializePreferences(); } if (UserPreferences.ContainsKey(keyIndex)) { UserPreferences[keyIndex] = newValue; } else { UserPreferences.Add(keyIndex, newValue); } if (save) { SerializeAndSavePreferences(); } } private static string GetPreferencesFilePath() { return Path.Combine(GetPreferencesDirectory(), "Preferences.ini"); } private static string GetPreferencesDirectory() { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Diogenes"); } public static void SerializeAndSavePreferences() { string prefsDirectory = GetPreferencesDirectory(); if (!Directory.Exists(prefsDirectory)) { Directory.CreateDirectory(prefsDirectory); } StringBuilder sb = new StringBuilder(); foreach (KeyValuePair row in UserPreferences) { // assume that windows clients will mess up the line endings, so use \r\n first sb.Append($"{row.Key}={BitUtility.BytesToHex(Encoding.UTF8.GetBytes(row.Value))}\r\n"); } File.WriteAllText(GetPreferencesFilePath(), sb.ToString()); } public static bool LoadAndDeserializePreferences() { string prefsPath = GetPreferencesFilePath(); if (!File.Exists(prefsPath)) { return false; } string[] iniRows = File.ReadAllText(prefsPath).Replace("\r", "").Split(new string[] {"\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string iniRow in iniRows) { string[] keyValue = iniRow.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries); PreferenceKey key = (PreferenceKey)int.Parse(keyValue[0]); string value = Encoding.UTF8.GetString(BitUtility.BytesFromHex(keyValue[1])); SetValue(key, value, false); } return true; } } } ================================================ FILE: Caesar/Diogenes/Program.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } } ================================================ FILE: Caesar/Diogenes/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Diogenes")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Diogenes")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("2216db99-eaac-46a8-b99a-28d659907de7")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.5.2.1")] [assembly: AssemblyFileVersion("1.5.2.1")] ================================================ FILE: Caesar/Diogenes/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace Diogenes.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Diogenes.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap accept { get { object obj = ResourceManager.GetObject("accept", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap application_xp_terminal { get { object obj = ResourceManager.GetObject("application_xp_terminal", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap asterisk_orange { get { object obj = ResourceManager.GetObject("asterisk_orange", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap blank { get { object obj = ResourceManager.GetObject("blank", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap box { get { object obj = ResourceManager.GetObject("box", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap brick { get { object obj = ResourceManager.GetObject("brick", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_black { get { object obj = ResourceManager.GetObject("bullet_black", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_blue { get { object obj = ResourceManager.GetObject("bullet_blue", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_go { get { object obj = ResourceManager.GetObject("bullet_go", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_green { get { object obj = ResourceManager.GetObject("bullet_green", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_orange { get { object obj = ResourceManager.GetObject("bullet_orange", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_pink { get { object obj = ResourceManager.GetObject("bullet_pink", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_purple { get { object obj = ResourceManager.GetObject("bullet_purple", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_red { get { object obj = ResourceManager.GetObject("bullet_red", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_star { get { object obj = ResourceManager.GetObject("bullet_star", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_white { get { object obj = ResourceManager.GetObject("bullet_white", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap bullet_yellow { get { object obj = ResourceManager.GetObject("bullet_yellow", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap cog { get { object obj = ResourceManager.GetObject("cog", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap computer_go { get { object obj = ResourceManager.GetObject("computer_go", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap connect { get { object obj = ResourceManager.GetObject("connect", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap diogenes { get { object obj = ResourceManager.GetObject("diogenes", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap folder { get { object obj = ResourceManager.GetObject("folder", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap house { get { object obj = ResourceManager.GetObject("house", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap information { get { object obj = ResourceManager.GetObject("information", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap key { get { object obj = ResourceManager.GetObject("key", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap lock_edit { get { object obj = ResourceManager.GetObject("lock_edit", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap page_white_edit { get { object obj = ResourceManager.GetObject("page_white_edit", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap report { get { object obj = ResourceManager.GetObject("report", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } } } ================================================ FILE: Caesar/Diogenes/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\Resources\asterisk_orange.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\brick.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_white.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\blank.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\computer_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_pink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\report.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\lock_edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_red.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_yellow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\key.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\connect.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\accept.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_star.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\application_xp_terminal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_orange.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\box.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_purple.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\page_white_edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\bullet_black.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\cog.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\house.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\diogenes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ================================================ FILE: Caesar/Diogenes/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace Diogenes.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } } ================================================ FILE: Caesar/Diogenes/Properties/Settings.settings ================================================  ================================================ FILE: Caesar/Diogenes/Reports/DTCReport.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public class DTCReport { public static void CreateDTCReport(List dtcContexts, ECUConnection connection, ECUVariant variant) { Cursor.Current = Cursors.WaitCursor; string reportDate = $"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToLongTimeString()}"; string containerChecksum = variant.ParentECU.ParentContainer.FileChecksum.ToString("X8"); string dVersion = MainForm.GetVersion(); string cVersion = CaesarContainer.GetCaesarVersionString(); string connectionData = connection is null ? "(Unavailable)" : connection.FriendlyProfileName; string ecuCbfVersion = variant.ParentECU.EcuXmlVersion; StringBuilder tableBuilder = new StringBuilder(); // back up every domain since some have overlaps foreach (DTCContext dtcCtx in dtcContexts) { StringBuilder tableRowBuilder = new StringBuilder(); // env, description for (int i = 0; i < dtcCtx.EnvironmentContext.Count; i++) { string tableRowBlock = $@" {dtcCtx.EnvironmentContext[i][0]} {dtcCtx.EnvironmentContext[i][1]} "; tableRowBuilder.Append(tableRowBlock); } string tableBlock = $@"

{dtcCtx.DTC.Qualifier}

{dtcCtx.DTC.Description}

{tableRowBuilder}
Environment Description
"; tableBuilder.Append(tableBlock); } string document = $@" {variant.ParentECU.Qualifier} : DTC Report

Diogenes

{variant.ParentECU.Qualifier}


CBF Checksum {containerChecksum}
Date {reportDate}
Client Version Diogenes: {dVersion}, Caesar: {cVersion}
ECU CBF Version {ecuCbfVersion}
ECU Variant {variant.Qualifier}
Connection Info {connectionData}
{connection.ConnectionProtocol.QueryECUMetadata(connection).GetHtmlTable(connection)} {tableBuilder}
End of report "; Cursor.Current = Cursors.Default; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new DTC report"; sfd.Filter = "HTML file (*.html)|*.html|All files (*.*)|*.*"; sfd.FileName = $"DTC_{variant.Qualifier}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.html"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllText(sfd.FileName, document.ToString()); MessageBox.Show($"Report successfully saved to {sfd.FileName}", "Export complete"); } } } } ================================================ FILE: Caesar/Diogenes/Reports/VCReport.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public class VCReport { public static void treeViewSelectVariantCodingBackup(TreeNode node, ECUConnection connection, List containers) { if (connection is null) { return; } Cursor.Current = Cursors.WaitCursor; string variantName = node.Parent.Text; string ecuName = node.Parent.Parent.Text; string reportDate = $"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToLongTimeString()}"; StringBuilder report = new StringBuilder(); CaesarContainer container = containers.Find(x => x.GetECUVariantByName(variantName) != null); ECU ecu = container.GetECUByName(ecuName); ECUVariant variant = container.GetECUVariantByName(variantName); string containerChecksum = container.FileChecksum.ToString("X8"); string dVersion = MainForm.GetVersion(); string cVersion = CaesarContainer.GetCaesarVersionString(); string connectionData = connection is null ? "(Unavailable)" : connection.FriendlyProfileName; string ecuCbfVersion = ecu.EcuXmlVersion; report.Append($"ECU Variant: {variant.Qualifier}\r\n"); StringBuilder tableBuilder = new StringBuilder(); // back up every domain since some have overlaps foreach (VCDomain domain in variant.VCDomains) { report.Append($"\r\nCoding Service: {domain.Qualifier}\r\n"); // find the read service, then execute it as-is DiagService readService = variant.GetDiagServiceByName(domain.ReadServiceName); byte[] response = connection.SendDiagRequest(readService); // isolate the traditional vc string DiagPreparation largestPrep = VCForm.GetLargestPreparation(readService.OutputPreparations); byte[] vcValue = response.Skip(largestPrep.BitPosition / 8).Take(largestPrep.SizeInBits / 8).ToArray(); StringBuilder tableRowBuilder = new StringBuilder(); // explain the vc string's settings for (int i = 0; i < domain.VCFragments.Count; i++) { VCFragment currentFragment = domain.VCFragments[i]; VCSubfragment subfragment = currentFragment.GetSubfragmentConfiguration(vcValue); string fragmentValue = subfragment is null ? "(?)" : subfragment.NameResolved; string fragmentSupplementKey = subfragment is null ? "(?)" : subfragment.SupplementKey; string tableRowBlock = $@" {currentFragment.Qualifier} {fragmentValue} {fragmentSupplementKey} "; tableRowBuilder.Append(tableRowBlock); } string tableBlock = $@"

{domain.Qualifier}

Coding String (Hex) {BitUtility.BytesToHex(vcValue, true)}
Raw Coding String (Hex) {BitUtility.BytesToHex(response, true)}
{tableRowBuilder}
Fragment Value Supplement Key
"; tableBuilder.Append(tableBlock); } string document = $@" {ecuName} : Backup

Diogenes

{ecuName}


CBF Checksum {containerChecksum}
Date {reportDate}
Client Version Diogenes: {dVersion}, Caesar: {cVersion}
ECU CBF Version {ecuCbfVersion}
ECU Variant {variantName}
Connection Info {connectionData}
{connection.ConnectionProtocol.QueryECUMetadata(connection).GetHtmlTable(connection)} {tableBuilder}
End of report "; Cursor.Current = Cursors.Default; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new VC backup"; sfd.Filter = "HTML file (*.html)|*.html|All files (*.*)|*.*"; sfd.FileName = $"VC_{variantName}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.html"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllText(sfd.FileName, document.ToString()); MessageBox.Show($"Backup successfully saved to {sfd.FileName}", "Export complete"); } } } } ================================================ FILE: Caesar/Diogenes/SecurityAccess/DllContext.cs ================================================ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Caesar; namespace Diogenes.SecurityAccess { public class DllContext { private IntPtr dllHandle = IntPtr.Zero; public List DllExports = new List(); private Dictionary dllAddressMappings = new Dictionary(); public string SHA1Hash = ""; public string FileDescription = ""; public string FileName = ""; public string DLLPath = ""; public string ECUName = ""; public string Comment = ""; public bool KeyGenerationCapability = false; public bool ModeSpecified = false; public List> AccessLevels = new List>(); public DllContext(string filePath, bool runHash = true) { DLLPath = filePath; if (!File.Exists(DLLPath)) { Console.WriteLine($"{DLLPath}: File does not exist"); return; } FileName = Path.GetFileName(filePath); // Compute and store the file hash if (runHash) { using (var cryptoProvider = new SHA1CryptoServiceProvider()) { SHA1Hash = BitConverter.ToString(cryptoProvider.ComputeHash(File.ReadAllBytes(filePath))).Replace("-", ""); } } // Get the module's exports DllExports = UnmanagedUtility.GetExports(DLLPath); if (DllExports.Count == 0) { Console.WriteLine($"{DLLPath}: No exports, possibly an invalid DLL"); return; } // Try to load the library into our process space dllHandle = UnmanagedUtility.LoadLibrary(filePath); if (dllHandle == IntPtr.Zero) { Console.WriteLine($"{DLLPath}: LoadLibrary failed"); return; } // Try to load addresses of all known exports dllAddressMappings = new Dictionary(); foreach (string knownExport in ExportDefinition.KnownExportedFunctions) { if (DllExports.Contains(knownExport)) { dllAddressMappings.Add(knownExport, UnmanagedUtility.GetProcAddress(dllHandle, knownExport)); } else { dllAddressMappings.Add(knownExport, IntPtr.Zero); } } // Set capabilities KeyGenerationCapability = DllExports.Contains("GenerateKeyEx") || DllExports.Contains("GenerateKeyExOpt"); ModeSpecified = DllExports.Contains("GetKeyLength") && DllExports.Contains("GetSeedLength") && DllExports.Contains("GetConfiguredAccessTypes"); // Store additional metadata FileDescription = FileVersionInfo.GetVersionInfo(DLLPath).FileDescription; LoadAdditionalDataFromDllCalls(); } public void LoadAdditionalDataFromDllCalls() { ECUName = GetECUName(); Comment = GetComment(); if (!ModeSpecified) { return; } // Access level, key size, seed size AccessLevels = new List>(); foreach (uint accessLevel in GetConfiguredAccessTypes()) { AccessLevels.Add(new Tuple(accessLevel, GetKeyLength(accessLevel), GetSeedLength(accessLevel))); } } // Automatically selects and invokes the correct key generation function. Prefers the "opt" variant public string GenerateKeyAuto(uint securityLevel, byte[] seed) { if (DllExports.Contains("GenerateKeyExOpt")) { return BitUtility.BytesToHex(GenerateKey(seed, securityLevel, true, out ExportDefinition.VKeyGenResultEx result), true); } else if (DllExports.Contains("GenerateKeyEx")) { return BitUtility.BytesToHex(GenerateKey(seed, securityLevel, false, out ExportDefinition.VKeyGenResultEx result), true); } else { return ""; } } public string GetECUName() { IntPtr procAddress = dllAddressMappings["GetECUName"]; if (procAddress == IntPtr.Zero) { return "(unavailable)"; } var fn = (ExportDefinition.GetECUName)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetECUName)); IntPtr resultPtr = fn(); return Marshal.PtrToStringAnsi(resultPtr); } public string GetComment() { IntPtr procAddress = dllAddressMappings["GetComment"]; if (procAddress == IntPtr.Zero) { return "(unavailable)"; } var fn = (ExportDefinition.GetComment)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetComment)); IntPtr resultPtr = fn(); return Marshal.PtrToStringAnsi(resultPtr); } public List GetConfiguredAccessTypes() { IntPtr procAddress = dllAddressMappings["GetConfiguredAccessTypes"]; if (procAddress == IntPtr.Zero) { return new List(); } uint[] accessTypes = new uint[1000]; var fn = (ExportDefinition.GetConfiguredAccessTypes)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetConfiguredAccessTypes)); int accessTypesCount = fn(accessTypes); return accessTypes.Take(accessTypesCount).ToList(); } public int GetSeedLength(uint securityLevel) { IntPtr procAddress = dllAddressMappings["GetSeedLength"]; if (procAddress == IntPtr.Zero) { return 0; } var fn = (ExportDefinition.GetSeedLength)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetSeedLength)); return fn(securityLevel); } public int GetKeyLength(uint securityLevel) { IntPtr procAddress = dllAddressMappings["GetKeyLength"]; if (procAddress == IntPtr.Zero) { return 0; } var fn = (ExportDefinition.GetKeyLength)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetKeyLength)); return fn(securityLevel); } private byte[] GenerateKey(byte[] seed, uint securityLevel, bool addOptionParameter, out ExportDefinition.VKeyGenResultEx returnError) { returnError = ExportDefinition.VKeyGenResultEx.UnknownError; IntPtr procAddress = dllAddressMappings[addOptionParameter ? "GenerateKeyExOpt" : "GenerateKeyEx"]; if ((!KeyGenerationCapability) || procAddress == IntPtr.Zero) { return new byte[] { }; } byte[] keyResult = new byte[0x1000]; uint actualkeySize; int keygenResult = (int)returnError; if (addOptionParameter) { var fn = (ExportDefinition.GenerateKeyExOpt)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GenerateKeyExOpt)); keygenResult = fn(seed, (uint)seed.Length, securityLevel, null, null, keyResult, (uint)keyResult.Length, out actualkeySize); } else { var fn = (ExportDefinition.GenerateKeyEx)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GenerateKeyEx)); keygenResult = fn(seed, (uint)seed.Length, securityLevel, null, keyResult, (uint)keyResult.Length, out actualkeySize); } returnError = (ExportDefinition.VKeyGenResultEx)keygenResult; keyResult = keyResult.Take((int)actualkeySize).ToArray(); return keyResult; } public void UnloadLibrary() { // WARNING: the instance will no longer be able to access native functions after this is called // This is a workaround if many DLLs have to be enumerated for their metadata -- Windows has a limit on the number of DLLs that can be loaded simultaneously UnmanagedUtility.FreeLibrary(dllHandle); } ~DllContext() { if (dllHandle != IntPtr.Zero) { UnmanagedUtility.FreeLibrary(dllHandle); } } } } ================================================ FILE: Caesar/Diogenes/SecurityAccess/ExportDefinition.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Diogenes.SecurityAccess { class ExportDefinition { public static string[] KnownExportedFunctions = new string[] { "GetECUName", "GetComment", "GetKeyLength", "GetSeedLength", "GetConfiguredAccessTypes", "GenerateKeyExOpt", "GenerateKeyEx" }; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr GetECUName(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr GetComment(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GetKeyLength(uint iSecurityLevel); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GetSeedLength(uint iSecurityLevel); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GetConfiguredAccessTypes(uint[] iSecurityLevels); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GenerateKeyExOpt(byte[] ipSeedArray, uint iSeedArraySize, uint iSecurityLevel, byte[] ipVariant, byte[] ipOptions, byte[] iopKeyArray, uint iMaxKeyArraySize, out uint oActualKeyArraySize); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GenerateKeyEx(byte[] ipSeedArray, uint iSeedArraySize, uint iSecurityLevel, byte[] ipVariant, byte[] iopKeyArray, uint iMaxKeyArraySize, out uint oActualKeyArraySize); public enum VKeyGenResultEx { OK = 0, BufferTooSmall = 1, SecurityLevelInvalid = 2, VariantInvalid = 3, UnknownError = 4 } } } ================================================ FILE: Caesar/Diogenes/SecurityAccess/SecurityAutoLogin.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes.SecurityAccess { public class SecurityAutoLogin { public static void ReceiveSecurityResponse(byte[] response, ECU parentEcu, ECUConnection connection) { if (response.Length == 2) { // level change ack Console.WriteLine($"Security level has been successfully changed to 0x{(response[1] - 1):X}"); } else { // seed received byte[] seedValue = response.Skip(2).ToArray(); string seedValueAsString = BitUtility.BytesToHex(seedValue, true); int receiveLevel = response[1]; bool manualUnlockRequired = true; if (QueryUnlockEcu(seedValue, parentEcu.Qualifier, receiveLevel, out byte[] key)) { if (RequestUnlock(connection, receiveLevel, key)) { Console.WriteLine($"ECU has been automatically unlocked for level {receiveLevel}"); manualUnlockRequired = false; } } if (manualUnlockRequired) { PromptClipboardCopyOfSeed(seedValueAsString); } } } private static bool RequestUnlock(ECUConnection connection, int receiveLevel, byte[] key) { List keyResponse = new List(); keyResponse.Add(0x27); keyResponse.Add((byte)(receiveLevel + 1)); keyResponse.AddRange(key); byte[] response = connection.SendMessage(keyResponse); if ((response.Length == 2) && (response[0] == 0x67)) { return true; } return false; } public static bool QueryUnlockEcu(byte[] seed, string ecuName, int level, out byte[] key) { string unlockEcuFolder = $"{Application.StartupPath}{Path.DirectorySeparatorChar}UnlockECU{Path.DirectorySeparatorChar}"; string binaryPath = $"{unlockEcuFolder}ConsoleUnlockECU.exe"; string dbPath = $"{unlockEcuFolder}db.json"; key = new byte[] { }; if (!(File.Exists(binaryPath) && File.Exists(dbPath))) { Console.WriteLine("Automatic unlock is unavailable (executable or database could not be found)"); return false; } string successIdentifier = "DIOGENES"; string args = $"-d \"{dbPath}\" -n {ecuName} -l {level} -s {BitUtility.BytesToHex(seed)} -p {successIdentifier}"; string result = RunProcessCaptureOutput(binaryPath, args); if (!result.StartsWith(successIdentifier)) { return false; } string responseAsString = result.Substring(successIdentifier.Length); Console.WriteLine($"UnlockECU (automatic) returns {responseAsString} for seed {BitUtility.BytesToHex(seed)} (ECU: {ecuName}, Level: {level})"); key = BitUtility.BytesFromHex(responseAsString); return true; } private static string RunProcessCaptureOutput(string filePath, string args) { // see https://stackoverflow.com/questions/285760/how-to-spawn-a-process-and-capture-its-stdout-in-net StringBuilder outputBuilder; ProcessStartInfo processStartInfo; Process process; outputBuilder = new StringBuilder(); processStartInfo = new ProcessStartInfo(); processStartInfo.CreateNoWindow = true; processStartInfo.RedirectStandardOutput = true; processStartInfo.RedirectStandardInput = true; processStartInfo.UseShellExecute = false; processStartInfo.Arguments = args; processStartInfo.FileName = filePath; process = new Process(); process.StartInfo = processStartInfo; // enable raising events because Process does not raise events by default process.EnableRaisingEvents = true; // attach the event handler for OutputDataReceived before starting the process process.OutputDataReceived += new DataReceivedEventHandler ( delegate (object sender, DataReceivedEventArgs e) { // append the new data to the data already read-in outputBuilder.Append(e.Data); } ); // start the process // then begin asynchronously reading the output // then wait for the process to exit // then cancel asynchronously reading the output process.Start(); process.BeginOutputReadLine(); process.WaitForExit(); process.CancelOutputRead(); // use the output return outputBuilder.ToString(); } private static void PromptClipboardCopyOfSeed(string seed) { if (MessageBox.Show($"Received a seed value of {seed}. \r\nCopy to clipboard?", "Security Access", MessageBoxButtons.YesNo) == DialogResult.Yes) { Clipboard.SetText(seed); } } } } ================================================ FILE: Caesar/Diogenes/Simulation/SimulatedDevice.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Diogenes.Simulation { // this whole simulation setup is required for my debugging as I don't always have access to my ECU/J2534 device public class SimulatedDevice { public virtual byte[] ReceiveRequest(IEnumerable request) { Console.WriteLine("ReceiveRequest was not overridden!"); return new byte[] { }; } } } ================================================ FILE: Caesar/Diogenes/Simulation/Simulated_CRD3.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using Caesar; namespace Diogenes.Simulation { public class Simulated_CRD3 : SimulatedDevice { // quacks like a CRD3 : 2131 from a DTC perspective public enum UDS : byte { UDS_AccessTimingParameters = 0x83, UDS_Authentication = 0x29, UDS_ClearDiagnosticInformation = 0x14, UDS_CommunicationControl = 0x28, UDS_ControlDTCSettings = 0x85, UDS_DiagnosticSessionControl = 0x10, UDS_DynamicallyDefineDataIdentifier = 0x2C, UDS_ECUReset = 0x11, UDS_InputOutputControlByIdentifier = 0x2F, UDS_LinkControl = 0x87, UDS_NegativeResponse = 0x7F, UDS_ReadDataByIdentifier = 0x22, UDS_ReadDataByIdentifierPeriodic = 0x2A, UDS_ReadDTCInformation = 0x19, UDS_ReadMemoryByAddress = 0x23, UDS_ReadScalingDataByIdentifier = 0x24, UDS_RequestDownload = 0x34, UDS_RequestFileTransfer = 0x38, UDS_RequestTransferExit = 0x37, UDS_RequestUpload = 0x35, UDS_ResponseOnEvent = 0x86, UDS_RoutineControl = 0x31, UDS_SecuredDataTransmission = 0x84, UDS_SecurityAccess = 0x27, UDS_TesterPresent = 0x3E, UDS_TransferData = 0x36, UDS_WriteDataByIdentifier = 0x2E, UDS_WriteMemoryByAddress = 0x3D, } public enum NR : byte { NR_PositiveResponse = 0x00, NR_GeneralReject = 0x10, NR_ServiceNotSupported = 0x11, NR_SubfunctionNotSupported = 0x12, NR_IncorrectMessageLengthOrInvalidFormat = 0x13, NR_ResponseTooLong = 0x14, NR_BusyRepeatRequest = 0x21, NR_ConditionsNotCorrect = 0x22, NR_RequestSequenceError = 0x24, NR_NoResponseFromSubnetComponent = 0x25, NR_FailurePreventsExecutionOfRequestedAction = 0x26, NR_RequestOutOfRange = 0x31, NR_SecurityAccessDenied = 0x33, NR_InvalidKey = 0x35, NR_ExceedNumberOfAttempts = 0x36, NR_RequiredTimeDelayNotExpired = 0x37, NR_UploadDownloadNotAccepted = 0x70, NR_TransferDataSuspended = 0x71, NR_GeneralProgrammingFailure = 0x72, NR_WrongBlockSequenceCounter = 0x73, NR_RequestCorrectlyReceivedResponsePending = 0x78, NR_SubfunctionNotSupportedInActiveSession = 0x7E, NR_ServiceNotSupportedInActiveSession = 0x7F, NR_RpmTooHigh = 0x81, NR_RpmTooLow = 0x82, NR_EngineRunning = 0x83, NR_EngineNotRunning = 0x84, NR_EngineRunTimeTooLow = 0x85, NR_TemperatureTooHigh = 0x86, NR_TemperatureTooLow = 0x87, NR_VehicleSpeedTooHigh = 0x88, NR_VehicleSpeedTooLow = 0x89, NR_ThrottlePedalTooHigh = 0x8A, NR_ThrottlePedalTooLow = 0X8B, NR_TransmissionRangeNotInNeutral = 0X8C, NR_TransmissionRangeNotInGear = 0x8D, NR_BrakeSwitchesNotClosed = 0x8F, NR_ShifterLeverNotInPark = 0x90, NR_TorqueConverterClutchLocked = 0x91, NR_VoltageTooHigh = 0x92, NR_VoltageTooLow = 0x93, } public enum Identifier : ushort { ID_SessionVariant = 0xF100, ID_SupplierIdentifier = 0xF154, ID_EROTAN = 0xF196, ID_VCFull = 0x1001, ID_VCPartial = 0x1002, } public enum Vendor : byte { VENDOR_Unspecified = 0, VENDOR_Becker = 1, VENDOR_Blaupunkt = 2, VENDOR_Bosch = 3, VENDOR_MB = 4, VENDOR_HuF = 5, VENDOR_Kammerer = 6, VENDOR_Kostal = 7, VENDOR_Siemens = 8, VENDOR_Stribel = 9, VENDOR_MicroHeat = 10, VENDOR_JATCO = 11, VENDOR_SWF = 16, VENDOR_VDO = 17, VENDOR_Webasto = 18, VENDOR_Dornier = 19, VENDOR_TEG = 20, VENDOR_Hella = 21, VENDOR_Lucas = 22, VENDOR_GKR = 23, VENDOR_MBB = 24, VENDOR_Motometer = 25, VENDOR_Borg = 32, VENDOR_Temic = 33, VENDOR_Teves = 34, VENDOR_Borg_Warner = 35, VENDOR_MED_SPA = 36, VENDOR_DENSO = 37, VENDOR_ZF = 38, VENDOR_TRW = 39, VENDOR_Dunlop = 40, VENDOR_LUK = 41, VENDOR_Magneti_Marelli = 48, VENDOR_DODUCO = 49, VENDOR_Alpine = 50, VENDOR_AMC_AEG_Mobile = 51, VENDOR_Bose = 52, VENDOR_Dasa = 53, VENDOR_Motorola = 54, VENDOR_Nokia = 55, VENDOR_Panasonic = 56, VENDOR_APAG = 57, VENDOR_Rialtosoft = 58, VENDOR_Applicom = 59, VENDOR_Conti_Temic = 60, VENDOR_Cherry = 61, VENDOR_TI_Automotive = 62, VENDOR_Kongsberg_Company = 63, VENDOR_Delphi = 64, VENDOR_Alfmeier = 65, VENDOR_Sidler = 66, VENDOR_Marquardt = 67, VENDOR_Wehrle = 68, VENDOR_megamos = 69, VENDOR_ADC = 70, VENDOR_BERU = 71, VENDOR_Valeo = 72, VENDOR_Magna = 73, VENDOR_Allison = 74, VENDOR_Isringhausen = 75, VENDOR_Grammer = 76, VENDOR_Funkwerk_Dabendorf = 77, VENDOR_Hella_Behr = 78, VENDOR_Pollak = 79, VENDOR_AKG = 80, VENDOR_Automotive_Lighting = 81, VENDOR_TAG = 82, VENDOR_UNITED_PARTS = 83, VENDOR_catem = 84, VENDOR_Alge = 85, VENDOR_Pierburg = 86, VENDOR_Brusa = 87, VENDOR_Ecostar = 88, VENDOR_Xcellsis = 89, VENDOR_Wabco_Automotive = 90, VENDOR_Voith = 91, VENDOR_Knorr = 92, VENDOR_TVI = 93, VENDOR_Stoneridge = 94, VENDOR_Telma = 95, VENDOR_STW = 96, VENDOR_Koyo = 97, VENDOR_Eberspacher = 98, VENDOR_ADVICS = 99, VENDOR_OMRON = 100, VENDOR_Mitsubishi_Heavy_Industry = 101, VENDOR_Methode = 102, VENDOR_UNISIAJECS = 103, VENDOR_UNISIA_JKC_Steering_Systems = 104, VENDOR_AISIN = 105, VENDOR_Zexel_Valeo = 106, VENDOR_Schrader = 107, VENDOR_Ballard = 108, VENDOR_SFT = 112, VENDOR_Kieckert_AG = 113, VENDOR_Behr = 114, VENDOR_MB_Lenkungen = 115, VENDOR_Sachs_Automotive = 116, VENDOR_Peiker = 117, VENDOR_Petri = 118, VENDOR_Autoliv = 119, VENDOR_Thien_Electronic = 120, VENDOR_Siemens_VDO = 121, VENDOR_Dornier_Consulting_GmbH = 122, VENDOR_Alps = 123, VENDOR_PREH = 124, VENDOR_Hitachi_Unisia = 125, VENDOR_Hitachi = 126, VENDOR_Reserved_127 = 127, VENDOR_Huntsville = 128, VENDOR_Yazaki = 129, VENDOR_Lear = 130, VENDOR_Johnson_Controls = 131, VENDOR_HarmanBecker = 132, VENDOR_Mitsubishi_Electric = 133, VENDOR_Tokico_USA_Inc = 134, VENDOR_Nippon_Seiki_International = 135, VENDOR_Inalfa = 136, VENDOR_Nippon_Seiki_UK = 137, VENDOR_GHSP = 138, VENDOR_Vector = 139, VENDOR_Gentex = 140, VENDOR_Visteon = 141, VENDOR_Tochigi_Fuji = 142, VENDOR_DCA = 143, VENDOR_May_and_Scofield = 144, VENDOR_DaimlerChrysler_Hamburg_Plant = 145, VENDOR_AISIN_AW = 146, VENDOR_TOYODA_MACHINE_WORKS = 147, VENDOR_Solectron_Invotronics = 148, VENDOR_Kicker = 149, VENDOR_American_Axle_Company = 150, VENDOR_GETRAG = 151, VENDOR_Promate = 152, VENDOR_ArvinMeritor = 153, VENDOR_Reserved_MMC = 160, VENDOR_Reserved_MMC_SMART = 161, VENDOR_Reserved_162 = 162, VENDOR_After_Market_Supplier = 254, VENDOR_Unidentified = 255, } public Simulated_CRD3() { } //ushort ECU_VARIANT = 0x2131; ushort ECU_VARIANT = 0x1000; // pretend to be eis166 for a while byte ECU_SUPPLIER_IDENTIFIER = (byte)Vendor.VENDOR_Delphi; byte ECU_SESSION = 1; // default byte ECU_GATEWAY_MODE = 2; ushort ECU_TIMING_RESOLUTION_1MS = 20; ushort ECU_TIMING_RESOLUTION_10MS = 200; byte[] ECU_VariantCoding = { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x21, 0x40, 0xAF, 0x8C, 0xE0, 0x24, 0x58, 0x91, 0x59, 0x98, 0x56, 0x20, 0x49, 0x47, 0x7D, 0x00, 0xE5, 0x00, 0x36, 0x36 }; byte[] ECU_Fingerprint = { 0x00, 0x40, 0x33, 0x10 }; byte[] ECU_SoftwareCalibrationNumber = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 }; byte[] ECU_EROTAN = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; byte[] EnvTest = {0x00, 0x90, 0x00, 0x2F, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x28, 0x02, 0x00, 0x24, 0x00, 0x93, 0x00, 0x38, 0x02, 0x0F, 0x01, 0x04, 0x7F, 0x7C, 0x00, 0x88, 0x8E, 0xA5, 0x3C, 0x0A, 0x00, 0x00, 0x00, 0x5F, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x03, 0x00, 0x24, 0x00, 0x93, 0x00, 0x38, 0x02, 0x0F, 0x01, 0x04, 0x7F, 0x7C, 0x00, 0x88, 0x8E, 0xA5, 0x3C, 0x0A, 0x00, 0x00, 0x00, 0x5F, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00 }; // this behaves a bit more like my uC implementation // performance is generally poorer, though the IO is fairly minimal // maybe wrap it in a class with a proper binarywriter List SharedResponse = new List(); public void WriteByte(byte inByte) { SharedResponse.Add(inByte); } public void WriteUint16(ushort inValue) { SharedResponse.Add((byte)((inValue >> 8) & 0xFF)); SharedResponse.Add((byte)(inValue & 0xFF)); } public void WriteInt16(short inValue) { SharedResponse.Add((byte)((inValue >> 8) & 0xFF)); SharedResponse.Add((byte)(inValue & 0xFF)); } public void WriteUint32(ushort inValue) { SharedResponse.Add((byte)((inValue >> 24) & 0xFF)); SharedResponse.Add((byte)((inValue >> 16) & 0xFF)); SharedResponse.Add((byte)((inValue >> 8) & 0xFF)); SharedResponse.Add((byte)(inValue & 0xFF)); } public void WriteInt32(int inValue) { SharedResponse.Add((byte)((inValue >> 24) & 0xFF)); SharedResponse.Add((byte)((inValue >> 16) & 0xFF)); SharedResponse.Add((byte)((inValue >> 8) & 0xFF)); SharedResponse.Add((byte)(inValue & 0xFF)); } public void WriteByteArray(byte[] inValue) { SharedResponse.AddRange(inValue); } public byte[] CreateNegativeResponse(UDS callingFunction, NR reason) { // throw new Exception("debugger please"); return new byte[] {0x7F, (byte)callingFunction, (byte)reason }; } public byte[] MemoryStreamWriterToArray(BinaryWriter writer) { return ((MemoryStream)writer.BaseStream).ToArray(); } public override byte[] ReceiveRequest(IEnumerable request) { SharedResponse = new List(); byte[] requestBytes = request.ToArray(); if (requestBytes.Length == 0) { // this shouldn't happen return new byte[] { }; } if (!Enum.IsDefined(typeof(UDS), requestBytes[0])) { return CreateNegativeResponse((UDS)requestBytes[0], NR.NR_ServiceNotSupported); } UDS requestCommand = (UDS)requestBytes[0]; WriteByte((byte)(requestBytes[0] + 0x40)); ushort identifier = 0; if (requestBytes.Length > 2) { identifier = (ushort)(requestBytes[1] << 8 | requestBytes[2]); } if ((requestCommand == UDS.UDS_TesterPresent) && (requestBytes.Length >= 2)) { WriteByte(requestBytes[1]); } else if ((requestCommand == UDS.UDS_DiagnosticSessionControl) && (requestBytes.Length >= 2)) { ECU_SESSION = requestBytes[1]; WriteByte(ECU_SESSION); WriteUint16(ECU_TIMING_RESOLUTION_1MS); WriteUint16(ECU_TIMING_RESOLUTION_10MS); } else if ((requestCommand == UDS.UDS_ReadDataByIdentifier) && (requestBytes.Length >= 3)) { WriteUint16(identifier); if (identifier == (ushort)Identifier.ID_SupplierIdentifier) { WriteByte(ECU_SUPPLIER_IDENTIFIER); } else if (identifier == (ushort)Identifier.ID_SessionVariant) { WriteByte(ECU_GATEWAY_MODE); WriteUint16(ECU_VARIANT); WriteByte(ECU_SESSION); } } else if ((requestCommand == UDS.UDS_WriteDataByIdentifier) && (requestBytes.Length >= 3)) { } else if ((requestCommand == UDS.UDS_ReadDTCInformation) && (requestBytes.Length >= 2)) { byte infoType = requestBytes[1]; WriteByte(infoType); byte mask = requestBytes[2]; if (infoType == 0x02) { /* // mask should go here? WriteByte(0xFF); // mask WriteByte(0x00); WriteByte(0x90); WriteByte(0x00); WriteByte(0x2F); */ WriteByteArray(BitUtility.BytesFromHex("5B D0 3D 2A 0B D0 32 2A 0B C0 19 2A 0B D0 38 2A 08 C1 22 87 0B D1 82 00 0B D1 80 00 0B 06 10 00 0B D1 81 00 03 D1 83 00 03 D1 98 00 41")); // eis166 } else if (infoType == 0x06) { /* WriteByte(0xFF); // mask WriteByteArray(EnvTest); */ WriteByteArray(BitUtility.BytesFromHex("D0 3D 2A 0B 01 00 2A C0 2A C0 09 00 ")); // eis166 } } else { // unrecognized return CreateNegativeResponse((UDS)requestBytes[0], NR.NR_ServiceNotSupported); } return SharedResponse.ToArray(); } public static ushort CRC16ARC(byte[] inData) { // tests: /* Console.WriteLine($"{Simulation.Simulated_CRD3.CRC16ARC(new byte[] { 0x78, 0x65, 0x36, 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x0B, 0x0B, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x81, 0x03, 0xFF, 0xC1, 0x74, 0x0E, 0xE8, 0x03, 0x72, 0x0B, 0xC8, 0x08, 0xC2, 0x01 }):X4}"); // expects E6 2B (0x2BE6) Console.WriteLine($"{Simulation.Simulated_CRD3.CRC16ARC(new byte[] { 0x78, 0x64, 0x70, 0x39, 0x0C, 0x00, 0x00, 0x04, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x1A, 0x00, 0xA6, 0x09, 0xE8, 0x03, 0xE8, 0x03, 0xC6, 0x07, 0x81, 0x01 }):X4}"); // expects C1 12 (0x12C1) */ uint[] crcTable = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, }; uint crc = 0; foreach (byte b in inData) { crc = (crc >> 8) ^ crcTable[(crc ^ b) & 0xFF]; } return (ushort)(crc & 0xFFFF); } } } ================================================ FILE: Caesar/Diogenes/TextboxWriter.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public class TextboxWriter : TextWriter { private TextBox InputTextbox; private Timer timer; private StringBuilder sb = new StringBuilder(); private bool dirty = false; private readonly object WriteLock = new object(); public TextboxWriter(TextBox inputTextbox) { InputTextbox = inputTextbox; timer = new Timer(); timer.Interval = 30; timer.Tick += Timer_Tick; timer.Enabled = true; } private void Timer_Tick(object sender, EventArgs e) { // using a timer since invoking an event on every character write gets expensive quickly if (dirty || (InputTextbox.Text.Length != sb.Length)) { InputTextbox.Text = sb.ToString(); dirty = false; InputTextbox.SelectionStart = InputTextbox.TextLength; InputTextbox.ScrollToCaret(); } } // fix append for crossthread : https://stackoverflow.com/questions/12645351/stringbuilder-tostring-throw-an-index-out-of-range-exception public override void Write(char value) { lock (WriteLock) { sb.Append(value); dirty = true; } } public override void Write(string value) { lock (WriteLock) { sb.Append(value); dirty = true; } } public void Clear() { sb = new StringBuilder(); dirty = true; } public override Encoding Encoding { get { return Encoding.Unicode; } } } } ================================================ FILE: Caesar/Diogenes/UnmanagedUtility.cs ================================================ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Diogenes { class UnmanagedUtility { /* Symbol enumeration: https://stackoverflow.com/questions/18249566/c-sharp-get-the-list-of-unmanaged-c-dll-exports */ [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)] bool fInvadeProcess); [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SymCleanup(IntPtr hProcess); [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile, string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags); [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SymEnumerateSymbols64(IntPtr hProcess, ulong BaseOfDll, SymEnumerateSymbolsProc64 EnumSymbolsCallback, IntPtr UserContext); public delegate bool SymEnumerateSymbolsProc64(string SymbolName, ulong SymbolAddress, uint SymbolSize, IntPtr UserContext); /* DLL invocation: https://stackoverflow.com/questions/16518943/dllimport-or-loadlibrary-for-best-performance */ [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] public static extern bool FreeLibrary(IntPtr hModule); public const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44; public const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45; public const int TVS_EX_DOUBLEBUFFER = 0x0004; public const int EM_SETCUEBANNER = 0x1501; [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam); private static List LibraryExports = new List(); public static bool SymbolEnumeratedCallback(string name, ulong address, uint size, IntPtr context) { // Useful for debug: // Console.WriteLine(name); LibraryExports.Add(name); return true; } private static bool EnumerateDllExports(string modulePath) { IntPtr hCurrentProcess = Process.GetCurrentProcess().Handle; ulong dllBase; // Initialize symbol handler with our own process handle if (!SymInitialize(hCurrentProcess, null, false)) { Console.WriteLine("SymInitialize function (dbghelp.h) failed"); return false; } // Load dll dllBase = SymLoadModuleEx(hCurrentProcess, IntPtr.Zero, modulePath, null, 0, 0, IntPtr.Zero, 0); if (dllBase == 0) { Console.Out.WriteLine($"Failed to load module: {modulePath}"); SymCleanup(hCurrentProcess); return false; } // Clean up the results list before it gets populated LibraryExports.Clear(); // Enumerate symbols. For every symbol, the callback method SymbolEnumeratedCallback is called. if (SymEnumerateSymbols64(hCurrentProcess, dllBase, SymbolEnumeratedCallback, IntPtr.Zero) == false) { Console.Out.WriteLine($"Failed to enumerate symbols for library {modulePath}"); return false; } SymCleanup(hCurrentProcess); return true; } public static List GetExports(string modulePath) { if (EnumerateDllExports(modulePath)) { return LibraryExports; } else { return new List(); } } public static void DumpExportsToConsole(string modulePath) { List exports = UnmanagedUtility.GetExports(modulePath); Console.WriteLine($"Retrieving exports for {modulePath}"); foreach (string s in exports) { Console.WriteLine($"{modulePath}: {s}"); } Console.WriteLine($"End of {modulePath} exports."); } } } ================================================ FILE: Caesar/Diogenes/VariantCoding.cs ================================================ using Caesar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Diogenes { public class VariantCoding { private static void ExecVCWrite(byte[] request, DiagService service, ECUConnection connection, bool writesEnabled) { bool allowVcWrite = writesEnabled; // allowWriteVariantCodingToolStripMenuItem.Checked; if (allowVcWrite) { connection.ExecUserDiagJob(request, service); Console.WriteLine("VC Write completed"); } else { MessageBox.Show("This VC write action has to be manually enabled under \r\nFile > Allow Write Variant Coding\r\nPlease make sure that you understand the risks before doing so.", "Accidental Brick Protection"); } } /* test: med40 jg: dumping pres jg: q: SID_RQ pos byte: 0 size bytes: 1 modecfg:323 fieldtype: IntegerType dump: 2E 00 00 00 jg: q: RecordDataIdentifier pos byte: 1 size bytes: 2 modecfg:324 fieldtype: IntegerType dump: 01 10 00 00 jg: q: #0 pos byte: 33 size bytes: 16 modecfg:6430 fieldtype: BitDumpType dump: jg: q: #1 pos byte: 49 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump: jg: q: #2 pos byte: 50 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump: jg: q: #3 pos byte: 51 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump: jg: q: #4 pos byte: 52 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump: jg: q: #5 pos byte: 3 size bytes: 50 modecfg:6410 fieldtype: ExtendedBitDumpType dump: jg: done dumping pres */ public static void DoVariantCoding(ECUConnection connection, VCForm vcForm, bool writesEnabled) { Console.WriteLine($"Operator requesting for VC: {BitUtility.BytesToHex(vcForm.VCValue, true)}"); RunDiagForm runDiagForm = new RunDiagForm(vcForm.WriteService); // construct a write command from presentations: fill up the VC value first, fill up all available dumps, then inherit the last values (fingerprints, scn) from the read command byte[] vcParameter = vcForm.VCValue; byte[] writeCommand = vcForm.WriteService.RequestBytes; byte[] priorReadCommand = vcForm.UnfilteredReadValue; // start with a list of all values that we will have to fill List preparationsToProcess = new List(vcForm.WriteService.InputPreparations); // fill up vc, which pretty much always uses the ExtendedBitDumpType type DiagPreparation vcPrep = preparationsToProcess.Find(x => x.FieldType == DiagPreparation.InferredDataType.ExtendedBitDumpType); if (vcPrep is null) { MessageBox.Show("VC: Could not find the VC ExtendedBitDump prep, stopping early to save your ECU.", "VC Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } int vcPrepSizeInBytes = vcPrep.SizeInBits / 8; int vcPrepBytePosition = vcPrep.BitPosition / 8; if (vcPrepSizeInBytes < vcParameter.Length) { MessageBox.Show("VC: VC string is longer than the parameter can fit, stopping early to save your ECU.", "VC Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // zero out the destination buffer for the param that we intend to write since there's a possibility that our param is shorter than the actual prep's size for (int i = vcPrepBytePosition; i < (vcPrepBytePosition + vcPrepSizeInBytes); i++) { writeCommand[i] = 0; } // copy the parameter in Array.ConstrainedCopy(vcParameter, 0, writeCommand, vcPrepBytePosition, vcParameter.Length); preparationsToProcess.Remove(vcPrep); // done with vc prep // merge prefilled constants such as the (SID_RQ, id..) List prefilledValues = new List(); foreach (DiagPreparation prep in preparationsToProcess) { if (prep.Dump.Length > 0) { prefilledValues.Add(prep); if (prep.FieldType == DiagPreparation.InferredDataType.IntegerType) { byte[] fixedDump = prep.Dump.Take(prep.SizeInBits / 8).Reverse().ToArray(); Array.ConstrainedCopy(vcParameter, 0, writeCommand, vcPrepBytePosition, vcParameter.Length); } else { Console.WriteLine($"Skipping prefill for {prep.Qualifier} as the data type {prep.FieldType} is unsupported."); } } } // "mark" the constants as done foreach (DiagPreparation prep in prefilledValues) { preparationsToProcess.Remove(prep); } // isolate the SCN if it exists foreach (DiagPreparation prep in preparationsToProcess) { int bytePosition = prep.BitPosition / 8; int byteLength = prep.SizeInBits / 8; // SCN is always 16-bytes if (byteLength != 16) { continue; } byte[] originalValue = new byte[byteLength]; Array.ConstrainedCopy(priorReadCommand, bytePosition, originalValue, 0, byteLength); // SCN values are ASCII numerals (between 0x30 - 0x39) bool isValidSCN = true; foreach (byte b in originalValue) { if ((b > 0x39) || (b < 0x30)) { isValidSCN = false; break; } } if (!isValidSCN) { continue; } Console.WriteLine($"Found SCN value: {Encoding.ASCII.GetString(originalValue)}"); // check if operator is using vediamo-style variant-coding, where the SCN is set to 0000000000000000 when writing VC // otherwise, we can reuse the last value as read from the ECU bool useVediamoBehaviorZeroSCN = Preferences.GetValue(Preferences.PreferenceKey.EnableSCNZero) == "true"; if (useVediamoBehaviorZeroSCN) { for (int i = 0; i < originalValue.Length; i++) { originalValue[i] = 0x30; } } Console.WriteLine($"Using {Encoding.ASCII.GetString(originalValue)} as new SCN value"); // write-back the recognized (and optionally, modified) SCN Array.ConstrainedCopy(originalValue, 0, writeCommand, bytePosition, byteLength); preparationsToProcess.Remove(prep); break; } // isolate the fingerprint if it exists // normally fingerprint is appended at the tail of the VC command List tailIndices = new List() { writeCommand.Length - 1, writeCommand.Length - 2, writeCommand.Length - 3, writeCommand.Length - 4 }; List possibleFingerprintFields = new List(); foreach (DiagPreparation prep in preparationsToProcess) { int bytePosition = prep.BitPosition / 8; int byteLength = prep.SizeInBits / 8; if ((prep.FieldType == DiagPreparation.InferredDataType.IntegerType) && (byteLength == 1) && (tailIndices.Contains(bytePosition))) { tailIndices.Remove(bytePosition); possibleFingerprintFields.Add(prep); } } if (possibleFingerprintFields.Count == 4) { // copy in the fingerprint, and "mark" the constants as done byte[] fingerprint = priorReadCommand.Skip(priorReadCommand.Length - 4).ToArray(); Console.WriteLine($"Found original fingerprint as {BitUtility.BytesToHex(fingerprint)}"); // default behavior is to clone last fingerprint, else use stored fingerprint if (Preferences.GetValue(Preferences.PreferenceKey.EnableFingerprintClone) == "false") { uint altFingerprintValue = uint.Parse(Preferences.GetValue(Preferences.PreferenceKey.FingerprintValue)); fingerprint[3] = (byte)(altFingerprintValue & 0xFF); altFingerprintValue >>= 8; fingerprint[2] = (byte)(altFingerprintValue & 0xFF); altFingerprintValue >>= 8; fingerprint[1] = (byte)(altFingerprintValue & 0xFF); altFingerprintValue >>= 8; fingerprint[0] = (byte)(altFingerprintValue & 0xFF); } Console.WriteLine($"Using {BitUtility.BytesToHex(fingerprint)} as new fingerprint value."); Array.ConstrainedCopy(fingerprint, 0, writeCommand, writeCommand.Length - 4, 4); foreach (DiagPreparation prep in possibleFingerprintFields) { preparationsToProcess.Remove(prep); } } // at this point, whatever that's left in preparationsToProcess are stuff that are variable, but should be copied verbatim from the original read request (e.g. fingerprints, scn) // log the assumptions, show it the operator just in case StringBuilder assumptionsMade = new StringBuilder(); if (preparationsToProcess.Count > 0) { if (writeCommand.Length != priorReadCommand.Length) { MessageBox.Show("There are some preparations that do not have a default value. \r\n" + "The input and output values do not have matching lengths, which means that the automatic assumption may be wrong. \r\n" + "Please be very careful when proceeding.", "Warning"); } foreach (DiagPreparation prep in preparationsToProcess) { int bytePosition = prep.BitPosition / 8; int byteLength = prep.SizeInBits / 8; Array.ConstrainedCopy(priorReadCommand, bytePosition, writeCommand, bytePosition, byteLength); assumptionsMade.Append($"{prep.Qualifier} : {BitUtility.BytesToHex(priorReadCommand.Skip(bytePosition).Take(byteLength).ToArray(), true)}\r\n"); } } /* // lazy me dumping the values for (int i = 0; i < vcForm.WriteService.InputPreparations.Count; i++) { DiagPreparation prep = vcForm.WriteService.InputPreparations[i]; Console.WriteLine($"debug: q: {prep.Qualifier} pos byte: {(prep.BitPosition / 8)} size bytes: {(prep.SizeInBits / 8)} modecfg:{prep.ModeConfig:X} fieldtype: {prep.FieldType} dump: {BitUtility.BytesToHex(prep.Dump, true)}"); } */ // we are done preparing the command, if we are confident we can send the command straight to the ECU, else, let the user review if (assumptionsMade.Length > 0) { if (MessageBox.Show("Some assumptions were made when preparing the write parameters. \r\n\r\n" + "You may wish to review them by selecting Cancel, or select OK to execute the write command immediately.\r\n\r\n" + assumptionsMade.ToString(), "Review assumptions", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK) { ExecVCWrite(writeCommand, vcForm.WriteService, connection, writesEnabled); } else { runDiagForm.Result = writeCommand; if (runDiagForm.ShowDialog() == DialogResult.OK) { ExecVCWrite(runDiagForm.Result, vcForm.WriteService, connection, writesEnabled); } } } else { // everything accounted for, immediately write ExecVCWrite(writeCommand, vcForm.WriteService, connection, writesEnabled); } } } } ================================================ FILE: Caesar/Diogenes/packages.config ================================================  ================================================ FILE: Caesar/Trafo/App.config ================================================  ================================================ FILE: Caesar/Trafo/Program.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using Caesar; using System.IO; using Newtonsoft.Json; namespace Trafo { class Program { static List VariantList; static void ReadScales (CaesarContainer container, DiagPresentation presentation, List scaleslist) { foreach (Scale Scale in presentation.Scales) { var ScaleRow = new { LowBound = Scale.EnumLowBound, UpBound = Scale.EnumUpBound, //PrepLowBound = Scale.PrepLowBound, //commented out fields purpose unknown //PrepUpBound = Scale.PrepUpBound, MultiplyFactor = Scale.MultiplyFactor, AddConstOffs = Scale.AddConstOffset, //SICount =Scale.SICount, //OffsetSI = Scale.OffsetSI, //USCount = Scale.USCount, //OffsetUS = Scale.OffsetUS, EnumDesc = container.CaesarCTFHeader.CtfLanguages[0].GetString(Scale.EnumDescription) }; scaleslist.Add(ScaleRow); } } static void ReadPreparation (CaesarContainer container, DiagPreparation prep, List preplist) { DiagPresentation Presentation = container.CaesarECUs[0].GlobalPresentations[prep.PresPoolIndex]; List ScalesList = new List(); ReadScales(container, Presentation, ScalesList); var PresentationRow = new { Qualifier = Presentation.Qualifier, Desc = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.Description_CTF), Units = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.DisplayedUnit_CTF), EnumMaxVal = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.EnumMaxValue), Desc2 = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.Description2_CTF), Scales = ScalesList }; var PreparationRow = new { Name = prep.Qualifier, LongName = container.CaesarCTFHeader.CtfLanguages[0].GetString(prep.Name_CTF), BitPos = prep.BitPosition, BitLen = prep.SizeInBits, Presentation = PresentationRow }; preplist.Add(PreparationRow); } static void ReadDiagService (CaesarContainer container, DiagService diagservice, List diagserviceslist) { List InputPrepList = new List(); foreach (DiagPreparation InputPrep in diagservice.InputPreparations) ReadPreparation(container, InputPrep, InputPrepList); List OutputPrepList = new List(); foreach (List OutputPreps in diagservice.OutputPreparations) { foreach (DiagPreparation OutputPrep in OutputPreps) ReadPreparation(container, OutputPrep, OutputPrepList); } string RequestArr = string.Join("", diagservice.RequestBytes.Select(b => string.Format("{0:X2} ", b))); var RequestBytesRow = new { RequestBytes = RequestArr }; var servicetype = (DiagService.ServiceType) diagservice.DataClass_ServiceType; var DiagServiceRow = new { DiagServiceName = diagservice.Qualifier, Desc = container.CaesarCTFHeader.CtfLanguages[0].GetString(diagservice.Description_CTF), Type = servicetype.ToString(), ClientAccessLevel = diagservice.ClientAccessLevel, SecurityAccessLevel = diagservice.SecurityAccessLevel, RequestBytes = RequestArr, InputPreps = InputPrepList, OutputPreps = OutputPrepList }; diagserviceslist.Add(DiagServiceRow); } static void ReadECUVariant (CaesarContainer container, ECUVariant variant ) { List domainList = new List(); foreach (VCDomain domain in variant.VCDomains) { DiagService ReadService = variant.GetDiagServiceByName(domain.ReadServiceName); DiagService WriteService = variant.GetDiagServiceByName(domain.WriteServiceName); string ReadArr = string.Join("", ReadService.RequestBytes.Select(b => string.Format("{0:X2} ", b))); string WriteArr = string.Join("", WriteService.RequestBytes.Select(b => string.Format("{0:X2} ", b))); List fragmentList = new List(); foreach (VCFragment fragment in domain.VCFragments) { List PresList = new List(); DiagPresentation Presentation = container.CaesarECUs[0].GlobalPresentations[fragment.MeaningB]; List ScalesList = new List(); ReadScales(container, Presentation, ScalesList); var FragmentInfo = new { Qualifier = Presentation.Qualifier, Desc = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.Description_CTF), Units = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.DisplayedUnit_CTF), EnumMaxVal = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.EnumMaxValue), Desc2 = container.CaesarCTFHeader.CtfLanguages[0].GetString(Presentation.Description2_CTF), Scales = ScalesList }; var fragmentRow = new { FragName = container.CaesarCTFHeader.CtfLanguages[0].GetString(fragment.Name_CTF), FragDesc = container.CaesarCTFHeader.CtfLanguages[0].GetString(fragment.Description_CTF), BitPos = fragment.ByteBitPos, BitLen = fragment.BitLength, ReadAccessLevel = fragment.ReadAccessLevel, WriteAccessLevel = fragment.WriteAccessLevel, ByteOrder = fragment.ByteOrder, Info = FragmentInfo }; fragmentList.Add(fragmentRow); } var domainRow = new { VCDName = domain.Qualifier, DumpSize = domain.DumpSize, ReadService = domain.ReadServiceName, WriteService = domain.WriteServiceName, ReadBytes = ReadArr, WriteBytes = WriteArr, VCDFragments = fragmentList }; var RequestBytesRow = new { ReadRequestBytes = ReadArr, WriteRequestBytes = WriteArr }; domainList.Add(domainRow); } List DTCList = new List(); foreach (DTC dtc in variant.DTCs) { List XrefsList = new List(); List EnvCtxForDTC = variant.GetEnvironmentContextsForDTC(dtc); for (int i = 0; i < dtc.XrefCount; i++) XrefsList.Add(EnvCtxForDTC[i].Qualifier); var DTCRow = new { Code = dtc.Qualifier, Desc = container.CaesarCTFHeader.CtfLanguages[0].GetString(dtc.Description_CTF), Ref = container.CaesarCTFHeader.CtfLanguages[0].GetString(dtc.Reference_CTF), Xrefs = XrefsList }; DTCList.Add(DTCRow); } List EnvCtxList = new List(); foreach (DiagService EnvCtx in variant.EnvironmentContexts) ReadDiagService(container, EnvCtx, EnvCtxList); List DiagServicesList = new List(); foreach (DiagService DiagService in variant.DiagServices) ReadDiagService(container, DiagService, DiagServicesList); var variantRow = new { VariantName = variant.Qualifier, VarcodingDomains = domainList, DTCs = DTCList, EnvironmentContexts = EnvCtxList, DiagServices = DiagServicesList }; VariantList.Add(variantRow); } static void Main(string[] args) { #if DEBUG string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\temp.CBF"; #else if ((args.Length == 0) || (args.Length > 2)) { Console.WriteLine("Usage:"); Console.WriteLine("trafo.exe [target CBF file] [parameter]"); Console.WriteLine("[parameter] can be:"); Console.WriteLine("listvar: list all variant names present in CBF file"); Console.WriteLine("[variant name]: export varcoding, DTC, environment context, diagnostic services sections of one specified variant"); Console.WriteLine("if no [parameter] is specified - export varcoding, DTC, environment context, diagnostic services sections of all variants"); return; } if (!File.Exists(args[0])) { Console.WriteLine("Specified CBF file does not exist, exiting"); return; } string path = args[0]; #endif byte[] cbfBytes = File.ReadAllBytes(path); CaesarContainer container = new CaesarContainer(cbfBytes); string mode = ""; if (args.Length == 2) mode = args[1]; bool VariantFound = false; if (mode == "listvar") { string combinedString = ""; foreach (ECU ecu in container.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) combinedString = combinedString + " " + variant.Qualifier; } Console.WriteLine(combinedString); } else { VariantList = new List(); foreach (ECU ecu in container.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { if (mode == "") { ReadECUVariant(container, variant); } else if (mode == variant.Qualifier) { VariantFound = true; ReadECUVariant(container, variant); break; } } } if (mode != "" && !VariantFound) { Console.WriteLine("Specified variant does not exist in provided CBF file, exiting"); return; } string newFilename = $"{Path.GetDirectoryName(path)}{Path.DirectorySeparatorChar}{Path.GetFileNameWithoutExtension(path)}_{mode}.json"; var caesarContainerJson = new { TrafoVersion = GetVersion(), OriginalFile = Path.GetFileName(path), container.CaesarCFFHeader, Variants = VariantList }; File.WriteAllText(newFilename, JsonConvert.SerializeObject(caesarContainerJson)); Console.WriteLine($"Converted CBF file {mode} variant to JSON at {newFilename}"); } #if DEBUG Console.ReadKey(); #endif } public static string GetVersion() { System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); return fvi.FileVersion; } } } ================================================ FILE: Caesar/Trafo/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Trafo")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Trafo")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("42a6f1fd-82cc-4721-bf0c-1658ae902875")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: Caesar/Trafo/Trafo.csproj ================================================  Debug AnyCPU {42A6F1FD-82CC-4721-BF0C-1658AE902875} Exe Trafo Trafo v4.6 512 true true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 trafo-256.ico ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll {71c43c61-7dc7-4d47-9947-1dd73e559911} Caesar ================================================ FILE: Caesar/Trafo/packages.config ================================================  ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 JinGen Lim Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ![CaesarSuite Banner](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/caesarsuite-banner.png) # Caesar Suite ![Counter](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/gh_shield_0.svg) Library and applications to work with Dаіmlеr diagnostics CBF files. - Caesar : Library to operate on CBF files - Diogenes: ECU-Coding utility - Trafo: Transforms CBF files into JSON - UnlockECU: [(External)](https://github.com/jglim/UnlockECU) ECU-Unlocking utility ![Header Image](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/diogenes-2.png) ## Warning This project is far from production ready. Please be careful if you are planning to use this with your vehicle. ## Getting Started Builds are available on the [Releases page](https://github.com/jglim/CaesarSuite/releases/) for the adventurous. Ensure that [.NET Framework 4.6 or newer](https://dotnet.microsoft.com/download) is installed. Optionally install .NET 5 too, if you intend to use [UnlockECU](https://github.com/jglim/UnlockECU). ## License MIT Icons from [http://www.famfamfam.com/lab/icons/silk/](http://www.famfamfam.com/lab/icons/silk/) --- # Caesar Caesar is an experimental parser for CBF files that is reverse engineered from the official, proprietary `c32s.dll` library. Names of classes, functions, properties will change often as they are matched with their disassembly's names. Please be mindful of this when referencing the Caesar library. # Trafo Trafo converts a CBF file into a simplified JSON representation and is backed by Caesar. At this point, the JSON should contain enough information to work with variant-coding strings. Usage is straightforward: drop a CBF file onto `Trafo.exe` and a JSON file will be created in the same folder as the input file. # Diogenes Diogenes is intended to be a FOSS replacement for Vediamo's variant-coding capabilities over J2534 interfaces. At this point, Diogenes can: - Load CBF files and display ECUs and their variants - Parse a variant's VC domain - Parse, visually modify and reinterpret a variant-coding string - Generate authentication seed-keys from standalone DLLS (borrowed from my [SecurityAccessQuery](https://github.com/jglim/SecurityAccessQuery)) (New:) - Open a UDS connection over J2534 (✅) - Enumerate connected ECUs and identify online devices with compatible CBF files (✅ : UDS) - Complete a seed-key challenge with a target ECU (✅ : Paired with [UnlockECU](https://github.com/jglim/UnlockECU)) - Write a new variant-coding string on a target ECU (✅* : Experimental, reuses fingerprints, still needs more testing) Diogenes will be "complete" when it can: - ❌: Test on an ECU that is installed in a vehicle. So far, tests have been made on a real ECU, but only on the bench. *If you are looking for an alternative with a broader feature set, check out [OpenVehicleDiag](https://github.com/rnd-ash/OpenVehicleDiag) instead* # Demo ## Establishing a connection ![Connection](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/demo-connect.gif) ## Reading ECU data ![Read Data](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/demo-data.gif) ## Variant coding ![VC](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/demo-vc.gif) _More information on variant coding in [this discussion](https://github.com/jglim/CaesarSuite/discussions/7)_ ## CFF flash export _Dump a CFF flash file's raw memory contents (assumes unencrypted, uncompressed data). Files are labeled with its intended memory address (IDA: File -> Load file -> Additional binary file)_ ![CFF](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/demo-cff.gif) ## (New!) CFF Splicer _Modify a CFF flash file's memory segment data (assumes unencrypted, uncompressed data). New segment data can be of different file sizes, and the destination ECU memory address can be changed._ ![CFF2](https://raw.githubusercontent.com/jglim/CaesarSuite/main/docs/resources/demo-cff-splice.gif) --- # Contributing ## Issues The primary roadblock for Caesar/Diogenes is the inability to parse Diagnostic Service code blobs, which are compiled binary scripts that automate tasks such as session switching, variant identification, ECU unlocking, and (apparently) variant coding. While Diogenes is usable on UDS, it still falls short for protocols like KW2C3PE because of this issue. ### Workaround - Session switching and variant identification on UDS devices is generally consistent and standardized. - ECU unlocking can be deferred to [UnlockECU](https://github.com/jglim/UnlockECU). - Variant coding typically contains 4 bytes for the signature of the last system that modified it. Diogenes will automatically clone this value. - By default, the 4 bytes contain seemingly random data (`00 40 33 10`) on a "fresh" ECU, and become `00 00 00 01` when written with Vediamo. - Some devices also include the SCN as part of the variant coding, which appears as an additional 128-bit/16-byte field. - Diogenes will detect "unfilled" values, and prompt for the next course of action. ### My lack of understanding There are concepts which I do not understand that may impede the development of this project: - The SCN seems to be a specific 16-byte string, where the first 10 characters are the part number (as printed on the device), and an unknown 6 characters. Are these 6 characters unique to the device? - The 16-character string is typically queried via `DT_STO_ID_Calibration_Identification`. There is also a function for `DT_STO_ID_Calibration_Verification_Number` which returns an unknown 4 bytes. Are these values matched? - Is there a way to query the ECU if the current SCN is valid and accepted? This is crucial to check if the variant-coding was successful. # Contributors These individuals have helped to improve Diogenes in some form (e.g. code, testing, traces/logs, knowledge sharing, assets). - @N0cynym - @Feezex - @rnd-ash Thank you for your contributions.