mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 16:49:50 +00:00
Merge pull request #8043 from sum2012/modules---
Allocate memory better by @unknownbrackets
This commit is contained in:
commit
27a124dcff
@ -244,8 +244,6 @@ void CWCheatEngine::SkipAllCodes() {
|
||||
|
||||
int CWCheatEngine::GetAddress(int value) { //Returns static address used by ppsspp. Some games may not like this, and causes cheats to not work without offset
|
||||
int address = (value + 0x08800000) & 0x3FFFFFFF;
|
||||
if (gameTitle == "ULUS10563" || gameTitle == "ULJS-00351" || gameTitle == "NPJH50352" ) //Offset to make God Eater Burst codes work
|
||||
address -= 0x7EF00;
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -1626,41 +1626,42 @@ int sceKernelLoadExec(const char *filename, u32 paramPtr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr)
|
||||
{
|
||||
static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
|
||||
if (!name) {
|
||||
ERROR_LOG(LOADER, "sceKernelLoadModule(NULL, %08x): Bad name", flags);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
|
||||
return hleLogError(LOADER, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad filename");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(lieAboutSuccessModules); i++) {
|
||||
if (!strcmp(name, lieAboutSuccessModules[i])) {
|
||||
INFO_LOG(LOADER, "Tries to load module %s. We return a fake module.", lieAboutSuccessModules[i]);
|
||||
|
||||
Module *module = new Module;
|
||||
kernelObjects.Create(module);
|
||||
loadedModules.insert(module->GetUID());
|
||||
memset(&module->nm, 0, sizeof(module->nm));
|
||||
module->isFake = true;
|
||||
return module->GetUID();
|
||||
module->nm.entry_addr = -1;
|
||||
module->nm.gp_value = -1;
|
||||
|
||||
// TODO: It would be more ideal to allocate memory for this module.
|
||||
|
||||
return hleLogSuccessInfoI(LOADER, module->GetUID(), "created fake module");
|
||||
}
|
||||
}
|
||||
|
||||
PSPFileInfo info = pspFileSystem.GetFileInfo(name);
|
||||
std::string error_string;
|
||||
s64 size = (s64)info.size;
|
||||
|
||||
if (!info.exists) {
|
||||
ERROR_LOG(LOADER, "sceKernelLoadModule(%s, %08x): File does not exist", name, flags);
|
||||
// ERRNO_FILE_NOT_FOUND
|
||||
return 0x80010002;
|
||||
const int ERROR_ERRNO_FILE_NOT_FOUND = 0x80010002;
|
||||
const u32 error = hleLogError(LOADER, ERROR_ERRNO_FILE_NOT_FOUND, "file does not exist");
|
||||
return hleDelayResult(error, "module loaded", 500);
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
ERROR_LOG(LOADER, "sceKernelLoadModule(%s, %08x): Module file is size 0", name, flags);
|
||||
return SCE_KERNEL_ERROR_FILEERR;
|
||||
const u32 error = hleLogError(LOADER, SCE_KERNEL_ERROR_FILEERR, "module file size is 0");
|
||||
return hleDelayResult(error, "module loaded", 500);
|
||||
}
|
||||
|
||||
// We log before hand because ELF loading logs a bunch.
|
||||
DEBUG_LOG(LOADER, "sceKernelLoadModule(%s, %08x)", name, flags);
|
||||
|
||||
if (flags != 0) {
|
||||
@ -1671,15 +1672,15 @@ static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr)
|
||||
lmoption = (SceKernelLMOption *)Memory::GetPointer(optionAddr);
|
||||
if (lmoption->position < PSP_SMEM_Low || lmoption->position > PSP_SMEM_HighAligned) {
|
||||
ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (%i)", name, (int)lmoption->position);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCKTYPE;
|
||||
return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCKTYPE, "module loaded", 500);
|
||||
}
|
||||
if (lmoption->position == PSP_SMEM_LowAligned || lmoption->position == PSP_SMEM_HighAligned) {
|
||||
ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (aligned)", name);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ALIGNMENT_SIZE;
|
||||
return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ALIGNMENT_SIZE, "module loaded", 500);
|
||||
}
|
||||
if (lmoption->position == PSP_SMEM_Addr) {
|
||||
ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (fixed)", name);
|
||||
return SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
|
||||
return hleDelayResult(SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED, "module loaded", 500);
|
||||
}
|
||||
WARN_LOG_REPORT(LOADER, "sceKernelLoadModule: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
|
||||
}
|
||||
@ -1690,6 +1691,7 @@ static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr)
|
||||
pspFileSystem.ReadFile(handle, temp, (size_t)size);
|
||||
u32 magic;
|
||||
u32 error;
|
||||
std::string error_string;
|
||||
module = __KernelLoadELFFromPtr(temp, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
delete [] temp;
|
||||
pspFileSystem.CloseFile(handle);
|
||||
@ -1697,27 +1699,19 @@ static u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr)
|
||||
if (!module) {
|
||||
if (magic == 0x46535000) {
|
||||
ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic);
|
||||
return -1;
|
||||
// TODO: What's actually going on here?
|
||||
error = -1;
|
||||
return hleDelayResult(error, "module loaded", 500);
|
||||
}
|
||||
|
||||
if (info.name == "BOOT.BIN")
|
||||
{
|
||||
if (info.name == "BOOT.BIN") {
|
||||
NOTICE_LOG_REPORT(LOADER, "Module %s is blacklisted or undecryptable - we try __KernelLoadExec", name);
|
||||
// Name might get deleted.
|
||||
const std::string safeName = name;
|
||||
return __KernelLoadExec(safeName.c_str(), 0, &error_string);
|
||||
}
|
||||
else if ((int)error >= 0)
|
||||
{
|
||||
// Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run..
|
||||
// Let's just act as if it worked.
|
||||
NOTICE_LOG(LOADER, "Module %s is blacklisted or undecryptable - we lie about success", name);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NOTICE_LOG(LOADER, "Module %s failed to load: %08x", name, error);
|
||||
return error;
|
||||
} else {
|
||||
hleLogError(LOADER, error, "failed to load");
|
||||
return hleDelayResult(error, "module loaded", 500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1924,11 +1918,11 @@ static u32 sceKernelUnloadModule(u32 moduleId)
|
||||
u32 error;
|
||||
Module *module = kernelObjects.Get<Module>(moduleId, error);
|
||||
if (!module)
|
||||
return error;
|
||||
return hleDelayResult(error, "module unloaded", 150);
|
||||
|
||||
module->Cleanup();
|
||||
kernelObjects.Destroy<Module>(moduleId);
|
||||
return moduleId;
|
||||
return hleDelayResult(moduleId, "module unloaded", 500);
|
||||
}
|
||||
|
||||
u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "Core/HLE/sceKernel.h"
|
||||
#include "Core/HLE/sceKernelMemory.h"
|
||||
#include "Core/HLE/sceKernelThread.h"
|
||||
#include "Core/HLE/sceUtility.h"
|
||||
|
||||
@ -60,10 +61,57 @@ const int SCE_ERROR_MODULE_BAD_ID = 0x80111101;
|
||||
const int SCE_ERROR_MODULE_ALREADY_LOADED = 0x80111102;
|
||||
const int SCE_ERROR_MODULE_NOT_LOADED = 0x80111103;
|
||||
const int SCE_ERROR_AV_MODULE_BAD_ID = 0x80110F01;
|
||||
const u32 PSP_MODULE_NET_HTTP = 261;
|
||||
const u32 PSP_MODULE_NET_HTTPSTORAGE = 264;
|
||||
const u32 PSP_MODULE_NET_HTTP = 0x0105;
|
||||
const u32 PSP_MODULE_NET_HTTPSTORAGE = 0x0108;
|
||||
int oldStatus = 100; //random value
|
||||
|
||||
struct ModuleLoadInfo {
|
||||
const int mod;
|
||||
const u32 size;
|
||||
const int *dependencies;
|
||||
};
|
||||
|
||||
static const int httpModuleDeps[] = {0x0102, 0x0103, 0x0104};
|
||||
static const int sslModuleDeps[] = {0x0102};
|
||||
static const int httpStorageModuleDeps[] = {0x00100, 0x0102, 0x0103, 0x0104, 0x0105};
|
||||
static const int atrac3PlusModuleDeps[] = {0x0300};
|
||||
static const int mpegBaseModuleDeps[] = {0x0300};
|
||||
static const int mp4ModuleDeps[] = {0x0300, 0x0303};
|
||||
|
||||
static const ModuleLoadInfo moduleLoadInfo[] = {
|
||||
{0x0100, 0x00014000},
|
||||
{0x0101, 0x00020000},
|
||||
{0x0102, 0x00058000},
|
||||
{0x0103, 0x00006000},
|
||||
{0x0104, 0x00002000},
|
||||
{0x0105, 0x00028000, httpModuleDeps},
|
||||
{0x0106, 0x00044000, sslModuleDeps},
|
||||
{0x0107, 0x00010000},
|
||||
{0x0108, 0x00008000, httpStorageModuleDeps},
|
||||
{0x0200, 0x00000000},
|
||||
{0x0201, 0x00000000},
|
||||
{0x0202, 0x00000000},
|
||||
{0x0203, 0x00000000},
|
||||
{0x02ff, 0x00000000},
|
||||
{0x0300, 0x00000000},
|
||||
{0x0301, 0x00000000},
|
||||
{0x0302, 0x00008000, atrac3PlusModuleDeps},
|
||||
{0x0303, 0x0000c000, mpegBaseModuleDeps},
|
||||
{0x0304, 0x00004000},
|
||||
{0x0305, 0x0000a300},
|
||||
{0x0306, 0x00004000},
|
||||
{0x0307, 0x00000000},
|
||||
{0x0308, 0x0003c000, mp4ModuleDeps},
|
||||
{0x03ff, 0x00000000},
|
||||
{0x0400, 0x0000c000},
|
||||
{0x0401, 0x00018000},
|
||||
{0x0402, 0x00048000},
|
||||
{0x0403, 0x0000e000},
|
||||
{0x0500, 0x00000000},
|
||||
{0x0600, 0x00000000},
|
||||
{0x0601, 0x00000000},
|
||||
};
|
||||
|
||||
enum UtilityDialogType {
|
||||
UTILITY_DIALOG_NONE,
|
||||
UTILITY_DIALOG_SAVEDATA,
|
||||
@ -85,21 +133,20 @@ static PSPNetconfDialog netDialog;
|
||||
static PSPScreenshotDialog screenshotDialog;
|
||||
static PSPGamedataInstallDialog gamedataInstallDialog;
|
||||
|
||||
static std::set<int> currentlyLoadedModules;
|
||||
static std::map<int, u32> currentlyLoadedModules;
|
||||
|
||||
void __UtilityInit()
|
||||
{
|
||||
void __UtilityInit() {
|
||||
currentDialogType = UTILITY_DIALOG_NONE;
|
||||
currentDialogActive = false;
|
||||
SavedataParam::Init();
|
||||
currentlyLoadedModules.clear();
|
||||
}
|
||||
|
||||
void __UtilityDoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("sceUtility", 1);
|
||||
if (!s)
|
||||
void __UtilityDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceUtility", 1, 2);
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.Do(currentDialogType);
|
||||
p.Do(currentDialogActive);
|
||||
@ -109,11 +156,19 @@ void __UtilityDoState(PointerWrap &p)
|
||||
netDialog.DoState(p);
|
||||
screenshotDialog.DoState(p);
|
||||
gamedataInstallDialog.DoState(p);
|
||||
p.Do(currentlyLoadedModules);
|
||||
|
||||
if (s >= 2) {
|
||||
p.Do(currentlyLoadedModules);
|
||||
} else {
|
||||
std::set<int> oldModules;
|
||||
p.Do(oldModules);
|
||||
for (auto it = oldModules.begin(), end = oldModules.end(); it != end; ++it) {
|
||||
currentlyLoadedModules[*it] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __UtilityShutdown()
|
||||
{
|
||||
void __UtilityShutdown() {
|
||||
saveDialog.Shutdown(true);
|
||||
msgDialog.Shutdown(true);
|
||||
oskDialog.Shutdown(true);
|
||||
@ -203,58 +258,68 @@ static u32 sceUtilityUnloadAvModule(u32 module)
|
||||
return hleDelayResult(0, "utility av module unloaded", 800);
|
||||
}
|
||||
|
||||
static u32 sceUtilityLoadModule(u32 module)
|
||||
{
|
||||
// TODO: Not all modules between 0x100 and 0x601 are valid.
|
||||
if (module < 0x100 || module > 0x601)
|
||||
{
|
||||
const ModuleLoadInfo *__UtilityModuleInfo(int module) {
|
||||
const ModuleLoadInfo *info = 0;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(moduleLoadInfo); ++i) {
|
||||
if (moduleLoadInfo[i].mod == module) {
|
||||
info = &moduleLoadInfo[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
static u32 sceUtilityLoadModule(u32 module) {
|
||||
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
|
||||
if (!info) {
|
||||
ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityLoadModule(%i): invalid module id", module);
|
||||
return SCE_ERROR_MODULE_BAD_ID;
|
||||
}
|
||||
|
||||
if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end())
|
||||
{
|
||||
if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end()) {
|
||||
ERROR_LOG(SCEUTILITY, "sceUtilityLoadModule(%i): already loaded", module);
|
||||
return SCE_ERROR_MODULE_ALREADY_LOADED;
|
||||
}
|
||||
INFO_LOG(SCEUTILITY, "sceUtilityLoadModule(%i)", module);
|
||||
// Fix Kamen Rider Climax Heroes OOO - ULJS00331 loading
|
||||
// Fix Naruto Shippuden Kizuna Drive (error module load failed)
|
||||
if (module == PSP_MODULE_NET_HTTPSTORAGE && !(currentlyLoadedModules.find(PSP_MODULE_NET_HTTP) != currentlyLoadedModules.end()))
|
||||
{
|
||||
ERROR_LOG(SCEUTILITY, "sceUtilityLoadModule: Library not found");
|
||||
return SCE_KERNEL_ERROR_LIBRARY_NOTFOUND;
|
||||
|
||||
// Some games, like Kamen Rider Climax Heroes OOO, require an error if dependencies aren't loaded yet.
|
||||
for (const int *dep = info->dependencies; dep && *dep == 0; ++dep) {
|
||||
if (currentlyLoadedModules.find(*dep) == currentlyLoadedModules.end()) {
|
||||
ERROR_LOG(SCEUTILITY, "sceUtilityLoadModule(%i): dependent module %i not loaded", module, *dep);
|
||||
return hleDelayResult(SCE_KERNEL_ERROR_LIBRARY_NOTFOUND, "utility module load attempt", 25000);
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(SCEUTILITY, "sceUtilityLoadModule(%i)", module);
|
||||
|
||||
u32 allocSize = info->size;
|
||||
char name[64];
|
||||
snprintf(name, sizeof(name), "UtilityModule/%x", module);
|
||||
currentlyLoadedModules[module] = userMemory.Alloc(allocSize, false, name);
|
||||
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
// Note: Some modules have dependencies, but they still resched.
|
||||
|
||||
currentlyLoadedModules.insert(module);
|
||||
|
||||
if (module == 0x3FF)
|
||||
return hleDelayResult(0, "utility module loaded", 130);
|
||||
else
|
||||
return hleDelayResult(0, "utility module loaded", 25000);
|
||||
}
|
||||
|
||||
static u32 sceUtilityUnloadModule(u32 module)
|
||||
{
|
||||
// TODO: Not all modules between 0x100 and 0x601 are valid.
|
||||
if (module < 0x100 || module > 0x601)
|
||||
{
|
||||
static u32 sceUtilityUnloadModule(u32 module) {
|
||||
const ModuleLoadInfo *info = __UtilityModuleInfo(module);
|
||||
if (!info) {
|
||||
ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityUnloadModule(%i): invalid module id", module);
|
||||
return SCE_ERROR_MODULE_BAD_ID;
|
||||
}
|
||||
|
||||
if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end())
|
||||
{
|
||||
if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) {
|
||||
WARN_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i): not yet loaded", module);
|
||||
return SCE_ERROR_MODULE_NOT_LOADED;
|
||||
}
|
||||
if (currentlyLoadedModules[module] != 0) {
|
||||
userMemory.Free(currentlyLoadedModules[module]);
|
||||
}
|
||||
currentlyLoadedModules.erase(module);
|
||||
|
||||
INFO_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i)", module);
|
||||
// TODO: Each module has its own timing, technically, but this is a low-end.
|
||||
// Note: If not loaded, it should not reschedule actually...
|
||||
if (module == 0x3FF)
|
||||
return hleDelayResult(0, "utility module unloaded", 110);
|
||||
else
|
||||
|
@ -85,17 +85,20 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT
|
||||
{
|
||||
if (b.size == needed)
|
||||
{
|
||||
if (offset >= grain_)
|
||||
InsertFreeBefore(&b, offset);
|
||||
b.taken = true;
|
||||
b.SetTag(tag);
|
||||
return b.start + offset;
|
||||
return b.start;
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertFreeAfter(&b, b.start + needed, b.size - needed);
|
||||
InsertFreeAfter(&b, b.size - needed);
|
||||
if (offset >= grain_)
|
||||
InsertFreeBefore(&b, offset);
|
||||
b.taken = true;
|
||||
b.size = needed;
|
||||
b.SetTag(tag);
|
||||
return b.start + offset;
|
||||
return b.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,16 +115,18 @@ u32 BlockAllocator::AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromT
|
||||
{
|
||||
if (b.size == needed)
|
||||
{
|
||||
if (offset >= grain_)
|
||||
InsertFreeAfter(&b, offset);
|
||||
b.taken = true;
|
||||
b.SetTag(tag);
|
||||
return b.start;
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertFreeBefore(&b, b.start, b.size - needed);
|
||||
InsertFreeBefore(&b, b.size - needed);
|
||||
if (offset >= grain_)
|
||||
InsertFreeAfter(&b, offset);
|
||||
b.taken = true;
|
||||
b.start += b.size - needed;
|
||||
b.size = needed;
|
||||
b.SetTag(tag);
|
||||
return b.start;
|
||||
}
|
||||
@ -185,22 +190,19 @@ u32 BlockAllocator::AllocAt(u32 position, u32 size, const char *tag)
|
||||
//good to go
|
||||
else if (b.start == alignedPosition)
|
||||
{
|
||||
InsertFreeAfter(&b, b.start + alignedSize, b.size - alignedSize);
|
||||
if (b.size != alignedSize)
|
||||
InsertFreeAfter(&b, b.size - alignedSize);
|
||||
b.taken = true;
|
||||
b.size = alignedSize;
|
||||
b.SetTag(tag);
|
||||
CheckBlocks();
|
||||
return position;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size1 = alignedPosition - b.start;
|
||||
InsertFreeBefore(&b, b.start, size1);
|
||||
if (b.start + b.size > alignedPosition + alignedSize)
|
||||
InsertFreeAfter(&b, alignedPosition + alignedSize, b.size - (alignedSize + size1));
|
||||
InsertFreeBefore(&b, alignedPosition - b.start);
|
||||
if (b.size > alignedSize)
|
||||
InsertFreeAfter(&b, b.size - alignedSize);
|
||||
b.taken = true;
|
||||
b.start = alignedPosition;
|
||||
b.size = alignedSize;
|
||||
b.SetTag(tag);
|
||||
|
||||
return position;
|
||||
@ -291,27 +293,30 @@ bool BlockAllocator::FreeExact(u32 position)
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::Block *BlockAllocator::InsertFreeBefore(Block *b, u32 start, u32 size)
|
||||
BlockAllocator::Block *BlockAllocator::InsertFreeBefore(Block *b, u32 size)
|
||||
{
|
||||
Block *inserted = new Block(start, size, false, b->prev, b);
|
||||
Block *inserted = new Block(b->start, size, false, b->prev, b);
|
||||
b->prev = inserted;
|
||||
if (inserted->prev == NULL)
|
||||
bottom_ = inserted;
|
||||
else
|
||||
inserted->prev->next = inserted;
|
||||
|
||||
b->start += size;
|
||||
b->size -= size;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
BlockAllocator::Block *BlockAllocator::InsertFreeAfter(Block *b, u32 start, u32 size)
|
||||
BlockAllocator::Block *BlockAllocator::InsertFreeAfter(Block *b, u32 size)
|
||||
{
|
||||
Block *inserted = new Block(start, size, false, b, b->next);
|
||||
Block *inserted = new Block(b->start + b->size - size, size, false, b, b->next);
|
||||
b->next = inserted;
|
||||
if (inserted->next == NULL)
|
||||
top_ = inserted;
|
||||
else
|
||||
inserted->next->prev = inserted;
|
||||
|
||||
b->size -= size;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,6 @@ private:
|
||||
void MergeFreeBlocks(Block *fromBlock);
|
||||
Block *GetBlockFromAddress(u32 addr);
|
||||
const Block *GetBlockFromAddress(u32 addr) const;
|
||||
Block *InsertFreeBefore(Block *b, u32 start, u32 size);
|
||||
Block *InsertFreeAfter(Block *b, u32 start, u32 size);
|
||||
Block *InsertFreeBefore(Block *b, u32 size);
|
||||
Block *InsertFreeAfter(Block *b, u32 size);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user