DVD support broken on Gamecube

Post Reply
Hornpipe2
Posts: 1
Joined: Mon Mar 12, 2012 4:00 pm

DVD support broken on Gamecube

Post by Hornpipe2 » Mon Mar 12, 2012 4:07 pm

FCEUGX and SNES9XGX are currently broken on Gamecube (and have been since they were at version 4.1.1) - both hang at the "Loading DVD" screen.

The maintainer of these projects, dborth, has marked these issues as "won't fix" claiming it is an upstream problem with libogc:
http://code.google.com/p/snes9x-gx/issues/detail?id=601
http://code.google.com/p/snes9x-gx/issues/detail?id=659

Since they've been outstanding issues for years now, I'm going to finally tackle the bugs and make the emulators functional again, so I can get my GC back out of storage. Consider this thread a WIP discussion about the bug.

First, a segment of code from SNES9XGX where the problem manifests:

Code: Select all

/****************************************************************************
 * MountDVD()
 *
 * Tests if a ISO9660 DVD is inserted and available, and mounts it
 ***************************************************************************/
bool MountDVD(bool silent)
{
	bool mounted = false;
	int retry = 1;

	if(unmountRequired[DEVICE_DVD])
	{
		unmountRequired[DEVICE_DVD] = false;
		ISO9660_Unmount("dvd:");
	}

	while(retry)
	{
		ShowAction("Loading DVD...");

		if(!dvd->isInserted())
		{
			if(silent)
				break;

			retry = ErrorPromptRetry("No disc inserted!");
		}
		else if(!ISO9660_Mount("dvd", dvd))
		{
			if(silent)
				break;

			retry = ErrorPromptRetry("Unrecognized DVD format.");
		}
		else
		{
			mounted = true;
			break;
		}
	}
	CancelAction();
	isMounted[DEVICE_DVD] = mounted;
	return mounted;
}

ccfreak2k
Posts: 14
Joined: Sat Mar 06, 2010 1:11 pm

Re: DVD support broken on Gamecube

Post by ccfreak2k » Thu Mar 15, 2012 3:21 pm

In all likelihood, the reason for this being an issue for so long is probably because no one bothered to use it after the change (the change being the revamped I/O), and probably not prior to it either. Even I just used an SD Gecko to access files; a disc offered no benefits.

Nevertheless, I'd start my search at the revision that this revamped I/O code appeared.

Tantric
Posts: 6
Joined: Wed May 20, 2009 10:37 pm

Re: DVD support broken on Gamecube

Post by Tantric » Thu Mar 15, 2012 4:10 pm

The DVD handling code in Snes9x GX here - http://code.google.com/p/snes9x-gx/sour ... gc/dvd.cpp

Was removed, and replaced by calls to the existing libogc GC DVD code here - http://devkitpro.svn.sourceforge.net/vi ... threv=4146

It's not a matter of going through the Snes9x GX and making changes there - it's a matter of going into libogc and figuring out why that code isn't working for you.

Your other option of course is to use 4.1.1 or older, which have the old code.

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: DVD support broken on Gamecube

Post by Eke » Wed Jan 22, 2014 11:28 am

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) ?

Post Reply

Who is online

Users browsing this forum: No registered users and 19 guests