gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Multiboot ROM format?

#16433 - Will - Mon Feb 16, 2004 6:58 am

I've just written (ported) a multi-boot loader to a microcontroller and can load a demo program that I include as hex in a header file, but I can't seem to compile multiboot code to send in the same manner. My loader code is heavily based on

http://ajo.thinknerd.com/gba/software.html and seems to work OK.

My test program is from the MultiplayerV1.zip in the "demo_data". Here it is below:

Code:

const unsigned char LineProg[] =
{
 0x2e,0x00,0x00,0xea,0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,
 0x84,0xe4,0x09,0xad,0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,
 0x93,0x09,0xce,0x20,0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,
 0x82,0xe3,0xce,0xbf,0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,
 0x13,0x72,0xa7,0xfc,0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,
 0xfc,0x03,0x98,0x76,0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,
 0x40,0xa7,0x0e,0xfd,0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,
 0x60,0xd6,0x80,0x25,0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,
 0xbb,0x3e,0x03,0x44,0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,
 0x87,0xf0,0x3c,0xaf,0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x30,0x31,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,

 0x12,0x00,0xa0,0xe3,0x00,0xf0,0x29,0xe1,0x70,0xd0,0x9f,0xe5,0x1f,0x00,0xa0,0xe3,
 0x00,0xf0,0x29,0xe1,0x60,0xd0,0x9f,0xe5,0x00,0x00,0x81,0xe5,0x4c,0x00,0x9f,0xe5,
 0x4c,0x10,0x9f,0xe5,0xb0,0x00,0xc1,0xe1,0x00,0x00,0xa0,0xe3,0x44,0x10,0x9f,0xe5,
 0xb0,0x00,0xc1,0xe1,0x06,0x14,0xa0,0xe3,0x96,0x2c,0xa0,0xe3,0x00,0x00,0xa0,0xe3,
 0xb2,0x00,0xc1,0xe0,0x01,0x20,0x52,0xe2,0xfc,0xff,0xff,0x1a,0x06,0x14,0xa0,0xe3,
 0x02,0x09,0xa0,0xe3,0x01,0x00,0x40,0xe2,0xa0,0x20,0xa0,0xe3,0x02,0x00,0x81,0xe4,
 0x1e,0x1e,0x81,0xe2,0x01,0x20,0x52,0xe2,0xfb,0xff,0xff,0x1a,0xfe,0xff,0xff,0xea,
 0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x7f,0x00,0x03,
 0xa0,0x7f,0x00,0x03,0x30,0x00,0x2d,0xe9,0x1e,0x4e,0xa0,0xe3,0x94,0x01,0x05,0xe0
};


This program draws a diagonal line on a blank screen. This works, and I can successfully boot the GB from my micro-controller and the program runs OK. (Yeah, I'm pretty please about that).

However, if I try and compile a multi-boot program from source (HamDevKit's Hello World demo), fix the header using either 'gbafix' or 'gbarm', then convert using bin2c (or bin2h, b2x etc), the file will load fine with a good CRC at the end, but the screen goes white when it tries to boot. I've verified this ROM is ok when multibooted by multi-booting it from one Gameboy to another using modified Multiplayer demo code.

Here's the hex code of the troublesome Hello World program:

Code:

const unsigned char HelloWorld[] =
{
 0x2e,0x00,0x00,0xea,0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,
 0x84,0xe4,0x09,0xad,0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,
 0x93,0x09,0xce,0x20,0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,
 0x82,0xe3,0xce,0xbf,0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,
 0x13,0x72,0xa7,0xfc,0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,
 0xfc,0x03,0x98,0x76,0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,
 0x40,0xa7,0x0e,0xfd,0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,
 0x60,0xd6,0x80,0x25,0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,
 0xbb,0x3e,0x03,0x44,0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,
 0x87,0xf0,0x3c,0xaf,0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x30,0x31,0x96,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,

 0x06,0x00,0x00,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x12,0x00,0xa0,0xe3,0x00,0xf0,0x29,0xe1,0xc4,0xd0,0x9f,0xe5,0x1f,0x00,0xa0,0xe3,
 0x00,0xf0,0x29,0xe1,0xbc,0xd0,0x9f,0xe5,0x01,0x00,0x8f,0xe2,0x10,0xff,0x2f,0xe1,
 0x2e,0x49,0x2f,0x48,0x08,0x60,0x2f,0x48,0x40,0x01,0x0a,0xd2,0x78,0x46,0x40,0x01,
 0x0c,0xd3,0x40,0x23,0x1b,0x03,0xda,0x01,0x16,0x1c,0x91,0x00,0x00,0xf0,0x40,0xf8,
 0x30,0x47,0x40,0x21,0x09,0x03,0xc8,0x01,0x00,0xf0,0x30,0xf8,0x03,0x20,0x00,0x06,
 0x25,0x49,0x00,0xf0,0x2b,0xf8,0x25,0x48,0x25,0x49,0x09,0x1a,0x00,0xf0,0x26,0xf8,
 0x24,0x49,0x25,0x4a,0x25,0x4c,0x00,0xf0,0x2a,0xf8,0x25,0x49,0x25,0x4a,0x26,0x4c,
 0x00,0xf0,0x25,0xf8,0x25,0x4a,0x26,0x49,0x53,0x1a,0x02,0xd0,0x25,0x4a,0x00,0xf0,
 0x1f,0xf8,0x25,0x49,0x25,0x4a,0x26,0x4c,0x00,0xf0,0x19,0xf8,0x25,0x4a,0x26,0x49,
 0x53,0x1a,0x02,0xd0,0x25,0x4a,0x00,0xf0,0x13,0xf8,0x00,0x20,0x00,0x21,0x24,0x4b,

... etc....


Any ideas why my HelloWorld program won't run? Its definately compiled as a multiboot program, and verfied by running it an emulator and checking the PC register.

Can anyone point me in the right direction on decoding the first few bytes of ROM and how the bootup works? I've tried to disassemble by hand, but gathering all the information is quite tricky. I know that the there is typically an unconditional jump at the start, but I'm not sure of the opcode and instruction formats.

I've tried playing with the header using 'gbarm', but that seems to make little difference.

#16440 - tepples - Mon Feb 16, 2004 4:15 pm

In your program, you have to include the following in exactly one source code file in order to get it to multiboot:
Code:
int __gba_multiboot;

You can test whether a ROM is multiboot compatible by renaming it to end in .mb and then running it in VisualBoyAdvance. If a ROM's name ends in .mb, VBA will try running it as a multiboot program, loading it into EWRAM and mapping nothing into ROM.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#16446 - dagamer34 - Mon Feb 16, 2004 7:08 pm

Oh yeah, I recently had the exact same problem when trying to fix the SGADE code to link with a multiboot ROM, and its not the ROM that is the problem but the code used to send it.

Before you start linking, wait for a VBlank to occur. I think it allows the sending of the ROM to finish properly. Amazing, isn't it?

This should fix your problem.
_________________
Little kids and Playstation 2's don't mix. :(

#16452 - Will - Mon Feb 16, 2004 10:18 pm

Tepples, I've already set that variable and tested it under both an emulator and by sending it from one gameboy multibooting it into another with a link cable. Please excuse any incorrect terminology I may be using as I haven't been immersed in the gameboy dev scene for very long. It does look very much like the symptom of trying to send a non-multiboot ROM.

Dagamer34, I'm not sure I understand? I'm sending from a micro-controller development board connected to a GB with no ROM cartridge. i.e. I'm building something similar to a smart multiboot cable. Are you referring to the VBlank on the sender or the receiver? If its the sender, then there is no VBlank as its not a GB. The loader looks like it goes to completion in both cases however.

If its the receiver, then I'm not sure how to wait for VBlank as its not running any code?

Thanks both for your input - any ideas or suggestions are most welcome as I'm out of ideas myself.

#16458 - Will - Tue Feb 17, 2004 3:11 am

I got it to work.

Not sure what the exact reason is, but if I compile code using HamDevKits release library (Ver 2.8), it loads fully and works. If I use the Debug or freeware library, it doesn't. DevKitAdv compiled code also doesn't seem to work with my current setup, although I'm sure it could be made to work.

When I load the debug/freeware lib versions, it loads about 1.4k of 66k, passes the CRC check then crashes when it goes to run the program. On the release lib version, it loads the full 48.3k, CRC check pass, then boots and runs the program.

I did a 'diff' of the two hex files and the differences show up much later in the ROM, around address 0x1d8.

I might link this post from the HAM forums to see if any HAM experts can tell me what differences might cause this. Its a bit academic now, but would be good to know.

#16459 - tepples - Tue Feb 17, 2004 3:25 am

It looks like your Hello World example is much longer. Try sending longer and longer binaries until you find the breaking point.

Then try slowing down the send.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#16460 - Will - Tue Feb 17, 2004 4:02 am

Doesn't seem to be length as different programs, long(95k) and short(15k) always bomb out at the same spot consistently, and now I've got a release lib compiled ROM to bomb out... so I'm back to square 1.

Looks like there might be something in the content that's making my loader bomb out, even though the CRC check passes which makes it look like all is OK.

I'm off to add some more debug code.

#16461 - Will - Tue Feb 17, 2004 4:53 am

Thanks Tepples, you were spot on with the length. I'm guility of looking for a complex problem when it was actually much simpler.

My code has a sizeof(array) reference in it, and I just checked the return type of size_t to be "unsigned int" which is 16 bits in length on the micro-controller platform I'm using, not 32!!!! Hence all code larger than 64k in length would have overflowed, resulting in the code being truncated. The CRC checks out becuase the send routine thinks the correct number of bytes has been sent and calculated the checksum based on the truncated length.