GP2X Gp2x Executable Format


Hmm, maybe you want three different transparent colors, one for each icon :)
 
Inopia posted on Oct 13 2005 at 07:31 PM said:
Hmm, maybe you want three different transparent colors, one for each icon :)
Oh shut up! ;)
 
Last edited by a moderator:
No really. And we should have a short and long description (one for the list and one for the detailed description). Or maybe we should have icons stored as a mipmap, so we can zoom smoothly. Or EPS perhaps? And it would be fun to include sounds as well, so we can play them when the user moves the cursor over a certain file.
 
OK, so now I want to add some more... a flag that says "ARM940 code present". If this flag is set, then there will be addresses and sizes for code, data, and bss for the 940 as well. The "Address of start of code section" for the 940 will need to be on a 24-bit (16MB) boundary, because the 940 code must be based at zero in its banked memory space. If this is done, the most significant byte of the 940's "Address of start of code section" will also be the value to be placed in the 940BANK special function register.

The value of 940BANK in the GP2X can only be 0 - 3 because of the 64MB RAM limit... so instead of having "Address of start of code section" for the 940, it could just be 2 bits in the flags byte.

Anyone got any ideas about a "standard" way of partitioning the RAM space? I guess we could put the 940's code at 0x01000000 and then start the heap just above that, so there will "only" be up to 16MB wasted.

Another possibility is to make the 940 code base anything above 0x02000000, and a "Start_940_Running" SDK function could poke 0x02000000 with a jump to the real start of the 940's code. I'd like to put the 940's code at 60MB or something... that gives 4MB for it to play with which should be more than enough.

I was wondering about another flag in the header that says "Start the 940 running before jumping to the 920's entry point"... so the loader would start both cores. Doesn't really seem worthwhile to me, as starting the 940 is a trivial operation.

Finally, I was wondering about having a field in the header for speed settings... like, CPU 200MHz, RAM 100MHz, peripherals 50MHz etc. The loader could set the speeds before entering the application. Again, it's not a big job to set it up so I don't really think it's worthwhile.

I'm doing an elf2g2x tool, and I'll also write up this format properly if we ever feel that it's complete :)
 
It might be an idea to consider other GP2X models to have more RAM, gamepark have told me they will likely up the RAM next year sometime and also the NAND as prices fall.

Although I doubt they would go above 128M Ram, NAND wise they have said they plan a 1gig model, although that should fit into things with no problem.

Of course this will only happen if the GP2X is a success, but it might be an idea to consider the possibility.

-Craig
 
Err... WTF???

Why would you make a console with more RAM and Flash? The vital thing about consoles is that they have the same hardware so that all games run on all consoles! Creating a situation where some games only run on the newer hardware would be absolutely daft.

If the odd geek wants to modify the hardware then that's up to them ;) but the manufacturer?!?!

As for the Flash, are they going to provide some sort of Linux file system driver to access the spare Flash? I'd say that routinely writing to the device that contains your operating system would cause lots of bricked GP2X's which *may* end up in extra sales but would more likely just end up with dead GP2X's gathering dust.

GPH is a very strange company...
 
Robster posted on Oct 23 2005 at 05:13 AM said:
OK at so now I want to add some more... a flag that says "ARM940 code present". If this flag is set, then there will be addresses and sizes for code, data, and bss for the 940 as well. The "Address of start of code section" for the 940 will need to be on a 24-bit (16MB) boundary, because the 940 code must be based at zero in its banked memory space. If this is done, the most significant byte of the 940's "Address of start of code section" will also be the value to be placed in the 940BANK special function register.

The value of 940BANK in the GP2X can only be 0 - 3 because of the 64MB RAM limit... so instead of having "Address of start of code section" for the 940, it could just be 2 bits in the flags byte.
Aren't there still bits left in the FLAGS byte? I recall so.
Anyone got any ideas about a "standard" way of partitioning the RAM space? I guess we could put the 940's code at 0x01000000 and then start the heap just above that, so there will "only" be up to 16MB wasted.
Only 16MB wasted... :blink:
Another possibility is to make the 940 code base anything above 0x02000000, and a "Start_940_Running" SDK function could poke 0x02000000 with a jump to the real start of the 940's code. I'd like to put the 940's code at 60MB or something... that gives 4MB for it to play with which should be more than enough.

I was wondering about another flag in the header that says "Start the 940 running before jumping to the 920's entry point"... so the loader would start both cores. Doesn't really seem worthwhile to me, as starting the 940 is a trivial operation.
I would rather have 920t code to start 940t.. instead if crt0/loader.
Finally, I was wondering about having a field in the header for speed settings... like, CPU 200MHz, RAM 100MHz, peripherals 50MHz etc. The loader could set the speeds before entering the application. Again, it's not a big job to set it up so I don't really think it's worthwhile.
IMHO does not belong to a header.
I'm doing an elf2g2x tool, and I'll also write up this format properly if we ever feel that it's complete :)
Integrating arm-elf-objcopy ? heh.
 
Last edited by a moderator:
personally, I quite like my current solution of the exe contains the 940 code inside itself and it just dumps it in memory and starts up the 940 itself.

hmmm, instead of being 940 specific, why not just have a generic "load this data to this location in physical ram" ? Would be much more flexible.

What I'm thinking is that - what happens if we want to change the code running on the 940 whilst the main app runs? The loader can't possibly support this.

so, in all, I think it's best to just let the main app startup the 940, BUT... Have the loader always place the 940 into reset before actually loading the app.
 
Actually.. I'd prefer having the 940 being handled mostly by linkerscript & then managed with some e.g. crt0 provided routines. Something like this:

Code:
  int CODE_IN_940 foo( int bar ) { ... }

  char DATA_IN940 blaat[] = "mr.spiv takes over..";

And let the linker do the trick with sections and then having a crt0 to copy
the code/data. No need for anything fancy in the header. This is how e.g.
GBA guys do their IWRAM stuff.

And the placement of the 940 code/data is then defined in the linkerscript.
If someone wants to change it he/she modifies the linkerscript. And no
changes to crt0 or the OXE header.

Wouldn't this be ok?
 
Erm, I don't quite understand what you're saying.

About the linker script and magic incantations in function declarations: well, these need to resolve to hard addresses at some stage. We've (perhaps unfortunately) already defined the start of the 920 executable as 0x00008000, and the 940 necessarily starts at 0x00000000, so if we leave the addresses as they are any 940 code + data that's bigger than 32k will cause a collision.

Personally, I prefer having a separate linker script for the 940, which bases the code at 0, then have separate link steps in the program makefile. This will result in 2 ELF files. I'm quite happy for my elf2g2x prog to take in 2 ELF files, and stick them into the same final object.

As for dealing with repositioning the 940 code in crt0 or whatever, well the loader is currently loading the g2x file into RAM, repositioning the 920 code and data etc, so I think it makes sense for the loader to do the same for the 940 code. This also removes the need for every dual-core application to carry the code to do this. The size and position of 940 code, data and bss will be in the g2x file somewhere anyway (whether as entries in a header, constant data in the code or whatever) so it might as well just go in the header.

Could you give more detailed examples of what you're suggesting?
 
Hmmmm, If the arm940 code is loaded and placed into memory by the loader, doesn't that mean that the memory will not actually be allocated? How are we going to make sure that a malloc sometime in the future is not going to return memory at some same address where the arm940 code has been located?

Are we going to have the same situation as linux - only allowing memory allocations within the first 32mb to ensure this? If this is the case, then I think I would prefer linker scripts per application.
 
Squidge posted on Oct 24 2005 at 07:26 AM said:
Hmmmm, If the arm940 code is loaded and placed into memory by the loader, doesn't that mean that the memory will not actually be allocated? How are we going to make sure that a malloc sometime in the future is not going to return memory at some same address where the arm940 code has been located?

Are we going to have the same situation as linux - only allowing memory allocations within the first 32mb to ensure this? If this is the case, then I think I would prefer linker scripts per application.

I didn't say the loader would load the code but the crt0. Slight difference. After linking etc the crt0 (or some dedicated static lib) has knowledge where the data & code for the 940 is. It is rather trivial to copy that to correct places then. And the start address of the 940 program with this method has the same benefits/problems as others proposed so far.
 
Last edited by a moderator:
Robster posted on Oct 24 2005 at 05:24 AM said:
Erm, I don't quite understand what you're saying.

About the linker script and magic incantations in function declarations: well, these need to resolve to hard addresses at some stage. We've (perhaps unfortunately) already defined the start of the 920 executable as 0x00008000, and the 940 necessarily starts at 0x00000000, so if we leave the addresses as they are any 940 code + data that's bigger than 32k will cause a collision.
Well now I don't quite get you.. ld & linkerscripts are able to compile codes belonging to separate address spaces into one binary. That's what I after. Just like GBA guys do it.. their normal code runs in cart rom address space and IWRAM tagged funtions run iwram address space. On start crt0 does the thing of placing the code where needed.
Why not taking this for gp2x also... and that can be even controlled, if someone wants, during normal 920 execution to reload new code/data into 940.
Personally, I prefer having a separate linker script for the 940, which bases the code at 0, then have separate link steps in the program makefile. This will result in 2 ELF files. I'm quite happy for my elf2g2x prog to take in 2 ELF files, and stick them into the same final object.
Have a look at devkitARM GBA linkerscripts.. :rolleyes:
As for dealing with repositioning the 940 code in crt0 or whatever, well the loader is currently loading the g2x file into RAM, repositioning the 920 code and data etc, so I think it makes sense for the loader to do the same for the 940 code. This also
I disagree here.. keep the loader away from the 940 :p
removes the need for every dual-core application to carry the code to do this. The size and position of 940 code, data and bss will be in the g2x file somewhere anyway (whether as entries in a header, constant data in the code or whatever) so it might as well just go in the header.
It can be made easily a makfile option.. so when single core code -> no extra code for 940 handling.
Could you give more detailed examples of what you're suggesting?
Check devkitARM GBA crt0s and linkerscripts.

Right... and after all this preaching I haven't tested in on GP2X :huh: But take a look at the devkitARM GBA stuff. If that is not feasible or there are some 'holes' that make it impossible or not worth the effort let me know. I'll shut up then... at least for a moment. This is just an alternative proposal and if it's non-working then I'll take it back.... <_<

Two complete separate programs for each CPU could have their good sides (like no way of mixing functions by mistake).
 
Last edited by a moderator:
Seems to me that if the linker/loader do the heavy lifting, then you end up with only two well defined threads; what if you want one main thread on the main CPU, and it switchign between a few threads on the other processor? (Thread is the wrong term.)

pseudocode on processor 1:

switch ( modefoo ) {

case '1':
send_to_940 ( code_one );
break;

case '2':
send_to_940 ( code_two );
break;

}

Sure, the 940 code could itself have an if-statement as well, but I like the idea of just shoving over bits as needed without linkage nuttyness.. ie: Loading modules from SD card.

pseudocode:

load_cpu () {

if ( cpu == 'Z80' ) {
handle = load_cpu_dll ( 'Z80' );
send_to_940 ( handle );
} else {...

Off the top of my head; I doubt I'd fire a z80 over to the 940, but I coudl see having it run audio one time, then rendering another, or perhaps swap between various fuinctions.

Heck, one could be running loader demos on the 940 while loading a game on the main CPU (aking to vertical blank demos on consoles)..

pseudocode on main cpu:

while ( loading ) {
handle = pick_demo_randomly();
send_to_940 ( handle );
}

These sorts of scenarios don't need a linked code segment per se, though it could easily be done with one.

Even still, a linker system coudl work fine, and then for the above scenario where you want the control on the 920, you'd just operate the 940 yourself and not have the linker details set.

So this post is moot :)

jeff
 
One thing that could be useful is being able to have resources in the oxe file rather than fixed spaces for certain thinks like icons/etc.

Each resource could be identified by a 32-bit value. So it could be like as folows:

"INFO" - Contains applications name/author/version/description/long description
"ICN0" - Contains the 32x32 icon
"ICN1" - Contains the 48x48 icon
"ICN2" - Contains the 64x64 icon.
"ICNx" - For future use (x = 3-9)

Anything in lower case could be user-defined per application, and the application could load the resources itself on startup.

Something like this would be very useful IMO, and make the format extremely flexible. It would mean not having to use external files for data such as arm940 code, or default configuration files, etc. Plus if we decide we want something else in the oxe in the future, we don't have to change the version number and break everything - we can just create another resource, and anything that doesn't understand the new resources will simply ignore them.

So, for example, if an application only has a single arm 940 code it could be defined as "A940" and loaded/optionally run by the crt0 startup code. If the application would like multiple code uploads, then it could use the user-defined resources such as "a940", "a941", "a942" etc (note lowercase as described above). This also means an app doesn't have to have external files simply because it has more than one arm940 code to upload.
 
The only problem with resources is you need a pretty smart parser to deal with them.. so the crt0 has to be much fatter than it would otherwise be. Still, easily done and its not like its the first time :) It would also allow for arbitrary resources which could be handy.

I'd do it, without any voodoo; one 920 codespace (since every app needs it), then perhaps resources; a standard API for loading the resource contents, and an API for launching them on the 940. No fancy crt0 needed.

UInt32 handle = rsrc_fetch ( 'A940', 0001 );

if ( handle ) {
a940_load ( handle );
a940_start();
}

Something like that.. API driven.

*shrug*

jeff
 
Ick. Ick, Ick, Ick.

That's all very well for Palm type programmers, but most people don't deal with "resources", they have this other concept called "files" :)

We must keep this thing as simple as possible, it can be extended externally if necessary.

I'm only going to try once more to convince you to put 940 code stuff in the header, then I'll go with the democratic decision... promise :)

Spiv's suggestion and mine are very similar, but incompatible (of course)... I'll try and explain each as simply as possible:

1) My suggestion:
2 linker scripts each with one memory segment defined, and 2 linker stages specified in the Makefile. The elf2g2x program reads two Elf files and creates a single output file with details in the header for the start and length of text, data, bss for the 920 *and* the 940.

C files do not need to have any special details in them, they are in effect two separate programs.

The loader performs two load-and-reposition operations.

2) Spiv's suggestion:
1 linker script with 2 memory segments defined. There will be sections called (for example) ".text" and ".text_940", ".data" and ".data_940" etc. In the C files, declarations of functions and variables for the 940 core will be prefixed with a section modifier.

The linker provides some named variables (for example, "text_begin" and "text_size", "text_940_begin" and "text_940_size"). In the C code, these variables are accessed and used by eg. crt0 to reposition the 940 code and data, and clear the 940's bss.

The loader only does one load-and-reposition operation.

Actually, there aren't really big reasons for one over the other, apart from the availability of build scripts etc. I've already got linker scripts and a generic Makefile for my method, and I'll make them available on cobbleware with some description in the near future.

If we decide to allow the "940 code exists" flag in the flags byte, as I suggested, it doesn't prevent programs written to spiv's suggestion from working. It does mean that the loader needs to be able to reposition the 940 code if that flag is set. But I'll provide example code for the loader which will do that.

All up, could we PLEEEZE have the extra flag and the extra optional fields in the header?
 
Sounds like Robsters method is 'simpler' than spivs; ie: two parallel but similar paths, rather than kludgimg out the sections. *shrug* I still think firing off the code from the main thread is the way to go though ;)

jeff
 
Back
Top