Check if the 4 GB memory allocation failed. (#1459)

* Check if the 4 GB memory allocation failed.

* Update UnleashedRecomp/locale/locale.cpp

Co-authored-by: Hyper <34012267+hyperbx@users.noreply.github.com>

* Update locale.cpp

* Add localizations.

* Fix installer not booting with the changes.

* Fix stale reference crash.

---------

Co-authored-by: Hyper <34012267+hyperbx@users.noreply.github.com>
This commit is contained in:
Skyth (Asilkan) 2025-03-28 22:38:07 +03:00 committed by GitHub
parent acf260af79
commit 33b557e68b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 41 additions and 3 deletions

View file

@ -322,6 +322,7 @@ static constexpr RenderFormat BACKBUFFER_FORMAT = RenderFormat::B8G8R8A8_UNORM;
static std::unique_ptr<RenderCommandSemaphore> g_acquireSemaphores[NUM_FRAMES]; static std::unique_ptr<RenderCommandSemaphore> g_acquireSemaphores[NUM_FRAMES];
static std::unique_ptr<RenderCommandSemaphore> g_renderSemaphores[NUM_FRAMES]; static std::unique_ptr<RenderCommandSemaphore> g_renderSemaphores[NUM_FRAMES];
static uint32_t g_backBufferIndex; static uint32_t g_backBufferIndex;
static std::unique_ptr<GuestSurface> g_backBufferHolder;
static GuestSurface* g_backBuffer; static GuestSurface* g_backBuffer;
static std::unique_ptr<RenderTexture> g_intermediaryBackBufferTexture; static std::unique_ptr<RenderTexture> g_intermediaryBackBufferTexture;
@ -1968,7 +1969,10 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
desc.renderTargetCount = 1; desc.renderTargetCount = 1;
g_gammaCorrectionPipeline = g_device->createGraphicsPipeline(desc); g_gammaCorrectionPipeline = g_device->createGraphicsPipeline(desc);
g_backBuffer = g_userHeap.AllocPhysical<GuestSurface>(ResourceType::RenderTarget); // NOTE: We initially allocate this on host memory to make the installer work, even if the 4 GB memory allocation fails.
g_backBufferHolder = std::make_unique<GuestSurface>(ResourceType::RenderTarget);
g_backBuffer = g_backBufferHolder.get();
g_backBuffer->width = 1280; g_backBuffer->width = 1280;
g_backBuffer->height = 720; g_backBuffer->height = 720;
g_backBuffer->format = BACKBUFFER_FORMAT; g_backBuffer->format = BACKBUFFER_FORMAT;
@ -2026,6 +2030,17 @@ static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
LoadTexture((uint8_t *)achievement.pImageBuffer, achievement.ImageBufferSize).release(); LoadTexture((uint8_t *)achievement.pImageBuffer, achievement.ImageBufferSize).release();
} }
// Move backbuffer to guest memory.
assert(!g_memory.IsInMemoryRange(g_backBuffer) && g_backBufferHolder != nullptr);
g_backBuffer = g_userHeap.AllocPhysical<GuestSurface>(std::move(*g_backBufferHolder));
// Check for stale reference. BeginCommandList() gets called before CreateDevice() which is where the assignment happens.
if (g_renderTarget == g_backBufferHolder.get()) g_renderTarget = g_backBuffer;
if (g_depthStencil == g_backBufferHolder.get()) g_depthStencil = g_backBuffer;
// Free the host backbuffer.
g_backBufferHolder = nullptr;
auto device = g_userHeap.AllocPhysical<GuestDevice>(); auto device = g_userHeap.AllocPhysical<GuestDevice>();
memset(device, 0, sizeof(*device)); memset(device, 0, sizeof(*device));

View file

@ -9,6 +9,9 @@ Memory::Memory()
if (base == nullptr) if (base == nullptr)
base = (uint8_t*)VirtualAlloc(nullptr, PPC_MEMORY_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); base = (uint8_t*)VirtualAlloc(nullptr, PPC_MEMORY_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (base == nullptr)
return;
DWORD oldProtect; DWORD oldProtect;
VirtualProtect(base, 4096, PAGE_NOACCESS, &oldProtect); VirtualProtect(base, 4096, PAGE_NOACCESS, &oldProtect);
#else #else
@ -17,6 +20,9 @@ Memory::Memory()
if (base == (uint8_t*)MAP_FAILED) if (base == (uint8_t*)MAP_FAILED)
base = (uint8_t*)mmap(NULL, PPC_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); base = (uint8_t*)mmap(NULL, PPC_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (base == nullptr)
return;
mprotect(base, 4096, PROT_NONE); mprotect(base, 4096, PROT_NONE);
#endif #endif

View file

@ -703,6 +703,17 @@ std::unordered_map<std::string_view, std::unordered_map<ELanguage, std::string>>
{ ELanguage::Italian, "Impossibile trovare il modulo \"%s\".\n\nAssicurati che:\n\n- Hai estratto questa copia di Unleashed Recompiled correttamente e non solo il file *.exe.\n- Non stai eseguendo Unleashed Recompiled da un file *.zip." } { ELanguage::Italian, "Impossibile trovare il modulo \"%s\".\n\nAssicurati che:\n\n- Hai estratto questa copia di Unleashed Recompiled correttamente e non solo il file *.exe.\n- Non stai eseguendo Unleashed Recompiled da un file *.zip." }
} }
}, },
{
"System_MemoryAllocationFailed",
{
{ ELanguage::English, "Failed to allocate game memory.\n\nPlease make sure that:\n\n- You meet the minimum system requirements (8 GB).\n- Your page file is configured with at least 4-8 GB of virtual memory." },
{ ELanguage::Japanese, "ゲームメモリの割り当てに失敗しました\n\n次の点を確認してください:\n\n※最小システム要件8 GBを満たしていること。\n※ページファイルに少なくとも48 GBの仮想メモリが設定されていること" },
{ ELanguage::German, "Fehler beim Zuweisen des Spielspeichers.\n\nBitte stelle sicher, dass:\n\n- Die Mindestanforderungen für das System erfüllt sind (8 GB).\n- Die Auslagerungsdatei mit mindestens 4-8 GB virtuellem Speicher konfiguriert ist." },
{ ELanguage::French, "Échec d'allocation de la mémoire du jeu.\n\nVeuillez vous assurer que :\n\n- Vous disposez de la configuration minimale requise (8 Go).\n- Votre fichier déchange est configuré avec au moins 4 à 8 Go de mémoire virtuelle." },
{ ELanguage::Spanish, "Fallo al asignar memoria del juego.\n\nPor favor, asegúrate de que:\n\n- Cumples los requisitos mínimos del sistema (8 GB).\n- Tu archivo de páginación está configurado con al menos 4 u 8 GB de memoria virtual." },
{ ELanguage::Italian, "Impossibile allocare la memoria per il gioco.\n\nAssicurati che:\n\n- Soddisfi i requisiti minimi di sistema (8 GB).\n- Il tuo file di paging sia configurato con almeno 4 o 8 GB di memoria virtuale." }
}
},
{ {
"IntegrityCheck_Success", "IntegrityCheck_Success",
{ {

View file

@ -53,14 +53,20 @@ void HostStartup()
CoInitializeEx(nullptr, COINIT_MULTITHREADED); CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif #endif
g_userHeap.Init();
hid::Init(); hid::Init();
} }
// Name inspired from nt's entry point // Name inspired from nt's entry point
void KiSystemStartup() void KiSystemStartup()
{ {
if (g_memory.base == nullptr)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("System_MemoryAllocationFailed").c_str(), GameWindow::s_pWindow);
std::_Exit(1);
}
g_userHeap.Init();
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game"); const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update"); const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game"); XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game");