# Config Version Mismatch Analysis ## Problem Summary When `LoadConfigsFromServer` calls `LoadUserConfigData`, the C# version throws an exception about version mismatch (`dwVer > EC_CONFIG_VERSION`). ## Root Cause Analysis ### Data Flow Comparison #### C++ Version (EC_GameRun.cpp lines 2067-2169) ```cpp bool CECGameRun::LoadConfigsFromServer(const void* pDataBuf, int iDataSize) { // 1. Read USERCFG_VERSION (version 3) DWORD dwVer = *(DWORD*)pData; pData += sizeof (DWORD); if (dwVer > USERCFG_VERSION) // USERCFG_VERSION = 3 { return false; } // 2. Uncompress data if version >= 3 if (dwVer >= 3) { dwRealLen = 4096; pUncompBuf = a_malloctemp(dwRealLen); AFilePackage::Uncompress(pData, iDataSize-sizeof(DWORD), pUncompBuf, &dwRealLen); pData = (BYTE*)pUncompBuf; // Point to uncompressed data } // 3. Create data reader with uncompressed data CECDataReader dr(pData, (int)dwRealLen); // 4. Read host configs int iSize = dr.Read_int(); pHost->LoadConfigData(dr.Read_Data(iSize)); // 5. Read UI configs iSize = dr.Read_int(); pGameUI->SetUserLayout(dr.Read_Data(iSize), iSize); // 6. Read user settings (if dwVer >= 2) if (dwVer >= 2) { iSize = dr.Read_int(); g_pGame->GetConfigs()->LoadUserConfigData(dr.Read_Data(iSize), iSize); // This data starts with EC_CONFIG_VERSION (36) } } ``` #### C# Version (CECGameRun.cs lines 273-392) ```csharp public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize) { const uint USERCFG_VERSION = 3; int offset = 0; // 1. Read USERCFG_VERSION uint dwVer = System.BitConverter.ToUInt32(pDataBuf, offset); offset += sizeof(uint); if (dwVer > USERCFG_VERSION) // USERCFG_VERSION = 3 { Debug.LogError($"version {dwVer} > {USERCFG_VERSION}"); return false; } byte[] pUncompBuf = null; uint dwRealLen = (uint)(iDataSize - sizeof(uint)); byte[] pData = pDataBuf; int dataOffset = offset; // ⚠️ This is set but never used! // 2. Uncompress if version >= 3 if (dwVer >= 3) { dwRealLen = 4096; pUncompBuf = new byte[dwRealLen]; byte[] compressedData = new byte[iDataSize - sizeof(uint)]; System.Array.Copy(pDataBuf, offset, compressedData, 0, compressedData.Length); int iRes = AFilePackage.Uncompress(compressedData, compressedData.Length, pUncompBuf, ref dwRealLen); if (iRes != 0) { return false; } pData = pUncompBuf; // ⚠️ Point to uncompressed buffer } // 3. Create data reader - ⚠️ PROBLEM HERE! // In C++, pData points to the uncompressed data // In C#, we should use the same approach CECDataReader dr = new CECDataReader(pData, (int)dwRealLen); // 4. Read host configs int iSize = dr.ReadInt(); byte[] hostConfigData = dr.ReadData(iSize); pHost.LoadConfigData(hostConfigData); // 5. Read UI configs iSize = dr.ReadInt(); byte[] uiConfigData = dr.ReadData(iSize); // 6. Read user settings if (dwVer >= 2) { iSize = dr.ReadInt(); byte[] settingsData = dr.ReadData(iSize); // ⚠️ HERE IS WHERE THE ERROR OCCURS if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize)) { return false; } } } ``` ### LoadUserConfigData Comparison #### C++ Version (EC_Configs.cpp lines 628-671) ```cpp bool CECConfigs::LoadUserConfigData(const void* pDataBuf, int iDataSize) { CECDataReader dr((void*)pDataBuf, iDataSize); // Read EC_CONFIG_VERSION (should be 36) DWORD dwVer = dr.Read_DWORD(); if (dwVer < 15) { DefaultUserConfigData(); goto End; } else if (dwVer > EC_CONFIG_VERSION) // EC_CONFIG_VERSION = 36 { throw CECException(CECException::TYPE_DATAERR); } m_vs.Read(dr, dwVer); m_gs.Read(dr, dwVer); m_bs.Read(dr, dwVer); m_cas.Read(dr, dwVer); } ``` #### C# Version (EC_Configs.cs lines 1070-1106) ```csharp public bool LoadUserConfigData(byte[] pDataBuf, int iDataSize) { using (MemoryStream ms = new MemoryStream(pDataBuf, 0, iDataSize)) using (BinaryReader reader = new BinaryReader(ms)) { // Read EC_CONFIG_VERSION (expecting 36) uint dwVer = reader.ReadUInt32(); if (dwVer < 15) { DefaultUserConfigData(); goto End; } else if (dwVer > EC_ConfigConstants.EC_CONFIG_VERSION) // 36 { throw new Exception("version mismatch dwVer=" + dwVer); } m_vs.Read(reader, dwVer); m_gs.Read(reader, dwVer); m_bs.Read(reader, dwVer); m_cas.Read(reader, dwVer); } } ``` ## The Actual Problem The issue is that **`settingsData` does NOT start with a proper version number**. When `LoadUserConfigData` tries to read the first 4 bytes as `dwVer`, it's reading garbage data that happens to be larger than 36. ## Possible Causes ### 1. CECDataReader.ReadData() Implementation Issue The C# `CECDataReader.ReadData(int size)` method may not be returning the correct data. Let me check if this method exists and how it's implemented. ### 2. Data Alignment/Packing Issue The structs being saved in C++ may have different memory layout than the C# structs due to packing/alignment differences. ### 3. SaveConfigsToServer Format Issue The data being saved might not match the expected format. The C++ version (lines 2040-2063) shows: - Version is NOT compressed - Only the config data after version is compressed - But when loading, after uncompressing, the data should contain all three config sections ## Solution Steps 1. **Add Debug Logging**: Log the first 16 bytes of `settingsData` to see what version number is being read 2. **Verify CECDataReader**: Ensure `ReadData()` returns the correct bytes 3. **Check Struct Sizes**: Verify that `Marshal.SizeOf()` for each struct matches the C++ `sizeof()` 4. **Verify Decompression**: Ensure the uncompressed data length matches expectations ## Immediate Fix Add debug logging in CECGameRun.cs after line 377: ```csharp byte[] settingsData = dr.ReadData(iSize); // DEBUG: Log the first 16 bytes BMLogger.LogError($"LoadConfigsFromServer - settingsData size: {iSize}, first 16 bytes: " + $"{BitConverter.ToString(settingsData.Take(Math.Min(16, settingsData.Length)).ToArray())}"); // DEBUG: Read the version to see what we're getting uint debugVer = System.BitConverter.ToUInt32(settingsData, 0); BMLogger.LogError($"LoadConfigsFromServer - Version read from settingsData: {debugVer} (expected <= 36)"); ``` This will help identify what data is actually being passed to `LoadUserConfigData`. ## Expected Data Format After uncompression, the data should be: ``` [4 bytes: host config size] [host config data...] [4 bytes: UI config size] [UI config data...] [4 bytes: user config size] [user config data...] ↑ This should start with EC_CONFIG_VERSION (36) ``` If the version being read is > 36, it means either: 1. The data reader is at the wrong position 2. The size being read is incorrect 3. The data format from server doesn't match expectations