3 methods if you count the homebrew ones and want to advance beyond includes in the binary.
1) DS filesystem stuff. The
DS cart protocol is annoying but doable (the popular hacking tool ndstool is actually part of devkitpro). I would not suggest it for homebrew for various reasons including it is likely to be read only unless you can otherwise argue against it.
2) GBA RAM. 32 megs from 08000000 to 09FFFFFF in memory is available. Used also in the case of ram expansions. Some older flash carts (these days most notably the EZ4) will load into RAM first before launching which troubles some things like tetris grand masters which ended up in the 50 megs range though this is technically part of 1).
3) DLDI and related methods. Here files are fetched from the SD card as per normal SD reading procedure (
http://chishm.drunkencoders.com/DLDI/ ). Related methods include the older nos_gba_fat I think it was and possibly pafs (part of the now deprecated PAlib) though I am not sure what that actually really was and you do not want to be using it anyway (issues with support). If you are so inclined you can stick an image of the would be fat filesystem that contains all your and attach it to the resulting DS file (it is called FCSR if you decide to go searching). Additionally later DLDI patches and the better supported carts got access to an additional feature called ARGV (more in the form of a workaround for those that lack it
http://devkitpro.org/wiki/Homebrew_Menu ).
All three can interplay in various things (aside from DS roms which only do 1) save for the browser which has RAM support). Commercial DS games additionally use overlays (small binary fragments compiled for given addresses and loaded in whenever necessary) and I have even seen games use them almost exclusively rather than more conventional files.
If it was not already clear unless poor obfuscation is your aim the DS filesystem and such like are vastly inferior methods to DLDI.