[SOLVED] Start a module with more than one argument...

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

Moderators: cheriff, TyRaNiD

Post Reply
darkness
Posts: 121
Joined: Sun Jun 15, 2008 8:42 pm

[SOLVED] Start a module with more than one argument...

Post by darkness »

Excuse me,
I'm trying to start a prx with more than one args but I don't know the argp structure, so if is possible, how to do this?
I've think to write the ars in different position but the args is not a simple string...
Here is a sample...

Code: Select all

...
...
strcpy(argp, "First Argument");
char* args2="Second Argument";

int a;
for&#40;a=0; a<=strlen&#40;args2&#41;; a++&#41;
&#123;
     argp&#91;50+a&#93;=args2&#91;a&#93;; // <---- I cannot do this, is a sample of I want to do...
     
&#125;


...
...

sceKernelStartModule&#40;mod, strlen&#40;argp&#41;+1, argp, NULL, NULL&#41;;
This is a sample of I want to do, so can anyone help me? :)
Thanks in advance!!
Last edited by darkness on Mon Jul 07, 2008 2:32 am, edited 1 time in total.
Pirata Nervo
Posts: 409
Joined: Tue Oct 09, 2007 4:22 am

Post by Pirata Nervo »

first, argp is not a structure, it's a pointer to the arguments. (as far as I know)
I don't really understand what you want.

I think what you want is this. (to pass the argument)

Code: Select all

SceUID module = sceKernelLoadModule&#40;"ms0&#58;/myprx", 0, NULL&#41;;

void * argumentP = NULL;

argumentP&#91;0&#93; = mystring1;
argumentP&#91;1&#93; = mystring2;

int status;

sceKernelStartModule&#40;module,&#40;strlen&#40;mystring1&#41;+1&#41;+&#40;strlen&#40;mystring2&#41;+1&#41;, argumentP, &status, NULL&#41;; // pass the first argument as NULL or as a SceKernelSMOption structure
I don't know if that will work tho. (didn't test it)

To get the argumentP[0] and argumentP[1], use this inside the loaded prx:

Code: Select all

char mystring1&#91;255&#93;, mystring2&#91;255&#93;;
strcpy&#40;mystring1, &#40;char*&#41;argp&#91;0&#93;&#41;;
strcpy&#40;mystring2, &#40;char*&#41;argp&#91;1&#93;&#41;;
As I said I didn't test it and I don't know if it works or not
Image
Upgrade your PSP
User avatar
jean
Posts: 489
Joined: Sat Jan 05, 2008 2:44 am

Post by jean »

As PN said args is not a struct but a pointer. However, it is a good idea to use a pointer to structure holding other types if you need to pass multiple arguments. If you don't know in advance how many parameters to pass, then a "bad design" bell should sound in your mind. In very rare and special case this is required and implemented through collections. Sorry, no demo code...however you now got the buzzwords.
PS: code by PN should not work...array must be initialized as local or allocated so that argumentP[...] can avoid write in not allocated area or onto other stack variables...
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

not exactly. I think it would be something like :

Code: Select all

SceUID module = sceKernelLoadModule&#40;"ms0&#58;/myprx", 0, NULL&#41;;

char data&#91;256*n&#93;;

int size = 0;

for &#40;i = 0; i < n; ++i&#41;
&#123;
    strncpy&#40;data+size, str&#91;i&#93;, 255&#41;;
    size += strlen&#40;str&#91;i&#93;&#41; + 1;
&#125;

int status;

sceKernelStartModule&#40;module,size, &#40;void *&#41;data, &status, NULL&#41;;
to retrieve them

Code: Select all

char str&#91;n*256&#93;;

char *data = &#40;char *&#41;argp;

int size = 0;

for &#40;i = 0; i < n; ++i&#41;
&#123;
    strncpy&#40;str&#91;i&#93;, data+size, 255&#41;;
    size += strlen&#40;data+size&#41; + 1;
&#125;
Pirata Nervo
Posts: 409
Joined: Tue Oct 09, 2007 4:22 am

Post by Pirata Nervo »

@jean, yeh as I predicted it would not work :P
I wrote a very simple way but would not work.
Yeh I forgot to allocate the void pointer data
@hlide, where does the str variable come from?
Image
Upgrade your PSP
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

if i'm not wrong, for the function which receives argp and args, there is always a copy of the content pointed by argp passed to sceKernelStartModulemust and args should get the bytes length to copy, so the contents couldn't be a structure with pointers.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Pirata Nervo wrote:@hlide, where does the str variable come from?
i wrote this code for a variable number of string to pass, str is just your array of string you want to pass (I replaced your mystring1, mystring2 for n = 2).

you need to coalesce your strings into one flat string where string separator is a null string '\0' to handle it as a flat block and pass the total size of this block (null separators included).
Pirata Nervo
Posts: 409
Joined: Tue Oct 09, 2007 4:22 am

Post by Pirata Nervo »

Yeh I understand what you mean :)
I do it on my program but didn't bother to open the file which passes arguments to a pbp
Image
Upgrade your PSP
darkness
Posts: 121
Joined: Sun Jun 15, 2008 8:42 pm

Post by darkness »

Excuse me, but I haven't understand very well the code of hlide:

Code: Select all

SceUID module = sceKernelLoadModule&#40;"ms0&#58;/myprx", 0, NULL&#41;;

char argument1&#91;256&#93;, argument2;
srtcpy&#40;argument1, "The first argument"&#41;;
strcpy&#40;argument2, "The second argument"&#41;;
And I've to put theese two string into srt?

Code: Select all


char data&#91;256*n&#93;;

int size = 0;

for &#40;i = 0; i < n; ++i&#41;
&#123;
    strncpy&#40;data+size, str&#91;i&#93;, 255&#41;;
    size += strlen&#40;str&#91;i&#93;&#41; + 1;
&#125;

int status;

sceKernelStartModule&#40;module,size, &#40;void *&#41;data, &status, NULL&#41;;
to retrieve them:

Code: Select all

char str&#91;n*256&#93;;

char *data = &#40;char *&#41;argp;

int size = 0;

for &#40;i = 0; i < n; ++i&#41;
&#123;
    strncpy&#40;str&#91;i&#93;, data+size, 255&#41;;
    size += strlen&#40;data+size&#41; + 1;
&#125;
But where is the results args? into srt separated by \0?
Excuse me please, but I'm doing a lot of confusion...
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

what do you need ? two strings to pass ?

Code: Select all

SceUID module = sceKernelLoadModule&#40;"ms0&#58;/myprx", 0, NULL&#41;;

char data&#91;256*2&#93;;

char *str1 = "my 1st argument";
char *str2 = "my 2nd argument";

int len1 = strlen&#40;str1&#41;;
int len2 = strlen&#40;str2&#41;;

strncpy&#40;data, str1, 255&#41;;
strncpy&#40;data+len1+1, str2, 255&#41;;

int status;

sceKernelStartModule&#40;module, len1+len2+2, &#40;void *&#41;data, &status, NULL&#41;; 
in your start module of your PRX

Code: Select all

char str&#91;2*256&#93;;

char *data = &#40;char *&#41;argp;

int size = 0;

for &#40;i = 0; i < 2; ++i&#41;
&#123;
    strncpy&#40;str&#91;i&#93;, data+size, 255&#41;;
    size += strlen&#40;data+size&#41; + 1;
&#125; 
str[0] <--- "my 1st argument"
str[1] <--- "my 2nd argument"
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Well as pointed out what happens when you call StartModule (and StartThread as it happens) is the kernel copies args bytes from the argp pointer to the top of the initial thread's stack, it then calls the entry point passing you a pointer to the data on the stack.

There is nothing stopping you passing anything you across, in fact no reason you cannot pass pointers (assuming you can access the memory in the new prx) just you have to ensure that the memory that points to is valid.

Ultimately it is up to you to decide how best to encode your data so you can unpack it again at the other side.

To convert between say standard style argc/argv you could do something like this (bad code warning :P):

Code: Select all

int build_args&#40;char *args, int argc, char **argv&#41;
&#123;   
    int loc = 0;
    int i;
    
    for&#40;i = 0; i < argc; i++&#41;
    &#123;   
        strcpy&#40;&args&#91;loc&#93;, argv&#91;i&#93;&#41;;
        loc += strlen&#40;argv&#91;i&#93;&#41; + 1;
    &#125;
    
    return loc;
&#125;

int unpack_args&#40;char *argp, int args, char **argv&#41;
&#123;
    int loc = 0;
    int argc = 0;

    *argc = 0;
    while&#40;loc < args&#41;
    &#123;
        argv&#91;argc++&#93; = &argp&#91;loc&#93;;
        loc += strlen&#40;&argp&#91;loc&#93;&#41; + 1;
    &#125;
    argv&#91;argc&#93; = NULL;

    return argc;
&#125;   

/* To pack the args for StartModule */
char argp&#91;1024&#93;;
char **argv = &#123; &#123;"1"&#125;, &#123;"2"&#125;, &#123;"3"&#125; &#125;;
args = build_args&#40;argp, 3, argv&#41;;

/* Unpack them at the other side */
char* argv&#91;16&#93;;
int argc;
argc = unpack_args&#40;argp, args, argv&#41;;
darkness
Posts: 121
Joined: Sun Jun 15, 2008 8:42 pm

Post by darkness »

Thanks very much...

EDIT:
puff, If I try to compile this code I have a lot of errors...
I'll use the hlide solution...
Last edited by darkness on Sun Jun 29, 2008 1:55 am, edited 2 times in total.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

TyRaNiD wrote:There is nothing stopping you passing anything you across, in fact no reason you cannot pass pointers (assuming you can access the memory in the new prx) just you have to ensure that the memory that points to is valid.
true but I preferred not to advise to do so. We could fear a lot of posts wondering why "my app crashes when I load my PRX ?" because someone is freeing some passed structures in argp while a PRX is using them for instance.

so kids, avoid doing so if you don't want big headaches ! especially if you don't know what you do.
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Well the same argument could be made for any args passed to a prx above and beyond simple argc/argv style stuff.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

TyRaNiD wrote: To convert between say standard style argc/argv you could do something like this (bad code warning :P):

Code: Select all

int build_args&#40;char *args, int argc, char **argv&#41;
&#123;   
    int loc = 0;
    int i;
    
    for&#40;i = 0; i < argc; i++&#41;
    &#123;   
        strcpy&#40;&args&#91;loc&#93;, argv&#91;i&#93;&#41;;
        loc += strlen&#40;argv&#91;i&#93;&#41; + 1;
    &#125;
    
    return loc;
&#125;

int unpack_args&#40;char *argp, int args, char **argv&#41;
&#123;
    int loc = 0;
    int argc = 0;

    *argc = 0;
    while&#40;loc < args&#41;
    &#123;
        argv&#91;argc++&#93; = &argp&#91;loc&#93;;
        loc += strlen&#40;&argp&#91;loc&#93;&#41; + 1;
    &#125;
    argv&#91;argc&#93; = NULL;

    return argc;
&#125;   

/* To pack the args for StartModule */
char argp&#91;1024&#93;;
char **argv = &#123; &#123;"1"&#125;, &#123;"2"&#125;, &#123;"3"&#125; &#125;;
args = build_args&#40;argp, 3, argv&#41;;

/* Unpack them at the other side */
char* argv&#91;16&#93;;
int argc;
argc = unpack_args&#40;argp, args, argv&#41;;
I want to mix and match between the length/*args combo that modules use, and the argc,**argv.

The above functions screw up sometimes depending on the contents of length/*args (presumably due to the presence of NULL characters which breaks strcpy).

I feel the ideal solution is to ALWAYS use only length/*args like modules use. Thats what the SCE functions use anyway.

How do you make an EBOOT that uses length/*args?
int main() only works with argc/**argv
Post Reply