Sorry to bump that old post but I have recently trying to figure out why DVD support was broken on gamecube and I think I found out the reason(s).
1) There is a restriction in the DVD interface that the DMA buffer start address must be 32-byte aligned.
This is now normally handled by the libiso9660 interface but I think is done incorrectly:
Indeed, in libiso9660.c, we have this
Code: Select all
typedef struct iso9660mount_s
{
const DISC_INTERFACE *disc_interface;
u8 read_buffer[BUFFER_SIZE] __attribute__((aligned(32)));
u8 cluster_buffer[BUFFER_SIZE] __attribute__((aligned(32)));
u32 cache_start;
u32 cache_sectors;
bool iso_unicode;
PATH_ENTRY *iso_rootentry;
PATH_ENTRY *iso_currententry;
char volume_id[32];
} MOUNT_DESCR;
which is
dynamically allocated here :
Code: Select all
static MOUNT_DESCR *_ISO9660_mdescr_constructor(const DISC_INTERFACE *disc_interface)
{
MOUNT_DESCR *mdescr = NULL;
mdescr = malloc(sizeof(MOUNT_DESCR));
Unless I am mistaken , this does NOT garantee "read_buffer" (which is later directly passed to DVD interface as destination buffer for DMA transfer) to be 32-byte aligned.
A quick fix would be to declare the structure as:
Code: Select all
typedef struct iso9660mount_s
{
u8 read_buffer[BUFFER_SIZE];
u8 cluster_buffer[BUFFER_SIZE];
const DISC_INTERFACE *disc_interface;
u32 cache_start;
u32 cache_sectors;
bool iso_unicode;
PATH_ENTRY *iso_rootentry;
PATH_ENTRY *iso_currententry;
char volume_id[32];
} MOUNT_DESCR;
then allocate it using:
Code: Select all
MOUNT_DESCR *mdescr = memalign(sizeof(MOUNT_DESCR), 32);
2) in dvd.c, dvdio_IsInserted() seems a little bit too restrictive
Code: Select all
static bool dvdio_IsInserted()
{
u32 status = 0;
DVD_LowGetStatus(&status, NULL);
if(DVD_STATUS(status) == DVD_STATUS_READY)
return true;
return false;
}
The thing is that this function is called in libiso9660 during the mount, before even attempting to spinup the drive.
I don't think DVD_STATUS_READY will be returned unless the disk is already spinning so it's probably better to always return "true" there or only return "false" when the status returned by the drive is "DVD_STATUS_COVER_OPENED" or "DVD_STATUS_NO_DISK" ?
3) in dvd.c, dvdio_Startup() attempts to distinguish between a real Gamecube DVD drive or a Wii DVD Drive accessed in Gamecube compatibility mode.
Code: Select all
static bool dvdio_Startup()
{
DVD_Init();
if (mfpvr() == 0x00083214) // GameCube
{
DVD_Mount();
}
else
{
DVD_Reset(DVD_RESETHARD);
DVD_ReadDiskID(&__dvd_block$15, &__dvd_tmpid0, callback);
}
return true;
}
It seems that the hard-coded return value of mfpvr() depends on the Gamecube hardware revision so is not entirely reliable to distinguish between a Gamecube and a Wii. There might be more reliable way known today, I don't know but it seems safer to always call DVD_Mount here since I don't see who would want to use homebrew in Gamecube compatibility mode on a Wii (apart from backup loaders, which unlikely would use libiso9660 anyway) ?