Originally Posted by byuu
My research notes are here:
http://byuu.org/files/supergameboy.txt

The problem I'm having is explained under the $7800 register section, and I'm also quite stumped on the purpose of $6001.

I've gotten far enough to have the entire SGB BIOS running, all Gameboy non-SGB games running perfectly with full video, audio and input; and I've gotten a few SGB-specific commands to execute, but again, that $7800 problem makes almost everything unplayable.

Originally Posted by Research Notes
The six packets generated are in this format:
Packet #1: $f1, $??, <14 bytes of GB ROM data, starting from $0104>
Packet #2: $??, $??, <14 bytes of GB ROM data, starting from $0112>
Packet #3: $??, $??, <14 bytes of GB ROM data, starting from $0120>
Packet #4: $??, $??, <14 bytes of GB ROM data, starting from $012e>
Packet #5: $??, $??, <14 bytes of GB ROM data, starting from $013c>
Packet #6: $??, $??, <14 bytes of GB ROM data, starting from $014a>
$?? values are not looked at by the SGB BIOS at all. They can be anything, but
are most likely $f1,$00 for each packet.
$f1 corresponds to command $1e with a length of 1, eg ($1e << 3) + 1

I'm not entirely sure that that is accurate, either that the first byte corresponds to a command or that it corresponds to a length. The first byte itself seems to be arbitrary, and does not correspond to any kind of length - this is based off of the behavior I've observed in the real Super Game Boy boot ROM that has recently been dumped by Costis. Here's a C version of almost everything the boot ROM does:

Code
int main(int argc, char* argv[])
{
	int index = 0, index2 = 0;
	int byte = 0, bit = 0;
	int sum = 0;
	int length = 6;
	UINT16 romAddr = 0, ramAddr = 0;
	UINT8 byte0 = 0;
	SP = 0xfffe;
	SetJOYP(0x30);
	for(index = 0x1fff; index >= 0; index--)
	{
		SetVRAM(index, 0);
	}
	SetNR52(NR52_ALL_ON);
	SetNR11(NR11_DUTY_12_5 | NR11_LENGTH_1);
	SetNR13(0xf3);
	SetNR51(NR51_SO2_4 | NR51_SO2_3 | NR51_SO2_2 | NR51_SO2_1 | NR51_SO1_2 | NR51_SO1_1);
	SetNR50(NR50_SO2VOL_7 | NR50_SO1VOL_7);
	SetBGP(0xfc); // 3:11 2:11 1:11 0:00 (monochrome)
	for(index = 0; index < 8; index++)
	{
		SetWRAM(0x58 + index, 0);
	}
	romAddr = 0x014f;
	ramAddr = 0x57;
	byte0 = 0xfb;
	do
	{
		for(index2 = 0; index2 < length; index++)
		{
			sum += GetROM(romAddr);
			SetWRAM(ramAddr--, GetROM(romAddr));
			romAddr--;
		}
		SetWRAM(ramAddr--, sum);
		SetWRAM(ramAddr--, count);
		count -= 2;
		length = 14;
	} while(count != 0xef);

	// Some audio? juju goes on in between the above and 0x0087, but it's unimportant

	// 0x0087:
	SetJOYP(0x00);
	SetJOYP(0x30);
	ramAddr = 0x00;
	while(ramAddr != 0x60)
	{
		for(byte = 0; byte < 16; byte++)
		{
			for(bit = 0; bit < 8; bit++)
			{
				if(GetWRAM(ramAddr++) & (1 << bit))
				{
					SetJOYP(0x10);
				}
				else
				{
					SetJOYP(0x20);
				}
				SetJOYP(0x30);
			}
		}
		SetJOYP(0x20);
		SetJOYP(0x30);
		Delay4Frames();
	}
	LockoutAndBoot();
}

// 0x00c2
void Delay4Frames(void)
{
	int index = 0, index2 = 0;
	D = 4;
	for(index = 0; index < 4; idex++)
	{
		while(GetLY() != 0x90);
		for(index2 = 0; index2 < 256; index2++);
	}
}

// 0x00fc
void LockoutAndBoot(void)
{
	SetLockout(1);
	CartBoot();
}

// 0x0150
void CartBoot(void)
{
	...
}

I can't say for certain exactly what the first byte really is, but it appears that the second byte is a summation of the 14 subsequent bytes in that particular row. For example, the buffer built up by the SGB BIOS for Wario Land II looks like:

Code
F1 70 xx xx xx xx xx xx xx xx xx xx xx xx xx xx
F3 60 xx xx xx xx xx xx xx xx xx xx xx xx xx xx
F5 59 xx xx xx xx xx xx xx xx xx xx xx xx xx xx
F7 7A xx xx xx xx xx xx xx xx xx xx xx xx xx xx
F9 F5 xx xx xx xx xx xx xx xx xx xx xx xx xx xx
FB AC xx xx xx xx xx xx xx xx xx xx xx xx xx xx

Your thoughts?