PSP now reads data directly from EBOOT if requested
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
16
src/main.c
16
src/main.c
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user