RE: VC08String
This is the current reverse engineering issue for the VC08String object (The way Star Wolves 3 handles strings).
Technical:
Note: All references here to structures and memory are in itself referencing the currently up-to-date IDA database for this game. Without it, most info here is hard to grasp or fact-check for yourself.
Star Wolves 3: VC08String Object Breakdown
This document outlines the memory layout and field functionality of the custom string class used in Star Wolves 3 (referred to as VC08String), likely compiled with Visual C++ 2008. The string implementation is composed of three nested classes, all featuring vTables, indicating polymorphic behavior.
Overall Structure
The main string object (VC08String_2025) encapsulates a memory allocator (MemoryAllocator_2025), which in turn manages the actual character buffer via a buffer holder class (MemoryAllocatedBuffer_2025).
VC08String_2025
|
+-- MemoryAllocator_2025
|
+-- MemoryAllocatedBuffer_2025
|
+-- char* (actual data)
Class Details
1. VC08String_2025 (Main String Class)
This is the top-level string object that client code would interact with.
-
Layout (Relative to start of
VC08String_2025):-
0x00:vTable_VC08String(Pointer)-
Purpose: Virtual function table for
VC08String_2025methods (e.g.,SetText,GetLength,GetText, etc.).
-
Purpose: Virtual function table for
-
0x04:MemoryAllocator(Instance ofMemoryAllocator_2025)- Purpose: Embedded instance responsible for managing the memory aspects of the string.
-
2. MemoryAllocator_2025 (Memory Management Logic)
This class is embedded within VC08String_2025 and handles the allocation strategies and core metadata for the string's content.
-
Layout (Relative to start of
MemoryAllocator_2025which is at0x04inVC08String_2025):-
0x00(0x04abs):vTable_MemoryAllocator(Pointer)-
Purpose: Virtual function table for
MemoryAllocator_2025methods (e.g.,AllocateLength).
-
Purpose: Virtual function table for
-
0x04(0x08abs):TextLength(UInt32)- Purpose: Stores the current length of the string in characters (excluding the null terminator).
-
0x08(0x0Cabs):GrowthIncrementSize(UInt32)-
Purpose: The block size (quantum) by which the buffer capacity is increased during normal growth. Example value:
32.
-
Purpose: The block size (quantum) by which the buffer capacity is increased during normal growth. Example value:
-
0x0C(0x10abs):ShrinkThresholdAndDecrementSize(UInt32)-
Purpose:
- Shrink Threshold: The minimum amount of unused space required before the buffer will be considered for shrinking.
- Decrement Size: The block size by which the buffer capacity is decreased if a shrink operation occurs.
- Example value:
128.
-
Purpose:
-
0x10(0x14abs):AllocatedBuffer(Instance ofMemoryAllocatedBuffer_2025)- Purpose: Embedded instance that directly holds the buffer pointer and its capacity.
-
3. MemoryAllocatedBuffer_2025 (Buffer Holder)
This class is embedded within MemoryAllocator_2025 and is the most direct manager of the raw character buffer.
-
Layout (Relative to start of
MemoryAllocatedBuffer_2025which is at0x10inMemoryAllocator_2025/0x14abs inVC08String_2025):-
0x00(0x14abs):vTable_MemoryAllocatedBuffer(Pointer)-
Purpose: Virtual function table for
MemoryAllocatedBuffer_2025. Its specific methods are less clear but likely internal buffer operations.
-
Purpose: Virtual function table for
-
0x04(0x18abs):AllocatedBufferSize(UInt32)-
Purpose: The current total allocated capacity of the
Bufferin bytes (including space for the null terminator).
-
Purpose: The current total allocated capacity of the
-
0x08(0x1Cabs):Buffer(char*)- Purpose: Pointer to the heap-allocated memory block holding the actual null-terminated character data.
-
0x0C(0x20abs):UseDoubleGrowthStrategyFlag(UInt32)-
Purpose: A flag that, if non-zero, triggers an alternative, more aggressive buffer growth strategy (e.g., doubling the desired length) instead of using
GrowthIncrementSize. Default is likely0.
-
Purpose: A flag that, if non-zero, triggers an alternative, more aggressive buffer growth strategy (e.g., doubling the desired length) instead of using
-
Key Functions (Identified)
-
MemoryAllocator_AllocateLength(int new_desired_length, MemoryAllocator_2025 *mem):- Core function for managing buffer resizing.
- Handles both growth and shrinkage based on
GrowthIncrementSize,ShrinkThresholdAndDecrementSize, andUseDoubleGrowthStrategyFlag. - Updates
mem->TextLengthandmem->AllocatedBuffer.AllocatedBufferSize.
-
VC08String_SetText(VC08String_2025 *thisString, const char *newText):- Sets the content of the string.
- Calculates the length of
newText. - Calls
MemoryAllocator_AllocateLengthto ensure sufficient capacity. - Copies
newTextinto the internalBuffer.
VTables
vtable_vc08string_2025
| Function | Signature | Mapped |
|---|---|---|
| Delete | void *__thiscall VC08String_2025_Delete(VC08String_2025 *this, MemoryDestructorFlags flags) | Yes |
vtable_memoryallocator_2025
| Function | Signature | Mapped |
|---|---|---|
| Delete | MemoryAllocator_2025 *__thiscall MemoryAllocator_Delete(MemoryAllocator_2025 *this, MemoryDestructorFlags flags) | Yes |
vtable_memoryallocatedbuffer_2025
| Function | Signature | Mapped |
|---|---|---|
| Delete | MemoryAllocatedBuffer_2025 *__thiscall MemoryAllocatedBuffer_Delete(MemoryAllocatedBuffer_2025 *this, MemoryDestructorFlags flags) | Yes |
NOTE: There are -many- more functions associated with VC08String, MemoryAllocator and MemoryAllocatedBuffer that are declared as non-vmts meaning they float around the engine and get called in a non thiscall way. The known ones will be listed here soon.
Static Member Functions
| Function Name | Description |
|---|---|
VC08String_Constructor |
Constructs a VC08String object. Initializes internal structures. |
VC08String_ScalarDestructor |
Destructs a VC08String object without deallocating memory. Used when object is stack-allocated or managed externally. |
VC08String_SetText |
Assigns a C-string to an existing VC08String object, reallocating if necessary. Handles nullptr input. |
VC08String_DestroyAndFree |
Destructs a VC08String object and deallocates its memory by calling its vTable destructor. Nullifies vTable post-deletion. |
VC08String_PlacementConstructWithText |
Initializes a pre-allocated VC08String memory block using a C-string. Equivalent to placement new with text. |
VC08String_PlacementConstructByCopy |
Initializes a pre-allocated VC08String by copying another VC08String. Placement copy constructor. |
VC08String_AssignStringContent |
Copies content from a source VC08String to an already initialized destination VC08String. Acts like assignment operator. |
VC08String_ExtractSubstring |
Public interface to create a substring from a VC08String. Delegates to internal logic after validation. |
VC08String_PerformSubstringExtraction |
Core logic to extract a substring of given length from source VC08String, starting at specified index. Handles boundary cases. |
VC08String_Append |
Appends content of one VC08String to another, modifying the base string in place. Returns modified base. |
VC08String_ConcatText |
Concatenates two VC08Strings into a destination VC08String. Initializes result then appends. |
VC08String_Concat |
Concatenates two VC08Strings using a temporary buffer. Result is second + first. |
VC08String_IsNotEqual_To_CString |
Compares VC08String to a C-string for inequality. Handles NULL by comparing against global empty string. |
VC08String_PlacementConstructWithSingleChar |
Initializes a VC08String with a single character. Allocates space for char + null terminator. |
VC08String_GetGlobalEmptyInstance |
Returns a pointer to a global empty VC08String instance. Ensures one-time init with cleanup registration. |
VC08String_SPrintF |
Formats a VC08String using a printf-style format string. Not thread-safe due to global buffer usage. |
VC08String_TrimCharacters |
Trims leading and trailing occurrences of a specified character from a VC08String in-place. |
VC08String_TrimWhitespaces |
Trims whitespace (spaces and tabs) from both ends of a VC08String in-place. |
VC08String_Equals |
Compares two VC08Strings for equality based on internal string content. |
VC08String_IsEqual_To_CString |
Compares a VC08String with a C-string for equality. Handles NULL as global empty string. |
Notes for RE
- All three classes are polymorphic (have vTables), suggesting a potentially complex inheritance hierarchy or interface-based design that might not be fully uncovered.
- The memory management is custom and aims for controlled growth/shrinkage, likely for performance reasons to avoid frequent small reallocations or excessive memory holding.
- Pay attention to how and when
UseDoubleGrowthStrategyFlagis set, as it changes allocation behavior. - The exact roles of all virtual functions in each vTable are not yet fully known and is subject to ongoing research.
ToDo:
- We still need to rename VC08String to a new more fitting name, since now we know that VC08 has nothing to do with these strings, even if it was an initial hunch. Perhaps we can name them
SWStringorManagedString
This breakdown should provide a good starting point for anyone joining the project, summarizing what's known about the string class structure and behavior. The use of absolute offsets (abs) in comments helps map directly to a memory dump of the VC08String_2025 object.