Beispiel #1
0
bool MemoryMap_Setup(u32 flags) {
#if PPSSPP_PLATFORM(UWP)
	// We reserve the memory, then simply commit in TryBase.
	base = (u8*)VirtualAllocFromApp(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
#else

	// Figure out how much memory we need to allocate in total.
	size_t total_mem = 0;
	for (int i = 0; i < num_views; i++) {
		if (views[i].size == 0)
			continue;
		SKIP(flags, views[i].flags);
		if (!CanIgnoreView(views[i]))
			total_mem += g_arena.roundup(views[i].size);
	}

	// Grab some pagefile backed memory out of the void ...
	g_arena.GrabLowMemSpace(total_mem);
#endif

#if !PPSSPP_PLATFORM(ANDROID)
	if (g_arena.NeedsProbing()) {
		int base_attempts = 0;
#if defined(_WIN32) && PPSSPP_ARCH(32BIT)
		// Try a whole range of possible bases. Return once we got a valid one.
		uintptr_t max_base_addr = 0x7FFF0000 - 0x10000000;
		uintptr_t min_base_addr = 0x01000000;
		uintptr_t stride = 0x400000;
#else
		// iOS
		uintptr_t max_base_addr = 0x1FFFF0000ULL - 0x80000000ULL;
		uintptr_t min_base_addr = 0x100000000ULL;
		uintptr_t stride = 0x800000;
#endif
		for (uintptr_t base_addr = min_base_addr; base_addr < max_base_addr; base_addr += stride) {
			base_attempts++;
			base = (u8 *)base_addr;
			if (Memory_TryBase(flags)) {
				INFO_LOG(MEMMAP, "Found valid memory base at %p after %i tries.", base, base_attempts);
				return true;
			}
		}
		ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base.");
		PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
		return false;
	}
	else
#endif
	{
#if !PPSSPP_PLATFORM(UWP)
		base = g_arena.Find4GBBase();
#endif
	}

	// Should return true...
	return Memory_TryBase(flags);
}
Beispiel #2
0
void MemoryMap_Setup(u32 flags)
{
	// Find a base to reserve 256MB
#if defined(_XBOX)
	base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE|MEM_LARGE_PAGES, PAGE_READWRITE);
#elif defined(__SYMBIAN32__)
	memmap = new RChunk();
	memmap->CreateDisconnectedLocal(0 , 0, 0x10000000);
	base = memmap->Base();
#else
	size_t total_mem = 0;

	for (int i = 0; i < num_views; i++)
	{
		if (views[i].size == 0)
			continue;
		SKIP(flags, views[i].flags);
		if (!CanIgnoreView(views[i]))
			total_mem += g_arena.roundup(views[i].size);
	}
	// Grab some pagefile backed memory out of the void ...
	g_arena.GrabLowMemSpace(total_mem);
	// 32-bit Windows retrieves base a different way
#if defined(_M_X64) || !defined(_WIN32)
	// This really shouldn't fail - in 64-bit, there will always be enough address space.
	// Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors.
	base = MemArena::Find4GBBase();
#endif
#endif


	// Now, create views in high memory where there's plenty of space.
#if defined(_WIN32) && !defined(_M_X64) && !defined(_XBOX)
	// Try a whole range of possible bases. Return once we got a valid one.
	int base_attempts = 0;
	u32 max_base_addr = 0x7FFF0000 - 0x10000000;

	for (u32 base_addr = 0x01000000; base_addr < max_base_addr; base_addr += 0x400000)
	{
		base_attempts++;
		base = (u8 *)base_addr;
		if (Memory_TryBase(flags)) 
		{
			INFO_LOG(MEMMAP, "Found valid memory base at %p after %i tries.", base, base_attempts);
			base_attempts = 0;
			break;
		}
	}

	if (base_attempts)
		PanicAlert("No possible memory base pointer found!");
#else
	// Try base we retrieved earlier
	if (!Memory_TryBase(flags))
	{
		ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base.");
		PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
	}
#endif
	return;
}
Beispiel #3
0
static bool Memory_TryBase(u32 flags) {
	// OK, we know where to find free space. Now grab it!
	// We just mimic the popular BAT setup.

#if defined(_XBOX)
	void *ptr;
#elif !defined(__SYMBIAN32__)
	size_t position = 0;
	size_t last_position = 0;
#endif

	// Zero all the pointers to be sure.
	for (int i = 0; i < num_views; i++)
	{
		if (views[i].out_ptr_low)
			*views[i].out_ptr_low = 0;
		if (views[i].out_ptr)
			*views[i].out_ptr = 0;
	}

	int i;
	for (i = 0; i < num_views; i++)
	{
		const MemoryView &view = views[i];
		if (view.size == 0)
			continue;
		SKIP(flags, view.flags);
		
#ifdef __SYMBIAN32__
		if (!CanIgnoreView(view)) {
			memmap->Commit(view.virtual_address & MEMVIEW32_MASK, view.size);
		}
		*(view.out_ptr) = (u8*)base + (view.virtual_address & MEMVIEW32_MASK);
#elif defined(_XBOX)
		if (!CanIgnoreView(view)) {
			*(view.out_ptr_low) = (u8*)(base + view.virtual_address);
			ptr = VirtualAlloc(base + (view.virtual_address & MEMVIEW32_MASK), view.size, MEM_COMMIT, PAGE_READWRITE);
		}
		*(view.out_ptr) = (u8*)base + (view.virtual_address & MEMVIEW32_MASK);
#else
		if (view.flags & MV_MIRROR_PREVIOUS) {
			position = last_position;
		} else {
			*(view.out_ptr_low) = (u8*)g_arena.CreateView(position, view.size);
			if (!*view.out_ptr_low)
				goto bail;
		}
#ifdef _M_X64
		*view.out_ptr = (u8*)g_arena.CreateView(
			position, view.size, base + view.virtual_address);
#else
		if (CanIgnoreView(view)) {
			// No need to create multiple identical views.
			*view.out_ptr = *views[i - 1].out_ptr;
		} else {
			*view.out_ptr = (u8*)g_arena.CreateView(
				position, view.size, base + (view.virtual_address & MEMVIEW32_MASK));
			if (!*view.out_ptr)
				goto bail;
		}
#endif
		last_position = position;
		position += g_arena.roundup(view.size);
#endif
	}

	return true;

#if !defined(_XBOX) && !defined(__SYMBIAN32__)
bail:
	// Argh! ERROR! Free what we grabbed so far so we can try again.
	for (int j = 0; j <= i; j++)
	{
		if (views[i].size == 0)
			continue;
		SKIP(flags, views[i].flags);
		if (views[j].out_ptr_low && *views[j].out_ptr_low)
		{
			g_arena.ReleaseView(*views[j].out_ptr_low, views[j].size);
			*views[j].out_ptr_low = NULL;
		}
		if (*views[j].out_ptr)
		{
			if (!CanIgnoreView(views[j])) {
				g_arena.ReleaseView(*views[j].out_ptr, views[j].size);
			}
			*views[j].out_ptr = NULL;
		}
	}
	return false;
#endif
}
Beispiel #4
0
static bool Memory_TryBase(u32 flags) {
	// OK, we know where to find free space. Now grab it!
	// We just mimic the popular BAT setup.

	size_t position = 0;
	size_t last_position = 0;

	// Zero all the pointers to be sure.
	for (int i = 0; i < num_views; i++) {
		if (views[i].out_ptr)
			*views[i].out_ptr = 0;
	}

	int i;
	for (i = 0; i < num_views; i++) {
		const MemoryView &view = views[i];
		if (view.size == 0)
			continue;
		SKIP(flags, view.flags);
		
		if (view.flags & MV_MIRROR_PREVIOUS) {
			position = last_position;
		}
#ifndef MASKED_PSP_MEMORY
		*view.out_ptr = (u8*)g_arena.CreateView(
			position, view.size, base + view.virtual_address);
		if (!*view.out_ptr) {
			goto bail;
			DEBUG_LOG(MEMMAP, "Failed at view %d", i);
		}
#else
		if (CanIgnoreView(view)) {
			// This is handled by address masking in 32-bit, no view needs to be created.
			*view.out_ptr = *views[i - 1].out_ptr;
		} else {
			*view.out_ptr = (u8*)g_arena.CreateView(
				position, view.size, base + (view.virtual_address & MEMVIEW32_MASK));
			if (!*view.out_ptr) {
				DEBUG_LOG(MEMMAP, "Failed at view %d", i);
				goto bail;
			}
		}
#endif
		last_position = position;
		position += g_arena.roundup(view.size);
	}

	return true;
bail:
	// Argh! ERROR! Free what we grabbed so far so we can try again.
	for (int j = 0; j <= i; j++) {
		if (views[i].size == 0)
			continue;
		SKIP(flags, views[i].flags);
		if (*views[j].out_ptr) {
			if (!CanIgnoreView(views[j])) {
				g_arena.ReleaseView(*views[j].out_ptr, views[j].size);
			}
			*views[j].out_ptr = NULL;
		}
	}
	return false;
}