My research notes are here:
http://byuu.org/files/supergameboy.txtThe 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.
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:
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:
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?