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.

C/C++ > Appending/including a binary file

#5485 - bakery2k - Tue Apr 29, 2003 5:25 pm

I have a relatively large binary file I would like to include in my ROM, so that the code can access it.

One option is to write a parser which will convert the file into a text file containing an array of u8 data, which can then be #included.

Is there a simpler way, for example somehow adding the binary data to the ROM at the compiling/linking stage?

#5487 - niltsair - Tue Apr 29, 2003 6:05 pm

I started a program where i need to do just that. Here's a solution...
Code:

#define END_OF_FILE          (0x08000000+ Size)
u8* pMyData;

pMyData = (u8*)END_OF_FILE;

....
... do stuff with pMyData
....

-Compile your program.
-Note the exact size of the rom
-Replace in the code 'size' with the exact size.
-Then just do this : copy yourRom.gba+yourRes.bin Rom.gba
-And voil?, Rom.gba contains both program and ressource.

This can be bothersome, since everytime change your program, the rom size will change accordingly. So, a workaround would be to pick a 'fixed size', say '400000'. And you create a small proggy that fills you rom with 0s untill you reach size '400000'. Then you append your datas.


If you have multiple ressources, you can do this (this is what i settled on) :
Basicly fill your rom with 0s 'till you reach a predefiend size(like earlier) then keep a certain amount of free space(depends on on many ressources you want to inludes) Let's refer to this area as Header.

After the Header, append all of your ressources, and for every one of them, write a pointer to it in the 'Header' area.

In your program, you only need to reads 32bits values starting at the predefined address (say 0x08000000 + 400000) which give you a pointer to the ressources. To get the next ressource, get the address to it at (0x08000000 + 400004), and so foth.

Hope i wasn't to vague :)

#5488 - tepples - Tue Apr 29, 2003 6:37 pm

niltsair wrote:
-Note the exact size of the rom

Not needed. Devkit Advance R5 beta 3 or later gives the exact size of the ROM in one of the header fields.

If you can't afford to wait for Devkit Advance R5 beta 3, you can pad the ROM size to (say) a 256 byte boundary, place a magic cookie at the start of your appended data, and search ROM space for the magic cookie. This is the approach of my GBFS.

Quote:
If you have multiple ressources, you can do this (this is what i settled on) :

What you describe is equivalent to making a primitive directory for the appended assets. GBFS does that too.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#5490 - niltsair - Tue Apr 29, 2003 6:59 pm

Yes, this is bascily what i do minus the 'magic number'. I developped the method as i was going. For now just saying that the Headers are at position X is suffcient for me. Less versatile though.

#5491 - lordmetroid - Tue Apr 29, 2003 7:07 pm

or you could use the tool which you can find on gbadev.org by anli bin2o which creates a variable with your prefered data for you... and then it's upto you how you want to define that variable and where you want to put it.
_________________
*Spam*
Open Solutions for an open mind, www.areta.org

Areta is an organization of coders codeing mostly open source project, but there is alot of sections like GBA dev, Language learning communities, RPG communities, etc...

#5499 - Paul Shirley - Tue Apr 29, 2003 8:48 pm

removed

Last edited by Paul Shirley on Sun Mar 28, 2004 9:59 pm; edited 1 time in total

#5897 - Jason Wilkins - Mon May 12, 2003 3:31 pm

You get a strange warning if you use that command line. To prevent it use this instead:

Code:

objcopy -I binary -O elf32-arm -B arm data.bin data.o


DevKit Advance R5 has a defines a few variable which contain information about appended assets. I'll write up an explanation right here, and later, post it to the DevKit web site. Please note that I do not have my laptop with me, so I may get some variable names wrong in this post.

In DevKit Advance R5, there are several variables which can be used to find the beginning and end of assets appended to the program image.

Code:

// This variable is in a well known location in the header
// and points to the __load_*_appended_ptr variables.
// Can be used by external programs to modify those variables.
// This is not very useful at runtime.
extern char *__crt0_footer_ptr;

// These variables are used at runtime to find appended assets,
/  appended end is not always useful, use this instead:
//  __appended_start + (__load_break_appended_ptr - __load_start_appended_ptr);
extern char __appended_start[];
extern char __appended_end[];

// These variables are stored at the end of a virgin program image.
extern char *__load_start_appended_ptr;
extern char *__load_break_appended_ptr; // end of assets in image
extern char *__load_limit_appended_ptr; // maximum assets


When you append something to the ROM, the variable __load_break_appended_ptr will become incorrect.
I intend to write a tool which will correct the value for you, but until Beta 4, i'll tell you how that tool will be written.

The variable __crt0_footer_ptr is located at file offset E0 on a typical rom. If the address starts with 0x02, substract 0x02000000 from it and use fseek, otherwise, subtracted 0x08000000 from it.

The first value at *__crt_footer_ptr is __load_break_appended_ptr. This value needs to be adjusted to the new end of image. It will either be 0x02000000 + filesize or 0x08000000 + filesize depending on if __crt0_footer_ptr started with 0x02 or 0x08.

A good program will make sure that the new __load_break_appended_ptr is not greater than __load_limit_appended_ptr. It is located at the footer offset + 8 in the file. Keep in mind that by default, this value equals __load_start_appended_ptr, so a program will have to adjust it to be the desired maximum size first.

The last value, __load_start_appended_ptr points to the first address of the appended data in the image. This value is here so the the footer can be expanded in the future, because it points past the last address of the footer. This value is located at the footer file offset + 4.

All these values are stored little endian, and they will all be file offsets + 0x02000000 or 0x08000000, depending on if the image is multiboot or a cartridge ROM.

You do not access assets at runtime using the __load_*_appended variables. These values are file offsets, and may not match the runtime address of the appended assets. The correct variable to use is __appended_start. The variable __appended_end points to the end of assets included by using the .appended section. This section is for debugging purposes (it allows you to have appended assets in a .elf file), so it will not equal the actual end of assets appended using an external program.

To find the end of appended assets are runtime, use __appended_start + (__load_break_appended_ptr - __load_break_start_ptr)

As mentioned before, it is possible to simulate appending assets by carefully placing variables in the .appended section. The resulting program image will have correct footer variables and appended assets just as if it had been done later. This is useful for creating mockups of appended data and then using a debugger to test the code which accesses them. Otherwise it would be difficult to test appended asset code because assets can only be appended to a binary and binaries contain no debug information.

I hope this is clear. I hope to write this up a little better soon, and provide example code, and a program which can, at a minimum, correct the footer after appending variables using cat.exe. This is just an example of how such a program would work!

EDIT: I modified the cat command line to keep the original binary.

Code:

$ assfix -v --set-limit=256k game0.mb
limit was 0x020080FC, is now 0x02040000
$ cat game0.mb assets.bin > game.mb
$ assfix -v game.mb
188kb new assets appended.
old break was 0x020080FC
new break is 0x02037400
limit is 0x02040000
35.8kb remain.
$


Of course, the program will have a more tactful name than that ^_^
_________________
http://devkitadv.sourceforge.net

#5929 - Quirky - Tue May 13, 2003 8:06 am

Jason Wilkins wrote:
You get a strange warning if you use that command line. To prevent it use this instead:

Code:

objcopy -I binary -O elf32-arm -B arm data.bin data.o



The version of objcopy in Devkit R5 (GNU objcopy 2.11.2) doesn't support the -B option.


Quote:
> objcopy -I binary -O elf32-arm -B arm gfx.raw gfx.all.rodata.o

/cygdrive/d/devkitadv/bin/objcopy: invalid option -- B
Usage: /cygdrive/d/devkitadv/bin/objcopy <switches> in-file [out-file]
The switches are:
-I --input-target <bfdname> Assume input file is in format <bfdname>
-O --output-target <bfdname> Create an output file in format <bfdname>
-F --target <bfdname> Set both input and output format to <bfdname>

--debugging Convert debugging information, if possible
-p --preserve-dates Copy modified/access timestamps to the output

-j --only-section <name> Only copy section <name> into the output
-R --remove-section <name> Remove section <name> from the output
-S --strip-all Remove all symbol and relocation information
-g --strip-debug Remove all debugging symbols
--strip-unneeded Remove all symbols not needed by relocations
-N --strip-symbol <name> Do not copy symbol <name>
-K --keep-symbol <name> Only copy symbol <name>
-L --localize-symbol <name> Force symbol <name> to be marked as a local
-G --keep-global-symbol <name> Localize all symbols except <name>
-W --weaken-symbol <name> Force symbol <name> to be marked as a weak
--weaken Force all global symbols to be marked as weak

-x --discard-all Remove all non-global symbols
-X --discard-locals Remove any compiler-generated symbols
-i --interleave <number> Only copy one out of every <number> bytes
-b --byte <num> Select byte <num> in every interleaved block
--gap-fill <val> Fill gaps between sections with <val>
--pad-to <addr> Pad the last section up to address <addr>
--set-start <addr> Set the start address to <addr>
{--change-start|--adjust-start} <incr>
Add <incr> to the start address
{--change-addresses|--adjust-vma} <incr>
Add <incr> to LMA, VMA and start addresses
{--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>
Change LMA and VMA of section <name> by <val>

--change-section-lma <name>{=|+|-}<val>
Change the LMA of section <name> by <val>
--change-section-vma <name>{=|+|-}<val>
Change the VMA of section <name> by <val>
{--[no-]change-warnings|--[no-]adjust-warnings}
Warn if a named section does not exist
--set-section-flags <name>=<flags>
Set section <name>'s properties to <flags>
--add-section <name>=<file> Add section <name> found in <file> to output
--change-leading-char Force output format's leading character style

--remove-leading-char Remove leading character from global symbols
--redefine-sym <old>=<new> Redefine symbol name <old> to <new>
--srec-len <number> Restrict the length of generated Srecords
--srec-forceS3 Restrict the type of generated Srecords to S3

--strip-symbols <file> -N for all symbols listed in <file>
--keep-symbols <file> -K for all symbols listed in <file>
--localize-symbols <file> -L for all symbols listed in <file>
--keep-global-symbols <file> -G for all symbols listed in <file>
--weaken-symbols <file> -W for all symbols listed in <file>
-v --verbose List all object files modified
-V --version Display this program's version number
-h --help Display this output
/cygdrive/d/dev/devkitadv/bin/objcopy: supported targets: elf32-littlearm elf32-
bigarm elf32-little elf32-big coff-arm-little coff-arm-big a.out-arm-little a.ou
t-arm-big srec symbolsrec tekhex binary ihex