forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

SceUtilitySavedataParam

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Thu Dec 06, 2007 1:01 am    Post subject: SceUtilitySavedataParam Reply with quote

I dont know if it is somewhere on net ...
I wanted to update all 3 ports (hexen, heretic, doom) with PSP's system functions, and i discovered bug in SceUtilitySavedataParam, i found correct things in memory of original game, there is fix:

Code:
typedef struct SceUtilitySavedataParam
{
   pspUtilityDialogCommon base;

   /** mode: 0 to load, 4 to load menu, 1 to save, 5 to save menu*/
       // Save/Load menu is that, you can choose from list of saves to save/load
   int mode;
   int unknown12;

   /** unknown13 use 1 */
   int unknown13;

   /** gameName: name used from the game for saves, equal for all saves */
   char gameName[16];
   /** saveName: name of the particular save, normally a number */
   char saveName[20]; // THIS IS FIX - only 20
   char *saveNames; // THIS IS NEW - For save/load menu (see example)
   /** fileName: name of the data file of the game for example DATA.BIN */
   char fileName[16];

   /** pointer to a buffer that will contain data file unencrypted data */
   void *dataBuf;
   /** size of allocated space to dataBuf */
   SceSize dataBufSize;
   SceSize dataSize;

   PspUtilitySavedataSFOParam sfoParam;

   PspUtilitySavedataFileData icon0FileData;
   PspUtilitySavedataFileData icon1FileData;
   PspUtilitySavedataFileData pic1FileData;
   PspUtilitySavedataFileData snd0FileData;

   unsigned char unknown17[4];
} SceUtilitySavedataParam;

how it works?
dont set saveName[20], but set savenames:
Code:
typedef struct // you can use more names, but terminator must exist, and must be full of 0
{
   char name1[20];
   char name2[20];
   char name3[20];
   char name4[20];
   char name5[20];
   char nothing[20]; // Terminator
} savenames_t;

in code:
   savenames_t savenames;
   memset(&savenames, 0, sizeof(savenames));
   sprintf(savenames.name1,"s1");
   sprintf(savenames.name2,"s2");
   sprintf(savenames.name3,"s3");
   sprintf(savenames.name4,"s4");
   sprintf(savenames.name5,"s5");
   SceUtilitySavedataParam data;
   memset(&data, 0, sizeof(data));
   data.base.size = sizeof(data);
   data.base.language = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH;
   data.base.buttonSwap = PSP_UTILITY_ACCEPT_CROSS;
   data.base.graphicsThread = 17;
   data.base.unknown = 19;
   data.base.fontThread = 18;
   data.base.soundThread = 16;
   data.mode = 5; // now saving menu
   data.unknown13 = 1;
   sprintf(data.gameName,"SOME-NAME");
   data.saveNames = &savenames; // <------- this is new
   sprintf(data.fileName,"DATA.BIN");
   data.dataBuf = savebuffer;
   data.dataBufSize = sizeof(savebuffer);
   data.dataSize = sizeof(savebuffer);
   sprintf(data.sfoParam.title,"Game Title");
   sprintf(data.sfoParam.savedataTitle,"Save Title");
   sprintf(data.sfoParam.detail,"Save details");

other is same as in SDK example


Last edited by kgsws on Thu Dec 06, 2007 3:44 am; edited 1 time in total
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Thu Dec 06, 2007 2:39 am    Post subject: Reply with quote

Here's the modified psputility_savedata.h that i use if you want :

Code:


/*
 * PSP Software Development Kit - http://www.pspdev.org
 * -----------------------------------------------------------------------
 * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
 *
 *  psputility_savedata.h - Definitions and Functions for savedata part of
 *                     pspUtility library
 *
 * Copyright (c) 2005    Shine
 *                       weltall <weltall@consoleworld.org>
 *                       Marcus R. Brown <mrbrown@ocgnet.org>
 *
 * $Id: psputility_savedata.h 2275 2007-07-28 22:02:11Z iwn $
 */

#ifndef __PSPUTILITY_SAVEDATA_H__
#define __PSPUTILITY_SAVEDATA_H__

#include <psptypes.h>

#ifdef __cplusplus
extern "C" {
#endif


#define PSP_UTILITY_SAVEDATA_LOADNOGRAPHIC      0
#define PSP_UTILITY_SAVEDATA_SAVENOGRAPHIC      1
#define PSP_UTILITY_SAVEDATA_LOAD            2
#define PSP_UTILITY_SAVEDATA_SAVE            3
#define PSP_UTILITY_SAVEDATA_LOADMULTIPLE      4
#define PSP_UTILITY_SAVEDATA_SAVEMULTIPLE      5


/** title, savedataTitle, detail: parts of the unencrypted SFO
    data, it contains what the VSH and standard load screen shows */
typedef struct PspUtilitySavedataSFOParam
{
   char title[0x80];
   char savedataTitle[0x80];
   char detail[0x400];
   unsigned char parentalLevel;
   unsigned char unknown[3];
} PspUtilitySavedataSFOParam;

typedef struct PspUtilitySavedataFileData {
   void *buf;
   SceSize bufSize;
   SceSize size;   /* ??? - why are there two sizes? */
   int unknown;
} PspUtilitySavedataFileData;

typedef struct PspUtilitySavedataInfoShow
{
   PspUtilitySavedataFileData icon;
   char *title;
} PspUtilitySavedataInfoShow;


/** Structure to hold the parameters for the ::sceUtilitySavedataInitStart function.
  */
typedef struct SceUtilitySavedataParam
{
   pspUtilityDialogCommon base;

   /** mode: 0 to load, 1 to save */
   int mode;
   int unknown12;

   /** unknown13 use 0x1 */
   int unknown13;

   /** gameName: name used from the game for saves, equal for all saves */
   char gameName[16];
   /** saveName: name of the particular save, normally a number */
   char saveName[20];

   /** saveNameMultiple: used by multiple modes */
   char **saveNameMultiple;

   /** fileName: name of the data file of the game for example DATA.BIN */
   char fileName[16];

   /** pointer to a buffer that will contain data file unencrypted data */
   void *dataBuf;
   /** size of allocated space to dataBuf */
   SceSize dataBufSize;
   SceSize dataSize;

   PspUtilitySavedataSFOParam sfoParam;

   PspUtilitySavedataFileData icon0FileData;
   PspUtilitySavedataFileData icon1FileData;
   PspUtilitySavedataFileData pic1FileData;
   PspUtilitySavedataFileData snd0FileData;

   PspUtilitySavedataInfoShow *infoShow;

   /* unknown1: ? */
   int unknown1;

   /* unknown2: ? */
   int unknown2[4];

#ifdef PSP_UTILITY_SAVEDATAWITHKEY

   /* key: encrypt/decrypt key for save with firmware >= 2.00 */
   char key[16];

   /* unknown3: ? */
   char unknown3[20];

#endif

} SceUtilitySavedataParam;


/**
 * Saves or Load savedata to/from the passed structure
 * After having called this continue calling sceUtilitySavedataGetStatus to
 * check if the operation is completed
 *
 * @param params - savedata parameters
 * @returns 0 on success
 */
int sceUtilitySavedataInitStart(SceUtilitySavedataParam * params);

/**
 * Check the current status of the saving/loading/shutdown process
 * Continue calling this to check current status of the process
 * before calling this call also sceUtilitySavedataUpdate
 * @returns 2 if the process is still being processed.
 * 3 on save/load success, then you can call sceUtilitySavedataShutdownStart.
 * 4 on complete shutdown.
 */
int sceUtilitySavedataGetStatus(void);


/**
 * Shutdown the savedata utility. after calling this continue calling
 * ::sceUtilitySavedataGetStatus to check when it has shutdown
 *
 * @return 0 on success
 *
 */
int sceUtilitySavedataShutdownStart(void);

/**
 * Refresh status of the savedata function
 *
 * @param unknown - unknown, pass 1
 */
void sceUtilitySavedataUpdate(int unknown);

#ifdef __cplusplus
}
#endif

#endif



And to use it, it's like you do :

Code:


PspUtilitySavedataInfoShow infoShow;
char *titleShow = "New data";
char nameMultiple[][20] =
{
 "0000",
 "0001",
 "0002",
 "0003",
 "0004",
 ""               // END OF LIST
};

char key[] = "SAMPLEKEYFOR2xxF";

void initSavedata(SceUtilitySavedataParam * savedata, int mode)
{
SceUID fd;
int fsize;

   memset(savedata, 0, sizeof(SceUtilitySavedataParam));
   savedata->base.size = sizeof(SceUtilitySavedataParam);

   savedata->base.language = 2;
   savedata->base.buttonSwap = 1;
   savedata->base.graphicsThread = 0x11;
   savedata->base.unknown = 0x13;
   savedata->base.fontThread = 0x12;
   savedata->base.soundThread = 0x10;

   savedata->mode = PSP_UTILITY_SAVEDATA_SAVEMULTIPLE;      /* mode: 0 = load, 1 = save */
   savedata->unknown13 = 1; //?

//   strncpy(savedata->key,key,16);

   strcpy(savedata->gameName, "DEMO11111");   /* first part of the save name, game identifier name */
   strcpy(savedata->saveName, "0000");   /* second part of the save name, save identifier name */


   savedata->saveNameMultiple = (char **) nameMultiple;

   strcpy(savedata->fileName, "DATA.BIN");   /* name of the data file */

   /* Allocate buffers used to store various parts of the save data. */
   savedata->dataBuf = malloc(DATABUFFLEN);
   savedata->dataBufSize = DATABUFFLEN;
   savedata->dataSize = DATABUFFLEN;

   strcpy(savedata->sfoParam.title,"Title");
   strcpy(savedata->sfoParam.savedataTitle,"Title 2");
   strcpy(savedata->sfoParam.detail,"Detail");
   savedata->sfoParam.parentalLevel = 1;

   infoShow.title = titleShow;

   savedata->infoShow = &infoShow;
   //savedata->unknown = 1;
}

Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Thu Dec 06, 2007 3:43 am    Post subject: Reply with quote

i am not sure about this line:
char **saveNameMultiple;
it is pointer to pointer to char(s), but what i use is just:
char *saveNameMultiple;
pointer to char(s)
and with this:
savedata->saveNameMultiple = (char **) nameMultiple;
isnt better to do
savedata->saveNameMultiple = &nameMultiple;
of course if you use only one pointer (not pointer to pointer)
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Thu Dec 06, 2007 10:46 am    Post subject: Reply with quote

kgsws wrote:
i am not sure about this line:
char **saveNameMultiple;
it is pointer to pointer to char(s), but what i use is just:
char *saveNameMultiple;
pointer to char(s)
and with this:
savedata->saveNameMultiple = (char **) nameMultiple;
isnt better to do
savedata->saveNameMultiple = &nameMultiple;
of course if you use only one pointer (not pointer to pointer)


I edited my post to cancel my bad reading.

You must use

savedata->saveNameMultiple = nameMultiple;

and not

savedata->saveNameMultiple = &nameMultiple;

simply because utility function takes a pointer to chars, if i use (char **), it's just for a more comprehensive reading.


Last edited by johnmph on Sat Dec 08, 2007 5:16 am; edited 3 times in total
Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Thu Dec 06, 2007 11:29 pm    Post subject: Reply with quote

but, in first post is this:
in struct SceUtilitySavedataParam:

char *saveNames;
pointer to char(s), is it right?

and after i defined new struct
typedef struct
{
char name1[20];
char name2[20];
char name3[20];
char name4[20];
char name5[20];
char nothing[20]; // Terminator
} savenames_t;
no pointers, is it right?
after i create:
savenames_t savenames;
and this is not pointer too, is it right?

and on this line:
data.saveNames = &savenames;
i am making pointer to chars from char[120], is it right?

that means, you dont need to define:
savenames_t savenames;
but only:
char savenames[120];
but you must fill it in correct order
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Fri Dec 07, 2007 2:35 am    Post subject: Reply with quote

kgsws wrote:
but, in first post is this:
in struct SceUtilitySavedataParam:

char *saveNames;
pointer to char(s), is it right?

and after i defined new struct
typedef struct
{
char name1[20];
char name2[20];
char name3[20];
char name4[20];
char name5[20];
char nothing[20]; // Terminator
} savenames_t;
no pointers, is it right?
after i create:
savenames_t savenames;
and this is not pointer too, is it right?

and on this line:
data.saveNames = &savenames;
i am making pointer to chars from char[120], is it right?

that means, you dont need to define:
savenames_t savenames;
but only:
char savenames[120];
but you must fill it in correct order


Yes i misread your first post, i don't know why i thought you used an array to chars ([][]), i am confused with my sample.
The sceUtilitySavedataInitStart takes a pointer to chars and he reads chars by 20, if he finds a empty string, he stops.

So you can use a string with 20, 40, 60, ... chars and use it like you said :

strcpy(&string[0],"0001");
strcpy(&string[20],"0002");
...
string[...] = 0; // terminator

with : savedata->saveNameMultiple = string;

if you use your structure declaration (char *saveNames;) or :

savedata->saveNameMultiple = (char **) string;

if you use my structure declaration (char **saveNameMultiple;)

But don't use : savedata->saveNameMultiple = &string;
Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Fri Dec 07, 2007 2:58 am    Post subject: Reply with quote

but if i define pointer to something, an non pointer, then i must use & character ...

char *point; // 4 bytes
char nonpoint // 1 byte

i can do:
nonpoint = 'X';
but i cant do:
point = 'X'; // becouse pointer is not set, and it will try to write to address 0x00000000
i can use:
point = malloc(1);
and after it, i can use that ...
if i do:
point = &nonpoint;
it will set address of point to address of nonpoint, so when i try:
nonpoint = 'A';
point = 'X'; // or point[0] = 'X';
nonpoint will be 'X' there ...

that is way i am thinking about pointers :P

i am not sure with:
x = (char **)y; // conversion
so, i dont use it, if i dont need
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Fri Dec 07, 2007 8:34 am    Post subject: Reply with quote

kgsws wrote:
but if i define pointer to something, an non pointer, then i must use & character ...

char *point; // 4 bytes
char nonpoint // 1 byte

i can do:
nonpoint = 'X';
but i cant do:
point = 'X'; // becouse pointer is not set, and it will try to write to address 0x00000000
i can use:
point = malloc(1);
and after it, i can use that ...
if i do:
point = &nonpoint;
it will set address of point to address of nonpoint, so when i try:
nonpoint = 'A';
point = 'X'; // or point[0] = 'X';
nonpoint will be 'X' there ...

that is way i am thinking about pointers :P

i am not sure with:
x = (char **)y; // conversion
so, i dont use it, if i dont need


You are right except a little mistake :

point = 'X'; // or point[0] = 'X'; is not the same !!!

point is the pointer, it contains address of pointed data and not data, here's the good writing (parentheses is not necessary in this sample) :

(*point) = 'X'; // or point[0] = 'X';

For this line :

x = (char **)y; // conversion

It's just a cast, if you do :

char **point = (char **) &nonpoint;
*((char *) point) = 'X';

it's the same that :

char *point = &nonpoint;
*point = 'X';

But it's off topic.

The reason why i use char **saveNameMultiple with an array of strings instead char *saveNameMultiple with a large string is because it's more easy i think.
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Fri Dec 07, 2007 8:39 am    Post subject: Reply with quote

and you can found many tutorials on pointers on internet
Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Fri Dec 07, 2007 11:01 pm    Post subject: Reply with quote

great, now i understant it more, but if i create:
Code:
char *names[6] = {
   "NAME1",
   "NAME2",
   "NAME3",
   "NAME4",
   "NAME5",
   "" // Terminator
};

then its size is 6*4 bytes, and every 4 bytes is pointer to char(s).
For every NAME, you must alloc memory (or use it like that example, it is defined in program)

But what i saw in memory of official game was this:
char nameschars[6*20]; // 5 savenames, every 20 chars long, and 20 chars terminator.
Of course, size is 6*20

If you point to 'names' then it is pointer to pointers to chars (and that was not in memory.

I dont know if savegame can work with pointer to pointers or only with pointer to chars, but i can try it (now i am using just pointer to chars, same as in original game)

(from your example):
Code:
char nameMultiple[][20] =
{
 "0000",
 "0001",
 "0002",
 "0003",
 "0004",
 ""               // END OF LIST
};

there isnt any pointer, right?
it is like char nameMultiple[6*20], and if i use "0000" as first name, it will be saved to nameMultiple[0], and "0001" to nameMultiple[20], right?

And you can make pointer from it by point = &nameMultiple like i.
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Sat Dec 08, 2007 3:06 am    Post subject: Reply with quote

Yes you are right and it's because i use :

savedata->saveNameMultiple = (char **) nameMultiple;

instead :

savedata->saveNameMultiple = (char **) &nameMultiple;

The savegame function takes a pointer to char and not a pointer to pointer to chars and it's why i use a large string (char nameMultiple[][20]) but when i reversed this function, i wrote it as char** instead char* because i think that it's more representive for the meaning of how it's used.

But you can also write it like (in structure) :

int nameMultiple;

and after use it like :

char name[120] = "...";
struct.nameMultiple = (int) name;

It's valid too but it's not very good to understand lol

So the savedata function takes a pointer to chars and reads the chars by 20 until he finds 0 as first char (terminator).
Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Sat Dec 08, 2007 3:40 am    Post subject: Reply with quote

i still dont understand why:
savedata->saveNameMultiple = (char **) nameMultiple;
and no:
savedata->saveNameMultiple = &nameMultiple;
(it is just pointer = pointer) (becouse & makes pointer from non pointer)

becouse there are two '**' markers, every marker means pointer, so it is pointer to pointer to ...

if i do:
char **something;
then it is pointer to pointer to char(s), so:
something = malloc(x * 4) // x = num pointers, 4 is size of pointer
and then i can do:
something[0] = malloc(10); // 10 chars
something[1] = malloc(20); // 20 chars
.....
and then:
printf(something[0]); // 10 chars
printf(something[1]); // 20 chars
.....

it is strange, becouse of compiler ...
sprintf accepts pointer to char (so char*)
but when i do:
char some[20];
and then:
printf(some); it automaticaly converts non pointer to pointer
(becouse if not, it will try to use first 4 chars as address of pointer, and that is bad)
Back to top
View user's profile Send private message
johnmph



Joined: 23 Jul 2005
Posts: 119

PostPosted: Sat Dec 08, 2007 5:05 am    Post subject: Reply with quote

Because an array = a pointer :

char some[20];

some is a pointer to 20 bytes data allocated statically.

char *some2 = some;

some2 is a pointer which points to the same memory, it's the same !
Back to top
View user's profile Send private message
kgsws



Joined: 06 Dec 2007
Posts: 7

PostPosted: Sat Dec 08, 2007 9:35 am    Post subject: Reply with quote

yes, but compiler can handle it diffrend way than creating a pointer by using *.

if you thing that way, then everything is pointer to some location in memory (yes, data must be stored somewhere)

int is array of 4 chars:
int somenum;
char somechars[4];

char is pointer without using *?
and why int isnt?

but compiler can make pointer from somechars automaticaly by using it as x = somechars; but if i use x = &somechars; it does not create pointer to pointer, then savedata

Size is same, i thing, everything hadles compiler, like MSVC .NET, it does not allow some things, what DEV C++ does. (yes i had some problems with it)

isnt '(char*)' just fake conversion, for using variable as diffrend type?

tested:
char text[] = "test text";
printf("0x%08X\n",text);
printf("0x%08X\n",&text);
both lines shown same hex number, so it does not depends on '&'
then i dont need to use it, but 'char *saveNames;' is right (only one pointer)
Back to top
View user's profile Send private message
Jim



Joined: 02 Jul 2005
Posts: 487
Location: Sydney

PostPosted: Sat Dec 08, 2007 11:58 am    Post subject: Reply with quote

Right, because if you have

char x[]="foo";
Then

x is type pointer to char
&x is type pointer to array of char

They're both point to the same address, but they have different types.

I don't know what you're all on about, this is utterly basic C programming.

Jim
_________________
http://www.dbfinteractive.com
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group