From 05136c13b7cc9e4a0431e5b8adf33d38cf198902 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 26 Aug 2022 20:46:19 -0400 Subject: [PATCH 1/5] Fixes Link getting Song as pocket item (#1326) --- soh/src/code/z_sram.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 952ce8e3c..c71bb4def 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -703,6 +703,8 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { if (getItem.modIndex == MOD_NONE) { if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { GiveLinkDungeonReward(getItem.getItemId); + } else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) { + GiveLinkSong(getItem.getItemId); } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { GiveLinkRupeesByGetItemId(giid); From a572c11f4f41a011733507296189161b758df7d0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 27 Aug 2022 03:27:20 -0400 Subject: [PATCH 2/5] Fixes ice trap gidata not getting cleared after trap is sprung. (#1322) --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index cd2950d65..e2c823012 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6121,6 +6121,8 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); Player_SetPendingFlag(this, globalCtx); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; return 1; } @@ -12866,6 +12868,8 @@ void func_8084E6D4(Player* this, GlobalContext* globalCtx) { } else { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } return; } From 776219fb52730541c402c1fd63b7b9bd470cdb22 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:47 -0400 Subject: [PATCH 3/5] Backports a fix for sheik checks from rando-next (#1340) * Fixes some Sheik checks I had accidentally set the wrong flag for. * Removes duplicate switch case from cherry-pick --- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 90e401f06..30ab5d06e 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -298,7 +298,7 @@ void GivePlayerRandoRewardSheikSong(EnXc* sheik, GlobalContext* globalCtx, Rando } } else if (check != RC_SHEIK_AT_TEMPLE) { if (GiveItemEntryFromActor(&sheik->actor, globalCtx, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = 0x55; + player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1; player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; } } From bf505dba5cef0aaffb4576c9b4c4f430e9bceb43 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:58 -0400 Subject: [PATCH 4/5] Fixes keys, maps, and compasses on develop-zhora rando (#1338) * Fixes keys, maps, and compasses on develop-zhora rando. * Adds randotodo comment as a note to adapt for the keysanity situation. --- .../Enhancements/randomizer/randomizer.cpp | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1fc95a04f..495850361 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2209,6 +2209,42 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: + //RANDO TODO: Fix this to return false if keysanity is on. + case RG_FOREST_TEMPLE_SMALL_KEY: + case RG_FIRE_TEMPLE_SMALL_KEY: + case RG_WATER_TEMPLE_SMALL_KEY: + case RG_SPIRIT_TEMPLE_SMALL_KEY: + case RG_SHADOW_TEMPLE_SMALL_KEY: + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + case RG_GERUDO_FORTRESS_SMALL_KEY: + case RG_GANONS_CASTLE_SMALL_KEY: + case RG_FOREST_TEMPLE_BOSS_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + case RG_GANONS_CASTLE_BOSS_KEY: + case RG_DEKU_TREE_COMPASS: + case RG_DODONGOS_CAVERN_COMPASS: + case RG_JABU_JABUS_BELLY_COMPASS: + case RG_FOREST_TEMPLE_COMPASS: + case RG_FIRE_TEMPLE_COMPASS: + case RG_WATER_TEMPLE_COMPASS: + case RG_SPIRIT_TEMPLE_COMPASS: + case RG_SHADOW_TEMPLE_COMPASS: + case RG_BOTTOM_OF_THE_WELL_COMPASS: + case RG_ICE_CAVERN_COMPASS: + case RG_DEKU_TREE_MAP: + case RG_DODONGOS_CAVERN_MAP: + case RG_JABU_JABUS_BELLY_MAP: + case RG_FOREST_TEMPLE_MAP: + case RG_FIRE_TEMPLE_MAP: + case RG_WATER_TEMPLE_MAP: + case RG_SPIRIT_TEMPLE_MAP: + case RG_SHADOW_TEMPLE_MAP: + case RG_BOTTOM_OF_THE_WELL_MAP: + case RG_ICE_CAVERN_MAP: return true; default: return false; From 584a4ad818df3046c2e13d0ab1c2e6a7f6c67fa6 Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Wed, 31 Aug 2022 22:59:38 -0400 Subject: [PATCH 5/5] Linux crash handler (#1209) * crash handler linux * cleanups * missing underscore * more cleanups * cleanups * 32 bit --- .gitignore | 2 + libultraship/libultraship/CMakeLists.txt | 7 + libultraship/libultraship/CrashHandler.cpp | 172 +++++++++++++++++++++ libultraship/libultraship/CrashHandler.h | 18 +++ soh/include/functions.h | 2 +- soh/include/segment_symbols.h | 12 +- soh/soh/OTRGlobals.h | 2 + soh/src/code/fault.c | 2 +- soh/src/code/main.c | 12 +- 9 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 libultraship/libultraship/CrashHandler.cpp create mode 100644 libultraship/libultraship/CrashHandler.h diff --git a/.gitignore b/.gitignore index 1df76208d..98fe2b637 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ .idea/ cmake-build-debug venv/ +.cache/ # Project-specific ignores build/ @@ -410,6 +411,7 @@ oot.otr *.sav shipofharkinian.ini shipofharkinian.json +imgui.ini # Switch Stuff diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index b59993660..aec229bfb 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -334,6 +334,12 @@ set(Source_Files__Resources__mpq ) source_group("Source Files\\Resources\\mpq" FILES ${Source_Files__Resources__mpq}) +set(Source_Files__Crash_Handler + "CrashHandler.cpp" + "CrashHandler.h" +) +source_group("Source Files\\Crash Handler" FILES ${Source_Files__Crash_Handler}) + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(Source_Files__Darwin "OSXFolderManager.mm" @@ -388,6 +394,7 @@ set(ALL_FILES ${Source_Files__Resources__Factories} ${Source_Files__Resources__Files} ${Source_Files__Resources__mpq} + ${Source_Files__Crash_Handler} ${Source_Files__Darwin} ${Source_Files__NintendoSwitch} ${Source_Files__CafeOS} diff --git a/libultraship/libultraship/CrashHandler.cpp b/libultraship/libultraship/CrashHandler.cpp new file mode 100644 index 000000000..f8d66beab --- /dev/null +++ b/libultraship/libultraship/CrashHandler.cpp @@ -0,0 +1,172 @@ +#include "spdlog/spdlog.h" +#include "Utils/StringHelper.h" +#include "CrashHandler.h" + +#if defined(__linux__) +#include +#include +#include // for __cxa_demangle +#include // for dladdr +#include +#include + +extern "C" void DeinitOTR(void); + + +static void PrintRegisters(ucontext_t* ctx) { + char regbuffer[1024]; + SPDLOG_CRITICAL("Registers:"); +#if defined(__x86_64__) + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); + SPDLOG_CRITICAL("RAX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); + SPDLOG_CRITICAL("RDI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); + SPDLOG_CRITICAL("RSI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); + SPDLOG_CRITICAL("RDX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); + SPDLOG_CRITICAL("RCX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); + SPDLOG_CRITICAL("R8 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); + SPDLOG_CRITICAL("R9 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); + SPDLOG_CRITICAL("R10: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); + SPDLOG_CRITICAL("R11: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); + SPDLOG_CRITICAL("RSP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); + SPDLOG_CRITICAL("RBX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); + SPDLOG_CRITICAL("RBP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); + SPDLOG_CRITICAL("R12: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); + SPDLOG_CRITICAL("R13: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); + SPDLOG_CRITICAL("R14: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); + SPDLOG_CRITICAL("R15: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); + SPDLOG_CRITICAL("RIP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); +#else + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); + SPDLOG_CRITICAL("EDI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); + SPDLOG_CRITICAL("ESI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); + SPDLOG_CRITICAL("EBP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); + SPDLOG_CRITICAL("ESP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); + SPDLOG_CRITICAL("EBX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); + SPDLOG_CRITICAL("EDX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); + SPDLOG_CRITICAL("ECX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); + SPDLOG_CRITICAL("EAX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); + SPDLOG_CRITICAL("EIP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFL : {} ", regbuffer); +#endif +} + +static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) +{ + std::array arr; + ucontext_t* ctx = static_cast(data); + constexpr size_t nMaxFrames = arr.size(); + size_t size = backtrace(arr.data(), nMaxFrames); + char** symbols = backtrace_symbols(arr.data(), nMaxFrames); + + SPDLOG_CRITICAL("(Signal: {})\n", sig); + + switch (sig) { + case SIGILL: + SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); + break; + case SIGABRT: + SPDLOG_CRITICAL("ABORT"); + break; + case SIGFPE: + SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); + break; + case SIGSEGV: + SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); + break; + } + + PrintRegisters(ctx); + + SPDLOG_CRITICAL("Traceback:\n"); + for (size_t i = 1; i < size; i++) + { + Dl_info info; + int gotAddress = dladdr(arr[i], &info); + std::string functionName(symbols[i]); + + if (gotAddress != 0 && info.dli_sname != nullptr) + { + FILE* pipe; + int32_t status; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* nameFound = info.dli_sname; + + if (status == 0) + { + nameFound = demangled; + } + #if 0 + char command[256]; + char addrLine[128]; + snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); + pipe = popen(command, "r"); + fgets(addrLine, 128, pipe); + #endif + + functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, + (char*)arr[i] - (char*)info.dli_saddr); + free(demangled); + } + + SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); + } + + free(symbols); + DeinitOTR(); + exit(1); +} + +static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { + DeinitOTR(); + exit(1); +} + +extern "C" void SetupHandlerLinux() { + struct sigaction action; + struct sigaction shutdownAction; + + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = ErrorHandler; + + sigaction(SIGILL, &action, nullptr); + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + + shutdownAction.sa_flags = SA_SIGINFO; + shutdownAction.sa_sigaction = ShutdownHandler; + sigaction(SIGINT, &shutdownAction, nullptr); + sigaction(SIGTERM, &shutdownAction, nullptr); + sigaction(SIGQUIT, &shutdownAction, nullptr); + sigaction(SIGKILL, &shutdownAction, nullptr); + + +} +#endif diff --git a/libultraship/libultraship/CrashHandler.h b/libultraship/libultraship/CrashHandler.h new file mode 100644 index 000000000..e068a4e38 --- /dev/null +++ b/libultraship/libultraship/CrashHandler.h @@ -0,0 +1,18 @@ +#ifndef CRASH_HANDLER_H +#define CRASH_HANDLER_H + +#ifdef __linux__ + +#ifdef __cplusplus +extern "C" { +#endif + +void SetupHandlerLinux(void); + +#ifdef __cplusplus +} +#endif + +#endif // __linux__ + +#endif // CRASH_HANDLER_H \ No newline at end of file diff --git a/soh/include/functions.h b/soh/include/functions.h index a336cb1ef..6339cff64 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1656,7 +1656,7 @@ void PadMgr_HandleRetraceMsg(PadMgr* padmgr); void PadMgr_HandlePreNMI(PadMgr* padmgr); // This function must remain commented out, because it is called incorrectly in // fault.c (actual bug in game), and the compiler notices and won't compile it -// void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); +void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); void PadMgr_Init(PadMgr* padmgr, OSMesgQueue* siIntMsgQ, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack); void Sched_SwapFrameBuffer(CfbInfo* cfbInfo); void func_800C84E4(SchedContext* sc, CfbInfo* cfbInfo); diff --git a/soh/include/segment_symbols.h b/soh/include/segment_symbols.h index 81fe34801..3b50b4eaa 100644 --- a/soh/include/segment_symbols.h +++ b/soh/include/segment_symbols.h @@ -3,20 +3,20 @@ #include "z64.h" -#define DECLARE_SEGMENT(name) \ - //extern u8 _##name##SegmentStart[]; \ +#define DECLARE_SEGMENT(name) + //extern u8 _##name##SegmentStart[]; //extern u8 _##name##SegmentEnd[]; -#define DECLARE_ROM_SEGMENT(name) \ - //extern u8 _##name##SegmentRomStart[]; \ +#define DECLARE_ROM_SEGMENT(name) + //extern u8 _##name##SegmentRomStart[]; //extern u8 _##name##SegmentRomEnd[]; #define DECLARE_BSS_SEGMENT(name) \ extern u8 _##name##SegmentBssStart[]; \ extern u8 _##name##SegmentBssEnd[]; -#define DECLARE_OVERLAY_SEGMENT(name) \ - //DECLARE_SEGMENT(ovl_##name) \ +#define DECLARE_OVERLAY_SEGMENT(name) + //DECLARE_SEGMENT(ovl_##name) //DECLARE_ROM_SEGMENT(ovl_##name) DECLARE_SEGMENT(boot) diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index dc304358d..089394e33 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -32,6 +32,8 @@ private: #endif #ifndef __cplusplus +void InitOTR(void); +void DeinitOTR(void); void VanillaItemTable_Init(); void OTRAudio_Init(); void InitAudio(); diff --git a/soh/src/code/fault.c b/soh/src/code/fault.c index c55a63a00..f7414766a 100644 --- a/soh/src/code/fault.c +++ b/soh/src/code/fault.c @@ -293,7 +293,7 @@ void Fault_Sleep(u32 duration) { void Fault_PadCallback(Input* input) { //! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C - PadMgr_RequestPadData(input, 0); + PadMgr_RequestPadData(&gPadMgr, input, 0); } void Fault_UpdatePadImpl() diff --git a/soh/src/code/main.c b/soh/src/code/main.c index ccfdc2019..8e9fe1776 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -3,6 +3,8 @@ #include #include "soh/OTRGlobals.h" +#include "../libultraship/CrashHandler.h" + s32 gScreenWidth = SCREEN_WIDTH; s32 gScreenHeight = SCREEN_HEIGHT; @@ -38,6 +40,10 @@ void Main_LogSystemHeap(void) { int main(int argc, char** argv) { +#ifdef __linux__ + SetupHandlerLinux(); +#endif + GameConsole_Init(); InitOTR(); BootCommands_Init(); @@ -64,14 +70,14 @@ void Main(void* arg) { Fault_Init(); SysCfb_Init(0); Heaps_Alloc(); - sysHeap = gSystemHeap; + sysHeap = (uintptr_t)gSystemHeap; fb = SysCfb_GetFbPtr(0); gSystemHeapSize = 1024 * 1024 * 4; // "System heap initalization" osSyncPrintf("システムヒープ初期化 %08x-%08x %08x\n", sysHeap, fb, gSystemHeapSize); - SystemHeap_Init(sysHeap, gSystemHeapSize); // initializes the system heap + SystemHeap_Init((void*)sysHeap, gSystemHeapSize); // initializes the system heap if (osMemSize >= 0x800000) { - debugHeap = SysCfb_GetFbEnd(); + debugHeap = (void*)SysCfb_GetFbEnd(); debugHeapSize = (0x80600000 - (uintptr_t)debugHeap); } else { debugHeapSize = 0x400;