Homebrew Implementing the AC:I service functions

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
Hello everyone,

I've been trying to implement the AC:I service, using the documentation found on 3dbrew. I slowly test each function, adding a new page on the wiki as I go further. I have some Citra3DS logs of the System Settings and Network Settings dev app as a starting point for the call order and parameters.

Here is what I got so far :
  • To read a network setting :
    • Call LoadNetworkSetting with the wanted network ID (0-1-2)
    • Read the values using the various getters
  • To update a network setting :
    • Call LoadNetworkSetting with the wanted network ID (0-1-2)
    • Call InitializeNetworkSetting with 1 as a parameter (I don't know what it represents but it's the value used by both System Settings and Network Settings)
    • Set all the values using the various setters
    • Call UpdateNetworkSetting to update the setting
  • To delete a network setting :
    • Just call RemoveNetworkSetting with the wanted network ID
  • At the end :
    • Always call FlushNetworkSetting to commit and save the changes
I successfully implemented the basic functions such as LoadNetworkSetting, InitializeNetworkSetting or RemoveNetworkSetting. However, I can't get all the getters to work : the ones with a "string" as return value (such as the getter for the ssid, password or proxy host) make the system freeze when calling the svcSendSyncRequest function. It just crashes. The other getters, such as the proxy state or proxy port are working just fine.

I know that these function doesn't require any additionnal parameters, and that they are not likely to use a shared memory buffer (as I would see it in Citra's logs). Here is the code of my implementation of the GetNetworkProxyHost function (I don't have any return value yet since the call freezes the console).

What am I doing wrong ? I do the AC:I calls in the exact same order than the System Settings app, but I might be missing something. Here are the Citra logs that I use, you can see all the unimplemented AC:I functions starting at line 60 - it starts with LoadNetworkSetting and immediatly reads all the values, starting with function 0x04070000, then the CRC...

Thanks for the help :)
 
Last edited by natinusala,

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
I'm almost 100% positive on that for 3 reasons :
  1. As you stated, the command header contains the number of parameters (0-4-8...). However, of you look at the wiki you'll see that all the getters are like 0x04XX0000 : no standard parameters and no translate parameters.
  2. If they would need parameters I would see it on the Citra logs (cmd_buff[x] = ...)
  3. Some setters work : the ones with integral values work, the ones with string values doesn't
I'm aware that the getters need some place to put the string to, like an output buffer... But since they doesn't need any additional parameters, there is only a few options left :
  • Either it gives a "read-only" string pointer to strcpy from
  • Either it uses shared memory, but I guess I would see the svcCreateMemoryBlock call in the Citra logs
But I can't test any of that since the call freezes the console. Could it come from the non-existent shared buffer ?
 
Last edited by natinusala,
D

Deleted User

Guest
Maybe. Unfortunately, I don't have that much knowledge of 3DS Hacking to give you a definitive answer. Sorry.

This may sound weird, but have you tried working with C++ strings? But you said the program crashes on svcSendSyncRequest(). Hrm.
 

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
The 3DS totally freezes when calling svcSendSyncRequest, I have to manually power it down by pressing the power button for 10s or so. I tried giving a garbage IPC header to see, and I have the same result, which makes me think that every time the SVC isn't happy with something it just crashes the system. I don't know if calling a service which needs a shared buffer will either return a bad value or crash the system... There is no reason for the freeze apart a missing shared buffer. I'll try this evening, even tho I don't know its size.

edit : Nope I just realized that even with a shared memory buffer it would be given as a parameter... they don't require any parameter and still they fail, why ? it's driving me crazy
 
Last edited by natinusala,
  • Like
Reactions: Deleted User

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
I just rebuild and ran Citra3DS, I can't find anything that I do wrong... those who are familiar with such function calls, how is the return value passed to the homebrew if there is no output buffer parameter ?
 
Last edited by natinusala,
D

Deleted User

Guest
I just rebuild and ran Citra3DS, I can't find anything that I do wrong... those who are familiar with such function calls, how does is the return value passed to the homebrew if there is no output buffer parameter ?

Oh, you're testing on Citra?

Have you done any testing on the actual 3DS?
 

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
Testing on the actual 3DS freezes it at the GetProxyHost svc call. Testing in Citra blurts out red unknown/uninmplemented ac:i functions, which is normal, but I use it to log service calls done by the System Settings app. I do the exact same calls on the 3DS and it freezes. Ugh.

edit : if anyone wants to read the OP Citra logs and point me to what i'm missing...
 
Last edited by natinusala,
  • Like
Reactions: Deleted User

Kartik

Well-Known Member
Member
Joined
Jun 6, 2015
Messages
653
Trophies
0
Location
github
XP
2,747
Country
India
This piece of code worked for me(ACI:GetConnectingSsid):-
Code:
Handle acHandle;
    Result ret;
    u8 *try = malloc(0x100);
    ret = srvGetServiceHandle(&acHandle,"ac:i");
    printf("%d\n",(int)ret);
    u32 *cmdbuf = getThreadCommandBuffer();
    cmdbuf[0] = 0x340000;
    u32 *staticbuf = getThreadStaticBuffers();
    staticbuf[0] = 0x80002;
    staticbuf[1] = try;
    ret = svcSendSyncRequest(acHandle);
    printf("ret,try: %d|%s\n",(int)ret,(char*)try);
 

Ryuzaki_MrL

Green Thunder
Member
Joined
Jun 23, 2015
Messages
781
Trophies
0
Age
26
XP
2,046
Country
Brazil
Did you try:
Code:
Result ACI_GetNetworkProxyHost(u16* out)
{
    Result ret;
    u32 *cmdbuf = getThreadCommandBuffer();
 
    cmdbuf[0] = IPC_MakeHeader(0x465,0,0); // 0x04650000

    if(R_FAILED(ret = svcSendSyncRequest(aciHandle)))return ret;

    if(out) memcpy(out, &cmdbuf[2], <whatever_is_the_max_length>);
    return (Result)cmdbuf[1];
}
May aswell be a char* if it's not using UTF-16.
 
Last edited by Ryuzaki_MrL,

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
This piece of code worked for me(ACI:GetConnectingSsid):-

I didn't know that getThreadStaticBuffers was a thing... it still freezes tho, could it come from the size of the try buffer ? Also, what is 0x80002 ? Here is my code.

Did you try:

May aswell be a char* if it's not using UTF-16.

The problem is not with reading the value, it's with the actual svc call which freezes the console. But if it uses the static buffer as @Kartik suggested, it might not work like you wrote it.
 

Kartik

Well-Known Member
Member
Joined
Jun 6, 2015
Messages
653
Trophies
0
Location
github
XP
2,747
Country
India
I didn't know that getThreadStaticBuffers was a thing... it still freezes tho, could it come from the size of the try buffer ? Also, what is 0x80002 ? Here is my code.



The problem is not with reading the value, it's with the actual svc call which freezes the console. But if it uses the static buffer as @Kartik suggested, it might not work like you wrote it.
Not sure why it is not work for you...As for in GetProxyHost()this should work:-
Code:
Result ACI_GetNetworkProxyHost(void)
{
    Result ret=0;
    ret = srvGetServiceHandle(&acHandle,"ac:i");
    printf("%d\n",ret);
    u32 *cmdbuf = getThreadCommandBuffer();
      
    cmdbuf[0] = IPC_MakeHeader(0x465,0,0); // 0x04650000
  
    u32 *staticbuf = getThreadStaticBuffers();
    u8* try = malloc(0x200);
    if(try==NULL)return 1;
    staticbuf[0] = 0x190002;
    staticbuf[1] = try;
 
    if(R_FAILED(ret = svcSendSyncRequest(aciHandle)))return ret;
 
    return (Result)cmdbuf[1];
}
 

Drakia

Well-Known Member
Member
Joined
Mar 15, 2008
Messages
1,644
Trophies
2
Age
36
XP
2,596
Country
Canada

natinusala

Win32 error 31 is not an error
OP
Member
Joined
Dec 1, 2012
Messages
1,032
Trophies
0
Age
44
XP
2,914
Country
France
I couldn't find a way to get 0x190002 back using this function =/ I put 0x200 as a size and tried each buffer ID (0x0 - 0xF).
 

Drakia

Well-Known Member
Member
Joined
Mar 15, 2008
Messages
1,644
Trophies
2
Age
36
XP
2,596
Country
Canada
Yeah, not sure how he got his specific numbers, just saying how libctru seems to get the number to use. If you look for all references to "getThreadStaticBuffers", you will see they all use "IPC_Desc_StaticBuffer" to get that specific value, passing in the buffer size. So I'd recommend just doing the same.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Xdqwerty @ Xdqwerty: https://youtu.be/eFb28u5GPsU?si=35a7C58FgPbaxIMm