private SceKernelVplInfo(string name, int partitionid, int attr, int size, int memType) { this.name = name; this.attr = attr; // Strange, the PSP is allocating a size of 0x1000 when requesting a size lower than 0x30... if (size <= 0x30) { size = 0x1000; } poolSize = size - vplHeaderSize; // 32 bytes overhead per VPL freeSize = poolSize; dataBlockMap = new Dictionary <int, int>(); uid = SceUidManager.getNewUid("ThreadMan-Vpl"); threadWaitingList = ThreadWaitingList.createThreadWaitingList(SceKernelThreadInfo.PSP_WAIT_VPL, uid, attr, VplManager.PSP_VPL_ATTR_PRIORITY); this.partitionid = partitionid; // Reserve psp memory int totalVplSize = Utilities.alignUp(size, vplAddrAlignment); // 8-byte align sysMemInfo = Modules.SysMemUserForUserModule.malloc(partitionid, string.Format("ThreadMan-Vpl-0x{0:x}-{1}", uid, name), memType, totalVplSize, 0); if (sysMemInfo == null) { throw new Exception("SceKernelVplInfo: not enough free mem"); } int addr = sysMemInfo.addr; // 24 byte header, probably not necessary to mimick this Memory mem = Memory.Instance; mem.write32(addr, addr - 1); mem.write32(addr + 4, size - 8); mem.write32(addr + 8, 0); // based on number of allocations mem.write32(addr + 12, addr + size - 16); mem.write32(addr + 16, 0); // based on allocations/fragmentation mem.write32(addr + 20, 0); // based on created size? magic? allocAddress = addr; MemoryChunk initialMemoryChunk = new MemoryChunk(addr + vplHeaderSize, totalVplSize - vplHeaderSize); freeMemoryChunks = new MemoryChunkList(initialMemoryChunk); }
/// <summary> /// do not instantiate unless there is enough free mem. /// use the static helper function tryCreateFpl. /// </summary> private SceKernelFplInfo(string name, int partitionid, int attr, int blockSize, int numBlocks, int memType, int memAlign) { this.name = name; this.attr = attr; this.blockSize = blockSize; this.numBlocks = numBlocks; freeBlocks = numBlocks; uid = SceUidManager.getNewUid("ThreadMan-Fpl"); this.partitionid = partitionid; blockAddress = new int[numBlocks]; blockAllocated = new bool[numBlocks]; for (int i = 0; i < numBlocks; i++) { blockAllocated[i] = false; } // Reserve psp memory int alignedBlockSize = memAlign == 0 ? blockSize : Utilities.alignUp(blockSize, memAlign - 1); int totalFplSize = alignedBlockSize * numBlocks; sysMemInfo = Modules.SysMemUserForUserModule.malloc(partitionid, string.Format("ThreadMan-Fpl-0x{0:x}-{1}", uid, name), memType, totalFplSize, 0); if (sysMemInfo == null) { throw new Exception("SceKernelFplInfo: not enough free mem"); } // Initialise the block addresses for (int i = 0; i < numBlocks; i++) { blockAddress[i] = sysMemInfo.addr + alignedBlockSize * i; } threadWaitingList = ThreadWaitingList.createThreadWaitingList(SceKernelThreadInfo.PSP_WAIT_FPL, uid, attr, FplManager.PSP_FPL_ATTR_PRIORITY); }