Dolphin Bootable ISO working!
This commit is contained in:
@@ -9,49 +9,86 @@
|
||||
#include "asset/asset.h"
|
||||
#include "util/string.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/endian.h"
|
||||
|
||||
#define ISO_SECTOR_SIZE 2048u
|
||||
#define ISO_PVD_SECTOR 16u
|
||||
|
||||
errorret_t assetInitDolphinDVD(void) {
|
||||
DVD_Init();
|
||||
DVD_Mount();
|
||||
|
||||
// Read disc header to find FST location
|
||||
u8 *hdr = (u8 *)assetDolphinDVDRead(0, 0x440);
|
||||
if(!hdr) errorThrow("Failed to read DVD disc header.");
|
||||
u32 fstOff = assetDolphinDVDReadBigEndian32(hdr + 0x424);
|
||||
u32 fstSize = assetDolphinDVDReadBigEndian32(hdr + 0x428);
|
||||
memoryFree(hdr);
|
||||
// ISO 9660 Primary Volume Descriptor is at sector 16.
|
||||
u8 *pvd = (u8 *)assetDolphinDVDRead(
|
||||
(s64)ISO_PVD_SECTOR * ISO_SECTOR_SIZE, ISO_SECTOR_SIZE
|
||||
);
|
||||
if(!pvd) errorThrow("Failed to read ISO 9660 PVD.");
|
||||
|
||||
// Read the FST
|
||||
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 = assetDolphinDVDReadBigEndian32(fst + 8);
|
||||
u8 *strTable = fst + numEntries * 12u;
|
||||
|
||||
u32 fileOff = 0, fileLen = 0;
|
||||
for(u32 i = 1; i < numEntries; i++) {
|
||||
u8 *e = fst + i * 12u;
|
||||
if(e[0] != 0) continue;
|
||||
|
||||
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 = assetDolphinDVDReadBigEndian32(e + 4);
|
||||
fileLen = assetDolphinDVDReadBigEndian32(e + 8);
|
||||
break;
|
||||
}
|
||||
// Sanity-check: type=1, identifier="CD001"
|
||||
if(pvd[0] != 1 || pvd[1] != 'C' || pvd[2] != 'D' ||
|
||||
pvd[3] != '0' || pvd[4] != '0' || pvd[5] != '1') {
|
||||
memoryFree(pvd);
|
||||
errorThrow("Not a valid ISO 9660 disc.");
|
||||
}
|
||||
memoryFree(fst);
|
||||
|
||||
if(!fileOff) errorThrow("Failed to find asset file on DVD.");
|
||||
// Root Directory Record starts at PVD+156.
|
||||
// ISO 9660 stores multi-byte fields in both byte orders; use the BE copies
|
||||
// (offset +6 for LBA, +14 for size) since the GameCube is big-endian.
|
||||
u32 rootLBA = assetDolphinDVDReadBigEndian32(pvd + 156 + 6);
|
||||
u32 rootSize = assetDolphinDVDReadBigEndian32(pvd + 156 + 14);
|
||||
memoryFree(pvd);
|
||||
|
||||
u8 *data = (u8 *)assetDolphinDVDRead((s64)fileOff, fileLen);
|
||||
if(!data) errorThrow("Failed to read asset file from DVD.");
|
||||
u8 *dir = (u8 *)assetDolphinDVDRead(
|
||||
(s64)rootLBA * ISO_SECTOR_SIZE, rootSize
|
||||
);
|
||||
if(!dir) errorThrow("Failed to read ISO 9660 root directory.");
|
||||
|
||||
// Scan directory records for dusk.dsk.
|
||||
// ISO 9660 level-1 names are uppercase with a ";1" version suffix, e.g.
|
||||
// "DUSK.DSK;1". We strip the suffix before comparing case-insensitively.
|
||||
u32 fileLBA = 0, fileSize = 0;
|
||||
u32 pos = 0;
|
||||
while(pos < rootSize) {
|
||||
u8 recLen = dir[pos];
|
||||
if(recLen == 0) {
|
||||
// Sector padding — skip to the start of the next sector.
|
||||
pos = (pos + (ISO_SECTOR_SIZE - 1u)) & ~(ISO_SECTOR_SIZE - 1u);
|
||||
continue;
|
||||
}
|
||||
|
||||
u8 flags = dir[pos + 25];
|
||||
u8 nameLen = dir[pos + 32];
|
||||
|
||||
if(!(flags & 0x02) && nameLen > 1) { // skip directories and "." / ".."
|
||||
const char_t *isoName = (const char_t *)(dir + pos + 33);
|
||||
|
||||
// Build a null-terminated copy of the base name (strip ";N" version).
|
||||
char_t baseName[32];
|
||||
u8 baseLen = 0;
|
||||
while(baseLen < nameLen && isoName[baseLen] != ';' && baseLen < 31) {
|
||||
baseName[baseLen] = isoName[baseLen];
|
||||
baseLen++;
|
||||
}
|
||||
baseName[baseLen] = '\0';
|
||||
|
||||
if(stringCompareInsensitive(baseName, ASSET_FILE_NAME) == 0) {
|
||||
fileLBA = assetDolphinDVDReadBigEndian32(dir + pos + 6);
|
||||
fileSize = assetDolphinDVDReadBigEndian32(dir + pos + 14);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos += recLen;
|
||||
}
|
||||
memoryFree(dir);
|
||||
|
||||
if(!fileLBA) errorThrow("Failed to find asset file on ISO.");
|
||||
|
||||
u8 *data = (u8 *)assetDolphinDVDRead(
|
||||
(s64)fileLBA * ISO_SECTOR_SIZE, fileSize
|
||||
);
|
||||
if(!data) errorThrow("Failed to read asset file from ISO.");
|
||||
|
||||
zip_error_t zerr;
|
||||
zip_source_t *src = zip_source_buffer_create(data, fileLen, 1, &zerr);
|
||||
zip_source_t *src = zip_source_buffer_create(data, fileSize, 1, &zerr);
|
||||
if(!src) {
|
||||
memoryFree(data);
|
||||
errorThrow("Failed to create zip source from DVD buffer.");
|
||||
|
||||
Reference in New Issue
Block a user