Merge branch 'skmp/oom-mitigation-3' into 'main'

Memory usage improvements and memleak fixes

See merge request skmp/dca3-game!72
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis
2025-03-25 18:07:56 +00:00
26 changed files with 922 additions and 349 deletions

View File

@@ -11,6 +11,8 @@
#include "AnimBlendAssocGroup.h"
#include "AnimManager.h"
void* re3StreamingAlloc(size_t size);
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
int32 CAnimManager::ms_numAnimBlocks;
@@ -837,7 +839,7 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
uint16_t flags;
CFileMgr::Read(fd, (char*)&flags, sizeof(flags));
seq->keyFrames = RwMalloc(dataSize);
seq->keyFrames = re3StreamingAlloc(dataSize);
assert(seq->keyFrames);
CFileMgr::Read(fd, (char*)seq->keyFrames, dataSize - sizeof(flags));
seq->type = flags;

View File

@@ -175,6 +175,12 @@ file_t fdPedSfx;
volatile uint32 nPedSfxReqReadId = 1;
volatile uint32 nPedSfxReqNextId = 1;
// this is very wasteful and temporary
#define BANK_STAGE_SIZE 16 * 2048
static uint8_t stagingBufferBank[BANK_STAGE_SIZE] __attribute__((aligned(32)));
std::mutex stagingBufferMtx;
static int32 DCStreamedLength[TOTAL_STREAMED_SOUNDS];
struct WavHeader {
@@ -568,26 +574,29 @@ cSampleManager::LoadSampleBank(uint8 nBank)
// TODO: Split per-bank sfx file
int fd = fs_open(SampleBankDataFilename, O_RDONLY);
assert(fd >= 0);
// this is very wasteful and temporary
void* stagingBuffer = memalign(32, 32 * 2048);
assert(stagingBuffer != 0);
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
while (fileSize > 0) {
size_t readSize = fileSize > 32 * 2048 ? 32 * 2048 : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
while (fileSize > 0) {
size_t readSize = fileSize > sizeof(stagingBufferBank) ? sizeof(stagingBufferBank) : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
}
}
fs_close(fd);
free(stagingBuffer);
for (int nSfx = BankStartOffset[nBank]; nSfx < BankStartOffset[nBank+1]; nSfx++) {
@@ -736,15 +745,19 @@ cSampleManager::LoadPedComment(uint32 nComment)
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -1268,6 +1281,8 @@ cSampleManager::InitialiseSampleBanks(void)
assert(m_aSamples[nComment].nByteSize <= PED_BLOCKSIZE_ADPCM);
}
assert(PED_BLOCKSIZE_ADPCM <= BANK_STAGE_SIZE);
LoadSampleBank(SFX_BANK_0);
return TRUE;

View File

@@ -2,6 +2,9 @@
#include "ColModel.h"
#include "Game.h"
#include "MemoryHeap.h"
#include "Collision.h"
void* re3StreamingAlloc(size_t size);
CColModel::CColModel(void)
{
@@ -22,12 +25,12 @@ CColModel::CColModel(void)
CColModel::~CColModel(void)
{
RemoveCollisionVolumes();
RemoveTrianglePlanes();
}
void
CColModel::RemoveCollisionVolumes(void)
{
CCollision::RemoveTrianglePlanes(this);
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
@@ -93,6 +96,8 @@ CColModel::operator=(const CColModel &other)
int i;
int numVerts;
CCollision::RemoveTrianglePlanes(this);
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
@@ -163,7 +168,7 @@ CColModel::operator=(const CColModel &other)
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
vertices = (CompressedVector*)re3StreamingAlloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
@@ -173,7 +178,7 @@ CColModel::operator=(const CColModel &other)
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
triangles = (CColTriangle*)re3StreamingAlloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];

View File

@@ -2287,6 +2287,15 @@ CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *poin
return (*point - closest).Magnitude();
}
void
CCollision::RemoveTrianglePlanes(CColModel *model)
{
if(model->trianglePlanes){
ms_colModelCache.Remove(model->GetLinkPtr());
model->RemoveTrianglePlanes();
}
}
void
CCollision::CalculateTrianglePlanes(CColModel *model)
{

View File

@@ -41,6 +41,7 @@ public:
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
static void RemoveTrianglePlanes(CColModel *model);
static void CalculateTrianglePlanes(CColModel *model);
// all these return true if there's a collision

View File

@@ -28,6 +28,8 @@
#include <kos/dbglog.h>
void* re3StreamingAlloc(size_t size);
char CFileLoader::ms_line[256];
const char*
@@ -221,7 +223,7 @@ CFileLoader::LoadCollisionFile(const char *filename)
mi = CModelInfo::GetModelInfo(modelname, nil);
if(mi){
if(mi->GetColModel()){
if(mi->GetColModel() && mi->DoesOwnColModel()){
LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname);
}else{
CColModel *model = new CColModel;
@@ -255,6 +257,24 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.boundingBox.max.z = *(float*)(buf+36);
model.numSpheres = *(int16*)(buf+40);
buf += 44;
if (model.spheres) {
RwFree(model.spheres);
}
if (model.lines) {
RwFree(model.lines);
}
if (model.boxes) {
RwFree(model.boxes);
}
if (model.vertices) {
RwFree(model.vertices);
}
if (model.triangles) {
RwFree(model.triangles);
}
if (model.trianglePlanes) {
CCollision::RemoveTrianglePlanes(&model);
}
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
REGISTER_MEMPTR(&model.spheres);
@@ -292,7 +312,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
int32 numVertices = *(int16*)buf;
buf += 4;
if(numVertices > 0){
model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));
model.vertices = (CompressedVector*)re3StreamingAlloc(numVertices*sizeof(CompressedVector));
REGISTER_MEMPTR(&model.vertices);
for(i = 0; i < numVertices; i++){
model.vertices[i].SetFixed(*(int16*)buf, *(int16*)(buf+2), *(int16*)(buf+4));
@@ -304,7 +324,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numTriangles = *(int16*)buf;
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
model.triangles = (CColTriangle*)re3StreamingAlloc(model.numTriangles*sizeof(CColTriangle));
REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(model.vertices, *(uint16*)buf, *(uint16*)(buf+2), *(uint16*)(buf+4), buf[6], buf[7]);

View File

@@ -1170,6 +1170,24 @@ bool re3EmergencyRemoveModel() {
return usedmem != CStreaming::ms_memoryUsed;
}
void* re3StreamingAlloc(size_t size) {
auto rv = RwMalloc(size);
while (rv == nil) {
if (re3RemoveLeastUsedModel()) {
rv = RwMalloc(size);
continue;
}
if (re3EmergencyRemoveModel()) {
rv = RwMalloc(size);
continue;
}
return nil;
}
return rv;
}
bool
CStreaming::RemoveLeastUsedModel(void)
{

View File

@@ -38,6 +38,14 @@ CBaseModelInfo::DeleteCollisionModel(void)
}
}
void CBaseModelInfo::SetColModel(CColModel *col, bool owns) {
if (m_bOwnsColModel) {
delete m_colModel;
}
m_colModel = col;
m_bOwnsColModel = owns;
}
void
CBaseModelInfo::AddRef(void)
{

View File

@@ -56,8 +56,7 @@ public:
}
char *GetModelName(void) { return m_name; }
void SetModelName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }
void SetColModel(CColModel *col, bool owns = false){
m_colModel = col; m_bOwnsColModel = owns; }
void SetColModel(CColModel *col, bool owns = false);
CColModel *GetColModel(void) { return m_colModel; }
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);

View File

@@ -197,6 +197,10 @@ CCutsceneHead::PlayAnimation(const char *animName)
RwStreamSkip(stream, offset*2048);
if(RwStreamFindChunk(stream, rwID_HANIMANIMATION, nil, nil)){
anim = RpHAnimAnimationStreamRead(stream);
if (hier->interpolator->currentAnim) {
RpHAnimAnimationDestroy(hier->interpolator->currentAnim);
hier->interpolator->currentAnim = nil;
}
RpHAnimHierarchySetCurrentAnim(hier, anim);
}

View File

@@ -17,6 +17,8 @@
#include "vmu/vmu.h"
void* re3StreamingAlloc(size_t size);
const char* _psGetUserFilesFolder();
C_PcSave PcSaveHelper;
@@ -93,16 +95,17 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
return size;
} else {
size &= ~0x80000000;
uint8* compressed = (uint8*)malloc(size);
uint8* compressed = (uint8*)re3StreamingAlloc(size);
assert(compressed);
err = CFileMgr::Read(file, (const char*)compressed, size) != size;
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
return 0;
}
lzo_uint decompressed_size = 0;
auto crv = lzo1x_decompress(compressed, size, data, &decompressed_size, NULL);
free(compressed);
RwFree(compressed);
if (crv != LZO_E_OK) {
return 0;
}
@@ -117,31 +120,37 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
bool
C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
{
void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS);
uint8* compressed = (uint8*)malloc(size*2);
void* wrkmem = re3StreamingAlloc(LZO1X_1_MEM_COMPRESS);
assert(wrkmem);
uint8* compressed = (uint8*)re3StreamingAlloc(size*2);
assert(compressed);
lzo_uint compressed_size;
int crv = lzo1x_1_compress(data, size, compressed, &compressed_size, wrkmem);
free(wrkmem);
RwFree(wrkmem);
if (crv == LZO_E_OK && compressed_size >= size) {
crv = LZO_E_NOT_COMPRESSIBLE;
}
if (crv == LZO_E_OK) {
uint32_t compressed_size32 = compressed_size | 0x80000000;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
err = CFileMgr::Write(file, (const char*)compressed, compressed_size) != compressed_size;
free(compressed);
RwFree(compressed);
if (err || CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
} else if (crv == LZO_E_NOT_COMPRESSIBLE) {
free(compressed);
RwFree(compressed);
uint32_t compressed_size32 = size;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
@@ -156,7 +165,7 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
return false;
}
} else {
free(compressed);
RwFree(compressed);
return false;
}

View File

@@ -12,6 +12,8 @@
#include "AnimManager.h"
#include "Streaming.h"
void* re3StreamingAlloc(size_t size);
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
int32 CAnimManager::ms_numAnimBlocks;
@@ -1312,7 +1314,7 @@ CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedA
uint16_t flags;
RwStreamRead(stream, &flags, sizeof(flags));
seq->keyFrames = RwMalloc(dataSize);
seq->keyFrames = re3StreamingAlloc(dataSize);
assert(seq->keyFrames);
RwStreamRead(stream, seq->keyFrames, dataSize - sizeof(flags));
seq->type = flags;

View File

@@ -419,7 +419,8 @@ CCutsceneMgr::DeleteCutsceneData(void)
CBaseModelInfo *minfo = CModelInfo::GetModelInfo(i);
CColModel *colModel = minfo->GetColModel();
if (colModel != &CTempColModels::ms_colModelPed1) {
delete colModel;
// no need to delete anymore, SetColModel will do it (~skmp)
//delete colModel;
minfo->SetColModel(&CTempColModels::ms_colModelPed1);
}
}

View File

@@ -182,6 +182,12 @@ uintptr_t gPlayerTalkData = 0;
uint32 gPlayerTalkReqId = 0;
#endif
// this is very wasteful and temporary
#define BANK_STAGE_SIZE 16 * 2048
static uint8_t stagingBufferBank[BANK_STAGE_SIZE] __attribute__((aligned(32)));
std::mutex stagingBufferMtx;
static int32 DCStreamedLength[TOTAL_STREAMED_SOUNDS];
struct WavHeader {
@@ -581,26 +587,29 @@ cSampleManager::LoadSampleBank(uint8 nBank)
// TODO: Split per-bank sfx file
int fd = fs_open(SampleBankDataFilename, O_RDONLY);
assert(fd >= 0);
// this is very wasteful and temporary
void* stagingBuffer = memalign(32, 8 * 2048);
assert(stagingBuffer != 0);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
while (fileSize > 0) {
size_t readSize = fileSize > 8 * 2048 ? 8 * 2048 : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
while (fileSize > 0) {
size_t readSize = fileSize > sizeof(stagingBufferBank) ? sizeof(stagingBufferBank) : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
}
}
fs_close(fd);
free(stagingBuffer);
for (int nSfx = BankStartOffset[nBank]; nSfx < BankStartOffset[nBank+1]; nSfx++) {
@@ -693,15 +702,19 @@ cSampleManager::LoadMissionAudio(uint8 nSlot, uint32 nSample)
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -787,15 +800,19 @@ cSampleManager::LoadPedComment(uint32 nComment)
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -1349,16 +1366,21 @@ cSampleManager::InitialiseSampleBanks(void)
for (uint32 nComment = SAMPLEBANK_PED_START; nComment <= SAMPLEBANK_PED_END; nComment++) {
pedBlocksizeMax = Max(pedBlocksizeMax, m_aSamples[nComment].nByteSize);
}
assert(pedBlocksizeMax <= BANK_STAGE_SIZE);
debugf("Max ped comment size: %d\n", pedBlocksizeMax);
#ifdef FIX_BUGS
// Find biggest player comment
uint32 nMaxPlayerSize = 0;
for (uint32 i = PLAYER_COMMENTS_START; i <= PLAYER_COMMENTS_END; i++)
for (uint32 i = PLAYER_COMMENTS_START; i <= PLAYER_COMMENTS_END; i++) {
nMaxPlayerSize = Max(nMaxPlayerSize, m_aSamples[i].nByteSize);
}
debugf("Max player comment size: %d\n", nMaxPlayerSize);
assert(nMaxPlayerSize < sizeof(stagingBufferBank));
gPlayerTalkData = snd_mem_malloc(nMaxPlayerSize);
ASSERT(gPlayerTalkData != 0);

View File

@@ -5,6 +5,8 @@
#include "MemoryHeap.h"
#include "Pools.h"
void* re3StreamingAlloc(size_t size);
CColModel::CColModel(void)
{
numSpheres = 0;
@@ -43,13 +45,13 @@ CColModel::operator delete(void *p, size_t) throw()
void
CColModel::RemoveCollisionVolumes(void)
{
CCollision::RemoveTrianglePlanes(this);
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
CCollision::RemoveTrianglePlanes(this);
}
numSpheres = 0;
numLines = 0;
@@ -109,6 +111,8 @@ CColModel::operator=(const CColModel &other)
int i;
int numVerts;
CCollision::RemoveTrianglePlanes(this);
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
@@ -179,7 +183,7 @@ CColModel::operator=(const CColModel &other)
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
vertices = (CompressedVector*)re3StreamingAlloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
@@ -189,7 +193,7 @@ CColModel::operator=(const CColModel &other)
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
triangles = (CColTriangle*)re3StreamingAlloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];

View File

@@ -30,6 +30,8 @@
#include "ColStore.h"
#include "Occlusion.h"
void* re3StreamingAlloc(size_t size);
char CFileLoader::ms_line[256];
const char*
@@ -303,6 +305,24 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.boundingBox.max.z = *(float*)(buf+36);
model.numSpheres = *(int16*)(buf+40);
buf += 44;
if (model.spheres) {
RwFree(model.spheres);
}
if (model.lines) {
RwFree(model.lines);
}
if (model.boxes) {
RwFree(model.boxes);
}
if (model.vertices) {
RwFree(model.vertices);
}
if (model.triangles) {
RwFree(model.triangles);
}
if (model.trianglePlanes) {
CCollision::RemoveTrianglePlanes(&model);
}
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
REGISTER_MEMPTR(&model.spheres);
@@ -360,7 +380,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numTriangles = *(int16*)buf;
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
model.triangles = (CColTriangle*)re3StreamingAlloc(model.numTriangles*sizeof(CColTriangle));
REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(*(uint16*)buf, *(uint16*)(buf+2), *(uint16*)(buf+4), buf[6]);

View File

@@ -1386,6 +1386,24 @@ bool re3EmergencyRemoveModel() {
return usedmem != CStreaming::ms_memoryUsed;
}
void* re3StreamingAlloc(size_t size) {
auto rv = RwMalloc(size);
while (rv == nil) {
if (re3RemoveLeastUsedModel()) {
rv = RwMalloc(size);
continue;
}
if (re3EmergencyRemoveModel()) {
rv = RwMalloc(size);
continue;
}
return nil;
}
return rv;
}
bool
CStreaming::RemoveLeastUsedModel(uint32 excludeMask)
{

View File

@@ -40,6 +40,14 @@ CBaseModelInfo::DeleteCollisionModel(void)
}
}
void CBaseModelInfo::SetColModel(CColModel *col, bool owns) {
if (m_bOwnsColModel) {
delete m_colModel;
}
m_colModel = col;
m_bOwnsColModel = owns;
}
void
CBaseModelInfo::AddRef(void)
{

View File

@@ -52,8 +52,7 @@ public:
bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE; }
char *GetModelName(void) { return m_name; }
void SetModelName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }
void SetColModel(CColModel *col, bool owns = false){
m_colModel = col; m_bOwnsColModel = owns; }
void SetColModel(CColModel *col, bool owns = false);
CColModel *GetColModel(void) { return m_colModel; }
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);

View File

@@ -271,13 +271,13 @@ CShadowCamera::InvertRaster()
RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255);
RwIm2DVertexSetScreenX (&vx[2], crw);
RwIm2DVertexSetScreenY (&vx[2], 0.0f);
RwIm2DVertexSetScreenY (&vx[2], crh);
RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ);
RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255);
RwIm2DVertexSetScreenX (&vx[3], crw);
RwIm2DVertexSetScreenY (&vx[3], crh);
RwIm2DVertexSetScreenY (&vx[3], 0.0f);
RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ);
RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255);
@@ -289,7 +289,7 @@ CShadowCamera::InvertRaster()
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, vx, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);

View File

@@ -384,23 +384,23 @@ RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwRe
RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetScreenX(&vx[2], x2);
RwIm2DVertexSetScreenY(&vx[2], y1);
RwIm2DVertexSetScreenX(&vx[2], x2);
RwIm2DVertexSetScreenY(&vx[2], y2);
RwIm2DVertexSetScreenZ(&vx[2], z);
RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255);
RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[2], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetScreenX(&vx[3], x2);
RwIm2DVertexSetScreenY(&vx[3], y2);
RwIm2DVertexSetScreenY(&vx[3], y1);
RwIm2DVertexSetScreenZ(&vx[3], z);
RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255);
RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[3], uvOffset, recipCamZ);
RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, vx, 4);
return TRUE;
}

View File

@@ -17,6 +17,8 @@
#include "vmu/vmu.h"
void* re3StreamingAlloc(size_t size);
const char* _psGetUserFilesFolder();
C_PcSave PcSaveHelper;
@@ -76,31 +78,37 @@ C_PcSave::SaveSlot(int32 slot)
bool
C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
{
void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS);
uint8* compressed = (uint8*)malloc(size*2);
void* wrkmem = re3StreamingAlloc(LZO1X_1_MEM_COMPRESS);
assert(wrkmem);
uint8* compressed = (uint8*)re3StreamingAlloc(size*2);
assert(compressed);
lzo_uint compressed_size;
int crv = lzo1x_1_compress(data, size, compressed, &compressed_size, wrkmem);
free(wrkmem);
RwFree(wrkmem);
if (crv == LZO_E_OK && compressed_size >= size) {
crv = LZO_E_NOT_COMPRESSIBLE;
}
if (crv == LZO_E_OK) {
uint32_t compressed_size32 = compressed_size | 0x80000000;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
err = CFileMgr::Write(file, (const char*)compressed, compressed_size) != compressed_size;
free(compressed);
RwFree(compressed);
if (err || CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
} else if (crv == LZO_E_NOT_COMPRESSIBLE) {
free(compressed);
RwFree(compressed);
uint32_t compressed_size32 = size;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
@@ -115,7 +123,7 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
return false;
}
} else {
free(compressed);
RwFree(compressed);
return false;
}
@@ -153,16 +161,17 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
return size;
} else {
size &= ~0x80000000;
uint8* compressed = (uint8*)malloc(size);
uint8* compressed = (uint8*)re3StreamingAlloc(size);
assert(compressed);
err = CFileMgr::Read(file, (const char*)compressed, size) != size;
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
return 0;
}
lzo_uint decompressed_size = 0;
auto crv = lzo1x_decompress(compressed, size, data, &decompressed_size, NULL);
free(compressed);
RwFree(compressed);
if (crv != LZO_E_OK) {
return 0;
}

View File

@@ -53,6 +53,9 @@ uint32_t pvr_map32(uint32_t offset32) {return 0;}
void Hackpresent() { }
void re3RemoveLeastUsedModel() { assert(false); }
void re3EmergencyRemoveModel() { assert(false); }
void* re3StreamingAlloc(size_t sz) {
return RwMalloc(sz);
}
void RwTexDictionaryGtaStreamRead1(rw::Stream*){ assert(false); }
void RwTexDictionaryGtaStreamRead2(rw::Stream*, rw::TexDictionary*) { assert(false); }
void pvr_ta_data(void* data, int size) {

View File

@@ -125,6 +125,8 @@ void x11_window_create()
x11_win = (void*)x11Window;
x11_vis = (void*)x11Visual->visual;
delete x11Visual;
x11_window_set_text("GTA3dc");
}

View File

@@ -221,6 +221,7 @@ AnimInterpolator::setCurrentAnim(Animation *anim)
{
int32 i;
AnimInterpolatorInfo *interpInfo = anim->interpInfo;
assert(this->currentAnim == nil || this->currentAnim == anim);
this->currentAnim = anim;
this->currentTime = 0.0f;
int32 maxkf = this->maxInterpKeyFrameSize;

File diff suppressed because it is too large Load Diff