PSP now reads data directly from EBOOT if requested

This commit is contained in:
2025-11-09 15:42:26 -06:00
parent aaa8622956
commit 5206d47b43
5 changed files with 160 additions and 20 deletions

View File

@@ -10,13 +10,136 @@
#include "util/string.h" #include "util/string.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "asset/assettype.h" #include "asset/assettype.h"
#include "engine/engine.h"
errorret_t assetInit(void) { errorret_t assetInit(void) {
memoryZero(&ASSET, sizeof(asset_t)); memoryZero(&ASSET, sizeof(asset_t));
// Engine may have been provided the launch path
if(ENGINE.argc > 0) {
// This first arg is the executable, so on most platforms it is say
// "/path/file" or "C:\Path\file.exe". On PSP this would be something
// like "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or if we are debugging it is
// "host0:/Dusk.prx"
// Get the directory of the executable
char_t buffer[FILENAME_MAX];
stringCopy(buffer, ENGINE.argv[0], FILENAME_MAX);
size_t len = strlen(buffer);
// Normalize slashes
for(size_t i = 0; i < FILENAME_MAX; i++) {
if(buffer[i] == '\0') break;
if(buffer[i] == '\\') buffer[i] = '/';
}
// Now find the last slash
char_t *end = buffer + len - 1;
do {
end--;
if(*end == '/') {
*end = '\0';
break;
}
} while(end != buffer);
// Did we find a slash?
if(end != buffer) {
// We found the directory, set as system path
stringCopy(ASSET.systemPath, buffer, FILENAME_MAX);
}
}
// Default system path, intended to be overridden by the platform // Default system path, intended to be overridden by the platform
stringCopy(ASSET.systemPath, ".", FILENAME_MAX); stringCopy(ASSET.systemPath, ".", FILENAME_MAX);
// PSP specific time.
#if PSP
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
// PSP is given either host0:/Dusk.prx (debugging) OR the PBP file.
if(stringEndsWith(ENGINE.argv[0], ".pbp") || ASSET_PBP_READ_PBP_FROM_HOST) {
const char_t *pbpPath = (
ASSET_PBP_READ_PBP_FROM_HOST ? "./EBOOT.PBP" : ENGINE.argv[0]
);
ASSET.pbpFile = fopen(pbpPath, "rb");
if(ASSET.pbpFile == NULL) {
errorThrow("Failed to open PBP file: %s", pbpPath);
}
// Get size of PBP file.
if(fseek(ASSET.pbpFile, 0, SEEK_END) != 0) {
fclose(ASSET.pbpFile);
errorThrow("Failed to seek to end of PBP file : %s", pbpPath);
}
size_t pbpSize = ftell(ASSET.pbpFile);
// Rewind to start
if(fseek(ASSET.pbpFile, 0, SEEK_SET) != 0) {
fclose(ASSET.pbpFile);
errorThrow("Failed to seek to start of PBP file : %s", pbpPath);
}
// Read the PBP header
size_t read = fread(
&ASSET.pbpHeader,
1,
sizeof(assetpbp_t),
ASSET.pbpFile
);
if(read != sizeof(assetpbp_t)) {
fclose(ASSET.pbpFile);
errorThrow("Failed to read PBP header", pbpPath);
}
if(memoryCompare(
ASSET.pbpHeader.signature,
ASSET_PBP_SIGNATURE,
sizeof(ASSET_PBP_SIGNATURE)
) != 0) {
fclose(ASSET.pbpFile);
errorThrow("Invalid PBP signature in file: %s", pbpPath);
}
// If we seek to the PSAR offset, we can read the WAD file from there
if(fseek(ASSET.pbpFile, ASSET.pbpHeader.psarOffset, SEEK_SET) != 0) {
fclose(ASSET.pbpFile);
errorThrow("Failed to seek to PSAR offset in PBP file: %s", pbpPath);
}
zip_uint64_t zipPsarOffset = (zip_uint64_t)ASSET.pbpHeader.psarOffset;
zip_int64_t zipPsarSize = (zip_int64_t)(
pbpSize - ASSET.pbpHeader.psarOffset
);
zip_source_t *psarSource = zip_source_filep_create(
ASSET.pbpFile,
zipPsarOffset,
zipPsarSize,
NULL
);
if(psarSource == NULL) {
fclose(ASSET.pbpFile);
errorThrow("Failed to create zip source in PBP file: %s", pbpPath);
}
ASSET.zip = zip_open_from_source(
psarSource,
ZIP_RDONLY,
NULL
);
if(ASSET.zip == NULL) {
zip_source_free(psarSource);
fclose(ASSET.pbpFile);
errorThrow("Failed to open zip from PBP file: %s", pbpPath);
}
errorOk();
}
#endif
// Open zip file // Open zip file
char_t searchPath[FILENAME_MAX]; char_t searchPath[FILENAME_MAX];
const char_t **path = ASSET_SEARCH_PATHS; const char_t **path = ASSET_SEARCH_PATHS;
@@ -29,6 +152,7 @@ errorret_t assetInit(void) {
); );
// Try open // Try open
printf("Trying to open asset at: %s\n", searchPath);
ASSET.zip = zip_open(searchPath, ZIP_RDONLY, NULL); ASSET.zip = zip_open(searchPath, ZIP_RDONLY, NULL);
if(ASSET.zip == NULL) continue; if(ASSET.zip == NULL) continue;
break;// Found! break;// Found!
@@ -125,4 +249,11 @@ void assetDispose(void) {
zip_close(ASSET.zip); zip_close(ASSET.zip);
ASSET.zip = NULL; ASSET.zip = NULL;
} }
#if PSP
if(ASSET.pbpFile != NULL) {
fclose(ASSET.pbpFile);
ASSET.pbpFile = NULL;
}
#endif
} }

View File

@@ -11,10 +11,21 @@
#if ASSET_TYPE == wad #if ASSET_TYPE == wad
#if PSP #if PSP
#define ASSET_PBP_READ_PBP_FROM_HOST 0
#define ASSET_PBP_SIGNATURE_LEN 4
#define ASSET_PBP_SIGNATURE "\0PBP"
typedef struct { typedef struct {
uint8_t signature[4]; char_t signature[ASSET_PBP_SIGNATURE_LEN];
uint16_t version[2]; uint32_t version;
unsigned int offset[8]; uint32_t sfoOffset;
uint32_t icon0Offset;
uint32_t icon1Offset;
uint32_t pic0Offset;
uint32_t pic1Offset;
uint32_t snd0Offset;
uint32_t pspOffset;
uint32_t psarOffset;
} assetpbp_t; } assetpbp_t;
#endif #endif
#else #else
@@ -44,6 +55,11 @@ typedef struct {
zip_t *zip; zip_t *zip;
char_t systemPath[FILENAME_MAX]; char_t systemPath[FILENAME_MAX];
uint8_t assetCount; uint8_t assetCount;
#if PSP
FILE *pbpFile;
assetpbp_t pbpHeader;
#endif
} asset_t; } asset_t;
static asset_t ASSET; static asset_t ASSET;

View File

@@ -18,9 +18,11 @@
engine_t ENGINE; engine_t ENGINE;
errorret_t engineInit(void) { errorret_t engineInit(const int32_t argc, const char_t **argv) {
memoryZero(&ENGINE, sizeof(engine_t)); memoryZero(&ENGINE, sizeof(engine_t));
ENGINE.running = true; ENGINE.running = true;
ENGINE.argc = argc;
ENGINE.argv = argv;
// Init systems. Order is important. // Init systems. Order is important.
timeInit(); timeInit();

View File

@@ -11,14 +11,19 @@
typedef struct { typedef struct {
bool_t running; bool_t running;
int32_t argc;
const char_t **argv;
} engine_t; } engine_t;
extern engine_t ENGINE; extern engine_t ENGINE;
/** /**
* Initializes the engine. * Initializes the engine.
*
* @param argc The argument count from main().
* @param argv The argument vector from main().
*/ */
errorret_t engineInit(void); errorret_t engineInit(const int32_t argc, const char_t **argv);
/** /**
* Updates the engine. * Updates the engine.

View File

@@ -11,28 +11,14 @@
#include "input/input.h" #include "input/input.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
// Write out launch args
printf("Launching Dusk with %d args:\n", argc);
for(int i = 0; i < argc; i++) {
printf(" Arg %d: %s\n", i, argv[i]);
}
errorret_t ret; errorret_t ret;
// Init engine // Init engine
ret = engineInit(); ret = engineInit(argc, (const char_t **)argv);
if(ret.code != ERROR_OK) { if(ret.code != ERROR_OK) {
errorCatch(errorPrint(ret)); errorCatch(errorPrint(ret));
return ret.code; return ret.code;
} }
// Setup system path on asset manager
if(argc > 0) {
stringCopy(
ASSET.systemPath, argv[0],
sizeof(ASSET.systemPath) / sizeof(char_t)
);
}
// Begin main loop // Begin main loop
do { do {