mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-09-05 01:26:17 -04:00
Avoid overlay files overflowing solid heaps (#2387)
This commit is contained in:
@@ -4580,6 +4580,7 @@ public:
|
||||
bool mHsChainInterpCurrValid;
|
||||
|
||||
bool mIsRollstab = false;
|
||||
void* mAnmBuffers[3] = {};
|
||||
#endif
|
||||
}; // Size: 0x385C
|
||||
|
||||
|
||||
@@ -89,6 +89,14 @@ public:
|
||||
#define PLAYER_CREATE_ANM_HEAP(heap, type, name) (heap).createHeap(type)
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
inline u32 daPy_getAnmResourceSize(u16 i_resId, u32 i_minSize) {
|
||||
JKRArchive* archive = dComIfGp_getAnmArchive();
|
||||
u32 size = archive->getFileSize(archive->findIdxResource(i_resId));
|
||||
return size > i_minSize ? size : i_minSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
class daPy_anmHeap_c {
|
||||
public:
|
||||
enum daAlinkHEAP_TYPE {
|
||||
@@ -105,6 +113,9 @@ public:
|
||||
void* mallocBuffer();
|
||||
#if TARGET_PC
|
||||
void createHeap(daAlinkHEAP_TYPE i_heapType, const char* name);
|
||||
void reserveBuffer(u16 i_resId);
|
||||
void* allocTempBuffer(u16 i_resId, u32* io_size);
|
||||
void freeTempBuffers();
|
||||
#else
|
||||
void createHeap(daAlinkHEAP_TYPE i_heapType);
|
||||
#endif
|
||||
@@ -134,6 +145,10 @@ public:
|
||||
/* 0x08 */ u32 mBufferSize;
|
||||
/* 0x0C */ u8* mBuffer;
|
||||
/* 0x10 */ JKRSolidHeap* mAnimeHeap;
|
||||
#if TARGET_PC
|
||||
u8* mOwnedBuffer = NULL;
|
||||
void** mTempBuffers = NULL;
|
||||
#endif
|
||||
}; // Size = 0x14
|
||||
|
||||
class daPy_actorKeep_c {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <limits>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <borealis/log.hpp>
|
||||
#include "JSystem/JKernel/JKRDvdRipper.h"
|
||||
#if _WIN32
|
||||
#include <malloc.h>
|
||||
@@ -21,6 +22,8 @@ std::atomic<u64> JKRArchive::sArcOverlayGeneration{0};
|
||||
|
||||
namespace {
|
||||
|
||||
inline constexpr borealis::Log Log{"JKRArchivePri"};
|
||||
|
||||
void* alloc_overlay_buffer(u32 size) {
|
||||
#if _WIN32
|
||||
return _aligned_malloc(size, alignof(std::max_align_t));
|
||||
@@ -452,12 +455,18 @@ bool JKRArchive::copyOverlayData(void* buffer, u32 bufferSize, SDIFileEntry* ent
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 copySize = overlaySize < bufferSize ? overlaySize : bufferSize;
|
||||
if (copySize != 0) {
|
||||
memcpy(buffer, overlayData, copySize);
|
||||
if (overlaySize > bufferSize) {
|
||||
std::string path;
|
||||
getOverlayPath(entry, path);
|
||||
Log.error("Overlay %s is %u bytes but the game reserved %u\n", path.c_str(), overlaySize,
|
||||
bufferSize);
|
||||
return false;
|
||||
}
|
||||
if (overlaySize != 0) {
|
||||
memcpy(buffer, overlayData, overlaySize);
|
||||
}
|
||||
if (outSize != nullptr) {
|
||||
*outSize = copySize;
|
||||
*outSize = overlaySize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4313,7 +4313,9 @@ int daAlink_c::createHeap() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JKRReadIdxResource(mFaceBckHeap.getBuffer(), 0xC00, dRes_ID_ALANM_BCK_FAT_e, dComIfGp_getAnmArchive());
|
||||
IF_DUSK(mFaceBckHeap.reserveBuffer(dRes_ID_ALANM_BCK_FAT_e);)
|
||||
JKRReadIdxResource(mFaceBckHeap.getBuffer(), DUSK_IF_ELSE(mFaceBckHeap.getBufferSize(), 0xC00),
|
||||
dRes_ID_ALANM_BCK_FAT_e, dComIfGp_getAnmArchive());
|
||||
J3DAnmTransform* bck = (J3DAnmTransform*)J3DAnmLoaderDataBase::load(mFaceBckHeap.getBuffer());
|
||||
if (!mFaceBck.init(bck, FALSE, J3DFrameCtrl::EMode_LOOP, 1.0f, 0, -1, false)) {
|
||||
return 0;
|
||||
@@ -14307,7 +14309,11 @@ BOOL daAlink_c::checkMagicArmorWearAbility() const {
|
||||
|
||||
J3DModelData* daAlink_c::loadAramBmd(u16 i_resIdx, u32 i_bufSize) {
|
||||
JKRArchive* anmArchive = dComIfGp_getAnmArchive();
|
||||
#if TARGET_PC
|
||||
u8* tmpBuffer = (u8*)mItemHeap[field_0x2fa0].allocTempBuffer(i_resIdx, &i_bufSize);
|
||||
#else
|
||||
u8* tmpBuffer = JKR_NEW_ARRAY_ARGS(u8, i_bufSize, 0x20);
|
||||
#endif
|
||||
|
||||
JKRReadIdxResource(tmpBuffer, i_bufSize, i_resIdx, anmArchive);
|
||||
#if DEBUG
|
||||
@@ -14328,7 +14334,11 @@ J3DModelData* daAlink_c::loadAramBmd(u16 i_resIdx, u32 i_bufSize) {
|
||||
}
|
||||
|
||||
void* daAlink_c::loadAram(u16 i_resIdx, u32 i_bufSize) {
|
||||
#if TARGET_PC
|
||||
u8* tmpBuffer = (u8*)mItemHeap[field_0x2fa0].allocTempBuffer(i_resIdx, &i_bufSize);
|
||||
#else
|
||||
u8* tmpBuffer = JKR_NEW_ARRAY_ARGS(u8, i_bufSize, 0x20);
|
||||
#endif
|
||||
JKRReadIdxResource(tmpBuffer, i_bufSize, i_resIdx, dComIfGp_getAnmArchive());
|
||||
#if DEBUG
|
||||
daPy_aramBufferCheck(tmpBuffer, i_bufSize);
|
||||
|
||||
@@ -11,6 +11,16 @@ static int daAlink_modelCallBack(J3DJoint* i_joint, int param_1);
|
||||
static int daAlink_headModelCallBack(J3DJoint* i_joint, int param_1);
|
||||
static int daAlink_wolfModelCallBack(J3DJoint* i_joint, int param_1);
|
||||
|
||||
#if TARGET_PC
|
||||
static void* read_anm_resource(void** o_buffer, u16 i_resIdx, u32 i_fixedSize) {
|
||||
u32 size = daPy_getAnmResourceSize(i_resIdx, i_fixedSize);
|
||||
*o_buffer = JKRAllocFromSysHeap(size, 0x20);
|
||||
JUT_ASSERT(__LINE__, *o_buffer);
|
||||
JKRReadIdxResource(*o_buffer, size, i_resIdx, dComIfGp_getAnmArchive());
|
||||
return *o_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
void daAlink_c::setArcName(BOOL i_isWolf) {
|
||||
if (i_isWolf) {
|
||||
mArcName = l_wArcName;
|
||||
@@ -247,8 +257,10 @@ void daAlink_c::changeModelDataDirectWolf(int param_0) {
|
||||
void daAlink_c::initStatusWindow() {
|
||||
onNoResetFlg2(FLG2_STATUS_WINDOW_DRAW);
|
||||
|
||||
#if !TARGET_PC
|
||||
void* tmpBuffer = JKR_NEW_ARRAY_ARGS(void*, 0x500, 0x20);
|
||||
JUT_ASSERT(394, tmpBuffer);
|
||||
#endif
|
||||
|
||||
u16 bckResIdx, btpResIdx, btkResIdx;
|
||||
if (checkWolf()) {
|
||||
@@ -268,7 +280,11 @@ void daAlink_c::initStatusWindow() {
|
||||
changeModelDataDirect(0);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void* tmpBuffer = read_anm_resource(&mAnmBuffers[0], bckResIdx, 0x1400);
|
||||
#else
|
||||
JKRReadIdxResource(tmpBuffer, 0x1400, bckResIdx, dComIfGp_getAnmArchive());
|
||||
#endif
|
||||
m_sWindowBck = JKR_NEW mDoExt_bckAnm();
|
||||
JUT_ASSERT(428, m_sWindowBck);
|
||||
|
||||
@@ -276,20 +292,28 @@ void daAlink_c::initStatusWindow() {
|
||||
JUT_ASSERT(433, FALSE);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
tmpBuffer = read_anm_resource(&mAnmBuffers[1], btpResIdx, 0x400);
|
||||
#else
|
||||
tmpBuffer = JKR_NEW_ARRAY_ARGS(void*, 0x100, 0x20);
|
||||
JUT_ASSERT(437, tmpBuffer);
|
||||
|
||||
JKRReadIdxResource(tmpBuffer, 0x400, btpResIdx, dComIfGp_getAnmArchive());
|
||||
#endif
|
||||
// this should call J3DAnmLoaderDataBase::load(const void*) but it breaks retail
|
||||
J3DAnmTexPattern* btp = (J3DAnmTexPattern*)J3DAnmLoaderDataBase::load(tmpBuffer, J3DLOADER_UNK_FLAG0);
|
||||
btp->setFrame(0.0f);
|
||||
btp->searchUpdateMaterialID(field_0x06c0);
|
||||
field_0x06c0->entryTexNoAnimator(btp);
|
||||
|
||||
#if TARGET_PC
|
||||
tmpBuffer = read_anm_resource(&mAnmBuffers[2], btkResIdx, 0x400);
|
||||
#else
|
||||
tmpBuffer = JKR_NEW_ARRAY_ARGS(void*, 0x100, 0x20);
|
||||
JUT_ASSERT(449, tmpBuffer);
|
||||
|
||||
JKRReadIdxResource(tmpBuffer, 0x400, btkResIdx, dComIfGp_getAnmArchive());
|
||||
#endif
|
||||
// this should call J3DAnmLoaderDataBase::load(const void*) but it breaks retail
|
||||
J3DAnmTextureSRTKey* btk = (J3DAnmTextureSRTKey*)J3DAnmLoaderDataBase::load(tmpBuffer, J3DLOADER_UNK_FLAG0);
|
||||
btk->setFrame(0.0f);
|
||||
@@ -387,4 +411,12 @@ void daAlink_c::resetStatusWindow() {
|
||||
|
||||
offNoResetFlg2(FLG2_STATUS_WINDOW_DRAW);
|
||||
m_sWindowBck = NULL;
|
||||
#if TARGET_PC
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (mAnmBuffers[i] != NULL) {
|
||||
JKRFreeToSysHeap(mAnmBuffers[i]);
|
||||
mAnmBuffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -496,6 +496,7 @@ int daMidna_c::createHeap() {
|
||||
}
|
||||
}
|
||||
|
||||
IF_DUSK(mBckHeap[0].reserveBuffer(0x1DC);)
|
||||
JKRReadIdxResource(mBckHeap[0].getBuffer(), mBckHeap[0].getBufferSize(), 0x1DC, dComIfGp_getAnmArchive());
|
||||
J3DAnmTransform* md_anm = (J3DAnmTransform*)J3DAnmLoaderDataBase::load(mBckHeap[0].getBuffer());
|
||||
modelData = (J3DModelData*)dComIfG_getObjectRes(l_arcName, 14);
|
||||
|
||||
@@ -224,6 +224,12 @@ daPy_anmHeap_c::~daPy_anmHeap_c() {
|
||||
if (mAnimeHeap != NULL) {
|
||||
mDoExt_destroySolidHeap(mAnimeHeap);
|
||||
}
|
||||
#if TARGET_PC
|
||||
freeTempBuffers();
|
||||
if (mOwnedBuffer != NULL) {
|
||||
JKRFreeToSysHeap(mOwnedBuffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void daPy_anmHeap_c::initData() {
|
||||
@@ -237,6 +243,56 @@ void* daPy_anmHeap_c::mallocBuffer() {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
constexpr u32 kAlignment = 0x20;
|
||||
|
||||
void daPy_anmHeap_c::reserveBuffer(u16 i_resId) {
|
||||
// Ensure mBuffer is large enough to hold the resource
|
||||
u32 size = daPy_getAnmResourceSize(i_resId, mBufferSize);
|
||||
if (size <= mBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, replace it with a new buffer allocated from the system heap. Callers still copy
|
||||
// archive data in on every load: setAnmTransform bswaps key tables in place, so we can't point
|
||||
// it at the archive's cached copy directly.
|
||||
u8* buffer = static_cast<u8*>(JKRAllocFromSysHeap(size, kAlignment));
|
||||
JUT_ASSERT(__LINE__, buffer != NULL);
|
||||
if (mOwnedBuffer != NULL) {
|
||||
JKRFreeToSysHeap(mOwnedBuffer);
|
||||
}
|
||||
mOwnedBuffer = buffer; // Mark it as owned so we release it later
|
||||
mBuffer = buffer;
|
||||
mBufferSize = size;
|
||||
}
|
||||
|
||||
void* daPy_anmHeap_c::allocTempBuffer(u16 i_resId, u32* io_size) {
|
||||
// Check if the resource can fit in io_size
|
||||
u32 size = daPy_getAnmResourceSize(i_resId, *io_size);
|
||||
if (size <= *io_size) {
|
||||
return JKR_NEW_ARRAY_ARGS(u8, *io_size, kAlignment);
|
||||
}
|
||||
|
||||
// If not, allocate a new temp buffer from the system heap, plus kAlignment extra bytes.
|
||||
// We stash a pointer to the next buffer at the beginning, forming a chain so we can free
|
||||
// them all later.
|
||||
void** temp = static_cast<void**>(JKRAllocFromSysHeap(kAlignment + size, kAlignment));
|
||||
JUT_ASSERT(__LINE__, temp != NULL);
|
||||
*temp = mTempBuffers;
|
||||
mTempBuffers = temp;
|
||||
*io_size = size;
|
||||
return reinterpret_cast<u8*>(temp) + kAlignment;
|
||||
}
|
||||
|
||||
void daPy_anmHeap_c::freeTempBuffers() {
|
||||
while (mTempBuffers != NULL) {
|
||||
void** temp = mTempBuffers;
|
||||
mTempBuffers = static_cast<void**>(*temp);
|
||||
JKRFreeToSysHeap(temp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void daPy_anmHeap_c::createHeap(daPy_anmHeap_c::daAlinkHEAP_TYPE i_heapType, const char* name) {
|
||||
u32 size;
|
||||
|
||||
@@ -310,6 +366,7 @@ void* daPy_anmHeap_c::loadData(u16 i_resId) {
|
||||
};
|
||||
|
||||
if (mArcNo == 0xFFFF) {
|
||||
IF_DUSK(reserveBuffer(i_resId);)
|
||||
JKRReadIdxResource(mBuffer, mBufferSize, i_resId, dComIfGp_getAnmArchive());
|
||||
#if DEBUG
|
||||
daPy_aramBufferCheck(mBuffer, mBufferSize);
|
||||
@@ -363,6 +420,7 @@ void* daPy_anmHeap_c::loadDataDemoRID(u16 i_resID, u16 i_arcNo) {
|
||||
|
||||
JKRHeap* daPy_anmHeap_c::setAnimeHeap() {
|
||||
mAnimeHeap->freeAll();
|
||||
IF_DUSK(freeTempBuffers();)
|
||||
return mDoExt_setCurrentHeap(mAnimeHeap);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user