diff --git a/BurnOutSharp.Wrappers/WrapperBase.cs b/BurnOutSharp.Wrappers/WrapperBase.cs index f776dc5f..4f7bd4fc 100644 --- a/BurnOutSharp.Wrappers/WrapperBase.cs +++ b/BurnOutSharp.Wrappers/WrapperBase.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Text; using static BurnOutSharp.Builder.Extensions; namespace BurnOutSharp.Wrappers @@ -127,16 +129,101 @@ namespace BurnOutSharp.Wrappers /// /// Position in the source to read from /// Length of the requested data + /// Number of characters needed to be a valid string /// String list containing the requested data, null on error - protected List ReadStringsFromDataSource(int position, int length) + protected List ReadStringsFromDataSource(int position, int length, int charLimit = 5) { // Read the data as a byte array first byte[] sourceData = ReadFromDataSource(position, length); if (sourceData == null) return null; + // If we have an invalid character limit, default to 5 + if (charLimit <= 0) + charLimit = 5; + + // Create the string list to return + var sourceStrings = new List(); + + // Setup cached data + int sourceDataIndex = 0; + string cachedString = string.Empty; + + // Check for ASCII strings + while (sourceDataIndex < sourceData.Length) + { + // If we have a control character or an invalid byte + if (sourceData[sourceDataIndex] < 0x20 || sourceData[sourceDataIndex] > 0x7F) + { + // If we have no cached string + if (cachedString.Length == 0) + { + sourceDataIndex++; + continue; + } + + // If we have a cached string greater than the limit + if (cachedString.Length >= charLimit) + sourceStrings.Add(cachedString); + + cachedString = string.Empty; + sourceDataIndex++; + continue; + } + + // All other characters get read in + cachedString += Encoding.ASCII.GetString(sourceData, sourceDataIndex, 1); + sourceDataIndex++; + } + + // If we have a cached string greater than the limit + if (cachedString.Length >= charLimit) + sourceStrings.Add(cachedString); + + // Reset cached data + sourceDataIndex = 0; + cachedString = string.Empty; + + // We are limiting the check for Unicode characters with a second byte of 0x00 for now + + // Check for Unicode strings + while (sourceDataIndex < sourceData.Length) + { + ushort ch = BitConverter.ToUInt16(sourceData, sourceDataIndex); + + // If we have a null terminator or "invalid" character + if (ch == 0x0000 || (ch & 0xFF00) != 0) + { + // If we have no cached string + if (cachedString.Length == 0) + { + sourceDataIndex += 2; + continue; + } + + // If we have a cached string greater than the limit + if (cachedString.Length >= charLimit) + sourceStrings.Add(cachedString); + + cachedString = string.Empty; + sourceDataIndex += 2; + continue; + } + + // All other characters get read in + cachedString += Encoding.Unicode.GetString(sourceData, sourceDataIndex, 2); + sourceDataIndex += 2; + } + + // If we have a cached string greater than the limit + if (cachedString.Length >= charLimit) + sourceStrings.Add(cachedString); + + // Deduplicate the string list for storage + sourceStrings = sourceStrings.Distinct().OrderBy(s => s).ToList(); + // TODO: Complete implementation of string finding - return null; + return sourceStrings; } ///