Asset compartmentalized
This commit is contained in:
@@ -14,208 +14,14 @@
|
||||
#include "debug/debug.h"
|
||||
#include "util/string.h"
|
||||
|
||||
asset_t ASSET;
|
||||
|
||||
errorret_t assetInit(void) {
|
||||
memoryZero(&ASSET, sizeof(asset_t));
|
||||
|
||||
#if DOLPHIN
|
||||
// Init FAT driver.
|
||||
if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem.");
|
||||
|
||||
char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS;
|
||||
char_t foundPath[FILENAME_MAX];
|
||||
foundPath[0] = '\0';
|
||||
do {
|
||||
// Try open dir
|
||||
DIR *pdir = opendir(*dolphinSearchPath);
|
||||
if(pdir == NULL) continue;
|
||||
|
||||
|
||||
// Scan if file is present
|
||||
while(true) {
|
||||
struct dirent* pent = readdir(pdir);
|
||||
if(pent == NULL) break;
|
||||
|
||||
if(stringCompareInsensitive(pent->d_name, ASSET_FILE) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy out filename
|
||||
snprintf(
|
||||
foundPath,
|
||||
FILENAME_MAX,
|
||||
"%s/%s",
|
||||
*dolphinSearchPath,
|
||||
ASSET_FILE
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// Close dir.
|
||||
closedir(pdir);
|
||||
|
||||
// Did we find the file here?
|
||||
if(foundPath[0] != '\0') break;
|
||||
} while(*(++dolphinSearchPath) != NULL);
|
||||
|
||||
if(foundPath[0] != '\0') {
|
||||
}
|
||||
|
||||
// Did we find the asset file?
|
||||
if(foundPath[0] == '\0') {
|
||||
errorThrow("Failed to find asset file on FAT filesystem.");
|
||||
}
|
||||
|
||||
ASSET.zip = zip_open(foundPath, ZIP_RDONLY, NULL);
|
||||
if(ASSET.zip == NULL) {
|
||||
errorThrow("Failed to open asset file on FAT filesystem.");
|
||||
}
|
||||
errorOk();
|
||||
#endif
|
||||
|
||||
// Engine may have been provided the launch path
|
||||
if(ENGINE.argc > 0) {
|
||||
// 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
|
||||
stringCopy(ASSET.systemPath, ".", FILENAME_MAX);
|
||||
|
||||
// PSP specific asset loading.
|
||||
#if PSP
|
||||
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
|
||||
|
||||
// PSP is given either the prx OR the PBP file.
|
||||
// In the format of "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or "host0:/Dusk.prx"
|
||||
// IF the file is the PBP file, we are loading directly on the PSP itself.
|
||||
// IF the file is the .prx then we are debugging and fopen will return
|
||||
// relative filepaths correctly, e.g. host0:/dusk.dsk will be on host.
|
||||
if(
|
||||
stringEndsWithCaseInsensitive(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
|
||||
char_t searchPath[FILENAME_MAX];
|
||||
const char_t **path = ASSET_SEARCH_PATHS;
|
||||
do {
|
||||
sprintf(
|
||||
searchPath,
|
||||
*path,
|
||||
ASSET.systemPath,
|
||||
ASSET_FILE
|
||||
);
|
||||
|
||||
// Try open
|
||||
ASSET.zip = zip_open(searchPath, ZIP_RDONLY, NULL);
|
||||
if(ASSET.zip == NULL) continue;
|
||||
break;// Found!
|
||||
} while(*(++path) != NULL);
|
||||
|
||||
// Did we open the asset?
|
||||
if(ASSET.zip == NULL) errorThrow("Failed to open asset file.");
|
||||
// assetInitPlatform must either define ASSET.zip or throw an error.
|
||||
errorChain(assetInitPlatform());
|
||||
assertNotNull(ASSET.zip, "Asset zip null without error.");
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -330,16 +136,14 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void assetDispose(void) {
|
||||
errorret_t assetDispose(void) {
|
||||
if(ASSET.zip != NULL) {
|
||||
zip_close(ASSET.zip);
|
||||
if(zip_close(ASSET.zip) != 0) {
|
||||
errorThrow("Failed to close asset zip archive.");
|
||||
}
|
||||
ASSET.zip = NULL;
|
||||
}
|
||||
|
||||
#if PSP
|
||||
if(ASSET.pbpFile != NULL) {
|
||||
fclose(ASSET.pbpFile);
|
||||
ASSET.pbpFile = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
errorChain(assetDisposePlatform());
|
||||
errorOk();
|
||||
}
|
||||
@@ -8,83 +8,24 @@
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include "assettype.h"
|
||||
#include "asset/assetplatform.h"
|
||||
|
||||
#if PSP
|
||||
#define ASSET_PBP_READ_PBP_FROM_HOST 0
|
||||
#define ASSET_PBP_SIGNATURE_SIZE 4
|
||||
#define ASSET_PBP_SIGNATURE "\0PBP"
|
||||
|
||||
typedef struct {
|
||||
char_t signature[ASSET_PBP_SIGNATURE_SIZE];
|
||||
uint32_t version;
|
||||
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;
|
||||
|
||||
#elif DOLPHIN
|
||||
#include <fat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char_t *ASSET_DOLPHIN_PATHS[] = {
|
||||
"/",
|
||||
"/Dusk",
|
||||
"/dusk",
|
||||
"/DUSK",
|
||||
"/apps",
|
||||
"/apps/Dusk",
|
||||
"/apps/dusk",
|
||||
"/apps/DUSK",
|
||||
".",
|
||||
"./",
|
||||
"./Dusk",
|
||||
"./dusk",
|
||||
"./DUSK",
|
||||
"./apps",
|
||||
"./apps/Dusk",
|
||||
"./apps/dusk",
|
||||
"./apps/DUSK",
|
||||
NULL
|
||||
};
|
||||
#ifndef assetInitPlatform
|
||||
#error "Platform must define assetInitPlatform function."
|
||||
#endif
|
||||
#ifndef assetDisposePlatform
|
||||
#error "Platform must define assetDisposePlatform function."
|
||||
#endif
|
||||
|
||||
#define ASSET_FILE "dusk.dsk"
|
||||
#define ASSET_FILE_NAME "dusk.dsk"
|
||||
#define ASSET_HEADER_SIZE 3
|
||||
|
||||
static const char_t *ASSET_SEARCH_PATHS[] = {
|
||||
"%s/%s",
|
||||
"%s",
|
||||
"../%s",
|
||||
"../../%s",
|
||||
"data/%s",
|
||||
"../data/%s",
|
||||
NULL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
zip_t *zip;
|
||||
char_t systemPath[FILENAME_MAX];
|
||||
uint8_t assetCount;
|
||||
|
||||
// PSP specific information.
|
||||
#if PSP
|
||||
FILE *pbpFile;
|
||||
assetpbp_t pbpHeader;
|
||||
#endif
|
||||
assetplatform_t platform;
|
||||
} asset_t;
|
||||
|
||||
static asset_t ASSET;
|
||||
extern asset_t ASSET;
|
||||
|
||||
/**
|
||||
* Initializes the asset system.
|
||||
@@ -110,5 +51,7 @@ errorret_t assetLoad(const char_t *filename, void *output);
|
||||
|
||||
/**
|
||||
* Disposes/cleans up the asset system.
|
||||
*
|
||||
* @return An error code if the asset system could not be disposed properly.
|
||||
*/
|
||||
void assetDispose(void);
|
||||
errorret_t assetDispose(void);
|
||||
@@ -77,6 +77,6 @@ errorret_t engineDispose(void) {
|
||||
localeManagerDispose();
|
||||
uiDispose();
|
||||
errorChain(displayDispose());
|
||||
assetDispose();
|
||||
errorChain(assetDispose());
|
||||
errorOk();
|
||||
}
|
||||
53
src/duskdolphin/asset/assetdolphin.c
Normal file
53
src/duskdolphin/asset/assetdolphin.c
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
// Init FAT driver.
|
||||
if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem.");
|
||||
|
||||
char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS;
|
||||
char_t foundPath[FILENAME_MAX];
|
||||
foundPath[0] = '\0';
|
||||
do {
|
||||
// Try open dir
|
||||
DIR *pdir = opendir(*dolphinSearchPath);
|
||||
if(pdir == NULL) continue;
|
||||
|
||||
|
||||
// Scan if file is present
|
||||
while(true) {
|
||||
struct dirent* pent = readdir(pdir);
|
||||
if(pent == NULL) break;
|
||||
|
||||
if(stringCompareInsensitive(pent->d_name, ASSET_FILE) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy out filename
|
||||
snprintf(
|
||||
foundPath,
|
||||
FILENAME_MAX,
|
||||
"%s/%s",
|
||||
*dolphinSearchPath,
|
||||
ASSET_FILE
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// Close dir.
|
||||
closedir(pdir);
|
||||
|
||||
// Did we find the file here?
|
||||
if(foundPath[0] != '\0') break;
|
||||
} while(*(++dolphinSearchPath) != NULL);
|
||||
|
||||
if(foundPath[0] != '\0') {
|
||||
}
|
||||
|
||||
// Did we find the asset file?
|
||||
if(foundPath[0] == '\0') {
|
||||
errorThrow("Failed to find asset file on FAT filesystem.");
|
||||
}
|
||||
|
||||
ASSET.zip = zip_open(foundPath, ZIP_RDONLY, NULL);
|
||||
if(ASSET.zip == NULL) {
|
||||
errorThrow("Failed to open asset file on FAT filesystem.");
|
||||
}
|
||||
errorOk();
|
||||
37
src/duskdolphin/asset/assetdolphin.h
Normal file
37
src/duskdolphin/asset/assetdolphin.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <fat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char_t *ASSET_DOLPHIN_PATHS[] = {
|
||||
"/",
|
||||
"/Dusk",
|
||||
"/dusk",
|
||||
"/DUSK",
|
||||
"/apps",
|
||||
"/apps/Dusk",
|
||||
"/apps/dusk",
|
||||
"/apps/DUSK",
|
||||
".",
|
||||
"./",
|
||||
"./Dusk",
|
||||
"./dusk",
|
||||
"./DUSK",
|
||||
"./apps",
|
||||
"./apps/Dusk",
|
||||
"./apps/dusk",
|
||||
"./apps/DUSK",
|
||||
NULL
|
||||
};
|
||||
@@ -10,4 +10,5 @@ target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(asset)
|
||||
add_subdirectory(debug)
|
||||
10
src/dusklinux/asset/CMakeLists.txt
Normal file
10
src/dusklinux/asset/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
assetlinux.c
|
||||
)
|
||||
81
src/dusklinux/asset/assetlinux.c
Normal file
81
src/dusklinux/asset/assetlinux.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "asset/asset.h"
|
||||
#include "engine/engine.h"
|
||||
#include "util/string.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
errorret_t assetInitLinux(void) {
|
||||
// Engine may have been provided the launch path
|
||||
if(ENGINE.argc > 0) {
|
||||
// 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.platform.systemPath, buffer, FILENAME_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
// Default system path, intended to be overridden by the platform
|
||||
stringCopy(ASSET.platform.systemPath, ".", FILENAME_MAX);
|
||||
|
||||
// Open zip file
|
||||
char_t searchPath[FILENAME_MAX];
|
||||
const char_t **path = ASSET_LINUX_SEARCH_PATHS;
|
||||
int32_t error;
|
||||
do {
|
||||
sprintf(
|
||||
searchPath,
|
||||
*path,
|
||||
ASSET.platform.systemPath,
|
||||
ASSET_FILE_NAME
|
||||
);
|
||||
|
||||
// Try open
|
||||
ASSET.zip = zip_open(searchPath, ZIP_RDONLY, &error);
|
||||
if(ASSET.zip == NULL) continue;
|
||||
if(error != 0) {
|
||||
printf("Warning: Opened asset file with non-zero error code: %d\n", error);
|
||||
ASSET.zip = NULL;
|
||||
continue;
|
||||
}
|
||||
break;// Found!
|
||||
} while(*(++path) != NULL);
|
||||
|
||||
// Did we open the asset?
|
||||
if(ASSET.zip == NULL) {
|
||||
errorThrow("Failed to open asset file.");
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetDisposeLinux(void) {
|
||||
errorOk();
|
||||
}
|
||||
37
src/dusklinux/asset/assetlinux.h
Normal file
37
src/dusklinux/asset/assetlinux.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
|
||||
static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
|
||||
"%s/%s",
|
||||
"%s",
|
||||
"../%s",
|
||||
"../../%s",
|
||||
"data/%s",
|
||||
"../data/%s",
|
||||
NULL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char_t systemPath[FILENAME_MAX];
|
||||
} assetlinux_t;
|
||||
|
||||
/**
|
||||
* Initializes the asset system on Linux.
|
||||
*
|
||||
* @return Error state if failed, otherwise returns success.
|
||||
*/
|
||||
errorret_t assetInitLinux(void);
|
||||
|
||||
/**
|
||||
* Disposes the asset system on Linux.
|
||||
*
|
||||
* @return Error state if failed, otherwise returns success.
|
||||
*/
|
||||
errorret_t assetDisposeLinux(void);
|
||||
13
src/dusklinux/asset/assetplatform.h
Normal file
13
src/dusklinux/asset/assetplatform.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/assetlinux.h"
|
||||
|
||||
typedef assetlinux_t assetplatform_t;
|
||||
#define assetInitPlatform assetInitLinux
|
||||
#define assetDisposePlatform assetDisposeLinux
|
||||
87
src/duskpsp/asset/assetpbp.c
Normal file
87
src/duskpsp/asset/assetpbp.c
Normal file
@@ -0,0 +1,87 @@
|
||||
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
|
||||
|
||||
// PSP is given either the prx OR the PBP file.
|
||||
// In the format of "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or "host0:/Dusk.prx"
|
||||
// IF the file is the PBP file, we are loading directly on the PSP itself.
|
||||
// IF the file is the .prx then we are debugging and fopen will return
|
||||
// relative filepaths correctly, e.g. host0:/dusk.dsk will be on host.
|
||||
if(
|
||||
stringEndsWithCaseInsensitive(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();
|
||||
}
|
||||
31
src/duskpsp/asset/assetpbp.h
Normal file
31
src/duskpsp/asset/assetpbp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#define ASSET_PBP_READ_PBP_FROM_HOST 0
|
||||
#define ASSET_PBP_SIGNATURE_SIZE 4
|
||||
#define ASSET_PBP_SIGNATURE "\0PBP"
|
||||
|
||||
typedef struct {
|
||||
char_t signature[ASSET_PBP_SIGNATURE_SIZE];
|
||||
uint32_t version;
|
||||
uint32_t sfoOffset;
|
||||
uint32_t icon0Offset;
|
||||
uint32_t icon1Offset;
|
||||
uint32_t pic0Offset;
|
||||
uint32_t pic1Offset;
|
||||
uint32_t snd0Offset;
|
||||
uint32_t pspOffset;
|
||||
uint32_t psarOffset;
|
||||
} assetpbpheader_t;
|
||||
|
||||
typedef struct {
|
||||
FILE *pbpFile;
|
||||
assetpbpheader_t pbpHeader;
|
||||
} assetpbp_t;
|
||||
@@ -48,10 +48,6 @@ errorret_t displaySDL2Init(void) {
|
||||
errorChain(errorGLCheck());
|
||||
|
||||
errorChain(displayOpenGLInit());
|
||||
|
||||
// #if DUSK_PSP
|
||||
// errorChain(displayPSPInit());
|
||||
// #endif
|
||||
|
||||
errorChain(errorGLCheck());
|
||||
errorOk();
|
||||
|
||||
Reference in New Issue
Block a user