PSM

From Vita Development Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

SceLibMonoBridge

Inside this module is the only documented case of executable memory being allocated by a user process.

struct {
    SceUID mem_block;
    void *base_addr;
    void *end_addr;
    u32_t is_allocated;
} code_block;

void pss_code_mem_initialize ()
{
    struct code_block *block = (void*)0x830032C0;
    u32_t r0 = 0x100;
    SceUID *mutex = (void*)0x830032BC;

    while(r0-- > 0)
    {
        block->mem_block = 0xFFFFFFFF;
        block->base_addr = 0xFFFFFFFF;
        block->end_addr = 0;
        block->is_allocated = 0;
        block++; // next element
    }
    *mutex = sceKernelCreateMutex ("ScePssCodeMutex", 0, 0, 0);
}

void pss_code_mem_lock ()
{
    u32_t *counter = (void*)0x83000284;
    SceUID *mutex = (void*)0x830032BC;
    if (*counter > 0)
    {
        SceSysmem_unkfunc6 (); // sub_82BB9BC0
        (*counter)--;
    }
    sceKernelUnlockMutex (*mutex, 1);
}

void pss_code_mem_unlock ()
{
    u32_t *counter = (void*)0x83000284;
    SceUID *mutex = (void*)0x830032BC;
    sceKernelLockMutex (*mutex, 1, 0);
    if (*counter == 0)
    {
        SceSysmem_unkfunc2 (); // sub_82BB9B80
        (*counter)++;
    }
}

void *pss_code_mem_alloc (unsigned int *length)
{
    struct code_block *blocks = (void*)0x830032C0;
    u32_t len = *length;
    int i = 0;
    struct code_block *cur_block = NULL;

    for (i = 0; i < 0x100; i++)
    {
        if (!blocks[i].is_allocated)
        {
            cur_block = &blocks[i];
            break;
        }
    }

    len = (len + 0xFFFFF) & ~0xFFFFF; // Round length to next 0x100000
    cur_block->mem_block = SceSysmem_unkfunc7 ("ScePssCodeMemBlock", len); // sub_82BB9BD0
    sceKernelGetMemBlockBase (cur_block->mem_block, &cur_block->base_addr);
    cur_block->end_addr = (void*) ((u32_t)cur_block->base_addr + len);
    cur_block->is_allocated = 1;
    pss_code_mem_unlock ();
    memset (cur_block->base_addr, 0, len);
    pss_code_mem_lock ();
    *length = len;
}

int pss_code_mem_free (void *code)
{
    struct code_block *blocks = (void*)0x830032C0;
    struct code_block *cur_block = NULL;
    int i;

    for (i = 0; i < 0x100; i++)
    {
        if (code >= blocks[i].base_addr && code <= blocks[i].end_addr)
        {
            cur_block = &blocks[i];
            break;
        }
    }

    if (cur_block->base_addr == code)
    {
        sceKernelFreeMemBlock (cur_block->mem_block);
        cur_block->is_allocated = 0;
    }

    return 0;
}

void pss_code_mem_flush_icache (uint8_t *code, int size)
{
    struct code_block *blocks = (void*)0x830032C0;
    int i;

    for (i = 0; i < 0x100; i++)
    {
        if (code >= blocks[i].base_addr && code <= blocks[i].end_addr)
        {
            SceSysmem_unkfunc1 (blocks[i].mem_block, code, size); // sub_82BB9B70
            break;
        }
    }
}

void pss_code_mem_terminate ()
{
    return;
}