However, there's still the front-end itself: the executable code, and the data segment.
Since my front-end it written in SDL, this amounts to around 1.5MB, which I can't afford wasting on low-memory PSP1.
Is there a way to completely unload the current module while starting another one?
Ideally I'd like something like exec(3) in Unix, which replaces the current process by another one.
However the module I loaded just before still can't use all memory, because it's started before the front-end is unloaded (even if it sleep(2) before the first malloc) - sceKernelMaxFreeMemSize() and more direct tests show that a few MB are still missing.
But it's possibly to use an intermediary module that waits a little bit, then starts the final module. The intermediary module can't use all memory as mentioned above, but the final module can (except for what the intermediary module consumes, but this one won't use SDL so that will be an acceptable memory loss).
This should do the trick (and so I can keep my sexy frontend instead of restricting myself to the pspDebugScreen :D).
In the loader module free the heap, load your app and call SelfStopUnloadModule. In module_start() of your app use sceKernelFindModule to check until your loader app is no longer present.. Then use malloc.
Torch wrote:In the loader module free the heap, load your app and call SelfStopUnloadModule. In module_start() of your app use sceKernelFindModule to check until your loader app is no longer present.. Then use malloc.
Well in the app I tried to start the main() with a sleep(5) - and the memory was still not freed. I suppose the loader module needs to be unloaded before a newly started app can claim its memory - hence the intermediary module :/
Well, you could make a small module whose only purpose is to load the first module, wait for it to unload, then load the next module. That should minimize the memory fragmentation you're getting.
Ya it didn't strike me that it could be fragmentation and not because of the memory not being freed. But in that case isn't it pretty much impossible to predict at which location the intermediate module will be loaded, regardless of how small, thus still fragmenting the memory and limiting the maximum malloc?
I guess the idealistic way will be to use a kernel mode intermediate loader like I did in Lockdown. That was the only way I could get 100% of the free user memory. moonlight does the same thing in his VLF sample to exit and load another module.
The first user mode frontend will load the kernel loader. The kernel loader will loop until sceKernelFindModule cannot find the frontend anymore. Then the user memory should be completely defragged and free. Then the kernel loader starts the app and unloads itself.
Torch wrote:Ya it didn't strike me that it could be fragmentation and not because of the memory not being freed. But in that case isn't it pretty much impossible to predict at which location the intermediate module will be loaded, regardless of how small, thus still fragmenting the memory and limiting the maximum malloc?
I guess the idealistic way will be to use a kernel mode intermediate loader like I did in Lockdown. That was the only way I could get 100% of the free user memory. moonlight does the same thing in his VLF sample to exit and load another module.
The first user mode frontend will load the kernel loader. The kernel loader will loop until sceKernelFindModule cannot find the frontend anymore. Then the user memory should be completely defragged and free. Then the kernel loader starts the app and unloads itself.
Kernel modules are loaded into the kernel partition. That means that when the user modules exit, the user partition is completely devoid of modules. Using a kernel module is your best bet to get the most memory. Just be sure to keep it small - you don't have much space in the kernel partition to play with.
J.F. wrote:Kernel modules are loaded into the kernel partition. That means that when the user modules exit, the user partition is completely devoid of modules. Using a kernel module is your best bet to get the most memory. Just be sure to keep it small - you don't have much space in the kernel partition to play with.
This makes sense.
How do you tell the PSP that your module is user- or kernel-mode?
(side question: is there a way to modify this memory partitionning?)
You'll find lots of example user, kernel, and vsh modules in this forum. Look around a little first, then ask. :)
Modifying the partitions is something you'd have to ask moonlight about. He does that when loading homebrew based of the memory flag on the slim to allow max memory, so clearly it can be done in some manner.
J.F. wrote:You'll find lots of example user, kernel, and vsh modules in this forum. Look around a little first, then ask. :)
Oh, a RTFM. Long time no see.
So according yo samples/prx/prx_loader/main.c, "kernel mode" just means "memory partition ID == mpid == 1", to be used in pspSdkLoadStart*().
J.F. wrote:Modifying the partitions is something you'd have to ask moonlight about. He does that when loading homebrew based of the memory flag on the slim to allow max memory, so clearly it can be done in some manner.
Though as it's only shortening the upper boundary, this might be done through other means.
Beuc wrote:
So according yo samples/prx/prx_loader/main.c, "kernel mode" just means "memory partition ID == mpid == 1", to be used in pspSdkLoadStart*().
The PRX also needs to be compiled with kernel mode flags, and hence will be linked to kernel libc and kernel versions of the sce* functions and the resulting file will be much smaller than a user mode one.
mpid needs to be specified as kernel partition, because thats just how it is. It won't work from the wrong partition anyway because of so many reasons.
Beuc wrote:Though as it's only shortening the upper boundary, this might be done through other means.
I don't think anyone has ever bothered to try to increase the size of the kernel partition. There are probably too many factors involved that would make touching anything FUBAR.
The exact patch for increasing the user memory space on the Slim is posted on the forums by moonlight. But I think this was only possible because of the arrangement of the partitions. The normal user partition and the partition used for the UMD cache are physically contiguous. Hence the patch allowed them both to become a single non-fragmented user partition. The two kernel partitions are in different physically separated areas already (on either extremes of the memory I think).
from the kernel module, it returns 0x80020149 (SCE_KERNEL_ERROR_ILLEGAL_PERM_CALL).
I read at http://forums.ps2dev.org/viewtopic.php?p=66785 that I can use USE_KERNEL_LIBS=1 to allow the kernel to use user-mode, but I already do that. I also tried with pspSdkSetK1(0).
How should I use sceKernelLoadModule in kernel mode?
Is there documentation about this?
Thinking about it, it may be better, in fact, to start a minimal "bootstrap" program that itself starts the front-end.
When the front-end quits, it saves the parameters in a file which is read by "bootstrap" to run the main game.
You lose 100-200k RAM in the process, but you avoid fragmentation, and at the same time you don't have to use a kernel module, so you remain compatible with HEN (and your front-end works on PSP-3000).