Skip to content

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_2025 methods (e.g., SetText, GetLength, GetText, etc.).
    • 0x04: MemoryAllocator (Instance of MemoryAllocator_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_2025 which is at 0x04 in VC08String_2025):
    • 0x00 (0x04 abs): vTable_MemoryAllocator (Pointer)
      • Purpose: Virtual function table for MemoryAllocator_2025 methods (e.g., AllocateLength).
    • 0x04 (0x08 abs): TextLength (UInt32)
      • Purpose: Stores the current length of the string in characters (excluding the null terminator).
    • 0x08 (0x0C abs): GrowthIncrementSize (UInt32)
      • Purpose: The block size (quantum) by which the buffer capacity is increased during normal growth. Example value: 32.
    • 0x0C (0x10 abs): ShrinkThresholdAndDecrementSize (UInt32)
      • Purpose:
        1. Shrink Threshold: The minimum amount of unused space required before the buffer will be considered for shrinking.
        2. Decrement Size: The block size by which the buffer capacity is decreased if a shrink operation occurs.
        • Example value: 128.
    • 0x10 (0x14 abs): AllocatedBuffer (Instance of MemoryAllocatedBuffer_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_2025 which is at 0x10 in MemoryAllocator_2025 / 0x14 abs in VC08String_2025):
    • 0x00 (0x14 abs): vTable_MemoryAllocatedBuffer (Pointer)
      • Purpose: Virtual function table for MemoryAllocatedBuffer_2025. Its specific methods are less clear but likely internal buffer operations.
    • 0x04 (0x18 abs): AllocatedBufferSize (UInt32)
      • Purpose: The current total allocated capacity of the Buffer in bytes (including space for the null terminator).
    • 0x08 (0x1C abs): Buffer (char*)
      • Purpose: Pointer to the heap-allocated memory block holding the actual null-terminated character data.
    • 0x0C (0x20 abs): 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 likely 0.

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, and UseDoubleGrowthStrategyFlag.
    • Updates mem->TextLength and mem->AllocatedBuffer.AllocatedBufferSize.
  • VC08String_SetText(VC08String_2025 *thisString, const char *newText):
    • Sets the content of the string.
    • Calculates the length of newText.
    • Calls MemoryAllocator_AllocateLength to ensure sufficient capacity.
    • Copies newText into the internal Buffer.

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 UseDoubleGrowthStrategyFlag is 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 SWString or ManagedString

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.

Edited by Viktor Legodzinski