How to work with file I/O in kernel PRX?

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

Moderators: cheriff, TyRaNiD

Post Reply
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

How to work with file I/O in kernel PRX?

Post by kweensey »

Hey,
I'm writing a KPRX plugin and I need to work with files.

I tried fopen and simillar functions (I can't tell it better - just that F functions like fopen, fread and so on) and Cygwin gave me errors like undefined reference to 'fopen'. So next I tried sceIo functions and my PSP crashes after start (after start of plugin).

Is there any way to work with files in Kernel PRX plugin? How to check "If file 'config.ini' exist" -> No: create it wih default values -> Yes: read value 1 and set variable A to that value for example?

I'll be happy for replies. Thanks..
kweensey
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

You CAN use sceIoOpen and stuff in kernel mode. Something else is wrong with your plugin.
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Hey,
firstly, thanks for reply. Secondary, really I can? I didn't find some guide to learn what I have in example in my first post to do it with sceIo so I only tried check file and if doesn't exist so create it and my PSP crashed. Could you write an algorithm If file "file.ini" exists then read number 1 (from file) and set variable A to it and then read number 2 and set variable B to it. Else create new "file.ini" and write default numbers to it.

Thank you.
kweensey
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Some thing like this:

Code: Select all

int a=10, b=15;
int bytesRead;
SceUID fd = sceIoOpen("file.ini");

if &#40;fd < 0&#41; //doesn't exist or some other error while opening
&#123;
    if&#40;&#40;fd = sceIoOpen&#40;"file.ini", PSP_O_WRONLY|PSP_O_TRUNC|PSP_O_CREAT, 0777&#41;&#41; >= 0&#41; //successfully created file
    &#123;
        sceIoWrite&#40;fd, &a, sizeof&#40;int&#41;&#41;;
        sceIoWrite&#40;fd, &b, sizeof&#40;int&#41;&#41;;
        sceIoClose&#40;fd&#41;;
    &#125;
&#125;
else
&#123;
    bytesRead = sceIoRead&#40;fd, &a, sizeof&#40;int&#41;&#41;;
    if &#40;bytesRead != sizeof&#40;int&#41;&#41;
    &#123;
        //error reading a
    &#125;
    //you probably shouldn't read b if reading a failed
    bytesRead = sceIoRead&#40;fd, &b, sizeof&#40;int&#41;&#41;;
    if &#40;bytesRead != sizeof&#40;int&#41;&#41;
    &#123;
        //error reading b
    &#125;
    sceIoClose&#40;fd&#41;;
&#125;
This will store/read the raw values like how its stored in memory. Its not meant to be human readable. If you want to have and editable file with numbers like a=15 then you will have to read it like a string and write code to interpret it, since fopen/fscanf doesn't work in kernel mode.
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Thank you so much! I'll try that..
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

So I tried that and my PSP successfully started.. :) But that's all. All my plugin works good but no file created.. :(

EDIT: I gave some visible actions for file create, error while reading and successfully read and I discovered nothing of that was executed.. I don't get it.. Why? Everything before and after works great..
Last edited by kweensey on Wed Feb 11, 2009 6:13 am, edited 1 time in total.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

kweensey wrote:So I tried that and my PSP successfully started.. :) But that's all. All my plugin works good but no file created.. :(
Where are you trying to create the file?
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Path is "file.ini" so file shall create in same direction as plugin is, doesn't it? Or I have to write instead of "file.ini" full path like "ms0:/seplugins/file.ini"?
Dariusc123456
Posts: 388
Joined: Tue Aug 12, 2008 12:46 am

Post by Dariusc123456 »

It can be created, written, and readed anywhere on the psp, or ms. Make sure you have 'PSP_O_CREAT' to make that file.
Cruiserx
Posts: 8
Joined: Thu Oct 23, 2008 11:06 am

Post by Cruiserx »

Dariusc123456 wrote:It can be created, written, and readed anywhere on the psp, or ms. Make sure you have 'PSP_O_CREAT' to make that file.
LOL. If you read Torch's previous post you can see that 'PSP_O_CREAT' is used...
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Torch,
I tested which part of conditions is executed in code you wrote here and it is if (fd < 0) (true) and if((fd = sceIoOpen("file.ini", PSP_O_WRONLY|PSP_O_TRUNC|PSP_O_CREAT, 0777)) >= 0) (else). That means file wasn't created, right? So that script works but why it can't create that file?

Thank you.
kweensey
NoEffex
Posts: 106
Joined: Thu Nov 27, 2008 6:48 am

Post by NoEffex »

You need to set your directory. sceIoChdir would do the trick.

Unlike the stdio functions, it doesn't automatically detect the file path, it is very specific.
Programming with:
Geany + Latest PSPSDK from svn
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

I had problems with fopen not detecting the path, while the sce functions worked fine.
NoEffex
Posts: 106
Joined: Thu Nov 27, 2008 6:48 am

Post by NoEffex »

I've always had to specify the path myself, else it'd think the files not there, for me. Usually however people set up a little thing in module_start function or main that would set the preset path(like, say you have a 40 byte buffer) to sceIoChdir so that way it'd be all ready.
Programming with:
Geany + Latest PSPSDK from svn
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

You have to pass along the argp and args to all the threads you start, right from module_start onwards. For some vague reason, this makes paths work fine for me without any additional code. Without sceIoChdir(argp) at the beginning too.
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Ehm.. :)

I know I'm noob, but could you give me some example, please? I don't understand what you mean..

Thanks.
kweensey
NoEffex
Posts: 106
Joined: Thu Nov 27, 2008 6:48 am

Post by NoEffex »

kweensey wrote:Ehm.. :)

I know I'm noob, but could you give me some example, please? I don't understand what you mean..

Thanks.
kweensey
int module_start(SceSize args, void *argp)
{
...
strcpy(some_buffer, argp);
sceIoChdir(some_buffer);
...
}

that's what works for me, though(not sure if it's just prx, because I don't make kernel eboots) you'll probably have to trim the filename off it.

For example, it'd give you like ms0:/seplugins/module.prx for a prx, so you'd note that the file length is 10 characters.

int module_start(SceSize args, void *argp)
{
...
memcpy(some_buffer, strlen(argp)-10);
sceIoChdir(some_buffer);
...
}

so that way it'd give you the directory rather than the file.
Programming with:
Geany + Latest PSPSDK from svn
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

I only got this in module_start():

Code: Select all

int module_start&#40;SceSize args, void *argp&#41;
&#123;
  int thid = sceKernelCreateThread&#40;"sthing", main_thread, 10, 0x2000, 0, NULL&#41;;
		
  if&#40;thid >= 0&#41;
  &#123;
	  sceKernelStartThread&#40;thid, args, argp&#41;;
	&#125; 
		
	return 0;
&#125;
Shall I add

Code: Select all

strcpy&#40;some_buffer, argp&#41;;
sceIoChdir&#40;some_buffer&#41;; 
memcpy&#40;some_buffer, strlen&#40;argp&#41;-10&#41;;
sceIoChdir&#40;some_buffer&#41;;
there?
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

You can't just subtract 10, you need to know the length of the name of your prx. You should search for the last / and use the characters upto that.

There is code to set the path in moonlight's VLF sample.
moonlight
Posts: 567
Joined: Wed Oct 26, 2005 7:46 pm

Post by moonlight »

And as safety use code like "if (argp)", just in case your module were started with no arguments, to avoid crash.
NoEffex
Posts: 106
Joined: Thu Nov 27, 2008 6:48 am

Post by NoEffex »

I know torch, I was saying, since my module's name that I was using in the example was 10 chars, you would get the length of the module you are using(lol8.prx would be 8, loolz.prx would be 9, z.prx would be 5, and so on).

But yeah, I knew some source I was gandering at had it, of course the one I didn't look at had it.
Programming with:
Geany + Latest PSPSDK from svn
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

Torch: That was example, I just wanted to know, if my "module_start" doesn't contain memspy or strcpy so shall I add

strcpy(some_buffer, argp);
sceIoChdir(some_buffer);
memcpy(some_buffer, strlen(argp)-10);
sceIoChdir(some_buffer);


there? (Instead of 10 will be different number of course.) And may that some_buffer be new buffer or that has to be some specific? And if I add that to "module_start" so that's all? Will work with files work good?

I saw to VLF sample and I didn't see anything special about save/load configuration.. I tried to save/load in normal EBOOT and that's allright but in KPRX I can't do that..

Thank you for help me, that's important for me..

moonlight: Thank you, I will.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Don't use hardcoded lengths, search for the last / and use the string up to that.
kweensey
Posts: 26
Joined: Thu Jan 29, 2009 5:43 pm

Post by kweensey »

I really don't get you, Torch.. :( I have "/" symbol only for notes or as dividing (i.e. 24/2 - 24:2)..

Could you make me a kprx, which loads variable from file, plese? I know you think I only want to copy that and have it without work but I'll study that code and I maybe understand that. It is very important to me and that is needed thing for my plugin.. :(

Thank you..
kweensey
Post Reply