def maketitleid(self, l): l = list(reversed(l)) #stupid non-subscriptable iterators... id = rawutil.hex(l[0:4]) gamecode = list(reversed(list(l[4]))) id += rawutil.hex(gamecode) cntp = CONTENT_TYPES[l[3]] return id, cntp
def extract_sci(self): root = self.tree['SCI'] data = self.unpack(EXTHEADER_SCI_STRUCT, self.sci) root['App-Title'] = data[0].decode('ascii') reserved = data[1] flags = data[2] root['Compress-ExeFS-code'] = bool(flags & 1) root['SD-Application'] = bool(flags & 2) root['Remaster-version'] = data[3] text_codesetinfo = data[4] root['Stack-size'] = data[5] ro_codesetinfo = data[6] reserved = data[7] data_codesetinfo = data[8] root['BSS-size'] = data[9] dependencies = data[10] system_info = data[11] root['Text-code-set-info'] = OrderedDict() sub = root['Text-code-set-info'] sub['Adress'] = txtree.hexformat(text_codesetinfo[0], 8) sub['Physical-region-size'] = text_codesetinfo[1] sub['Size'] = text_codesetinfo[2] root['Read-Only-code-set-info'] = OrderedDict() sub = root['Read-Only-code-set-info'] sub['Adress'] = txtree.hexformat(ro_codesetinfo[0], 8) sub['Physical-region-size'] = ro_codesetinfo[1] sub['Size'] = ro_codesetinfo[2] root['Data-code-set-info'] = OrderedDict() sub = root['Data-code-set-info'] sub['Adress'] = txtree.hexformat(data_codesetinfo[0], 8) sub['Physical-region-size'] = data_codesetinfo[1] sub['Size'] = data_codesetinfo[2] root['Dependencies'] = [ rawutil.hex(el, 16) for el in dependencies if el != 0 ] root['System-Info'] = OrderedDict() sys = root['System-Info'] sys['Savedata-size'] = system_info[0] sys['Jump-ID'] = rawutil.hex(system_info[1], 16) reserved = system_info[2]
def readheader(self,): data = self.unpack_from(NCCH_HEADER_STRUCT, self.data, 0) self.rsa_signature = data[0] magic = data[1] if magic != b'NCCH': error.InvalidMagicError('Invalid magic %s, expected NCCH' % byterepr(magic)) self.content_size = data[2] #In media units self.partition_id = rawutil.hex(data[3], 16) self.maker_code = data[4] self.version = data[5] self.id_hash = data[6] self.tid_high = rawutil.hex(data[7] >> 32, 8) self.tid_low = rawutil.hex(data[7] & 0xffffffff, 8) #reserved = data[8] self.logo_hash = data[9] self.product_code = data[10].decode('ascii') self.extheader_hash = data[11] self.extheader_size = data[12] #in bytes #reserved = data[13] ncchflags = data[14] self.crypto_keyslot = CRYPTO_KEYSLOTS[ncchflags[3]] self.platform = PLATFORMS[ncchflags[4]] self.content_types = self.extract_contenttypes(ncchflags[5]) self.unitsize = 0x200 << ncchflags[6] flags = ncchflags[7] self.fixed_cryptokey = bool(flags & 0x01) self.has_romfs = not bool(flags & 0x02) self.has_crypto = not bool(flags & 0x04) self.use_new_keyYgen = bool(flags & 0x20) #Everything is in media units self.plain_offset = data[15] self.plain_size = data[16] self.logo_offset = data[17] self.logo_size = data[18] self.exefs_offset = data[19] self.exefs_size = data[20] self.exefs_hashregion_size = data[21] #reserved = data[22] self.romfs_offset = data[23] self.romfs_size = data[24] self.romfs_hashregion_size = data[25] #reserved = data[26] self.exefs_hash = data[27] self.romfs_hash = data[28]
def extract_data(self): tree = OrderedDict() tree['NCCH'] = OrderedDict() root = tree['NCCH'] root['PartitionID'] = self.partition_id, 16 root['TitleID'] = {'High': self.tid_high, 'Low ': self.tid_low} root['Product-code'] = self.product_code root['Version'] = self.version root['Makercode'] = self.maker_code root['Platform'] = self.platform root['Content-types'] = self.content_types root['Has-RomFS'] = self.has_romfs root['Has-Crypto'] = self.has_crypto root['Fixed-Crypto-key'] = self.fixed_cryptokey root['Crypto-Keyslot'] = self.crypto_keyslot root['Uses-new-KeyY-generator'] = self.use_new_keyYgen root['RSA-signature'] = self.rsa_signature root['Hashes'] = OrderedDict() hashes = root['Hashes'] hashes['ExeFS'] = rawutil.hex(self.exefs_hash) hashes['RomFS'] = rawutil.hex(self.romfs_hash) hashes['Logo'] = rawutil.hex(self.logo_hash) hashes['ExtHeader'] = rawutil.hex(self.extheader_hash) hashes['ID'] = rawutil.hex(self.id_hash, 8) root['Structure'] = OrderedDict() struct = root['Structure'] struct['Media-size-unit'] = self.unitsize struct['Comment'] = 'All these sizes and offsets are in bytes' struct['ExtHeader-size'] = self.extheader_size struct['Plain-offset'] = self.plain_offset struct['Plain-size'] = self.plain_size struct['Logo-offset'] = self.logo_offset struct['Logo-size'] = self.logo_size struct['ExeFS-offset'] = self.exefs_offset struct['ExeFS-size'] = self.exefs_size struct['ExeFS-HashRegion-size'] = self.exefs_hashregion_size struct['RomFS-offset'] = self.romfs_offset struct['RomFS-size'] = self.romfs_size struct['RomFS-HashRegion-size'] = self.romfs_hashregion_size final = txtree.dump(tree) write(final, self.outdir + 'header.txt')
def extract_aci(self, raw, root): root['ARM11-Local-system-capabilities'] = OrderedDict() arm11_sys = root['ARM11-Local-system-capabilities'] root['ARM11-Kernel-capabilities'] = OrderedDict() arm11_kernel = root['ARM11-Kernel-capabilities'] root['ARM9-Access-control'] = OrderedDict() arm9_access = root['ARM9-Access-control'] data = self.unpack(EXTHEADER_ACI_STRUCT, raw) arm11_sys['ProgramID'] = rawutil.hex(data[0][0], 16) arm11_sys['Core-version'] = rawutil.hex(data[0][1], 8) flag1, flag2, flag0, priority = data[0][2:6] arm11_sys['Enable-L2-cache'] = bool(flag1 & 1) arm11_sys['CPU-speed-804MHz'] = bool(flag1 & 2) arm11_sys['New3DS-system-mode'] = NEW3DS_SYSTEM_MODES[flag2 & 0b111] arm11_sys['Ideal-processor'] = flag0 & 0b11 arm11_sys['Affinity-mask'] = (flag0 & 0b1100) >> 2 arm11_sys['Old3DS-system-mode'] = OLD3DS_SYSTEM_MODES[ (flag0 & 0b11110000) >> 4] arm11_sys['Priority'] = priority arm11_sys['Resources-limits-descriptors'] = data[0][6] arm11_sys['Storage-info'] = OrderedDict() stor = arm11_sys['Storage-info'] sub = data[0][7] stor['ExtData-ID'] = rawutil.hex(sub[0], 16) stor['System-Savedata-ID'] = rawutil.hex(sub[1], 16) stor['Accessible-unique-ID'] = rawutil.hex(sub[2], 16) fs_access = sub[3] stor['FileSystem-access-info'] = self.extract_fsaccess(fs_access) otherattrs = (fs_access & 0xff00000000000000) >> 56 stor['Use-RomFS'] = not bool(otherattrs & 1) stor['Use-Extended-Savedata-access'] = bool(otherattrs & 2) arm11_sys['Services-access'] = [ el[0].rstrip(b'\x00').decode('ascii') for el in data[0][8] if el[0] != bytes(8) ] reserved = data[0][9] arm11_sys['Resource-limit-category'] = RESOURCE_LIMIT_CATEGORIES[ data[0][10]] map_adressrange = [] descs = data[1][0] reserved = data[1][1] for desc in descs: type = (desc & 0xfff00000) >> 20 if not type & 0b000100000000: arm11_kernel['Interrupt-info'] = desc & 0x0fffffff elif not type & 0b000010000000: arm11_kernel['System-call-mask-table-index'] = ( desc & 0x03000000) >> 24 arm11_kernel['System-call-mask'] = desc & 0x00ffffff elif not type & 0b000000100000: arm11_kernel['Kernel-Major-Version'] = (desc & 0xff00) >> 8 arm11_kernel['Kernel-Minor-Version'] = desc & 0xff elif not type & 0b000000010000: arm11_kernel['Handle-Table-size'] = desc & 0x3ffff elif not type & 0b000000001000: arm11_kernel['Kernel-Flags'] = self.extract_kernelflags(desc) elif not type & 0b000000000110: map_adressrange.append(desc & 0x7ffff) elif not type & 0b000000000001: arm11_kernel['Mapped-Memory-page'] = desc & 0x7ffff arm11_kernel['Mapped-Memory-Read-Only'] = bool(desc & 0x100000) if map_adressrange != []: arm11_kernel['Mapped-Adress-range'] = map_adressrange desc = data[2][0] arm9_access['Accesses'] = self.extract_arm9accesses(desc) arm9_access['ARM9-Descriptor-version'] = data[2][2]
def readpai1(self, ptr): data = self.unpack_from(pai1_SECTION, self.file, ptr) magic = data[0] if magic != b'pai1': error.InvalidMagicError('Invalid pai1 magic %s' % byterepr(magic)) seclen = data[1] framesize = data[2] flags = data[3] #padding = data[4] timgcount = data[5] entrycount = data[6] entryoffset = data[7] timgoffsets = data[8] self.root['pai1'] = OrderedDict() node = self.root['pai1'] node['frame-size'] = framesize node['flags'] = flags timgs = [] for (offset, ) in timgoffsets: timgs.append( self.unpack_from('n', self.file, ptr + offset + 20)[0].decode('ascii')) node['timgs'] = timgs offsets = [] for i in range(entrycount): offsets.append( self.unpack_from('I', self.file, ptr + entryoffset + i * 4)[0]) node['entries'] = [] for offset in offsets: entry = OrderedDict() data = self.unpack_from(pai1_ENTRY, self.file, offset + ptr) entry['name'] = data[0] tagcount = data[1] ismaterial = data[2] #padding = data[3] tagoffsets = data[4] entry['tags'] = [] for (tagoffset, ) in tagoffsets: tagpos = ptr + offset + tagoffset tag = OrderedDict() data = self.unpack_from(pai1_TAG, self.file, tagpos) type = data[0].decode('ascii') entrycount = data[1] #padding = data[2] suboffsets = data[3] tag['type'] = type tag['entries'] = [] for (suboffset, ) in suboffsets: pos = tagpos + suboffset tagentry = OrderedDict() data = self.unpack_from(pai1_TAGENTRY, self.file, pos) type1 = data[0] type2 = data[1] datatype = data[2] coordcount = data[3] totag = data[4] tagentry['type1'] = type1 tagentry['type2'] = self.gettype(type2, type) tagentry['data-type'] = datatype tagentry['coord-count'] = coordcount tagentry['offset-to-tag'] = rawutil.hex(totag, 8) if datatype == 0x100: tagentry['frame'], tagentry[ 'data2'] = self.unpack_from('2f', self.file) elif datatype == 0x200: tagentry['frame'], tagentry['value'], tagentry[ 'blend'] = self.unpack_from('3f', self.file) tag['entries'].append(tagentry) entry['tags'].append(tag) node['entries'].append(entry)