mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-19 15:25:34 -04:00
Fixed FST for disc.py completely, found bad hex offsets in decryptBlock, and fixed/tidied soem other stuff.
This commit is contained in:
parent
f9ba9fbeab
commit
59e8030f38
148
disc.py
148
disc.py
@ -126,15 +126,14 @@ class WOD: #WiiOpticalDisc
|
|||||||
except:
|
except:
|
||||||
self.markedBlocks.append(blockStart + x)
|
self.markedBlocks.append(blockStart + x)
|
||||||
|
|
||||||
print '%s (%i blocks marked)' % (self.markedBlocks, len(self.markedBlocks))
|
#print '%s (%i blocks marked)' % (self.markedBlocks, len(self.markedBlocks))
|
||||||
|
|
||||||
def decryptBlock(self, block):
|
def decryptBlock(self, block):
|
||||||
if len(block) != 0x8000:
|
if len(block) != 0x8000:
|
||||||
raise Exception('Block size too big/small')
|
raise Exception('Block size too big/small')
|
||||||
|
|
||||||
blockIV = block[0x3d0:0x3dF + 1]
|
blockIV = block[0x3d0:0x3e0]
|
||||||
print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
|
#print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
|
||||||
blockData = block[0x0400:0x7FFF]
|
blockData = block[0x0400:0x8000]
|
||||||
|
|
||||||
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
|
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
|
||||||
|
|
||||||
@ -144,18 +143,16 @@ class WOD: #WiiOpticalDisc
|
|||||||
readLen = (align(size, 0x7C00)) / 0x7C00
|
readLen = (align(size, 0x7C00)) / 0x7C00
|
||||||
blob = ''
|
blob = ''
|
||||||
|
|
||||||
print 'Read at 0x%x (Start on %i block, ends at %i block) for %i bytes' % (offset, readStart, readStart + readLen, size)
|
#print 'Read at 0x%x (Start on %i block, ends at %i block) for %i bytes' % (offset, readStart, readStart + readLen, size)
|
||||||
|
|
||||||
self.fp.seek(self.partitionOffset + 0x20000 + (0x8000 * readStart))
|
self.fp.seek(self.partitionOffset + 0x20000 + (0x8000 * readStart))
|
||||||
if readLen == 0:
|
|
||||||
blob += self.decryptBlock(self.fp.read(0x8000))
|
|
||||||
else:
|
|
||||||
for x in range(readLen + 1):
|
for x in range(readLen + 1):
|
||||||
blob += self.decryptBlock(self.fp.read(0x8000))
|
blob += self.decryptBlock(self.fp.read(0x8000))
|
||||||
|
|
||||||
self.markContent(offset, size)
|
self.markContent(offset, size)
|
||||||
|
|
||||||
print 'Read from 0x%x to 0x%x' % (offset, offset + size)
|
#print 'Read from 0x%x to 0x%x' % (offset, offset + size)
|
||||||
offset -= readStart * 0x7C00
|
offset -= readStart * 0x7C00
|
||||||
return blob[offset:offset + size]
|
return blob[offset:offset + size]
|
||||||
|
|
||||||
@ -166,60 +163,91 @@ class WOD: #WiiOpticalDisc
|
|||||||
# FIXMII : Needs testing, extracting the tmd cause to have 10 null bytes in the end instead of 10 useful bytes at start :|
|
# FIXMII : Needs testing, extracting the tmd cause to have 10 null bytes in the end instead of 10 useful bytes at start :|
|
||||||
self.fp.seek(self.partitionOffset + 0x2A4 + offset)
|
self.fp.seek(self.partitionOffset + 0x2A4 + offset)
|
||||||
return self.fp.read(size)
|
return self.fp.read(size)
|
||||||
|
class fstObject(object):
|
||||||
def parseFst(self, fst, names, i, isLast):
|
#TODO: add ability to extract file by path
|
||||||
|
def __init__(self, name, iso=None):
|
||||||
fileName = names[struct.unpack(">I", fst[12 * i:12 * i + 4])[0] & 0x00ffffff]
|
''' do init stuff here '''
|
||||||
fileSize = struct.unpack(">I", fst[12 * i + 8:12 * i + 8 + 4])[0]
|
self.parent = None
|
||||||
|
self.type = 1 #directory: 1, file:0
|
||||||
|
self.name = name
|
||||||
|
self.nameOff = 0
|
||||||
|
self.fileOffset = 0
|
||||||
|
self.size = 0
|
||||||
|
self.children = []
|
||||||
|
self.iso = iso
|
||||||
|
def addChild(self, child):
|
||||||
|
if self.type == 0:
|
||||||
|
raise Exception('I am not a directory.')
|
||||||
|
child.parent = self
|
||||||
|
self.children.append(child)
|
||||||
|
def getISO(self):
|
||||||
|
if(self.parent == None):
|
||||||
|
return self.iso
|
||||||
|
return self.parent.getISO()
|
||||||
|
def getList(self, pad=0):
|
||||||
|
if self.type == 0:
|
||||||
|
return ("\t" * pad) + self.getPath() + "\n"
|
||||||
|
str = "%s[%s]\n" % ("\t" * (pad), self.getPath())
|
||||||
|
for child in self.children:
|
||||||
|
str += child.getList(pad+1)
|
||||||
|
return str
|
||||||
|
def count(self):
|
||||||
|
if self.type == 0:
|
||||||
|
return 1
|
||||||
|
i = 0
|
||||||
|
for child in self.children:
|
||||||
|
i += child.count()
|
||||||
|
return i
|
||||||
|
def getPath(self):
|
||||||
|
if(self.parent == None):
|
||||||
|
return "/"
|
||||||
|
if(self.type == 1):
|
||||||
|
return self.parent.getPath() + self.name + "/"
|
||||||
|
return self.parent.getPath() + self.name
|
||||||
|
def write(self, cwd):
|
||||||
|
if(self.type==0):
|
||||||
|
print cwd + self.getPath()
|
||||||
|
#print self.nameOff
|
||||||
|
open(cwd + self.getPath(), 'w+b').write(self.getISO().readPartition(self.fileOffset, self.size))
|
||||||
|
if(self.type==1):
|
||||||
|
if(self.parent != None):
|
||||||
|
try:
|
||||||
|
os.makedirs(cwd + self.getPath())
|
||||||
|
except:
|
||||||
|
j = None
|
||||||
|
for child in self.children:
|
||||||
|
child.write(cwd)
|
||||||
|
def parseFst(self, fst, names, i, fstDir):
|
||||||
|
size = struct.unpack(">I", fst[12 * i + 8:12 * i + 8 + 4])[0]
|
||||||
|
nameOff = struct.unpack(">I", fst[12 * i:12 * i + 4])[0] & 0x00ffffff
|
||||||
|
fileName = names[nameOff:]
|
||||||
|
fileName = fileName[:fileName.find('\0')]
|
||||||
|
|
||||||
if i == 0:
|
if i == 0:
|
||||||
for j in range(1, fileSize):
|
j = 1
|
||||||
self.parseFst(fst, names, j, (j == fileSize - 1))
|
while(j<size):
|
||||||
return fileSize
|
j = self.parseFst(fst, names, j, fstDir)
|
||||||
|
return size
|
||||||
if fst[12 * i]:
|
if fst[12 * i] == '\x01':
|
||||||
parentDir = struct.unpack(">I", fst[12 * i + 4:12 * i + 4 + 4])[0]
|
newDir = self.fstObject(fileName)
|
||||||
isLast = struct.unpack(">I", fst[12 * parentDir + 8:12 * parentDir + 8 + 4] == fileSize)[0]
|
j = i+1
|
||||||
|
while(j<size):
|
||||||
for j in range(1, fileSize):
|
j = self.parseFst(fst, names, j, newDir)
|
||||||
self.parseFst(fst, names, j, (j == fileSize - 1))
|
fstDir.addChild(newDir)
|
||||||
|
return size
|
||||||
return fileSize
|
|
||||||
else:
|
else:
|
||||||
fileOffset = 4 * struct.unpack(">I", fst[12 * i + 4, 12 * i + 4 + 4])
|
fileOffset = 4 * struct.unpack(">I", fst[12 * i + 4: 12 * i + 4 + 4])[0]
|
||||||
markContent(fileOffset, fileSize)
|
newFile = self.fstObject(fileName)
|
||||||
open(fileName, 'w+b').write(self.readPartition(fileOffset, fileSize))
|
newFile.type = 0
|
||||||
|
newFile.fileOffset = fileOffset
|
||||||
"""def parseFst(self, buffer):
|
newFile.size = size
|
||||||
rootFiles = struct.unpack('>I', buffer[8:12])[0]
|
newFile.nameOff = nameOff
|
||||||
namesTable = buffer[12 * (rootFiles):]
|
fstDir.addChild(newFile)
|
||||||
|
#self.markContent(fileOffset, size)
|
||||||
open('fst.bin', 'w+b').write(buffer)
|
return i+1
|
||||||
|
|
||||||
for i in range(1, rootFiles):
|
|
||||||
fstTableEntry = buffer[12 * i:12 * (i + 1)]
|
|
||||||
|
|
||||||
if fstTableEntry[0] == '\x01':
|
|
||||||
fileType = 1
|
|
||||||
else:
|
|
||||||
fileType = 0
|
|
||||||
|
|
||||||
temp = struct.unpack('>I', fstTableEntry[0x0:0x4])[0]
|
|
||||||
nameOffset = struct.unpack('>I', fstTableEntry[0x0:0x4])[0] & 0x00ffffff
|
|
||||||
fileName = namesTable[nameOffset:].split('\x00')[0]
|
|
||||||
#print '%s' % namesTable[nameOffset:]
|
|
||||||
#print '%s %s\n' % (namesTable[nameOffset:].split('\x00')[0], namesTable[nameOffset:].split('\x00')[1])
|
|
||||||
fileOffset = 4 * (struct.unpack('>I', fstTableEntry[0x4:0x8])[0])
|
|
||||||
fileLenght = struct.unpack('>I', fstTableEntry[0x8:0x0c])[0]
|
|
||||||
if fileName == '':
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
print '%s [%i] [0x%X] [0x%X] [0x%X]' % (fileName, fileType, fileOffset, fileLenght, nameOffset)
|
|
||||||
|
|
||||||
os.chdir('..')"""
|
|
||||||
|
|
||||||
def openPartition(self, index):
|
def openPartition(self, index):
|
||||||
if index > self.partitionCount:
|
if index+1 > self.partitionCount:
|
||||||
raise ValueError('Partition index too big')
|
raise ValueError('Partition index too big')
|
||||||
|
|
||||||
self.partitionOpen = index
|
self.partitionOpen = index
|
||||||
@ -258,8 +286,6 @@ class WOD: #WiiOpticalDisc
|
|||||||
|
|
||||||
def getFst(self):
|
def getFst(self):
|
||||||
fstBuf = self.readPartition(self.fstOffset, self.fstSize)
|
fstBuf = self.readPartition(self.fstOffset, self.fstSize)
|
||||||
fileNumber = 1000#struct.unpack(">I", fstBuf[0x8:0xc])
|
|
||||||
self.parseFst(fstBuf, fstBuf[12 * fileNumber], 0, 0)
|
|
||||||
return fstBuf
|
return fstBuf
|
||||||
|
|
||||||
def getIsoBootmode(self):
|
def getIsoBootmode(self):
|
||||||
|
25
tests/testDISC.py
Normal file
25
tests/testDISC.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from disc import *
|
||||||
|
from title import *
|
||||||
|
from Struct import Struct
|
||||||
|
import os
|
||||||
|
|
||||||
|
iso = WOD('/enter/other/wii/SUPER_MARIO_GALAXY.iso')
|
||||||
|
iso.openPartition(1)
|
||||||
|
#print '%s' % iso
|
||||||
|
#iso.decryptAll()
|
||||||
|
#open('appldr.bin', 'w+b').write(iso.getPartitionApploader())
|
||||||
|
fstBuf = iso.getFst()
|
||||||
|
open('fst.bin', 'w+b').write(fstBuf)
|
||||||
|
|
||||||
|
fileNumber = struct.unpack(">I", fstBuf[0x8:0xc])[0]
|
||||||
|
fileObject = iso.fstObject("", iso)
|
||||||
|
iso.parseFst(fstBuf, fstBuf[12 * fileNumber:], 0, fileObject)
|
||||||
|
print fileObject.getList()
|
||||||
|
fileObject.write(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region)
|
||||||
|
|
||||||
|
#open('h3.bin', 'w+b').write(iso.getPartitionH3Table())
|
||||||
|
#isoTik = Ticket('tik.bin')
|
||||||
|
#print '%s' % isoTik
|
||||||
|
#open('main.dol', 'w+b').write(iso.getPartitionMainDol())
|
||||||
|
#isoTmd = TMD(iso.getPartitionTmd())
|
||||||
|
#print isoTmd
|
Loading…
Reference in New Issue
Block a user