u32 AllocMemoryBlock(const char *pname, u32 type, u32 size, u32 paramsAddr) { // Just support allocating a block in the user region. u32 blockPtr = userMemory.Alloc(size, type == 1, pname); INFO_LOG(HLE,"%08x=AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %08x, %08x)", blockPtr, pname, type, size, paramsAddr); // Create a UID object??? Nah, let's just us the UID itself (hack!) return blockPtr; }
//sceKernelCreateFpl(const char *name, SceUID mpid, SceUint attr, SceSize blocksize, int numBlocks, optparam) void sceKernelCreateFpl() { const char *name = Memory::GetCharPointer(PARAM(0)); u32 mpid = PARAM(1); u32 attr = PARAM(2); u32 blockSize = PARAM(3); u32 numBlocks = PARAM(4); u32 totalSize = blockSize * numBlocks; bool atEnd = false; // attr can change this I think u32 address = userMemory.Alloc(totalSize, atEnd, "FPL"); if (address == (u32)-1) { DEBUG_LOG(HLE,"sceKernelCreateFpl(\"%s\", partition=%i, attr=%i, bsize=%i, nb=%i) FAILED - out of ram", name, mpid, attr, blockSize, numBlocks); RETURN(SCE_KERNEL_ERROR_NO_MEMORY); return; } FPL *fpl = new FPL; SceUID id = kernelObjects.Create(fpl); strncpy(fpl->nf.name, name, 32); fpl->nf.size = sizeof(fpl->nf); fpl->nf.mpid = mpid; // partition fpl->nf.attr = attr; fpl->nf.blocksize = blockSize; fpl->nf.numBlocks = numBlocks; fpl->nf.numWaitThreads = 0; fpl->blocks = new bool[fpl->nf.numBlocks]; memset(fpl->blocks, 0, fpl->nf.numBlocks * sizeof(bool)); fpl->address = address; DEBUG_LOG(HLE,"%i=sceKernelCreateFpl(\"%s\", partition=%i, attr=%i, bsize=%i, nb=%i)", id, name, mpid, attr, blockSize, numBlocks); RETURN(id); }
u32 AllocMemoryBlock(const char *pname, u32 type, u32 size, u32 paramsAddr) { // Just support allocating a block in the user region. if (paramsAddr) { u32 length = Memory::Read_U32(paramsAddr); if (length != 4) { WARN_LOG(HLE, "AllockMemoryBlock(SysMemUserForUser_FE707FDF) : unknown parameters with length %d", length); } } if (type < 0 || type > 1) { return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCKTYPE; } u32 blockPtr = userMemory.Alloc(size, type == 1, pname); if (!blockPtr) { return SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED; } INFO_LOG(HLE,"%08x=AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %08x, %08x)", blockPtr, pname, type, size, paramsAddr); // Create a UID object??? Nah, let's just us the UID itself (hack!) return blockPtr; }
SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize, u32 optPtr) { if (!name) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): invalid name", SCE_KERNEL_ERROR_ERROR); return SCE_KERNEL_ERROR_ERROR; } if (partition < 1 || partition > 9 || partition == 7) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition); return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } // We only support user right now. if (partition != 2 && partition != 6) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition); return SCE_KERNEL_ERROR_ILLEGAL_PERM; } if (((attr & ~PSP_VPL_ATTR_KNOWN) & ~0xFF) != 0) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr); return SCE_KERNEL_ERROR_ILLEGAL_ATTR; } if (vplSize == 0) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): invalid size", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE); return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE; } // Block Allocator seems to A-OK this, let's stop it here. if (vplSize >= 0x80000000) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVpl(): way too big size", SCE_KERNEL_ERROR_NO_MEMORY); return SCE_KERNEL_ERROR_NO_MEMORY; } // Can't have that little space in a Vpl, sorry. if (vplSize <= 0x30) vplSize = 0x1000; vplSize = (vplSize + 7) & ~7; // We ignore the upalign to 256 and do it ourselves by 8. u32 allocSize = vplSize; u32 memBlockPtr = userMemory.Alloc(allocSize, (attr & PSP_VPL_ATTR_HIGHMEM) != 0, "VPL"); if (memBlockPtr == (u32)-1) { ERROR_LOG(HLE, "sceKernelCreateVpl: Failed to allocate %i bytes of pool data", vplSize); return SCE_KERNEL_ERROR_NO_MEMORY; } VPL *vpl = new VPL; SceUID id = kernelObjects.Create(vpl); strncpy(vpl->nv.name, name, KERNELOBJECT_MAX_NAME_LENGTH); vpl->nv.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; vpl->nv.attr = attr; vpl->nv.size = sizeof(vpl->nv); vpl->nv.poolSize = vplSize - 0x20; vpl->nv.numWaitThreads = 0; vpl->nv.freeSize = vpl->nv.poolSize; // A vpl normally has accounting stuff in the first 32 bytes. vpl->address = memBlockPtr + 0x20; vpl->alloc.Init(vpl->address, vpl->nv.poolSize); DEBUG_LOG(HLE, "%x=sceKernelCreateVpl(\"%s\", block=%i, attr=%i, size=%i)", id, name, partition, vpl->nv.attr, vpl->nv.poolSize); return id; }
SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSize, u32 count, u32 optionsPtr) { if (!name) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY); return SCE_KERNEL_ERROR_NO_MEMORY; } if ((attr & ~PSP_TLS_ATTR_KNOWN) >= 0x100) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr); return SCE_KERNEL_ERROR_ILLEGAL_ATTR; } if (partition < 1 || partition > 9 || partition == 7) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition); return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } // We only support user right now. if (partition != 2 && partition != 6) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition); return SCE_KERNEL_ERROR_ILLEGAL_PERM; } // There's probably a simpler way to get this same basic formula... // This is based on results from a PSP. bool illegalMemSize = blockSize == 0 || count == 0; if (!illegalMemSize && (u64) blockSize > ((0x100000000ULL / (u64) count) - 4ULL)) illegalMemSize = true; if (!illegalMemSize && (u64) count >= 0x100000000ULL / (((u64) blockSize + 3ULL) & ~3ULL)) illegalMemSize = true; if (illegalMemSize) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE); return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE; } int index = -1; for (int i = 0; i < TLS_NUM_INDEXES; ++i) if (tlsUsedIndexes[i] == false) { index = i; break; } if (index == -1) { WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateTls(): ran out of indexes for TLS objects", PSP_ERROR_TOO_MANY_TLS); return PSP_ERROR_TOO_MANY_TLS; } u32 totalSize = blockSize * count; u32 blockPtr = userMemory.Alloc(totalSize, (attr & PSP_TLS_ATTR_HIGHMEM) != 0, name); userMemory.ListBlocks(); if (blockPtr == (u32) -1) { ERROR_LOG(HLE, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x): failed to allocate memory", SCE_KERNEL_ERROR_NO_MEMORY, name, partition, attr, blockSize, count, optionsPtr); return SCE_KERNEL_ERROR_NO_MEMORY; } TLS *tls = new TLS(); SceUID id = kernelObjects.Create(tls); tls->ntls.size = sizeof(tls->ntls); strncpy(tls->ntls.name, name, KERNELOBJECT_MAX_NAME_LENGTH); tls->ntls.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; tls->ntls.attr = attr; tls->ntls.index = index; tlsUsedIndexes[index] = true; tls->ntls.blockSize = blockSize; tls->ntls.totalBlocks = count; tls->ntls.freeBlocks = count; tls->ntls.numWaitThreads = 0; tls->address = blockPtr; tls->usage.resize(count, 0); WARN_LOG(HLE, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x)", id, name, partition, attr, blockSize, count, optionsPtr); // TODO: just alignment? if (optionsPtr != 0) WARN_LOG(HLE, "sceKernelCreateTls(%s) unsupported options parameter: %08x", name, optionsPtr); if ((attr & PSP_TLS_ATTR_PRIORITY) != 0) WARN_LOG(HLE, "sceKernelCreateTls(%s) unsupported attr parameter: %08x", name, attr); return id; }
void * operator new(size_t /* s */) { return ball.Alloc(); }