diff --git a/src/dusk/util/memory.c b/src/dusk/util/memory.c index e6e90fa0..bc112f57 100644 --- a/src/dusk/util/memory.c +++ b/src/dusk/util/memory.c @@ -21,6 +21,15 @@ void * memoryAllocate(const size_t size) { return ptr; } +void * memoryAlign(size_t alignment, size_t size) { + assertTrue(alignment > 0, "Alignment must be greater than 0."); + assertTrue(size > 0, "Cannot allocate 0 bytes of memory."); + void *ptr = memalign(alignment, size); + assertNotNull(ptr, "Aligned memory allocation failed."); + MEMORY_POINTERS_IN_USE++; + return ptr; +} + void memoryFree(void *ptr) { assertNotNull(ptr, "Cannot free NULL memory."); free(ptr); diff --git a/src/dusk/util/memory.h b/src/dusk/util/memory.h index 0bf38a9d..12b1dd31 100644 --- a/src/dusk/util/memory.h +++ b/src/dusk/util/memory.h @@ -25,6 +25,15 @@ size_t memoryGetAllocatedCount(void); */ void * memoryAllocate(const size_t size); +/** + * Allocates aligned memory. + * + * @param alignment The alignment of the memory to allocate. + * @param size The size of the memory to allocate. + * @return The allocated memory. + */ +void * memoryAlign(size_t alignment, size_t size); + /** * Frees memory. * diff --git a/src/duskdolphin/asset/assetdolphindvd.c b/src/duskdolphin/asset/assetdolphindvd.c index ff5c3bff..86414cb4 100644 --- a/src/duskdolphin/asset/assetdolphindvd.c +++ b/src/duskdolphin/asset/assetdolphindvd.c @@ -8,48 +8,26 @@ #include "assetdolphindvd.h" #include "asset/asset.h" #include "util/string.h" -#include -#include -#include +#include "util/memory.h" +#include "util/endian.h" -#define DUSK_DVD_ALIGN 32u -#define DUSK_DVD_ALIGN_UP(n) \ - (((u32)(n) + DUSK_DVD_ALIGN - 1u) & ~(DUSK_DVD_ALIGN - 1u)) - -static u32 dvdBe32(const u8 *p) { - return ((u32)p[0] << 24) | ((u32)p[1] << 16) | ((u32)p[2] << 8) | (u32)p[3]; -} - -static void *dvdRead(s64 offset, u32 size) { - u32 padded = DUSK_DVD_ALIGN_UP(size); - void *buf = memalign(DUSK_DVD_ALIGN, padded); - if(!buf) return NULL; - DCInvalidateRange(buf, padded); - dvdcmdblk block; - if(DVD_ReadPrio(&block, buf, padded, offset, 0) <= 0) { - free(buf); - return NULL; - } - return buf; -} - -errorret_t assetInitDolphin(void) { +errorret_t assetInitDolphinDVD(void) { DVD_Init(); DVD_Mount(); // Read disc header to find FST location - u8 *hdr = (u8 *)dvdRead(0, 0x440); + u8 *hdr = (u8 *)assetDolphinDVDRead(0, 0x440); if(!hdr) errorThrow("Failed to read DVD disc header."); - u32 fstOff = dvdBe32(hdr + 0x424); - u32 fstSize = dvdBe32(hdr + 0x428); + u32 fstOff = assetDolphinDVDReadBigEndian32(hdr + 0x424); + u32 fstSize = assetDolphinDVDReadBigEndian32(hdr + 0x428); free(hdr); // Read the FST - u8 *fst = (u8 *)dvdRead((s64)fstOff, fstSize); + u8 *fst = (u8 *)assetDolphinDVDRead((s64)fstOff, fstSize); if(!fst) errorThrow("Failed to read DVD FST."); // Root entry (index 0) bytes 8-11 = total entry count - u32 numEntries = dvdBe32(fst + 8); + u32 numEntries = assetDolphinDVDReadBigEndian32(fst + 8); u8 *strTable = fst + numEntries * 12u; u32 fileOff = 0, fileLen = 0; @@ -60,22 +38,22 @@ errorret_t assetInitDolphin(void) { u32 nameOff = ((u32)e[1] << 16) | ((u32)e[2] << 8) | (u32)e[3]; const char_t *name = (const char_t *)(strTable + nameOff); if(stringCompareInsensitive(name, ASSET_FILE_NAME) == 0) { - fileOff = dvdBe32(e + 4); - fileLen = dvdBe32(e + 8); + fileOff = assetDolphinDVDReadBigEndian32(e + 4); + fileLen = assetDolphinDVDReadBigEndian32(e + 8); break; } } - free(fst); + memoryFree(fst); if(!fileOff) errorThrow("Failed to find asset file on DVD."); - u8 *data = (u8 *)dvdRead((s64)fileOff, fileLen); + u8 *data = (u8 *)assetDolphinDVDRead((s64)fileOff, fileLen); if(!data) errorThrow("Failed to read asset file from DVD."); zip_error_t zerr; zip_source_t *src = zip_source_buffer_create(data, fileLen, 1, &zerr); if(!src) { - free(data); + memoryFree(data); errorThrow("Failed to create zip source from DVD buffer."); } @@ -88,6 +66,23 @@ errorret_t assetInitDolphin(void) { errorOk(); } -errorret_t assetDisposeDolphin(void) { +void *assetDolphinDVDRead(const s64 offset, const u32 size) { + u32 padded = ASSET_DOLPHIN_DVD_ALIGN_UP(size); + void *buf = memoryAlign(ASSET_DOLPHIN_DVD_ALIGN, padded); + if(!buf) return NULL; + DCInvalidateRange(buf, padded); + dvdcmdblk block; + if(DVD_ReadPrio(&block, buf, padded, offset, 0) <= 0) { + memoryFree(buf); + return NULL; + } + return buf; +} + +u32 assetDolphinDVDReadBigEndian32(const u8 *p) { + return ((u32)p[0] << 24) | ((u32)p[1] << 16) | ((u32)p[2] << 8) | (u32)p[3]; +} + +errorret_t assetDisposeDolphinDVD(void) { errorOk(); } diff --git a/src/duskdolphin/asset/assetdolphindvd.h b/src/duskdolphin/asset/assetdolphindvd.h index 75b0fbaa..883a290b 100644 --- a/src/duskdolphin/asset/assetdolphindvd.h +++ b/src/duskdolphin/asset/assetdolphindvd.h @@ -7,10 +7,61 @@ #pragma once #include "error/error.h" +#include +#include + +/** Alignment for Dolphin DVD asset reads. */ +#define ASSET_DOLPHIN_DVD_ALIGN 32u + +/** + * Gets the next multiple of ASSET_DOLPHIN_DVD_ALIGN greater than or equal to n. + * This is used to ensure that DVD reads are properly aligned and padded. + * + * @param n The number to align. + * @return The aligned number. + */ +#define ASSET_DOLPHIN_DVD_ALIGN_UP(n) \ + (((u32)(n) + ASSET_DOLPHIN_DVD_ALIGN - 1u) & ~(ASSET_DOLPHIN_DVD_ALIGN - 1u)) typedef struct { uint8_t nothing; -} assetdolphin_t; +} assetdolphindvd_t; -errorret_t assetInitDolphin(void); -errorret_t assetDisposeDolphin(void); +/** + * Initializes the Dolphin DVD asset system. + * + * This will; + * - Initialize the DVD subsystem and mount the disc. + * - Read the disc header to find the FST location. + * - Read the FST and find the offset and length of the "data" file. + * - Store the offset and length for later use when loading assets. + * + * @return An errorret_t indicating success or failure. + */ +errorret_t assetInitDolphinDVD(void); + +/** + * Reads a block of data from the DVD at the specified offset and size. + * The returned buffer is aligned to 32 bytes and padded. The caller is + * responsible for freeing the buffer. + * + * @param offset The offset on the DVD to read from. + * @param size The number of bytes to read. + * @return A pointer to the buffer, or NULL on failure. + */ +void * assetDolphinDVDRead(const s64 offset, const u32 size); + +/** + * Reads a big-endian 32-bit integer from the given data. + * + * @param data The data to read from. + * @return The big-endian 32-bit integer as a host-endian uint32_t. + */ +u32 assetDolphinDVDReadBigEndian32(const u8 *data); + +/** + * Disposes of the Dolphin DVD asset system. + * + * @return An errorret_t indicating success or failure. + */ +errorret_t assetDisposeDolphinDVD(void); \ No newline at end of file diff --git a/src/duskdolphin/asset/assetdolphinfat.c b/src/duskdolphin/asset/assetdolphinfat.c index 5d64172c..38bcfdba 100644 --- a/src/duskdolphin/asset/assetdolphinfat.c +++ b/src/duskdolphin/asset/assetdolphinfat.c @@ -17,7 +17,7 @@ #include #include -errorret_t assetInitDolphin(void) { +errorret_t assetInitDolphinFAT(void) { if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem."); char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS; @@ -55,6 +55,6 @@ errorret_t assetInitDolphin(void) { errorOk(); } -errorret_t assetDisposeDolphin(void) { +errorret_t assetDisposeDolphinFAT(void) { errorOk(); } diff --git a/src/duskdolphin/asset/assetdolphinfat.h b/src/duskdolphin/asset/assetdolphinfat.h index 6b418b47..77543729 100644 --- a/src/duskdolphin/asset/assetdolphinfat.h +++ b/src/duskdolphin/asset/assetdolphinfat.h @@ -31,7 +31,24 @@ static const char_t *ASSET_DOLPHIN_PATHS[] = { typedef struct { uint8_t nothing; -} assetdolphin_t; +} assetdolphinfat_t; -errorret_t assetInitDolphin(void); -errorret_t assetDisposeDolphin(void); +/** + * Initializes the Dolphin FAT asset system. + * + * FAT being the general term for the FAT filesystem, on Wii this would likely + * be the SD Card, on Gamecube it can be something like the SD Gecko or the + * Slot2 SD Card. + * + * As far as I know this doesn't (currently) work on the CUBEODE? + * + * @return An errorret_t indicating success or failure. + */ +errorret_t assetInitDolphinFAT(void); + +/** + * Disposes of the Dolphin FAT asset system. + * + * @return An errorret_t indicating success or failure. + */ +errorret_t assetDisposeDolphinFAT(void); \ No newline at end of file diff --git a/src/duskdolphin/asset/assetplatform.h b/src/duskdolphin/asset/assetplatform.h index d728ebc9..5ef73420 100644 --- a/src/duskdolphin/asset/assetplatform.h +++ b/src/duskdolphin/asset/assetplatform.h @@ -9,11 +9,13 @@ #ifdef DUSK_DOLPHIN_BUILD_ISO #include "assetdolphindvd.h" + #define assetInitPlatform assetInitDolphinDVD + #define assetDisposePlatform assetDisposeDolphinDVD + typedef assetdolphindvd_t assetplatform_t; #else #include "assetdolphinfat.h" + #define assetInitPlatform assetInitDolphinFAT + #define assetDisposePlatform assetDisposeDolphinFAT + typedef assetdolphinfat_t assetplatform_t; #endif -#define assetInitPlatform assetInitDolphin -#define assetDisposePlatform assetDisposeDolphin - -typedef assetdolphin_t assetplatform_t;