Skip to content

Commit 1c382d5

Browse files
roblablayellows8
authored andcommitted
Avoid using duplicate keys in service_access
Splits service_access into service_host and service_access, both arrays of strings. We output service_host first, as that seems to be what Nintendo is doing - all their NPDMs have service hosts before service accesses.
1 parent ab742da commit 1c382d5

File tree

1 file changed

+69
-11
lines changed

1 file changed

+69
-11
lines changed

src/npdmtool.c

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -383,35 +383,93 @@ int CreateNpdm(const char *json, void **dst, u32 *dst_size) {
383383
aci0->SacOffset = (aci0->FahOffset + aci0->FahSize + 0xF) & ~0xF;
384384

385385
/* Sac. */
386-
services = cJSON_GetObjectItemCaseSensitive(npdm_json, "service_access");
387-
if (!cJSON_IsObject(services)) {
388-
fprintf(stderr, "Service Access must be an object!\n");
386+
u8 *sac = (u8*)aci0 + aci0->SacOffset;
387+
u32 sac_size = 0;
388+
389+
services = cJSON_GetObjectItemCaseSensitive(npdm_json, "service_host");
390+
if (!cJSON_IsArray(services)) {
391+
fprintf(stderr, "Service Host must be an array!\n");
389392
status = 0;
390393
goto NPDM_BUILD_END;
391394
}
392-
393-
u8 *sac = (u8*)aci0 + aci0->SacOffset;
394-
u32 sac_size = 0;
395+
395396
cJSON_ArrayForEach(service, services) {
396-
if (!cJSON_IsBool(service)) {
397-
fprintf(stderr, "Services must be of form service_name (str) : is_host (bool)\n");
397+
int is_host = 1;
398+
char *service_name;
399+
400+
if (!cJSON_IsString(service)) {
401+
fprintf(stderr, "service_access must be an array of string\n");
402+
status = 0;
403+
goto NPDM_BUILD_END;
404+
}
405+
service_name = service->valuestring;
406+
407+
int cur_srv_len = strlen(service_name);
408+
if (cur_srv_len > 8 || cur_srv_len == 0) {
409+
fprintf(stderr, "Services must have name length 1 <= len <= 8!\n");
398410
status = 0;
399411
goto NPDM_BUILD_END;
400412
}
401-
int cur_srv_len = strlen(service->string);
413+
u8 ctrl = (u8)(cur_srv_len - 1);
414+
if (is_host) {
415+
ctrl |= 0x80;
416+
}
417+
sac[sac_size++] = ctrl;
418+
memcpy(sac + sac_size, service_name, cur_srv_len);
419+
sac_size += cur_srv_len;
420+
}
421+
422+
services = cJSON_GetObjectItemCaseSensitive(npdm_json, "service_access");
423+
if (!(cJSON_IsObject(services) || cJSON_IsArray(services))) {
424+
fprintf(stderr, "Service Access must be an array!\n");
425+
status = 0;
426+
goto NPDM_BUILD_END;
427+
}
428+
429+
int sac_obj = 0;
430+
if (cJSON_IsObject(services)) {
431+
sac_obj = 1;
432+
fprintf(stderr, "Using deprecated service_access format. Please turn it into an array.\n");
433+
}
434+
435+
cJSON_ArrayForEach(service, services) {
436+
int is_host = 0;
437+
char *service_name;
438+
439+
if (sac_obj) {
440+
if (!cJSON_IsBool(service)) {
441+
fprintf(stderr, "Services must be of form service_name (str) : is_host (bool)\n");
442+
status = 0;
443+
goto NPDM_BUILD_END;
444+
}
445+
is_host = cJSON_IsTrue(service);
446+
service_name = service->string;
447+
} else {
448+
if (!cJSON_IsString(service)) {
449+
fprintf(stderr, "service_access must be an array of string\n");
450+
status = 0;
451+
goto NPDM_BUILD_END;
452+
}
453+
is_host = 0;
454+
service_name = service->valuestring;
455+
}
456+
457+
int cur_srv_len = strlen(service_name);
402458
if (cur_srv_len > 8 || cur_srv_len == 0) {
403459
fprintf(stderr, "Services must have name length 1 <= len <= 8!\n");
404460
status = 0;
405461
goto NPDM_BUILD_END;
406462
}
407463
u8 ctrl = (u8)(cur_srv_len - 1);
408-
if (cJSON_IsTrue(service)) {
464+
if (is_host) {
409465
ctrl |= 0x80;
410466
}
411467
sac[sac_size++] = ctrl;
412-
memcpy(sac + sac_size, service->string, cur_srv_len);
468+
memcpy(sac + sac_size, service_name, cur_srv_len);
413469
sac_size += cur_srv_len;
414470
}
471+
472+
415473
memcpy((u8 *)acid + acid->SacOffset, sac, sac_size);
416474
aci0->SacSize = sac_size;
417475
acid->SacSize = sac_size;

0 commit comments

Comments
 (0)