Use separate heap for DVD decompression

This fixes crashes when first entering North Faaron cave and
Renado's Sanctuary due to system heap exhaustion resulting from
multiple threads allocating on the heap at once.

There's some sort of weird contention going on - for some reason the
game gobbles up seemingly any amount of memory you throw at it when
the two threads are competing for heap space. Using a separate heap
in the async thread sidesteps the issue.
This commit is contained in:
Max Roncace
2026-03-29 01:12:40 -04:00
parent 6491062dab
commit d2c5614a47
3 changed files with 30 additions and 0 deletions
@@ -36,6 +36,9 @@ public:
static JSUList<JKRDMCommand> sDvdAsyncList;
static u32 sSZSBufferSize;
static bool errorRetry;
#if TARGET_PC
static JKRHeap* sHeap;
#endif
enum EAllocDirection {
UNKNOWN_EALLOC_DIRECTION = 0,
@@ -54,6 +57,12 @@ public:
static bool isErrorRetry(void) { return errorRetry; }
inline static u32 getSZSBufferSize() { return sSZSBufferSize; }
#if TARGET_PC
static inline JKRHeap* getHeap() { return sHeap; }
static inline void setHeap(JKRHeap* i_heap) { sHeap = i_heap; }
#endif
};
// void JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32, u32*);
+12
View File
@@ -13,6 +13,8 @@
#include <vi.h>
#include <stdint.h>
#include "JSystem/JKernel/JKRExpHeap.h"
static int JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32, u32*);
static int decompSZS_subroutine(u8*, u8*);
static u8* firstSrcData();
@@ -240,6 +242,8 @@ static OSMutex decompMutex;
u32 JKRDvdRipper::sSZSBufferSize = 0x00000400;
JKRHeap* JKRDvdRipper::sHeap = NULL;
static u8* szpBuf;
static u8* szpEnd;
@@ -282,12 +286,20 @@ static int JKRDecompressFromDVD(JKRDvdFile* dvdFile, void* dst, u32 fileSize, u3
OSLockMutex(&decompMutex);
u32 result = 0;
u32 szsBufferSize = JKRDvdRipper::getSZSBufferSize();
#if TARGET_PC
szpBuf = (u8 *)JKRAllocFromHeap(JKRDvdRipper::getHeap(), szsBufferSize, -0x20);
#else
szpBuf = (u8 *)JKRAllocFromSysHeap(szsBufferSize, -0x20);
#endif
JUT_ASSERT(909, szpBuf != NULL);
szpEnd = szpBuf + szsBufferSize;
if (inFileOffset != 0) {
#if TARGET_PC
refBuf = (u8 *)JKRAllocFromHeap(JKRDvdRipper::getHeap(), 0x1120, -4);
#else
refBuf = (u8 *)JKRAllocFromSysHeap(0x1120, -4);
#endif
JUT_ASSERT(918, refBuf != NULL);
refEnd = refBuf + 0x1120;
refCurrent = refBuf;
+9
View File
@@ -29,6 +29,10 @@
#include "DynamicLink.h"
#include "os_report.h"
#if TARGET_PC
#include <assert.h>
#endif
#if !PLATFORM_GCN
#include <revolution/sc.h>
#include <revolution/wpad.h>
@@ -991,6 +995,11 @@ int mDoMch_Create() {
GXSetVerifyCallback((GXVerifyCallback)&myGXVerifyCallback);
#endif
JKRDvdRipper::setSZSBufferSize(0x4000);
#if TARGET_PC
JKRHeap* dvdHeap = JKRCreateExpHeap(0x10000, NULL, false);
assert(dvdHeap != NULL);
JKRDvdRipper::setHeap(dvdHeap);
#endif
JKRDvdAramRipper::setSZSBufferSize(0x4000);
JKRAram::setSZSBufferSize(0x2000);
mDoDvdThd::create(OSGetThreadPriority(OSGetCurrentThread()) - 2);