 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Thu Dec 06, 2007 1:01 am Post subject: SceUtilitySavedataParam |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Thu Dec 06, 2007 2:39 am Post subject: |
|
|
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 |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Thu Dec 06, 2007 3:43 am Post subject: |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Thu Dec 06, 2007 10:46 am Post subject: |
|
|
| 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 |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Thu Dec 06, 2007 11:29 pm Post subject: |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Fri Dec 07, 2007 2:35 am Post subject: |
|
|
| 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 |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Fri Dec 07, 2007 2:58 am Post subject: |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Fri Dec 07, 2007 8:34 am Post subject: |
|
|
| 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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Fri Dec 07, 2007 8:39 am Post subject: |
|
|
| and you can found many tutorials on pointers on internet |
|
| Back to top |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Fri Dec 07, 2007 11:01 pm Post subject: |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Sat Dec 08, 2007 3:06 am Post subject: |
|
|
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 |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Sat Dec 08, 2007 3:40 am Post subject: |
|
|
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 |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Sat Dec 08, 2007 5:05 am Post subject: |
|
|
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 |
|
 |
kgsws
Joined: 06 Dec 2007 Posts: 7
|
Posted: Sat Dec 08, 2007 9:35 am Post subject: |
|
|
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 |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Sat Dec 08, 2007 11:58 am Post subject: |
|
|
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 |
|
 |
|
|
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
|