From 3681a0fd1d12c725e45aa2c4c7b94c653db0bc6c Mon Sep 17 00:00:00 2001 From: "Giuseppe (LemonBoy)" Date: Wed, 24 Jun 2009 12:02:36 +0200 Subject: [PATCH] zomg we haz imagez 4 saves! (color are screwed sometimes :|) --- disc.py | 115 +++++++++++++--------------------------------- savedata.py | 56 ++++++++++++++-------- tests/testLOC.py | 9 ++++ tests/testSAVE.py | 9 ++++ 4 files changed, 87 insertions(+), 102 deletions(-) create mode 100644 tests/testLOC.py create mode 100644 tests/testSAVE.py diff --git a/disc.py b/disc.py index bc81b1e..6b31b3f 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 @@ -119,7 +98,7 @@ class WOD: #WiiOpticalDisc blockStart = offset / 0x7C00 blockLen = (align(size, 0x7C00)) / 0x7C00 - for x in range(blockStart, blockStart + blockLen): + for x in range(blockStart, blockLen): try: self.markedBlocks.index(blockStart + x) except: @@ -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): @@ -327,59 +306,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/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()