Restarting a map on SP with numerous custom scripts can cause an out-of-memory error #1

Open
opened 2025-07-16 14:04:31 +00:00 by Future · 1 comment
Owner

Restarting a map on SP with numerous custom scripts can cause an out-of-memory error.

"Persona Non Grata"

userraw.zip

💡 Idea from H1-Mod: https://github.com/auroramod/h1-mod/blob/develop/src/client/component/gsc/script_loading.cpp

Implement custom heap alloc code and pop it by implementing PMem_PopFromSource_NoDebug

Restarting a map on SP with numerous custom scripts can cause an out-of-memory error. "Persona Non Grata" [userraw.zip](/attachments/83a67eca-f74f-44d6-97d2-dbb4c31a4943) 💡 Idea from H1-Mod: https://github.com/auroramod/h1-mod/blob/develop/src/client/component/gsc/script_loading.cpp Implement custom heap alloc code and pop it by implementing `PMem_PopFromSource_NoDebug`
Author
Owner

I asked Grok 3 to backport S1/H1's version of the pop function

#include <stdint.h>
#include <stdbool.h>

// Assuming these are defined elsewhere
typedef struct {
    unsigned char *buf;
    PhysicalMemoryPrim prim[2];
} PhysicalMemory;

typedef struct {
    const char *allocName;
    unsigned int allocListCount;
    unsigned int pos;
    PhysicalMemoryAllocation allocList[32];
} PhysicalMemoryPrim;

typedef struct {
    const char *name;
    unsigned int pos;
} PhysicalMemoryAllocation;

enum PMem_Source {
    PMEM_SOURCE_EXTERNAL,
    PMEM_SOURCE_DATABASE,
    PMEM_SOURCE_MOVIE,
    PMEM_SOURCE_SCRIPT,
};

// External variables
extern PhysicalMemory g_mem;
extern PhysicalMemory g_scriptmem;

// External functions (assumed to exist in iw5)
extern bool DB_IsAlloc(void);
extern uint32_t DB_GetAllocType(void);
extern void Sys_OutOfMemErrorInternal(void);

int __cdecl PMem_PopFromSource_NoDebug(void *ptr, unsigned int size, unsigned int alignment, unsigned int type, PMem_Source source) {
    PhysicalMemory *mem;
    uint32_t allocDir;
    PhysicalMemoryPrim *prim;
    uint32_t alignedPos;
    unsigned char *basePtr;

    // Select the appropriate memory pool based on source
    if (source == PMEM_SOURCE_SCRIPT) {
        mem = &g_scriptmem;
    } else {
        mem = &g_mem;
        if (source == PMEM_SOURCE_MOVIE) {
            allocDir = 0; // Low pool for movie source
            goto select_pool;
        }
    }

    // Determine allocation direction (0 for low, 1 for high)
    if (DB_IsAlloc()) {
        allocDir = DB_GetAllocType();
    } else {
        allocDir = (type != 4); // 0 if type == 4, 1 otherwise
    }

select_pool:
    prim = &mem->prim[allocDir];
    basePtr = mem->buf;

    // Calculate aligned position for comparison
    alignment = alignment - 1;

    if (allocDir == 0) {
        // Low pool: memory is allocated upward
        uint32_t currentPos = prim->pos - size;
        if (&basePtr[currentPos] == ptr) {
            // Ensure alignment
            if ((currentPos + alignment) & ~alignment == currentPos) {
                prim->pos = currentPos;
                return 1; // Success
            }
        }
    } else {
        // High pool: memory is allocated downward
        uint32_t currentPos = prim->pos;
        if (&basePtr[currentPos] == ptr) {
            // Ensure alignment
            if ((currentPos + alignment) & ~alignment == currentPos) {
                prim->pos = currentPos + size;
                return 1; // Success
            }
        }
    }

    // Failure: pointer does not match the expected position
    return 0;
}
I asked Grok 3 to backport S1/H1's version of the pop function ``` #include <stdint.h> #include <stdbool.h> // Assuming these are defined elsewhere typedef struct { unsigned char *buf; PhysicalMemoryPrim prim[2]; } PhysicalMemory; typedef struct { const char *allocName; unsigned int allocListCount; unsigned int pos; PhysicalMemoryAllocation allocList[32]; } PhysicalMemoryPrim; typedef struct { const char *name; unsigned int pos; } PhysicalMemoryAllocation; enum PMem_Source { PMEM_SOURCE_EXTERNAL, PMEM_SOURCE_DATABASE, PMEM_SOURCE_MOVIE, PMEM_SOURCE_SCRIPT, }; // External variables extern PhysicalMemory g_mem; extern PhysicalMemory g_scriptmem; // External functions (assumed to exist in iw5) extern bool DB_IsAlloc(void); extern uint32_t DB_GetAllocType(void); extern void Sys_OutOfMemErrorInternal(void); int __cdecl PMem_PopFromSource_NoDebug(void *ptr, unsigned int size, unsigned int alignment, unsigned int type, PMem_Source source) { PhysicalMemory *mem; uint32_t allocDir; PhysicalMemoryPrim *prim; uint32_t alignedPos; unsigned char *basePtr; // Select the appropriate memory pool based on source if (source == PMEM_SOURCE_SCRIPT) { mem = &g_scriptmem; } else { mem = &g_mem; if (source == PMEM_SOURCE_MOVIE) { allocDir = 0; // Low pool for movie source goto select_pool; } } // Determine allocation direction (0 for low, 1 for high) if (DB_IsAlloc()) { allocDir = DB_GetAllocType(); } else { allocDir = (type != 4); // 0 if type == 4, 1 otherwise } select_pool: prim = &mem->prim[allocDir]; basePtr = mem->buf; // Calculate aligned position for comparison alignment = alignment - 1; if (allocDir == 0) { // Low pool: memory is allocated upward uint32_t currentPos = prim->pos - size; if (&basePtr[currentPos] == ptr) { // Ensure alignment if ((currentPos + alignment) & ~alignment == currentPos) { prim->pos = currentPos; return 1; // Success } } } else { // High pool: memory is allocated downward uint32_t currentPos = prim->pos; if (&basePtr[currentPos] == ptr) { // Ensure alignment if ((currentPos + alignment) & ~alignment == currentPos) { prim->pos = currentPos + size; return 1; // Success } } } // Failure: pointer does not match the expected position return 0; } ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alterware/iw5-mod#1
No description provided.