From c35ceeb27413e0e3e6c9e60bb34e067bb3308d89 Mon Sep 17 00:00:00 2001 From: smiRaphi <87574679+smiRaphi@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:11:07 +0200 Subject: [PATCH] Nintendo Switch NSO --- README.md | 1 + patterns/nso.hexpat | 81 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 patterns/nso.hexpat diff --git a/README.md b/README.md index 029dee17..61977250 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | NotepadStateFile | | [`patterns/notepad-state.hexpat`](patterns/notepad-state.hexpat) | Windows Notepad .bin State files | | NotepadWindowState | | [`patterns/notepadwindowstate.hexpat`](patterns/notepadwindowstate.hexpat) | Windows 11 Notepad - Window State .bin file | | NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files | +| NSO | | [`patterns/nso.hexpat`](patterns/nso.hexpat) | Nintendo Switch NSO files | | NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC | | NTFS | | [`patterns/fs/ntfs.hexpat`](patterns/fs/ntfs.hexpat) | NTFS (NT File System) | | NTFS (DFIR) | | [`patterns/DFIR/NTFS.hexpat`](patterns/DFIR/NTFS.hexpat) | Imported by DISK_PARSER.hexpat | diff --git a/patterns/nso.hexpat b/patterns/nso.hexpat new file mode 100644 index 00000000..ba98c394 --- /dev/null +++ b/patterns/nso.hexpat @@ -0,0 +1,81 @@ +#pragma description Nintendo Switch NSO +#pragma author smiRaphi +#pragma magic [ 4E 53 4F 30 ?? 00 00 00 00 00 00 00 ?? 00 00 00] @ 0x00 + +import type.magic; + +struct Data { + u8 tag_size = 4; + if (tag_size > size) tag_size = size; + u8 start[tag_size] @ $ [[name(name + ":start")]]; + padding[size]; // so the size actually shows in the table + u8 end[tag_size] @ ($ - tag_size) [[name(name + ":end")]]; +}; + +struct MOD0 { + padding[4]; + u32 offset; + $ += offset - 8; + + type::Magic<"MOD0"> magic; + u32 dyn_offset; + u32 bss_start_offset; + u32 bss_end_offset; + u32 eh_frame_hdr_start_offset; + u32 eh_frame_hdr_end_offset; + u32 runtime_generated_module_obj_offset; +}; + +bitfield Flags { + bool TextCompress:1; + bool RoCompress:1; + bool DataCompress:1; + bool TextHash:1; + bool RoHash:1; + bool DataHash:1; + bool ExecuteOnlyMemory:1; + bool UseZbicCompression:1; + padding:24; +}; +struct Header { + type::Magic<"NSO0"> magic; + u32 version; + padding[4]; + Flags flags; + u32 text_file_offset; + u32 text_mem_offset; + u32 text_size; + u32 module_name_offset; + u32 ro_file_offset; + u32 ro_mem_offset; + u32 ro_size; + u32 module_name_size; + u32 data_file_offset; + u32 data_mem_offset; + u32 data_size; + u32 bss_size; + u8 module_id[0x20]; + u32 text_file_size; + u32 ro_file_size; + u32 data_file_size; + padding[0x1C]; + u32 embedded_offset; + u32 embedded_size; + u32 dyn_str_offset; + u32 dyn_str_size; + u32 dyn_sym_offset; + u32 dyn_sym_size; + u8 text_hash[0x20]; + u8 ro_hash[0x20]; + u8 data_hash[0x20]; + + char module_name[module_name_size] @ module_name_offset; + + Data text @ text_file_offset [[name(".text")]]; + Data ro @ ro_file_offset [[name(".rodata")]]; + Data data @ data_file_offset [[name(".data")]]; + + if (!flags.TextCompress) MOD0 mod0 @ text_file_offset; +}; + +Header header @ 0;