diff --git a/disc.py b/disc.py index cc49d27..4d8f714 100644 --- a/disc.py +++ b/disc.py @@ -8,28 +8,6 @@ from common import * class WOD: #WiiOpticalDisc - class fsentry: - name = "" - type = 0 - parent = None - offset = 0 - lenght = 0 - - def __init__(self, name, type, parent, offset, len): - self.name = "" - if(parent != None): - self.parent = parent - def path(self): - return parent.path() + "/" + name - - class fsdir(fsentry): - def __init__(self, name, parent): - fsentry.__init__(self, name, parent) - - class fsfile(fsentry): - size = 0 - offset = 0 - class discHeader(Struct): __endian__ = Struct.BE def __format__(self): @@ -84,11 +62,12 @@ class WOD: #WiiOpticalDisc ret += 'Found %i channels (table at 0x%x)\n' % (self.channelsCount, self.chansTableOffset) ret += '\n' ret += 'Partition %i opened (type 0x%x) at 0x%x\n' % (self.partitionOpen, self.partitionType, self.partitionOffset) - ret += '%s' % self.partitionHdr - ret += 'Partition key %s\n' % hexdump(self.partitionKey) - ret += 'Tmd at 0x%x (%x)\n' % (self.tmdOffset, self.tmdSize) - ret += 'main.dol at 0x%x (%x)\n' % (self.dolOffset, self.dolSize) - ret += 'FST at 0x%x (%x)\n' % (self.fstSize, self.fstOffset) + ret += 'Partition name : %s' % self.partitionHdr + ret += 'Partition key : %s\n' % hexdump(self.partitionKey) + ret += 'Partition IOS : IOS%i\n' % self.partitionIos + ret += 'Partition tmd : 0x%x (%x)\n' % (self.tmdOffset, self.tmdSize) + ret += 'Partition main.dol : 0x%x (%x)\n' % (self.dolOffset, self.dolSize) + ret += 'Partition FST : 0x%x (%x)\n' % (self.fstSize, self.fstOffset) ret += '%s\n' % (self.appLdr) return ret @@ -242,7 +221,7 @@ class WOD: #WiiOpticalDisc newFile.size = size newFile.nameOff = nameOff fstDir.addChild(newFile) - #self.markContent(fileOffset, size) + self.markContent(fileOffset, size) return i+1 def openPartition(self, index): @@ -282,6 +261,8 @@ class WOD: #WiiOpticalDisc self.appLdr = self.Apploader().unpack(self.readPartition (0x2440, 32)) self.partitionHdr = self.discHeader().unpack(self.readPartition (0x0, 0x400)) + + self.partitionIos = TMD(self.getPartitionTmd()).getIOSVersion() & 0x00ffffff def getFst(self): fstBuf = self.readPartition(self.fstOffset, self.fstSize) @@ -327,59 +308,27 @@ class WOD: #WiiOpticalDisc def getPartitionMainDol(self): return self.readPartition (self.dolOffset, self.dolSize) - def extractPartition(self, index, fn = ""): +class updateInf(): + def __init__(self, f): + self.buffer = open(f, 'r+b').read() + def __str__(self): + out = '' + + self.buildDate = self.buffer[:0xa] + self.fileCount = struct.unpack('I', self.buffer[0x13:0x13 + 4])[0] + + out += 'This update partition was built on %s and has %i files\n\n' % (self.buildDate, self.fileCount) + out += '[File] [Type] [File name %30s] [Title description ]\n\n' % '' + + for x in range(self.fileCount): + updateEntry = self.buffer[0x2f + x * 0x200:0x2f + (x + 1) * 0x200] + titleType = ord(updateEntry[0]) + titleFile = updateEntry[0x1:0x1 + 0x50] + titleFile = titleFile[:titleFile.find('\x00')] + titleName = updateEntry[0x1 + 0x50:0x1 + 0x50 + 0x40] + titleName = titleName[:titleName.find('\x00')] + out += '[%04i] [0x%02x] [%40s] [%20s]\n' % (x, titleType, titleFile, titleName) + + return out + - if(fn == ""): - fn = os.path.dirname(self.f) + "/" + os.path.basename(self.f).replace(".", "_") + "_out" - try: - origdir = os.getcwd() - os.mkdir(fn) - except: - pass - os.chdir(fn) - - self.fp.seek(0x18) - if(struct.unpack(">I", self.fp.read(4))[0] != 0x5D1C9EA3): - self.fp.seek(-4, 1) - raise ValueError("Not a valid Wii Disc (GC not supported)! Magic: %08x" % struct.unpack(">I", self.fp.read(4))[0]) - - self.fp.seek(partitionoffs) - - tikdata = self.fp.read(0x2A3) - open("tik").write(tikdata) - self.tik = Ticket("tik") - self.titlekey = self.tik.getTitleKey() - - tmdsz = struct.unpack(">I", self.fp.read(4))[0] - tmdoffs = struct.unpack(">I", self.fp.read(4))[0] - - certsz = struct.unpack(">I", self.fp.read(4))[0] - certoffs = struct.unpack(">I", self.fp.read(4))[0] - - h3offs = struct.unpack(">I", self.fp.read(4))[0] << 2 - h3sz = 0x18000 - - dataoffs = struct.unpack(">I", self.fp.read(4))[0] << 2 - datasz = struct.unpack(">I", self.fp.read(4))[0] << 2 - if(tmdoffs != self.fp.tell()): - raise ValueError("TMD is in wrong place, something is fucked...wtf?") - - tmddata = self.fp.read(tmdsz) - open("tmd").write(tmddata) - - self.tmd = TMD("tmd") - - - print tmd.getIOSVersion() - - - fst.seek(dataoffs) - - - - os.chdir("..") - def _recurse(self, parent, names, recursion): - if(recursion == 0): - pass - - diff --git a/savedata.py b/savedata.py index 6ac79ba..b6ec61a 100644 --- a/savedata.py +++ b/savedata.py @@ -3,7 +3,9 @@ import os, struct, subprocess, fnmatch, shutil, urllib, array from Struct import Struct from common import * -from title import * +from title import * +from TPL import * +from PIL import Image class Savegame(): class savegameHeader(Struct): @@ -108,9 +110,10 @@ class Savegame(): ret += 'Wii MAC address %02x:%02x:%02x:%02x:%02x:%02x\n' % (self.bkHdr.wiiMacAddr[0], self.bkHdr.wiiMacAddr[1], self.bkHdr.wiiMacAddr[2], self.bkHdr.wiiMacAddr[3], self.bkHdr.wiiMacAddr[4], self.bkHdr.wiiMacAddr[5]) ret += 'Found %i files for %i bytes\n' % (self.bkHdr.filesCount, self.bkHdr.filesSize) ret += 'Total size : %i bytes\n' % self.bkHdr.totalSize + ret += 'This save is %i blocks wise' % (self.bkHdr.totalSize / 0x20000) return ret - + def extractFiles(self): try: @@ -196,43 +199,60 @@ class Savegame(): self.fileStartOffset = self.fd.tell() + def eraseWiiMac(self): + self.fd.seek(0xF128) + print self.fd.write('\x00' * 6) + def getBanner(self): - return self.bnr.banner + try: + os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId) + except: + pass + + os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId) + + return Image.fromstring("RGBA", (192, 64), TPL('').RGB5A3((192, 64), self.bnr.banner)).save('banner', 'png') def getIcon(self, index): if index < 0 or index > 7 or index > self.iconCount: return -1 + + try: + os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId) + except: + pass + + os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId) + if index == 0: - return self.bnr.icon0 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon0)).save('icon' + str(index), 'png') if index == 1: - return self.bnr.icon1 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon1)).save('icon' + str(index), 'png') if index == 2: - return self.bnr.icon2 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon2)).save('icon' + str(index), 'png') if index == 3: - return self.bnr.icon3 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon3)).save('icon' + str(index), 'png') if index == 4: - return self.bnr.icon4 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon4)).save('icon' + str(index), 'png') if index == 5: - return self.bnr.icon5 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon5)).save('icon' + str(index), 'png') if index == 6: - return self.bnr.icon6 + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon6)).save('icon' + str(index), 'png') if index == 7: - return self.bnr.icon7 - - def eraseWiiMac(self): - self.fd.seek(0xF128) - print self.fd.write('\x00' * 6) + return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon7)).save('icon' + str(index), 'png') def getIconsCount(self): return self.iconCount def getSaveString(self, string): - if string == 'GAMEID': + if string == 'id': return self.bkHdr.gameId - elif string == 'GAMETITLE': + elif string == 'title': return self.bnr.gameTitle - elif string == 'GAMESUBTITLE': + elif string == 'subtitle': return self.bnr.gameSubTitle + elif string == 'mac': + return self.bkHdr.wiiMacAddr[0] + ':' + self.bkHdr.wiiMacAddr[1] + ':' + self.bkHdr.wiiMacAddr[2] + ':' + self.bkHdr.wiiMacAddr[3] + ':' + self.bkHdr.wiiMacAddr[4] + ':' + self.bkHdr.wiiMacAddr[5] def getFilesCount(self): return self.bkHdr.filesCount diff --git a/tests/fakesign.py b/tests/fakesign.py new file mode 100644 index 0000000..5bebafe --- /dev/null +++ b/tests/fakesign.py @@ -0,0 +1,30 @@ +from disc import * +from title import * +from Struct import Struct +import os + +def fakesignPartition(self, iso, index) + iso = WOD(iso) + iso.openPartition(index) + fstBuf = iso.getFst() " + fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'appldr.bin', 'w+b') + fn.write(iso.getPartitionApploader()) #saved to cwd/GAMEID/PARTITION/file + fn.close() + fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'h3.bin', 'w+b') + fn.write(iso.getPartitionH3Table()) + fn.close() + fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'main.dol', 'w+b') + fn.write(iso.getPartitionMainDol()) + fn.close() + fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'fst.bin', 'w+b') + fn.write(fstBuf) + fn.close() + fileNumber = struct.unpack(">I", fstBuf[0x8:0xc])[0] + fileObject = iso.fstObject("", iso) + iso.parseFst(fstBuf, fstBuf[12 * fileNumber:], 0, fileObject) + fileObject.write(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/") + fileObject.close() + isoTik = Ticket(iso.getPartitionTik()) + isoTik.dump(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + "tik") + isoTMD = TMD(iso.getPartitionTmd()) + isoTMD.dump(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + "tmd") diff --git a/tests/testLOC.py b/tests/testLOC.py new file mode 100644 index 0000000..c70524a --- /dev/null +++ b/tests/testLOC.py @@ -0,0 +1,9 @@ +from formats import locDat + +sdLoc = locDat('/home/giuseppe/Scrivania/sysmenu/loc.dat') + +print '%s' % sdLoc + +#concorsiMii = sdLoc.getTitle(0, 0, 0) +sdLoc.delTitle(0, 0, 0) + diff --git a/tests/testSAVE.py b/tests/testSAVE.py new file mode 100644 index 0000000..85c9d09 --- /dev/null +++ b/tests/testSAVE.py @@ -0,0 +1,9 @@ +from savedata import * + +save = Savegame('/home/giuseppe/Scrivania/data' + str(4) + '.bin') +save.analyzeHeader() +print '%s' % save +save.getBanner() +for i in range(save.getIconsCount()): + save.getIcon(i) +save.extractFiles()