// dvxResource.c -- DVX resource runtime API // // Reads the resource block appended to DXE3 files. The resource // block is located by reading the footer at the end of the file. #include "dvxRes.h" #include "../tools/dvxResWrite.h" #include #include #include DvxResHandleT *dvxResOpen(const char *path) { if (!path) { return NULL; } FILE *f = fopen(path, "rb"); if (!f) { return NULL; } // Read footer from end of file if (fseek(f, -(int32_t)sizeof(DvxResFooterT), SEEK_END) != 0) { fclose(f); return NULL; } DvxResFooterT footer; if (fread(&footer, sizeof(footer), 1, f) != 1) { fclose(f); return NULL; } if (footer.magic != DVX_RES_MAGIC || footer.entryCount == 0) { fclose(f); return NULL; } // Read directory if (fseek(f, footer.dirOffset, SEEK_SET) != 0) { fclose(f); return NULL; } DvxResDirEntryT *entries = (DvxResDirEntryT *)malloc(footer.entryCount * sizeof(DvxResDirEntryT)); if (!entries) { fclose(f); return NULL; } if (fread(entries, sizeof(DvxResDirEntryT), footer.entryCount, f) != footer.entryCount) { free(entries); fclose(f); return NULL; } fclose(f); DvxResHandleT *h = (DvxResHandleT *)malloc(sizeof(DvxResHandleT)); if (!h) { free(entries); return NULL; } strncpy(h->path, path, sizeof(h->path) - 1); h->path[sizeof(h->path) - 1] = '\0'; h->entries = entries; h->entryCount = footer.entryCount; return h; } const DvxResDirEntryT *dvxResFind(DvxResHandleT *h, const char *name) { if (!h || !name) { return NULL; } for (uint32_t i = 0; i < h->entryCount; i++) { if (strcmp(h->entries[i].name, name) == 0) { return &h->entries[i]; } } return NULL; } void *dvxResRead(DvxResHandleT *h, const char *name, uint32_t *outSize) { const DvxResDirEntryT *entry = dvxResFind(h, name); if (!entry) { return NULL; } FILE *f = fopen(h->path, "rb"); if (!f) { return NULL; } if (fseek(f, entry->offset, SEEK_SET) != 0) { fclose(f); return NULL; } void *buf = malloc(entry->size); if (!buf) { fclose(f); return NULL; } if (fread(buf, 1, entry->size, f) != entry->size) { free(buf); fclose(f); return NULL; } fclose(f); if (outSize) { *outSize = entry->size; } return buf; } void dvxResClose(DvxResHandleT *h) { if (h) { free(h->entries); free(h); } } int32_t dvxResAppend(const char *path, const char *name, uint32_t type, const void *data, uint32_t dataSize) { return dvxResAppendEntry(path, name, type, data, dataSize); }