PSM

From Vita Development Wiki
Jump to: navigation, search

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;
}