How to write homebrew for v2.0 firmware

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

How to write homebrew for v2.0 firmware

Post by Fanjita »

Here's a short guide, with hints and tips for making sure your code will work well on v2.0 firmware. I'll update it from time to time as more factors come to light.

Kernel mode
This is the biggie. You can't currently use any kernel-mode features in v2.0 homebrew. Here's what that means in practice:
  • You can request kernel-mode (in the PSPSDK, this means that the second argument to MODULE_INFO() is '0x1000'), so long as you don't break any of the rules below. The loader will attempt to automatically patch up your app to remove typical 'unnecessary' kernel access (e.g. stdio handlers, exception handlers) that cannot be supported in user mode. This also usually means that your init() function will not get called. Preferably, you should use user-mode, to avoid any problems, but this level of kernel-mode tolerance means that you can usually get away with using a single source for 1.5 and 2.0, with better debugging support etc. on the 1.5 platform.
  • You can use wi-fi, so long as the users use the special wifi hack for the loader. If you are going to use wifi, you should use the new PSPSDK support for loading the network modules, because the loader can automatically patch this when starting the app. PSPPet's wifi sample code will also usually work, depending on how heavily you modified it. Other methods for starting the network modules may not be supported.
  • You can use stdio stream handlers, but they won't have any effect.
  • You can install exception handlers, but they won't have any effect.
  • You can't access kernel-space memory.
Stability tips
The environment when running under v2.0 is pretty close to that under v1.5 - once loaded, your app will make system calls in exactly the same way, will be loaded in memory in exactly the same place, etc. There are some small differences you might want to be aware of, because these can help improve your stability on 2.0.
  • Memory allocation: The environment that the loader starts in has a restricted global heap, with only approx 3Mb left in the official sceKernelAllocPartitionMemory() user partition (#2). Because of this, the loader hooks the memory management APIs, and uses any spare RAM not being used by the program code to provide an additional pool. Typically this gives an average-sized app approx another 16Mb to use.
    Access to this memory is transparent to your app, so long as you use the standard sceKernelAllocPartitionMemory calls, as before. (The extra memory is added to partition 2, so you don't need to change any parameters). A few notes:
    • Alloc calls will be offered to the official Alloc API first. The extra pool is only used if the API can't satisfy the alloc request.
    • The extra pool only supports the 'allocate from lowest memory' option.
    • Re-merge handling of freed memory is limited. Freeing anything except the most-recently allocated memory from the extra pool will result in a leak.
    • It seems that libnewlibc provides its own malloc manager, rather than passing calls directly to the Sony API. It allocates the largest single memory block available at initialisation (this will be the entire extra pool), and services mallocs from that block. So, if you want the maximum available RAM, it is probably best to use sceKernelAllocPartitionMe mory() etc. rather than malloc, when running with libnewlibc.
  • Thread management : The loader also hooks some thread management calls (sceKernelRunThread(), sceKernelExitThread(), etc.) so that it can keep track of whether the app has exited.

    General tips
    A few general coding tips, to make it easier for people running your code under v2.0:
    • Although there's handling in place in the loader to check for hard-coded file paths, and warn the user, it's best to avoid these altogether. Various development libraries provide support for relative (rather than absolute) file paths, and even if you're not using one of those, you can easily make your app use relative paths by checking argv[0] in main() : this will contain the full absolute path to your EBOOT.PBP file, so you can process this to build the correct absolute paths to your files without having to assume that your app will be installed in a specific path.
    • Make sure you're using the latest PSPSDK toolchain, because that's the version the loader is usually tested against. Older versions of the SDK may use different startup code, which may not behave quite as expected under 2.0.
    • Try to use a unique module name in the MODULE_INFO() statement. This helps to distinguish between apps for special case handling. There are an awful lot of apps that still use "HelloWorld" or "SDKSample" or similar as their module name.
    • Include an alternative way to exit your app, rather than relying just on the HOME button. HOME doesn't work on v2.0 homebrew (yet), and the available workaround has limitations. Far better to have a menu option that just calls SceExitGame().
EDIT: Updated for the current loader version, 0.9.
Last edited by Fanjita on Fri Dec 02, 2005 9:51 am, edited 1 time in total.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Stickied.
Duo
Posts: 25
Joined: Fri Oct 21, 2005 5:15 am

Post by Duo »

An option in the compiler that checks for 2.0 compatibility, giving line numbers of incompatible code would be cool.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Duo wrote:An option in the compiler that checks for 2.0 compatibility, giving line numbers of incompatible code would be cool.
That will never happen. Anyway, the compatiblity requirements listed by Fanjita should be more than enough.
Paolo
Posts: 12
Joined: Tue Nov 08, 2005 12:34 am

Post by Paolo »

Is there existing examples of using sceKernelAllocPartitionMemory() ...?
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

Paolo wrote:Is there existing examples of using sceKernelAllocPartitionMemory() ...?
See the SDK files : pspsysmem.h, I think, for example usage.

It's a lot like malloc, the main difference is that you get back a block ID, that you need to call sceKernelGetBlockHeadAddr on to get the actual address of your memory.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
Paolo
Posts: 12
Joined: Tue Nov 08, 2005 12:34 am

Post by Paolo »

The kernel memory manager seems to some kind of frame based memory
allocator, at least the option to allocate from lowest or highest available
address would indicate to that, no?

But, how do I define the partition id -argument? What is it and what should
I use? For example, if I would make a texture manager which allocates a
big chunk of memory from vram, I would use PSP_SMEM_Addr as a block
type, and point the mem address to somewhere beyond the depth buffer?
What would be the partition id?

What benefit does this give compared to malloc?

Sorry if this is too noobish... :)
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

There's a memory map in wiki.ps2dev.org that describes the different partitions.

Ordinarily, you'll use the user partition, which (from memory) I think is 2.

I don't believe that there is an option to allocate from VRAM, but I could be wrong on that.

Incidentally, I've generally found that requesting a specific address doesn't work, even when I'm sure that a block of the right size at that address is free. Perhaps I was doing something wrong, but I couldn't see what it was.

There's no compelling advantage to using the native memory management interface. On v2.0, it will give you access to a slightly larger memory pool, as described above. It will also be slightly faster than using mallocs that just ultimately map to the native calls anyway.

Note though that some libc libraries (newlib is one, I think) seem to just use the native interface to alloc the largest single block they're allowed, and then run their own allocation scheme within that block for malloc calls etc.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

(Updated original post with the latest info - most of the restrictions have now been lifted)
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Is there a cheap way to detect if the EBOOT loader is active? I need to manually call _init() to initialize C++, and I also need to avoid calling anything that triggers a kernel access.
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

There are probably a few ways, none of which is extremely reliable.

Simplest would be to check if your thread has the VSH attributes. But that's not future-proof.

Most future-proof is probably to check for the presence of a thread called "restartThread" - I doubt that will change.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

About the EBOOT laoder and C++ global constructors...

Post by mrbrown »

So, we figured out that rRootage was crashing on 2.0 systems because _init() wasn't being called by the EBOOT loader. To recap, _init() is the function that goes through and executes the constructors used in C++ static classes and C functions using GCC's "constructor" attribute.

rRootage uses SDL, and it depends on libSDL_main to provide main() and all of the PSP-specific code (exception handling, exit callback, etc.). SDL's PSP main() code includes a constructor function that normally installs an exception handler for 1.0 and 1.5 systems. If the 2.0 EBOOT loader were to call this function, it would immediately crash as 2.0 doesn't have access to kernel mode. The EBOOT loader can be configured to call _init(), but it's usually safer for it not to, so that more applications will work under 2.0. So we need to be able to call _init() if the EBOOT loader doesn't call it, and we need to make sure that we don't call any functions in our constructors that require kernel access.

What follows is the solution I used for libSDL_main. In the loaderInit() constructor function, I use sceKernelDevkitVersion() to determine the PSP firmware version. If it's less than 0x02000010 we know that we can access the kernel. At the end of this function I set a flag indicating that _init() was called. In main(), we check this flag, and if it's zero we call _init() ourselves.

This solution should fix any applications that depend on C++ static constructors (Fanjita mentioned UAE and PSP-GBA also have this issue).

Code: Select all

/* If this flag is set to 1, the _init() function was called and all
   global/static constructors have been called. */
static int init_was_called = 0;

__attribute__ ((constructor))
void loaderInit()
{
    int kmode_is_available = &#40;sceKernelDevkitVersion&#40;&#41; < 0x02000010&#41;;

    if &#40;kmode_is_available&#41; &#123;
        /* Do nefarious kernel stuff here */
    &#125;

    init_was_called = 1;
&#125;

extern void _init&#40;void&#41;;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
    /* Fanjita's EBOOT loader can be configured to skip the call to _init&#40;&#41;.
       Since we need _init&#40;&#41; for C++, we check to see if _init&#40;&#41; has been
       called.  If it hasn't we call it manually, after determining whether or
       not we can access the kernel. */
    if &#40;!init_was_called&#41; &#123;
        _init&#40;&#41;;
    &#125;

    ...
&#125;
mICrO
Posts: 25
Joined: Mon Oct 17, 2005 2:48 am
Location: Madrid (Spain)

Re: About the EBOOT laoder and C++ global constructors...

Post by mICrO »

So, where its the 'real' _init function?

Because if I reproduce that code in my c++ code its said the tipical: unresolved externall.

mrbrown wrote:So, we figured out that rRootage was crashing on 2.0 systems because _init() wasn't being called by the EBOOT loader. To recap, _init() is the function that goes through and executes the constructors used in C++ static classes and C functions using GCC's "constructor" attribute.

rRootage uses SDL, and it depends on libSDL_main to provide main() and all of the PSP-specific code (exception handling, exit callback, etc.). SDL's PSP main() code includes a constructor function that normally installs an exception handler for 1.0 and 1.5 systems. If the 2.0 EBOOT loader were to call this function, it would immediately crash as 2.0 doesn't have access to kernel mode. The EBOOT loader can be configured to call _init(), but it's usually safer for it not to, so that more applications will work under 2.0. So we need to be able to call _init() if the EBOOT loader doesn't call it, and we need to make sure that we don't call any functions in our constructors that require kernel access.

What follows is the solution I used for libSDL_main. In the loaderInit() constructor function, I use sceKernelDevkitVersion() to determine the PSP firmware version. If it's less than 0x02000010 we know that we can access the kernel. At the end of this function I set a flag indicating that _init() was called. In main(), we check this flag, and if it's zero we call _init() ourselves.

This solution should fix any applications that depend on C++ static constructors (Fanjita mentioned UAE and PSP-GBA also have this issue).

Code: Select all

/* If this flag is set to 1, the _init&#40;&#41; function was called and all
   global/static constructors have been called. */
static int init_was_called = 0;

__attribute__ &#40;&#40;constructor&#41;&#41;
void loaderInit&#40;&#41;
&#123;
    int kmode_is_available = &#40;sceKernelDevkitVersion&#40;&#41; < 0x02000010&#41;;

    if &#40;kmode_is_available&#41; &#123;
        /* Do nefarious kernel stuff here */
    &#125;

    init_was_called = 1;
&#125;

extern void _init&#40;void&#41;;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
    /* Fanjita's EBOOT loader can be configured to skip the call to _init&#40;&#41;.
       Since we need _init&#40;&#41; for C++, we check to see if _init&#40;&#41; has been
       called.  If it hasn't we call it manually, after determining whether or
       not we can access the kernel. */
    if &#40;!init_was_called&#41; &#123;
        _init&#40;&#41;;
    &#125;

    ...
&#125;
mICrO^NewOlds
ja_medina at hotmail dot com

There is no such thing as a moral or an immoral book.

Books are well written or badly written.
(Oscar Wilde)
User avatar
groepaz
Posts: 305
Joined: Thu Sep 01, 2005 7:44 am
Contact:

Post by groepaz »

it usually is provided by one of the CRT files, crtstart.o most likely. if you are still fiddling with your own toolchain, you have to come up with it yourself.
mICrO
Posts: 25
Joined: Mon Oct 17, 2005 2:48 am
Location: Madrid (Spain)

Channel assigned error on 2.0

Post by mICrO »

I first test my game engine on psp ver 2.0, and dosen't work, i check My log file and get something like :

Code: Select all

MGE &#58;-&#41;
25/11/2005 - 09&#58;48&#58;24 Log Init
25/11/2005 - 09&#58;48&#58;24 Init Base app
25/11/2005 - 09&#58;48&#58;24     + Init Control
25/11/2005 - 09&#58;48&#58;25     + Init Control &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;25     + Init RenderDevice
25/11/2005 - 09&#58;48&#58;26         - Init VRAM Screen
25/11/2005 - 09&#58;48&#58;26             . Init Screen
25/11/2005 - 09&#58;48&#58;27                 # Logging Screen class
25/11/2005 - 09&#58;48&#58;28                     + Screen Size = 480x272
25/11/2005 - 09&#58;48&#58;29                     + Clip Area = &#40;0,0&#41;-&#40;479,271&#41;
25/11/2005 - 09&#58;48&#58;29             . Init Screen &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;30         - Init VRAM Screen &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;31         - Init VRAM Screen
25/11/2005 - 09&#58;48&#58;31             . Init Screen
25/11/2005 - 09&#58;48&#58;32                 # Logging Screen class
25/11/2005 - 09&#58;48&#58;33                     + Screen Size = 480x272
25/11/2005 - 09&#58;48&#58;33                     + Clip Area = &#40;0,0&#41;-&#40;479,271&#41;
25/11/2005 - 09&#58;48&#58;34             . Init Screen &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;35         - Init VRAM Screen &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;36         - Logging RenderDevice class
25/11/2005 - 09&#58;48&#58;36             . Screen Size = 480x272
25/11/2005 - 09&#58;48&#58;37             . Buffer Width = 512
25/11/2005 - 09&#58;48&#58;37             . Screen Format&#40;RGBA&#41; = 5&#58;6&#58;5&#58;0
25/11/2005 - 09&#58;48&#58;38     + Init RenderDevice &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;39     + Init CMGESoundDevice
25/11/2005 - 09&#58;48&#58;39         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;40             . Sound Thread Create &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;40             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;41                 # - id 0
25/11/2005 - 09&#58;48&#58;42         - Init CMGEAudioChannel &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;42         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;43             . Sound Thread Create &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;44             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;44                 # - id 1
25/11/2005 - 09&#58;48&#58;45         - Init CMGEAudioChannel &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;46         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;46             . Sound Thread Create &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;47             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;48                 # - id 2
25/11/2005 - 09&#58;48&#58;48         - Init CMGEAudioChannel &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;49         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;50             . Sound Thread Create &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;50             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;51                 # - id 3
25/11/2005 - 09&#58;48&#58;52         - Init CMGEAudioChannel &#91;Ok&#93;
25/11/2005 - 09&#58;48&#58;52         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;53             . Fail to assign channel 4
25/11/2005 - 09&#58;48&#58;54             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;54                 # - id -2144993277
25/11/2005 - 09&#58;48&#58;55         - Init CMGEAudioChannel &#91;Fail&#93;
25/11/2005 - 09&#58;48&#58;56         - Init CMGEAudioChannel
25/11/2005 - 09&#58;48&#58;56             . Fail to assign channel 5
25/11/2005 - 09&#58;48&#58;57             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;48&#58;58                 # - id -2144993277
25/11/2005 - 09&#58;48&#58;58         - Init CMGEAudioChannel &#91;Fail&#93;
25/11/2005 - 09&#58;48&#58;59         - Init CMGEAudioChannel
25/11/2005 - 09&#58;49&#58;00             . Fail to assign channel 6
25/11/2005 - 09&#58;49&#58;00             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;49&#58;01                 # - id -2144993277
25/11/2005 - 09&#58;49&#58;02         - Init CMGEAudioChannel &#91;Fail&#93;
25/11/2005 - 09&#58;49&#58;02         - Init CMGEAudioChannel
25/11/2005 - 09&#58;49&#58;03             . Fail to assign channel 7
25/11/2005 - 09&#58;49&#58;03             . Logging CMGEAudioChannel class
25/11/2005 - 09&#58;49&#58;04                 # - id -2144993277
25/11/2005 - 09&#58;49&#58;05         - Init CMGEAudioChannel &#91;Fail&#93;
25/11/2005 - 09&#58;49&#58;06         - Logging CMGESoundDevice class
25/11/2005 - 09&#58;49&#58;06     + Init CMGESoundDevice &#91;Fail&#93;
25/11/2005 - 09&#58;49&#58;06     + Fail to init Sound device
25/11/2005 - 09&#58;49&#58;07 Init Base app &#91;Fail&#93;
Checking my code, i see that:

Code: Select all

		#if defined &#40;PSP_VER&#41;
			//reserve the channel
			m_id = sceAudioChReserve&#40;num,max_buffer_size,&#40;m_stereo?PSP_AUDIO_FORMAT_STEREO&#58;PSP_AUDIO_FORMAT_MONO&#41;&#41;;						
		#else
			m_id=num;
		#endif

		if&#40;m_id>=0&#41;
		&#123;
			// channel reserved ok			

			#if defined &#40;PSP_VER&#41;
				char sBuff&#91;255&#93;;
				sprintf&#40;sBuff,"sound thread%d",m_id&#41;;

				m_thread = sceKernelCreateThread&#40;sBuff, ProcessSound, 0x12, 0x1000, 0, NULL &#41;;

				if &#40;m_thread >= 0&#41; 
				&#123;			
					CMGELog&#58;&#58;SysLog&#40;CMGELog&#58;&#58;lInfo,"Sound Thread Create &#91;Ok&#93;"&#41;;			
					sceKernelStartThread &#40;m_thread, sizeof&#40;int&#41;, &m_id&#41;;
				&#125;
				else
				&#123;			
					CMGELog&#58;&#58;SysLog&#40;CMGELog&#58;&#58;lError,"Error creating sound thread %s",sBuff&#41;;
					CMGELog&#58;&#58;SysLog&#40;CMGELog&#58;&#58;lError,"Sound Thread Create &#91;Fail&#93;"&#41;;
					m_bOk=false;
				&#125;		
			#else

			#endif
		&#125;
		else
		&#123;
			CMGELog&#58;&#58;SysLog&#40;CMGELog&#58;&#58;lError,"Fail to assign channel %d",num&#41;;
			m_bOk=false;
		&#125;
I used all hardware channels, so I prepare samples and music a bit fastter, and left hardware mixer to mix then all, its use less cpu that mixing with the main MIPS, son for every channel I do:

Code: Select all

	m_id = sceAudioChReserve&#40;num,max_buffer_size,&#40;m_stereo?PSP_AUDIO_FORMAT_STEREO&#58;PSP_AUDIO_FORMAT_MONO&#41;&#41;;


But thats, in 2.0 using eboot loader, work for channels from 0 to 3, but don't to channels from 4 to 7, seems like they are allready assigned, some how.

So, now, how to fixt it?, should I to call sceAudioChRelease, before reserved it, or should the loader have some 'option' to reset all before calle the eboot?
mICrO^NewOlds
ja_medina at hotmail dot com

There is no such thing as a moral or an immoral book.

Books are well written or badly written.
(Oscar Wilde)
mICrO
Posts: 25
Joined: Mon Oct 17, 2005 2:48 am
Location: Madrid (Spain)

Post by mICrO »

but, if its provide by the crt, why I get an error when the application its linked?
groepaz wrote:it usually is provided by one of the CRT files, crtstart.o most likely. if you are still fiddling with your own toolchain, you have to come up with it yourself.
mICrO^NewOlds
ja_medina at hotmail dot com

There is no such thing as a moral or an immoral book.

Books are well written or badly written.
(Oscar Wilde)
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

Micro, you should try unassigning the channels yourself.

If it helps, let me know, and I'll incorporate something into the loader to do it automatically.

Thanks.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
mICrO
Posts: 25
Joined: Mon Oct 17, 2005 2:48 am
Location: Madrid (Spain)

Post by mICrO »

Ok, thats Works, I tested, so if I used sceAudioChRelease to unassiging assigned channels, before assigned myself works OK under eboot loader 0.9.

Fanjita told me that the next version of the loader will take care of it.

Fanjita wrote:Micro, you should try unassigning the channels yourself.

If it helps, let me know, and I'll incorporate something into the loader to do it automatically.

Thanks.
mICrO^NewOlds
ja_medina at hotmail dot com

There is no such thing as a moral or an immoral book.

Books are well written or badly written.
(Oscar Wilde)
User avatar
groepaz
Posts: 305
Joined: Thu Sep 01, 2005 7:44 am
Contact:

Post by groepaz »

but, if its provide by the crt, why I get an error when the application its linked?
probably because the way you are linking the app doesnt pull in crtstart.o :) try using gcc (not ld) for linking, that might fix it...depends on how your toolchain is set up.
mICrO
Posts: 25
Joined: Mon Oct 17, 2005 2:48 am
Location: Madrid (Spain)

Post by mICrO »

Damm, I founded, I put _init declaration, by error, outside off extern "C" {, since I used c++, linker couldn't find it.

Now fixed.

Thanks groepa

groepaz wrote:
but, if its provide by the crt, why I get an error when the application its linked?
probably because the way you are linking the app doesnt pull in crtstart.o :) try using gcc (not ld) for linking, that might fix it...depends on how your toolchain is set up.
mICrO^NewOlds
ja_medina at hotmail dot com

There is no such thing as a moral or an immoral book.

Books are well written or badly written.
(Oscar Wilde)
hubevolution
Posts: 32
Joined: Wed Mar 17, 2004 6:59 pm

Post by hubevolution »

would these restrictions apply to 2.01+ eLoader too ?

Thx
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

Actually most of this advice is out of date now.

I'll update the post at some point in the near future, but in the meantime the main things you need to avoid if possible are:

- using true kernel-mode functionality, e.g. API functions / memory access that is only available in kernel mode. A lot of the common items are stubbed out by the loader (e.g. setting exception handlers, reassigning stdio) but not all.

- relying on mainline application initialisation (e.g. global variables, etc.) in attribute(constructor) functions. When trying to run a kernel-mode app, the loader will usually just NOP out the call to _init(), which runs these functions.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
hubevolution
Posts: 32
Joined: Wed Mar 17, 2004 6:59 pm

Post by hubevolution »

thanks for fast reply fanjita ;)
weak
Posts: 114
Joined: Thu Jan 13, 2005 8:31 pm
Location: Vienna, Austria

Post by weak »

fanjita: how about atrac support? i know, loads of work for you, but a lot of games would benefit from atrac support ;)
Post Reply