Skip to content

Update NacpStruct to match switchbrew wiki#716

Open
masagrator wants to merge 8 commits intoswitchbrew:masterfrom
masagrator:patch-2
Open

Update NacpStruct to match switchbrew wiki#716
masagrator wants to merge 8 commits intoswitchbrew:masterfrom
masagrator:patch-2

Conversation

@masagrator
Copy link
Contributor

@masagrator masagrator commented Feb 21, 2026

To figure out:

  • Should we do decompression inside nsGetApplicationControlData functions and discard last 0x3000 bytes? Since it's useless on S1.
  • Do everything on stack or allow passing decompression buffer by user?
  • Do we include zlib internally or rely on pacman's Switch-zlib?

@masagrator masagrator marked this pull request as draft February 21, 2026 09:21
@masagrator masagrator marked this pull request as ready for review February 21, 2026 11:24
@DarkMatterCore
Copy link
Contributor

  1. My humble opinion is that even if the decompressed data after 0x3000 isn't used, it is not left unpopulated. As mentioned in the currently open issue report, the SupportedLanguage bitflags do use the new bits for Polish and Thai languages. Even if just for completeness sake, I firmly believe the full 0x6000-byte long block should be preserved, and let the user decide what to do with it.
  2. Let the user take care of passing an output buffer, but make it abundantly clear (e.g. via comments, etc.) that it should have a capacity of at least 0x6000 bytes.
  3. No comments here, this is pretty much the sole reason why I didn't provide a PR myself after figuring out what was going on.

@masagrator
Copy link
Contributor Author

masagrator commented Feb 21, 2026

  1. My humble opinion is that even if the decompressed data after 0x3000 isn't used, it is not left unpopulated. As mentioned in the currently open issue report, the SupportedLanguage bitflags do use the new bits for Polish and Thai languages. Even if just for completeness sake, I firmly believe the full 0x6000-byte long block should be preserved, and let the user decide what to do with it.

We can solve this by providing externally buffer for decompressing as optional argument.
nullptr buffer = no decompression
>= 0x6000 Buffer = 0x6000 buffer will contain full NacpLanguageEntry array and optionally overwrite original NacpStruct.

Something like this:

Result nsGetApplicationControlData2(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u8 flag1, u8 flag2, u64* actual_size, u32* unk, NacpLanguageEntry* langs, size_t langs_size) {
    // Old code here
    if (!langs) 
        return 0;
    return nacp_decompress(buffer, langs, langs_size);
}

or

Result nsGetApplicationControlData2(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u8 flag1, u8 flag2, u64* actual_size, u32* unk, NacpLanguageEntry* langs, size_t langs_size) {
    // Old code here
    if (!langs) 
        return 0;
    rc = nacp_decompress(buffer, langs, langs_size);
    if (R_FAILED(rc))
        return rc;
    memcpy(buffer, langs_size, sizeof(NacpLanguageEntry[16]);
    return 0;
}

Or create new AppControlData struct with new NacpStruct to which we will convert original AppControlData and NacpStruct with NacpLanguageEntry[32], then put on top of it decompressed data.

Something like this:

/// ApplicationControlDataV21
typedef struct {
    NacpStructV21 nacp;         ///< \ref NacpStructV21
    u8 icon[0x20000];           ///< JPEG
} NsApplicationControlDataV21;

Result nsGetApplicationControlData2V21(NsApplicationControlSource source, u64 application_id, NsApplicationControlDataV21* buffer, size_t size, u8 flag1, u8 flag2, u64* actual_size, u32* unk, void* dec_buffer, size_t dec_buffer_size) {
    Result rc = nsGetApplicationControlData2(source, application_id, buffer, flag1, flag2, actual_size, unk);
	if (R_FAILED(rc))
		return rc;
	memmove(&buffer->icon, ((NsApplicationControlData*)buffer)->icon, sizeof(buffer->icon));
	// Our custom decompress function, returns false on fail - but noone stops you from implementing proper result handling
	if (!nacp_decompress(buffer, dec_buffer, dec_buffer_size)) {
		return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
	}
	return 0;
}

@DarkMatterCore
Copy link
Contributor

DarkMatterCore commented Feb 21, 2026

I'm comfortable with any of those options. Let's wait and see what others think about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants