How do I access certain xRegistry settings via webMAN-MOD?

shawly

Member
I actually want to be able to change my display output via webMAN, since my PS3 is hooked up to two TVs, my normal HDTV via HDMI to play PS3 games and I've also connected the AV port to my CRT TV for playing PSX and PS2 games, it just feels more nostalgic.

To switch I have to go into the settings and change the video output depending on where I want to play, so this requires me to turn on the last used TV and change the setting. If I can get webMAN to change this setting for me I can just change it on my computer or smartphone and reboot the PS3.

The first step I wanted to do is being able to read the value of /setting/display/0/type, I looked around a little and found this page http://www.psdevwiki.com/ps3/Talk:VSH#xsetting_4712F276, where I found values for changing the display type (0xA0) and (0xA4) for getting the display configuration.

I tried to look at the existing code to figure out how I could implement this feature but I'm a little confused since I can only code Java and I've never even looked at C. So I scrolled down and looked at the example code at the bottom but this is where it already starts to confuse me:
Code:
char nick[0x80];
memset(nick,0,0x80);

I'm a total C noob so have no idea what memset does, the value for getting the system nick seems to be 0x30 and the example code uses 0x80, so I wanted to know how I'd calculate the address I needed for changing or reading the display type.
I've also looked at xsetting_4712F276_class_t within the xregistry.h of webMAN-MOD but everything is commented out and there aren't any descriptions so I don't really know which line I'd need to uncomment and edit to be able to change the display type.

Maybe one of you guys would like to help me out a little on understanding how this stuff works?
 
I actually want to be able to change my display output via webMAN, since my PS3 is hooked up to two TVs, my normal HDTV via HDMI to play PS3 games and I've also connected the AV port to my CRT TV for playing PSX and PS2 games, it just feels more nostalgic.

To switch I have to go into the settings and change the video output depending on where I want to play, so this requires me to turn on the last used TV and change the setting. If I can get webMAN to change this setting for me I can just change it on my computer or smartphone and reboot the PS3.

The first step I wanted to do is being able to read the value of /setting/display/0/type, I looked around a little and found this page http://www.psdevwiki.com/ps3/Talk:VSH#xsetting_4712F276, where I found values for changing the display type (0xA0) and (0xA4) for getting the display configuration.

I tried to look at the existing code to figure out how I could implement this feature but I'm a little confused since I can only code Java and I've never even looked at C. So I scrolled down and looked at the example code at the bottom but this is where it already starts to confuse me:
Code:
char nick[0x80];
memset(nick,0,0x80);

I'm a total C noob so have no idea what memset does, the value for getting the system nick seems to be 0x30 and the example code uses 0x80, so I wanted to know how I'd calculate the address I needed for changing or reading the display type.
I've also looked at xsetting_4712F276_class_t within the xregistry.h of webMAN-MOD but everything is commented out and there aren't any descriptions so I don't really know which line I'd need to uncomment and edit to be able to change the display type.

Maybe one of you guys would like to help me out a little on understanding how this stuff works?
Strings don't exist as such in C, arrays of characters are used instead. So in C the string "hello" would be declared like this:
Code:
char s[6]="hello";
You may ask why declare an array of 6 characters when the string only contains 5 characters... That is because '\0' is added automatically as the terminating character of any character array so you must remember that when declaring the size of a char array. Basically the array could also be declared like this:
Code:
char s[6]={'h', 'e', 'l', 'l', 'o', '\0'};
This second declaration of the variable s produces an identical array to the the first. In C there are usually various ways to do the same thing...

In this code snippet, the first line declares a char array variable & allocates 0x80 bytes of memory to it.
Code:
char nick[0x80];
memset(nick,0,0x80);
int nick_len=0;
The second line sets every single byte of the memory allocated to the variable nick (number of bytes to set=0x80} to 0.
The 3rd line declares the integer nick_len variable & sets it to 0.
The variables initialization is now complete & both are ready to be used.
Here is the memset syntax:
Code:
 memset(variable, value to assign to individual bytes, number of bytes to set to value)
memset does not return a value (it returns what we call in C a void type). Note that memset allows you to choose the number of bytes to set. In this case, everything single byte is set to 0 because the variable size is 0x80 bytes & memset was given 0x80 bytes to set to 0.
This is basic variable initialization in C.

For the rest, here is another example with xsetting_D0261D72_class_t:

The xsetting_D0261D72_class_t offers the following subs:
uint32_t (*saveRegistryIntValue)(int32_t, int32_t); // id, value
uint32_t (*loadRegistryIntValue)(int32_t, int32_t*); // id, value

Code:
#include "xregistry.h"  //this header is necessary to access the xregistry functions made available via vsh... 
...
(void*&)(xsetting_D0261D72) = (void*)((int)getNIDfunc("xsetting",0xD0261D72)); // setting up xsetting functions usage for export. This line must be run to enable the use of xsetting_D0261D72. The getNIDfunc(...) function is available in wMM so no problem there but remember that if it were another project you would need to implement it. 
...
int id1=0x10;
int id2=0x11;
int val=1;  
int ret=0;
//To set xsetting id1 with value val, call:
xsetting_D0261D72()->saveRegistryIntValue(id1,val);
//to read the value in xsetting id2, call:
xsetting_D0261D72()->loadRegistryIntValue(id2,&ret);
Now the variable ret contains the registry value for xsetting id2. 
For info, in this context, the & character prefixing a variable, like &ret, indicates that the variable ret is passed to the function by reference, not by value. It means that the function can modify the passed variable. It's very important because if you omitted to use the & character, the ret integer variable would remain 0 instead of being updated with the value of xsetting id2. 

Those 2 functions deal with xsetting items using integer values but as you can see in registry.h there are 2 other functions that manage string values. They are logically named loadRegistryStringValue & saveRegistryStringValue. 
If the setting you are trying to modify contains a string & not an integer number then those are the 2 functions to use. In this case, you will need to use a char array variable just like in the first code snippet example with memset.

However in your case, if you must use xsetting_4712F276_class_t, I am afraid that it isn't documented. You have the id of the settings to change but not the subs to access its value....
In xregistry.h, 4 of the commented subs for xsetting_4712F276_class_t are probably functions like loadRegistryIntValue/saveRegistryIntValue & loadRegistryStringValue/saveRegistryStringValue, taking 2 parameters, id & value, but unless you can reverse engineer, the only way to know is to test the subs one after the other!

I hope it helps a little...
Once you have the subs identified, it's a piece of cake. Once done, you can easily create a new web command in wMM so you could use a custom combo for instance to switch modes...
 
Last edited:
That's a big help thank you! I guess I'll have to try the subs one by one, if I make any progress I'll add it to the wiki.
 
@shawly I know this isn't what you are looking exactly for, but maybe it will help as the end result is the same, I think.

If you was to take a backup of your xregistry.sys etc file when set up for your CRT, and then switch over to your HDTV settings, and take that first backup and put it on your hdd somewhere, then what you can do use following webman command to swap the files and reboot.

Code:
http://localhost/swap.ps3/dev_hdd0/path_to_back_up_here/xregistry.sys&to=/dev_flash2/etc/;copy.ps3/dev_flash2/etc/xregistry.sys&to=/dev_flash2/etc/backup/?restart.ps3

You could even make your own XMB icon that performs the switch if you wanted or just use an external device to trigger the swap.

Code:
<View id="display_swap">
<Attributes>
<Table key="display_swap">
<Pair key="icon"><String>/dev_hdd0/path_to_icon/icon.png</String></Pair>
<Pair key="title"><String>Swap over to other Display</String></Pair>
<Pair key="info"><String></String></Pair>
<Pair key="module_name"><String>webrender_plugin</String></Pair>
<Pair key="module_action"><String>http://localhost/swap.ps3/dev_hdd0/path_to_back_up_here/xregistry.sys&to=/dev_flash2/etc/;copy.ps3/dev_flash2/etc/xregistry.sys&to=/dev_flash2/etc/backup/?restart.ps3</String></Pair>
</Table>
</Attributes>
<Items>
<Query
class="type:x-xmb/module-action"
key="display_swap"
attr="display_swap"
/>
</Items>
</View>

You could also use my configuration manager mod to do this.
 
Last edited:
If you decide to use DeViL303's suggestion then you could also create a custom combo like this:
Code:
GET /swap.ps3/dev_hdd0/path_to_back_up/xregistry.sys&to=/dev_flash2/etc/;copy.ps3/dev_flash2/etc/xregistry.sys&to=/dev_flash2/etc/backup/?restart.ps3
 
Last edited:
That's an awesome alternative DeVil303! Thank you, I'll definitely try if I can make any progress in finding the right subs, but this is great if I can't get it to work with my non-existant C knowledge!
 
That's an awesome alternative DeVil303! Thank you, I'll definitely try if I can make any progress in finding the right subs, but this is great if I can't get it to work with my non-existant C knowledge!
I suggest you try to find the getRegistryIntValue function first. It will be easier if you already know the value of the xsetting. Remember we initialized the ret variable to 0 so if the expected xsetting value is also 0, you would not know if the sub worked. In this case, initialize the ret variable with another value...
The XRegistry Editor tool is unfinished & clunky but it might come in handy to check xsetting values in xregistry.sys...

Edit xregistry.h.
First you might try adding a declaration like
int (*getRegistryIntValue)(int, int*);
or
int *(loadRegistryIntValue)(int, int*);
to see if such a function exists in this class...

If those functions do not exist, you may want to try calling the subs via the sub_xxxxxx name & see if that works...

Uncomment the first sub of the class you need to use & modify it like this:
Code:
 int32_t (*sub_453EE4)(int32_t, int32_t*);
In wMM main.c, on top of the code I gave you previously, you will also need to add a tiny snippet to display the value of ret after the tested sub has been called.
You could use something like
Code:
char message[50]="";
sprintf(message,"Testing Sub: ret value = %i",ret);
show_msg(message);
This will display a pop-up with the value of the ret variable.
Compile & run the code.
If the variable ret does not hold the value you expect, revert all the changes in xregistry.h & move on to the next sub.
It's a tedious task but without any IDA/RE/C skills, it is the easiest way I can suggest.

For setRegistryIntValue testing, the parameters are nearly identical except the second one is not a pointer(no * character suffixing int32_t), for the first sub it would be:
Code:
int32_t (*sub_453EE4)(int32_t, int32_t);
 
Last edited:
That's how I imagined how it'd work, even if it's a little tedious someone has to do it, thanks a bunch for your help!
I'll set up my build environment this weekend and try it out.

@bguerville
Since your explanations are great, I'm curious to know how already defined settings can be accessed via method names instead of the subs, like these:
Code:
typedef struct xsetting_0AF1F161_class_t  // 28
{
...
int32_t (*SetSystemLanguage)(int32_t);
int32_t (*GetSystemLanguage)(int32_t *);
int32_t (*SetSystemNickname)(char *);
int32_t (*GetSystemNickname)(char *, int32_t *); // nick, length
...
} xsetting_0AF1F161_class;

I haven't found a line of code where the sub names get mapped to these functions, are they mapped by the order in which they are defined or are these the actual sub names?

It kinda confused me, since I can't just rename the sub like I want it to be called, right?
 
Last edited:
That's how I imagined how it'd work, even if it's a little tedious someone has to do it, thanks a bunch for your help!
I'll set up my build environment this weekend and try it out.

@bguerville
Since your explanations are great, I'm curious to know how already defined settings can be accessed via method names instead of the subs, like these:
Code:
typedef struct xsetting_0AF1F161_class_t  // 28
{
...
int32_t (*SetSystemLanguage)(int32_t);
int32_t (*GetSystemLanguage)(int32_t *);
int32_t (*SetSystemNickname)(char *);
int32_t (*GetSystemNickname)(char *, int32_t *); // nick, length
...
} xsetting_0AF1F161_class;

I haven't found a line of code where the sub names get mapped to these functions, are they mapped by the order in which they are defined or are these the actual sub names?

It kinda confused me, since I can't just rename the sub like I want it to be called, right?
The sub_xxxxxx names were found by reverse engineering/disassembling the code, each of those subs has a real name though. Unfortunately, the lack of documentation for this class means that we don't know its functions real names. Further research is necessary.

If you wish to use a different name, like getRegistryIntValue or anything else you wish, in your code instead of the sub name to make the code easier to read, you can add a line of code like this
Code:
#define getRegistryIntValue sub_453EE4
It's what we call a macro.
Basically with this macro, before compilation & linking begins, the preprocessor takes care of automatically replacing the occurrences of getRegistryIntValue with the real name sub_453EE4.

Like I said before, in C there are always several ways to do something. In this case, another option is to wrap the sub.
Consider this function from xsetting_D0261D72_class_t
Code:
int loadRegistryPadMagnetometer()	
{
   int v;
   loadRegistryIntValue(0x6F, &v);
   return v;
}  //0x6F || "/setting/pad/magnetometer"
You could write similar functions to manage the settings you wish to access through _xsetting_4712F276.
For example:
Code:
void setRegistryDisplayType(int v)	
{
   sub_XXXXXX(0xA0, v);
}  //0xA0 || "/setting/display/0/type"
I assumed here that the DisplayType xsetting value is an integer. You would need to change the int variable to a char array if the value is a string.

Also depending on your code, you may need to check the value for errors before assigning it to the registry xsetting.
For example let us imagine that the DisplayType xsetting value can only be 1, 2 or 3, you could add this check
Code:
if(v<=0 || v>3) return;
before calling sub_XXXXXX(0xA0, v); in the setRegistryDisplayType() function above.

Alternatively to avoid error checking, if the range of possible values is very small, you can just write a dedicated wrapping function with a hardcoded value for each possibility. In the situation above with 3 possible values 1,2 or 3, you would implement 3 functions like this.
void setRegistryDisplayType_1()
{
sub_XXXXXX(0xA0, 1);
}
setRegistryDisplayType_2...
setRegistryDisplayType_3...

Keep in mind that part of the information I gave you is theory...
Good luck... [emoji6]
Let us know how you get on...
 
Last edited:
That helps, with all the info you gave me I should be able to make this work and I even learned something about C, thank you again!

I guess I I'll make two backups of the xRegistry for each setup first and compare the values that have changed so I can find out which settings I'd have to change to switch between both TVs, since the audio options should change too.
 
That helps, with all the info you gave me I should be able to make this work and I even learned something about C, thank you again!

I guess I I'll make two backups of the xRegistry for each setup first and compare the values that have changed so I can find out which settings I'd have to change to switch between both TVs, since the audio options should change too.
To code your feature there may be another interface offering xregistry functions.
It might be worth investigating because if it works it would make your task much simpler...

For example, with x3, you get access to those 2 vsh export functions:
1. at address 0x4D0651A7 you have xRegistryGetValue
2. at address 0xECACA8AD you get xRegistrySetValue
The usage example provided:
int xRegistrySetValue(handle, "/setting/categoryVersion", 0,0,0);

At the moment, x3.h is full of commented addresses. You would need to add a declaration for both functions using something like this (Note that I am just guessing the types according to the code example in psdevwiki, it might need changes or improvements).
int xRegistrySetValue(void*, const char*, int, int, int);
For the get function, we don't know how many parameters it takes so you could try something like this first and add one or 2 other int parameters if it does not work. Remember to check the compiler output, you may get info I'd the parameters are wrong....
int xRegistryGetValue(void*, const char*, int*);

Then in wMM, include the x3 header file if it's not already done & add the 2 getNIDfunc calls using the memory addresses specified above in "x3".
Then you will get access to the x3 class to call your functions like this x3->xRegistrySetValue(...);

I have not used x3 before so I have no idea whether or not these 2 functions will work for your purposes but it's food for thoughts...
 
Last edited:
The first step I wanted to do is being able to read the value of /setting/display/0/type, I looked around a little and found this page http://www.psdevwiki.com/ps3/Talk:VSH#xsetting_4712F276, where I found values for changing the display type (0xA0) and (0xA4) for getting the display configuration.

To read that setting try using this function:
Code:
u32 val_lang = get_xreg_value("/setting/display/0/type", 0XA0);

The function get_xreg_value is currently commented out because it is not needed, but you can uncomment it if you need it.
https://github.com/aldostools/webMAN-MOD/blob/master/include/language.h#L251

To write the setting is a different story, because you also need to calculate the checksum and I don't know how it is calculated.

IMHO The easiest way to do the change the display type is to backup the xregistry.sys for each setting, and swap the files using the /swap.ps3 like DeViL303 suggested with the combo.
 
To read that setting try using this function:
Code:
u32 val_lang = get_xreg_value("/setting/display/0/type", 0XA0);

Thanks aldos, that makes things already easier!

Does someone have the latest source for stokers XRegistry Editor? His homepage isn't online anymore.
 
Awesome thank you!

Edit: I'd like to know where the checksum is actually relevant, I thought if I find and edit the right subs, that I could just edit values within the xRegistry like bguerville said in his post.

From what it seems within the source code of stoker I've found on line 174 within the Main.cs, it doesn't actually calculate any checksums, it just converts the hex string to an unsigned integer.
Code:
entry.Checksum = UInt16.Parse(txtID.Text, NumberStyles.HexNumber);
Or is this what you guys meant by calculating the checksum?
 
Last edited:
Awesome thank you!

Edit: I'd like to know where the checksum is actually relevant, I thought if I find and edit the right subs, that I could just edit values within the xRegistry like bguerville said in his post.

From what it seems within the source code of stoker I've found on line 174 within the Main.cs, it doesn't actually calculate any checksums, it just converts the hex string to an unsigned integer.
Code:
entry.Checksum = UInt16.Parse(txtID.Text, NumberStyles.HexNumber);
Or is this what you guys meant by calculating the checksum?

IIRC the xRegistryEditor.exe of stoker25 does not calculate the checksum. It simply prompts for the value in a form and stores it in the data structure of the xRegistry.sys. Similar to the way I do in my "PS3 Registry Editor.exe" included in the ps3tools coolection.

PS3_Registry_Editor.png
 

Similar threads

Back
Top