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