diff --git a/cube/patches/base/dolphin/dvd.h b/cube/patches/base/dolphin/dvd.h index 78cd8caa..3d7f8139 100644 --- a/cube/patches/base/dolphin/dvd.h +++ b/cube/patches/base/dolphin/dvd.h @@ -34,7 +34,26 @@ struct DVDDiskID { u8 gameVersion; u8 streaming; u8 streamingBufSize; - u8 padding[22]; + u8 padding[18]; + u32 magic; }; +typedef struct DVDDriveInfo { + u16 revisionLevel; + u16 deviceCode; + u32 releaseDate; + u8 padding[24]; +} DVDDriveInfo; + +typedef struct DVDBB2 { + u32 bootFilePosition; + u32 FSTPosition; + u32 FSTLength; + u32 FSTMaxLength; + void *FSTAddress; + u32 userPosition; + u32 userLength; + u32 padding; +} DVDBB2; + #endif /* DVD_H */ diff --git a/cube/patches/stub/asmfunc.S b/cube/patches/stub/asmfunc.S index 24684a62..8b830ee9 100644 --- a/cube/patches/stub/asmfunc.S +++ b/cube/patches/stub/asmfunc.S @@ -65,44 +65,77 @@ xmit_spi: srwi r3, r0, 24 blr + .globl dvd_inquiry +dvd_inquiry: + lis r6, 0x1200 + li r5, 0 + li r4, 32 + b dvd_readdma + .globl dvd_read dvd_read: + lis r6, 0xA800 + +dvd_readdma: addi r4, r4, 31 rlwinm r3, r3, 0, 6, 26 rlwinm. r4, r4, 0, 6, 26 srwi r5, r5, 2 beq 3f - li r6, 0 - srwi r7, r4, 5 - mtctr r7 -1: dcbi r6, r3 - addi r6, r6, 32 + li r7, 0 + srwi r8, r4, 5 + mtctr r8 +1: dcbi r7, r3 + addi r7, r7, 32 bdnz 1b - lis r6, 0x0C00 - li r7, 0x6000 + 7*4 - eciwx r0, r7, r6 + lis r7, 0x0C00 + li r8, 0x6000 + 7*4 + eciwx r0, r8, r7 andi. r0, r0, 0b001 bne 3f - li r7, 0x6000 + 2*4 - lis r0, 0xA800 - ecowx r0, r7, r6 - li r7, 0x6000 + 3*4 - ecowx r5, r7, r6 - li r7, 0x6000 + 4*4 - ecowx r4, r7, r6 - li r7, 0x6000 + 5*4 - ecowx r3, r7, r6 - li r7, 0x6000 + 6*4 - ecowx r4, r7, r6 - li r7, 0x6000 + 7*4 + li r8, 0x6000 + 2*4 + ecowx r6, r8, r7 + li r8, 0x6000 + 3*4 + ecowx r5, r8, r7 + li r8, 0x6000 + 4*4 + ecowx r4, r8, r7 + li r8, 0x6000 + 5*4 + ecowx r3, r8, r7 + li r9, 0x6000 + 6*4 + ecowx r4, r9, r7 + li r9, 0x6000 + 7*4 li r0, 0b011 - ecowx r0, r7, r6 -2: eciwx r0, r7, r6 + ecowx r0, r9, r7 +2: eciwx r0, r9, r7 andi. r0, r0, 0b001 bne 2b - li r7, 0x6000 + 5*4 - eciwx r0, r7, r6 + eciwx r0, r8, r7 subf r3, r3, r0 blr 3: li r3, 0 blr + + .globl flippy_reset +flippy_reset: + lis r3, 0x0C00 + li r4, 0x6000 + 1*4 + li r0, 0b100 + ecowx r0, r4, r3 + li r5, 0x6000 + 2*4 + lis r0, 0xB500 + ori r0, r0, 0x0005 + ecowx r0, r5, r3 + li r5, 0x6000 + 3*4 + lis r0, 0xAA55 + ori r0, r0, 0xF641 + ecowx r0, r5, r3 + li r5, 0x6000 + 7*4 + li r0, 0b001 + ecowx r0, r5, r3 +1: eciwx r0, r5, r3 + andi. r0, r0, 0b001 + bne 1b +2: eciwx r0, r4, r3 + andi. r0, r0, 0b100 + beq 2b + blr diff --git a/cube/patches/stub/main.c b/cube/patches/stub/main.c index 4f92185b..e3fba1da 100644 --- a/cube/patches/stub/main.c +++ b/cube/patches/stub/main.c @@ -21,6 +21,7 @@ #include #include #include "dolphin/dolformat.h" +#include "dolphin/dvd.h" #include "dolphin/exi.h" #include "dolphin/os.h" #include "eltorito.h" @@ -50,7 +51,9 @@ static bool memeq(const void *a, const void *b, size_t size) return true; } +uint32_t dvd_inquiry(DVDDriveInfo *info); uint32_t dvd_read(void *address, uint32_t length, uint32_t offset); +void flippy_reset(void); static void dvd_load(uint32_t offset) { @@ -68,13 +71,13 @@ static void dvd_load(uint32_t offset) for (int i = 0; i < DOL_MAX_TEXT; i++) { if (dvd_read(image.text[i], image.textLen[i], - offset + image.textData[i]) != image.textLen[i]) return; + offset + image.textData[i]) < image.textLen[i]) return; ICInvalidateRange(image.text[i], image.textLen[i]); } for (int i = 0; i < DOL_MAX_DATA; i++) { if (dvd_read(image.data[i], image.dataLen[i], - offset + image.dataData[i]) != image.dataLen[i]) return; + offset + image.dataData[i]) < image.dataLen[i]) return; } run(image.entry); @@ -82,6 +85,21 @@ static void dvd_load(uint32_t offset) void dvd_main(void) { + DVDDriveInfo info __attribute((aligned(32))); + if (!dvd_inquiry(&info)) return; + + switch (info.releaseDate) { + case 0x20220426: + flippy_reset(); + case 0x20220420: + { + DVDBB2 BB2 __attribute((aligned(32))); + if (dvd_read(&BB2, sizeof(BB2), 0x420) != sizeof(BB2)) return; + if (BB2.bootFilePosition) dvd_load(BB2.bootFilePosition); + break; + } + } + uint32_t offset = 17 * DI_SECTOR_SIZE; struct di_boot_record boot_record __attribute((aligned(32)));