mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-19 15:25:34 -04:00
Merge git@github.com:icefire/Wii.py
This commit is contained in:
commit
8d928288dc
105
disc.py
105
disc.py
@ -8,28 +8,6 @@ from common import *
|
|||||||
|
|
||||||
|
|
||||||
class WOD: #WiiOpticalDisc
|
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):
|
class discHeader(Struct):
|
||||||
__endian__ = Struct.BE
|
__endian__ = Struct.BE
|
||||||
def __format__(self):
|
def __format__(self):
|
||||||
@ -84,11 +62,12 @@ class WOD: #WiiOpticalDisc
|
|||||||
ret += 'Found %i channels (table at 0x%x)\n' % (self.channelsCount, self.chansTableOffset)
|
ret += 'Found %i channels (table at 0x%x)\n' % (self.channelsCount, self.chansTableOffset)
|
||||||
ret += '\n'
|
ret += '\n'
|
||||||
ret += 'Partition %i opened (type 0x%x) at 0x%x\n' % (self.partitionOpen, self.partitionType, self.partitionOffset)
|
ret += 'Partition %i opened (type 0x%x) at 0x%x\n' % (self.partitionOpen, self.partitionType, self.partitionOffset)
|
||||||
ret += '%s' % self.partitionHdr
|
ret += 'Partition name : %s' % self.partitionHdr
|
||||||
ret += 'Partition key %s\n' % hexdump(self.partitionKey)
|
ret += 'Partition key : %s\n' % hexdump(self.partitionKey)
|
||||||
ret += 'Tmd at 0x%x (%x)\n' % (self.tmdOffset, self.tmdSize)
|
ret += 'Partition IOS : IOS%i\n' % self.partitionIos
|
||||||
ret += 'main.dol at 0x%x (%x)\n' % (self.dolOffset, self.dolSize)
|
ret += 'Partition tmd : 0x%x (%x)\n' % (self.tmdOffset, self.tmdSize)
|
||||||
ret += 'FST at 0x%x (%x)\n' % (self.fstSize, self.fstOffset)
|
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)
|
ret += '%s\n' % (self.appLdr)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@ -242,7 +221,7 @@ class WOD: #WiiOpticalDisc
|
|||||||
newFile.size = size
|
newFile.size = size
|
||||||
newFile.nameOff = nameOff
|
newFile.nameOff = nameOff
|
||||||
fstDir.addChild(newFile)
|
fstDir.addChild(newFile)
|
||||||
#self.markContent(fileOffset, size)
|
self.markContent(fileOffset, size)
|
||||||
return i+1
|
return i+1
|
||||||
|
|
||||||
def openPartition(self, index):
|
def openPartition(self, index):
|
||||||
@ -283,6 +262,8 @@ class WOD: #WiiOpticalDisc
|
|||||||
self.appLdr = self.Apploader().unpack(self.readPartition (0x2440, 32))
|
self.appLdr = self.Apploader().unpack(self.readPartition (0x2440, 32))
|
||||||
self.partitionHdr = self.discHeader().unpack(self.readPartition (0x0, 0x400))
|
self.partitionHdr = self.discHeader().unpack(self.readPartition (0x0, 0x400))
|
||||||
|
|
||||||
|
self.partitionIos = TMD(self.getPartitionTmd()).getIOSVersion() & 0x00ffffff
|
||||||
|
|
||||||
def getFst(self):
|
def getFst(self):
|
||||||
fstBuf = self.readPartition(self.fstOffset, self.fstSize)
|
fstBuf = self.readPartition(self.fstOffset, self.fstSize)
|
||||||
return fstBuf
|
return fstBuf
|
||||||
@ -327,59 +308,27 @@ class WOD: #WiiOpticalDisc
|
|||||||
def getPartitionMainDol(self):
|
def getPartitionMainDol(self):
|
||||||
return self.readPartition (self.dolOffset, self.dolSize)
|
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 = ''
|
||||||
|
|
||||||
if(fn == ""):
|
self.buildDate = self.buffer[:0xa]
|
||||||
fn = os.path.dirname(self.f) + "/" + os.path.basename(self.f).replace(".", "_") + "_out"
|
self.fileCount = struct.unpack('I', self.buffer[0x13:0x13 + 4])[0]
|
||||||
try:
|
|
||||||
origdir = os.getcwd()
|
|
||||||
os.mkdir(fn)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
os.chdir(fn)
|
|
||||||
|
|
||||||
self.fp.seek(0x18)
|
out += 'This update partition was built on %s and has %i files\n\n' % (self.buildDate, self.fileCount)
|
||||||
if(struct.unpack(">I", self.fp.read(4))[0] != 0x5D1C9EA3):
|
out += '[File] [Type] [File name %30s] [Title description ]\n\n' % ''
|
||||||
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)
|
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)
|
||||||
|
|
||||||
tikdata = self.fp.read(0x2A3)
|
return out
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
66
savedata.py
66
savedata.py
@ -4,6 +4,8 @@ from Struct import Struct
|
|||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
from title import *
|
from title import *
|
||||||
|
from TPL import *
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
class Savegame():
|
class Savegame():
|
||||||
class savegameHeader(Struct):
|
class savegameHeader(Struct):
|
||||||
@ -108,6 +110,7 @@ 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 += '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 += 'Found %i files for %i bytes\n' % (self.bkHdr.filesCount, self.bkHdr.filesSize)
|
||||||
ret += 'Total size : %i bytes\n' % self.bkHdr.totalSize
|
ret += 'Total size : %i bytes\n' % self.bkHdr.totalSize
|
||||||
|
ret += 'This save is %i blocks wise' % (self.bkHdr.totalSize / 0x20000)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -196,43 +199,60 @@ class Savegame():
|
|||||||
|
|
||||||
self.fileStartOffset = self.fd.tell()
|
self.fileStartOffset = self.fd.tell()
|
||||||
|
|
||||||
|
def eraseWiiMac(self):
|
||||||
|
self.fd.seek(0xF128)
|
||||||
|
print self.fd.write('\x00' * 6)
|
||||||
|
|
||||||
def getBanner(self):
|
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):
|
def getIcon(self, index):
|
||||||
if index < 0 or index > 7 or index > self.iconCount:
|
if index < 0 or index > 7 or index > self.iconCount:
|
||||||
return -1
|
return -1
|
||||||
if index == 0:
|
|
||||||
return self.bnr.icon0
|
|
||||||
if index == 1:
|
|
||||||
return self.bnr.icon1
|
|
||||||
if index == 2:
|
|
||||||
return self.bnr.icon2
|
|
||||||
if index == 3:
|
|
||||||
return self.bnr.icon3
|
|
||||||
if index == 4:
|
|
||||||
return self.bnr.icon4
|
|
||||||
if index == 5:
|
|
||||||
return self.bnr.icon5
|
|
||||||
if index == 6:
|
|
||||||
return self.bnr.icon6
|
|
||||||
if index == 7:
|
|
||||||
return self.bnr.icon7
|
|
||||||
|
|
||||||
def eraseWiiMac(self):
|
try:
|
||||||
self.fd.seek(0xF128)
|
os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
print self.fd.write('\x00' * 6)
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon0)).save('icon' + str(index), 'png')
|
||||||
|
if index == 1:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon1)).save('icon' + str(index), 'png')
|
||||||
|
if index == 2:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon2)).save('icon' + str(index), 'png')
|
||||||
|
if index == 3:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon3)).save('icon' + str(index), 'png')
|
||||||
|
if index == 4:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon4)).save('icon' + str(index), 'png')
|
||||||
|
if index == 5:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon5)).save('icon' + str(index), 'png')
|
||||||
|
if index == 6:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon6)).save('icon' + str(index), 'png')
|
||||||
|
if index == 7:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon7)).save('icon' + str(index), 'png')
|
||||||
|
|
||||||
def getIconsCount(self):
|
def getIconsCount(self):
|
||||||
return self.iconCount
|
return self.iconCount
|
||||||
|
|
||||||
def getSaveString(self, string):
|
def getSaveString(self, string):
|
||||||
if string == 'GAMEID':
|
if string == 'id':
|
||||||
return self.bkHdr.gameId
|
return self.bkHdr.gameId
|
||||||
elif string == 'GAMETITLE':
|
elif string == 'title':
|
||||||
return self.bnr.gameTitle
|
return self.bnr.gameTitle
|
||||||
elif string == 'GAMESUBTITLE':
|
elif string == 'subtitle':
|
||||||
return self.bnr.gameSubTitle
|
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):
|
def getFilesCount(self):
|
||||||
return self.bkHdr.filesCount
|
return self.bkHdr.filesCount
|
||||||
|
30
tests/fakesign.py
Normal file
30
tests/fakesign.py
Normal file
@ -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")
|
9
tests/testLOC.py
Normal file
9
tests/testLOC.py
Normal file
@ -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)
|
||||||
|
|
9
tests/testSAVE.py
Normal file
9
tests/testSAVE.py
Normal file
@ -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()
|
Loading…
Reference in New Issue
Block a user