Fixed PSP trying to load entirely into memory

This commit is contained in:
2026-08-31 19:07:51 -05:00
parent 15bd9fc43c
commit d37109f5f7
26 changed files with 995 additions and 232 deletions
+25 -79
View File
@@ -9,129 +9,75 @@
#include "asset/assetdsk.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "util/math.h"
errorret_t assetInitPBP(const char_t *pbpPath) {
assertNotNull(pbpPath, "PBP path cannot be null.");
assertStrLenMin(pbpPath, 1, "PBP path cannot be empty.");
assertStrLenMax(pbpPath, ASSET_PBP_PATH_MAX, "PBP path is too long.");
ASSET.platform.pbpFile = fopen(pbpPath, "rb");
if(ASSET.platform.pbpFile == NULL) {
FILE *pbpFile = fopen(pbpPath, "rb");
if(pbpFile == NULL) {
errorThrow("Failed to open PBP file: %s", pbpPath);
}
// Get size of PBP file.
if(fseek(ASSET.platform.pbpFile, 0, SEEK_END) != 0) {
fclose(ASSET.platform.pbpFile);
if(fseek(pbpFile, 0, SEEK_END) != 0) {
fclose(pbpFile);
errorThrow("Failed to seek to end of PBP file : %s", pbpPath);
}
size_t pbpSize = ftell(ASSET.platform.pbpFile);
size_t pbpSize = ftell(pbpFile);
if(pbpSize == -1L) {
fclose(ASSET.platform.pbpFile);
fclose(pbpFile);
errorThrow("Failed to get size of PBP file : %s", pbpPath);
}
if(pbpSize < sizeof(assetpbpheader_t)) {
fclose(ASSET.platform.pbpFile);
fclose(pbpFile);
errorThrow("PBP file is too small to be valid: %s", pbpPath);
}
// Rewind to start
if(fseek(ASSET.platform.pbpFile, 0, SEEK_SET) != 0) {
fclose(ASSET.platform.pbpFile);
if(fseek(pbpFile, 0, SEEK_SET) != 0) {
fclose(pbpFile);
errorThrow("Failed to seek to start of PBP file : %s", pbpPath);
}
// Read the PBP header
size_t read = fread(
&ASSET.platform.pbpHeader,
1,
sizeof(assetpbpheader_t),
ASSET.platform.pbpFile
&ASSET.platform.pbpHeader, 1, sizeof(assetpbpheader_t), pbpFile
);
fclose(pbpFile);
if(read != sizeof(assetpbpheader_t)) {
fclose(ASSET.platform.pbpFile);
errorThrow("Failed to read PBP header", pbpPath);
}
if(memoryCompare(
ASSET.platform.pbpHeader.signature,
ASSET_PBP_SIGNATURE,
sizeof(ASSET_PBP_SIGNATURE)
) != 0) {
fclose(ASSET.platform.pbpFile);
errorThrow("Invalid PBP signature in file: %s", pbpPath);
}
// If we seek to the PSAR offset, we can read the WAD file from there.
// I'm not sure what PSAR was intended for, but it holds any user data we
// want, so I shoved the entire dusk wad there.
if(fseek(
ASSET.platform.pbpFile, ASSET.platform.pbpHeader.psarOffset, SEEK_SET
) != 0) {
fclose(ASSET.platform.pbpFile);
errorThrow("Failed to seek to PSAR offset in PBP file: %s", pbpPath);
}
// The PSAR region holds the embedded dusk.dsk (DSK2) archive - I'm not
// sure what PSAR was intended for, but it holds any user data we want,
// so I shoved the entire dusk.dsk there. Opened lazily/on-demand
// straight from the PBP file by path+offset (see
// assetDskOpenFromPathRange), the same way every other platform opens
// dusk.dsk, rather than reading the whole PSAR into memory up front.
size_t psarSize = pbpSize - ASSET.platform.pbpHeader.psarOffset;
errorChain(assetDskOpenFromPathRange(
pbpPath,
ASSET.platform.pbpHeader.psarOffset,
psarSize,
&ASSET.zip,
&ASSET.zipStored
));
// Read the whole PSAR (the embedded dusk.dsk zip archive) into memory up
// front and hand libzip an in-memory buffer, instead of a lazily-seeked
// FILE source: repeated seeked reads directly against the open PBP file
// proved unreliable on PSP (zip_fread() failing with EINVAL, then with
// zlib data corruption, depending on the read chunk size used). Reading
// once, straight through, and letting libzip operate on memory from then
// on avoids that read path entirely. psarSize is small (tens of KB) so
// holding it fully in RAM is cheap.
uint8_t *psarData = (uint8_t *)malloc(psarSize);
if(psarData == NULL) {
fclose(ASSET.platform.pbpFile);
errorThrow("Failed to allocate PSAR buffer for file: %s", pbpPath);
}
size_t totalRead = 0;
while(totalRead < psarSize) {
size_t chunkSize = mathMin(
psarSize - totalRead, ASSET_FILE_READ_CHUNK_MAX
);
size_t chunkRead = fread(
psarData + totalRead, 1, chunkSize, ASSET.platform.pbpFile
);
if(chunkRead == 0) {
free(psarData);
fclose(ASSET.platform.pbpFile);
errorThrow("Failed to read PSAR data from file: %s", pbpPath);
}
totalRead += chunkRead;
}
fclose(ASSET.platform.pbpFile);
ASSET.platform.pbpFile = NULL;
errorret_t ret = assetDskOpenFromBuffer(
psarData, psarSize, &ASSET.zip, &ASSET.zipStored
);
if(errorIsNotOk(ret)) {
free(psarData);
errorChain(ret);
}
ASSET.platform.dskData = psarData;
errorOk();
}
errorret_t assetDisposePBP(void) {
if(ASSET.platform.pbpFile != NULL) {
fclose(ASSET.platform.pbpFile);
ASSET.platform.pbpFile = NULL;
}
if(ASSET.platform.dskData != NULL) {
free(ASSET.platform.dskData);
ASSET.platform.dskData = NULL;
}
errorOk();
}
-6
View File
@@ -28,13 +28,7 @@ typedef struct {
} assetpbpheader_t;
typedef struct {
FILE *pbpFile;
assetpbpheader_t pbpHeader;
// Whole dusk.dsk (PSAR) blob, kept alive for as long as ASSET.zip/
// ASSET.zipStored are open since they're non-owning windows into it (see
// assetDskOpenFromBuffer). Freed in assetDisposePBP.
uint8_t *dskData;
} assetpbp_t;
/**