If you get that, that is 10: SLEEP; 20: GOTO 10 stuff then most likely you've got some hardware registers wrong. There are several that keep magic values like HW revision - DC BIOS (except DEV maybe) will refuse to boot if it doesn't like what it sees. I can't go through MESS sources right now (but maybe during weekend?) so check if you have:
/** System bus revision number (R). */
#define HOLLY_SB_SBREV 0x005F689C
/** G2 bus version (R). */
#define HOLLY_SB_G2ID 0x005F7880
/** Device ID (R). */
#define HOLLY_ID 0x005F8000
/** Revision number (R). */
#define HOLLY_REVISION 0x005F8004
HOLLY_REJ (HOLLY_SB_SBREV) = 0x0000000b;
HOLLY_REJ (HOLLY_SB_G2ID) = 0x00000012;
HOLLY_REJ (HOLLY_ID) = 0x17fd11db;
HOLLY_REJ (HOLLY_REVISION) = 0x00000011;
All of these are read-only and if memory serves me right BIOS will (on purpose?) try to write to one of those - so make sure you don't let that happen. Those just say "Hello I'm HOLLY chip, rev. 2.42" - that's Dreamcast and newest DEV boxes.
This is not immediately required but since we are here, set:
/** System mode (R). */
#define HOLLY_SB_G1SYSM 0x005F74B0
HOLLY_REJ (HOLLY_SB_G1SYSM) = 0x00002000; // USA
HOLLY_REJ (HOLLY_SB_G1SYSM) = 0x00000800; // JP
HOLLY_REJ (HOLLY_SB_G1SYSM) = 0x00006000; // EU
Read-only as well, this is being latched from external HOLLY pins during power-on reset. Just pick one to match BIOS if you don't want game booting troubles in future.
/** TA FIFO remaining amount (R). */
#define HOLLY_SB_TFREM 0x005F6880
HOLLY_REJ (HOLLY_SB_TFREM) = 0x00000008;
Make it R/O and forget it exists as no code ever bothers to check that anyway - and it still works...
Now for connected video-cable - oh, this is fun. Part of the code below is kinda redundant as BIOS will read one (?) place and write the rest, but I can't quite remember the correct order so get all 3 places covered to be sure:
/** Sync pulse generator control. */
#define HOLLY_SPG_CONTROL 0x005F80D0
HOLLY_REJ (HOLLY_SPG_CONTROL) |= (g_kabel << 6); // video-cable code
Use 0 for VGA, 2 for RGB EURO/SCART, 3 for composite/UHF modulator (some docs say 1 is valid too, can't remember for what now).
// This is AICA-visible address space! Add 0x00700000 on SH4 side
#define AICA_AV_CTRL 0x00002c00
AICA_REJ (AICA_AV_CTRL) = (g_kabel << 8) | 0x0001; // same code as above
You'll also (and this I think is the most important place to get it right) need to set it up so that SH4 direct I/O ports will read the same video-cable code. Now this is... tricky. You can try to emulate the I/O and internal pullups and stuff or make a hack. Your choice.
Port A is 16-bits wide and BIOS expects to see ((g_kabel << 8) | 0x0003). Now the tricky part is the lowest 2 bits are some sort of cable connector being plugged detection (or something) and need to behave. BIOS will zero each bit then read back the port register - and expect both of them to be down. In other words, setting 3 - reads out as 3. Setting 1 or 2 (or 0 of course) reads out as zero. This took me day or so, here's my code for reading back (quick translation):
uint32_t w = 0;
(...)
// PDTRA:16
case 12:
// pull-ups not exactly supported
for (int i = 0; i < 16; i++)
{
// in/out bit (every 2nd bit)
if (SH4.PCTRA & (1 << (i << 1)))
w |= SH4.PDTRA & (1 << i);
else
w |= SH4.portA & (1 << i);
}
#ifdef SH4_DREAMCAST
if ((w & 0x0003) != 0x0003)
w &= ~0x0003;
#endif
break;
(...)
return w;
"SH4.portA" is a variable that pretends being Port A input. This is the thing I set with ((g_kabel << 8) | 0x0003).
That reminds me - there's a register SH4 has that is not covered in the manual (actually it seems there are more of those, but that's not important now). It's "Cache and TLB controller" region, register 12 (0xff000030). Add it, make it always return 0x00000080 and BIOS will skip some weird code trying to setup watchdog and some other stuff a retail console is not supposed to have. WEIRD. I strongly suggest you do this if BIOS gives you trouble.
More importantly BSC.RFCR _has_ to be either incremented per read or set to some big enough value (I increment it by 0x20). This is SDRAM refresh counter. Checked only during POST as far as I can tell. This is a must though.
This should get you past POST, though you might experience 10s or so delay if GD-ROM isn't detected (in our case - emulated). I think ARM might be broken but AICA timers must advance - and you will see the logo animation. Assuming you have TA+PVR2 covered, as BIOS uses 3D only (and heavily) and relies on the order-independant transparency much. Hopefully next thing to stop you will be time/date setup screen, which is "almost there" phase.