def fileName(self): bt = None if not self.titleId in Titles.keys(): if not Title.getBaseId(self.titleId) in Titles.keys(): Print.info('could not find title key for ' + str(self.titleId) + ' or ' + str(Title.getBaseId(self.titleId))) return None bt = Titles.get(Title.getBaseId(self.titleId)) t = Title() t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' + bt.name) else: t = Titles.get(self.titleId) if not t: Print.error('could not find title id ' + str(self.titleId)) return None try: if not t.baseId in Titles.keys(): Print.info('could not find baseId for ' + self.path) return None except BaseException as e: print('exception: could not find title id ' + str(self.titleId) + ' ' + str(e)) return None bt = Titles.get(t.baseId) if t.isDLC: format = Config.paths.getTitleDLC(not self.hasValidTicket) elif t.isDemo: if t.idExt != 0: format = Config.paths.getTitleDemoUpdate( not self.hasValidTicket) else: format = Config.paths.getTitleDemo(not self.hasValidTicket) elif t.idExt != 0: format = Config.paths.getTitleUpdate(not self.hasValidTicket) else: format = Config.paths.getTitleBase(not self.hasValidTicket) format = format.replace('{id}', self.cleanFilename(t.id)) format = format.replace('{region}', self.cleanFilename(t.getRegion() or '')) format = format.replace('{name}', self.cleanFilename(t.getName() or '')) format = format.replace('{version}', str(self.getVersion() or 0)) format = format.replace('{baseId}', self.cleanFilename(bt.id)) baseName = self.cleanFilename(bt.getName() or '') result = format.replace('{baseName}', baseName) while (len(os.path.basename(result).encode('utf-8')) > 240 and len(baseName) > 3): baseName = baseName[:-1] result = format.replace('{baseName}', baseName) return result
def title(self): if not self.titleId: raise IOError('NSP no titleId set') if self.titleId in Titles.keys(): return Titles.get(self.titleId) t = Title.Title() t.setId(self.titleId) Titles.data()[self.titleId] = t return t
def open(self, file=None, mode='rb', cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): super(NcaHeader, self).open(file, mode, cryptoType, cryptoKey, cryptoCounter) self.rewind() self.signature1 = self.read(0x100) self.signature2 = self.read(0x100) self.magic = self.read(0x4) self.isGameCard = self.readInt8() self.contentType = self.readInt8() try: self.contentType = Fs.Type.Content(self.contentType) except: pass self.cryptoType = self.readInt8() self.keyIndex = self.readInt8() self.size = self.readInt64() self.titleId = hx(self.read(8)[::-1]).decode('utf-8').upper() self.contentIndex = self.readInt32() self.sdkVersion = self.readInt32() self.cryptoType2 = self.readInt8() self.read(0xF) # padding self.rightsId = hx(self.read(0x10)) if self.magic not in [b'NCA3', b'NCA2']: raise Exception('Failed to decrypt NCA header: ' + str(self.magic)) self.sectionHashes = [] for i in range(4): self.sectionTables.append(SectionTableEntry(self.read(0x10))) for i in range(4): self.sectionHashes.append(self.sectionTables[i]) self.masterKey = (self.cryptoType if self.cryptoType > self.cryptoType2 else self.cryptoType2) - 1 if self.masterKey < 0: self.masterKey = 0 self.encKeyBlock = self.getKeyBlock() #for i in range(4): # offset = i * 0x10 # key = encKeyBlock[offset:offset+0x10] # Print.info('enc %d: %s' % (i, hx(key))) #crypto = aes128.AESECB(Keys.keyAreaKey(self.masterKey, 0)) self.keyBlock = Keys.unwrapAesWrappedTitlekey(self.encKeyBlock, self.masterKey) self.keys = [] for i in range(4): offset = i * 0x10 key = self.keyBlock[offset:offset + 0x10] #Print.info('dec %d: %s' % (i, hx(key))) self.keys.append(key) if self.hasTitleRights(): titleRightsTitleId = self.rightsId.decode()[0:16].upper() if titleRightsTitleId in Titles.keys() and Titles.get( titleRightsTitleId).key: self.titleKeyDec = Keys.decryptTitleKey( uhx(Titles.get(titleRightsTitleId).key), self.masterKey) else: Print.info('could not find title key!') else: self.titleKeyDec = self.key() return True
def fileName(self, forceNsp=False): bt = None if self.titleId not in Titles.keys(): if not Title.getBaseId(self.titleId) in Titles.keys(): Print.error('could not find base title for ' + str(self.titleId) + ' or ' + str(Title.getBaseId(self.titleId))) return None bt = Titles.get(Title.getBaseId(self.titleId)) t = Title.Title() if bt.name is not None: t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' + bt.name) else: t.setId(self.titleId) else: t = Titles.get(self.titleId) if not t: Print.error('could not find title id ' + str(self.titleId)) return None try: if t.baseId not in Titles.keys(): Print.info('could not find baseId for ' + self.path) return None except BaseException as e: Print.error('exception: could not find title id ' + str(self.titleId) + ' ' + str(e)) return None bt = Titles.get(t.baseId) isNsx = not self.hasValidTicket and not forceNsp try: if t.isDLC: format = Config.paths.getTitleDLC(isNsx, self.path) elif t.isDemo: if t.idExt != 0: format = Config.paths.getTitleDemoUpdate(isNsx, self.path) else: format = Config.paths.getTitleDemo(isNsx, self.path) elif t.idExt != 0: if bt and bt.isDemo: format = Config.paths.getTitleDemoUpdate(isNsx, self.path) else: format = Config.paths.getTitleUpdate(isNsx, self.path) else: format = Config.paths.getTitleBase(isNsx, self.path) except BaseException as e: Print.error('calc path exception: ' + str(e)) return None if not format: return None newName = self.cleanFilename(t.getName() or '') format = format.replace('{id}', self.cleanFilename(t.id)) format = format.replace( '{region}', self.cleanFilename(t.getRegion() or bt.getRegion())) format = format.replace('{name}', newName) format = format.replace('{version}', str(self.getVersion() or 0)) format = format.replace('{baseId}', self.cleanFilename(bt.id)) if '{cr}' in format: format = format.replace('{cr}', str(self.getCr())) if '{icr}' in format: format = format.replace('{icr}', str(self.getCr(True))) bn = os.path.basename(self.path) if (not newName or len(newName) == 0) and not bn.upper().startswith(t.id.upper()): Print.error('could not get new name for ' + bn) return os.path.join(os.path.dirname(format), os.path.basename(self.path)) baseName = self.cleanFilename(bt.getName() or '') if not baseName or len(baseName) == 0: baseName = os.path.basename(self.path) result = format.replace('{baseName}', baseName) while (len(os.path.basename(result).encode('utf-8')) > 240 and len(baseName) > 3): baseName = baseName[:-1] result = format.replace('{baseName}', baseName) return os.path.abspath(result)