http://gbatemp.net/index.php?showtopic=39979&hl= has some on the boot procedure of the GBA although that is not quite what is happening here for the endgame although you will still need to know it for this.
You would then have to watch what happens as you select a game- I imagine it would just involve clearing the memory and jumping to the game of your choosing. What you then get to do is find a suitable point after the initialisation of the menu (you could wait until you got to the menu if you liked but I would look for earlier myself) and then replicate the launch or jump to the launch routine.
I did however just try it- reset might be one thing but pressing back on the menu eventually brings me right back to the press start screen (prior even to the selection box) at least for the second game which might complicate things in as much as it might not like it if you hacked the menu in some way but cross that bridge when you come to it although I suppose normal use will not come to that.
At the same time I had a very cursory scan of the memory to see if something changed when I hovered over a different selection but if it was there I missed it and equally I am not inclined to blindly speculate on how the devs might have done for this.
Still how I would have done it/what I have seen and speculation based on it
Initialise rom as per usual
Launch into menu code
[press start] (not what I would have done but it is there)
Secondary selection menu- idle here (scrolling text and audio in this case)
On key press of up or down move to the corresponding menu (it looks like it holds rather than scrolling back around as well) (this means some OAM stuff and other boring things but should mean a value somewhere else is changed (I doubt they would have hooked into the OAM)- you probably want to find this although you might be able to get away with it.
On key press of A or possibly start (I did not check this) check currently selected value (presumably against the mystery value I mentioned above) and jump (branch) to either load routine or the game itself. The fact I could go back possibly throws a wrench in proceedings (or at least my reset and load hypothesis) or it might just be that it is true example of what C code is usually about (a whole series of routines branching at will).
Tools for the job
VBA-SDL-h or another high end debugger ( Boycot Advance or NO$GBA debug version being the main two other than this). You could do this straight in a disassembly but why make things difficult.
http://www.romhacking.net/docs/361/ is a nice guide and the docs of VBA-sdl-h
http://labmaster.bios.net.nz/vba-sdl-h/
I imagine this will boil down to but one or two instructions in a destructive capacity (overwriting existing code) which I would consider encoding by hand (
http://nocash.emubase.de/gbatek.htm#thumbinstructionsummary has encodings for THUMB and ARM elsewhere on the page). Still an assembler will be nice if your disassembly tool does not hold up.
Splitting roms- if it is how I imagine it the rom is something like the following
rom
Header as per usual GBA roms
Micro menu
Full GBA rom A) (or near enough)
Full GBA rom B) (or near enough)
Usual padding to "power of 2" Mbit size.
There might have been shared data but I doubt the devs would have bothered as it would not have made much difference to the size. Looking at what I found out above if they have interleaved it (kicked all audio for both games into one block or something) I would give up as it it too much hassle beyond maybe shaving a few extra kilobytes off is the secondary game's data is at the end of the rom.
Assuming it is not interleaved you should then be able to blank out and ultimately trim the secondary rom whatever it ends up being without too much trouble. You could blank the first as well but it would be kind of pointless unless you programmed your expansion pack loader to skip 00's and jump to anther section or something.
The reason you can not just shift the secondary rom forwards is because a lot of things point to a certain place in the rom itself (which as mentioned is viewable entirely in memory) rather than the memory (thinking systems where the code loads entirely into memory) or kicking it to a read command/list loaded at the start of the game like the DS and most other file system based things (the exception here being things like some PS2 games with LBA reads rather than normal file system stuff ostensibly as a small measure of protection).
There are three addresses for the GBA rom and while you probably could do an automated change of most of them and maybe even DMA transfers you also get to deal with compression (easy enough) or obfuscation (not so easy but still workable) as well as hoping the devs did not do something like generate an address with a command the results of which are not obvious unless you run the game (see the halting problem or maybe some of the stuff done in cheats where values are held on a stack or located by pointers as it is a similar logic).
Basically you are up against the GBA memory layout (a feature hackers but love and have immense frustration caused by)- it makes it nice to hack in as much as you are rarely more than two steps (usually just one) from a location in the rom for the data you want but at the same time almost guarantees you get to fiddle with pointers with formats that are either bare metal type formats or wound tight into the GBA rom.