mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-18 23:05:48 -04:00
Merge branch 'master' of git@github.com:icefire/Wii.py
This commit is contained in:
commit
4d1ee39820
15
TPL.py
15
TPL.py
@ -1,7 +1,6 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
@ -549,11 +548,11 @@ class TPL():
|
|||||||
def RGB5A3(self, (w, h), jar):
|
def RGB5A3(self, (w, h), jar):
|
||||||
out = [0 for i in range(w * h)]
|
out = [0 for i in range(w * h)]
|
||||||
i = 0
|
i = 0
|
||||||
for y in range(0, h, 4):
|
for y1 in range(0, h, 4):
|
||||||
for x in range(0, w, 4):
|
for x1 in range(0, w, 4):
|
||||||
for y1 in range(y, y + 4):
|
for y in range(y1, y1 + 4):
|
||||||
for x1 in range(x, x + 4):
|
for x in range(x1, x1 + 4):
|
||||||
if(y1 >= h or x1 >= w):
|
if(y >= h or x >= w):
|
||||||
continue
|
continue
|
||||||
pixel = jar[i]
|
pixel = jar[i]
|
||||||
i += 1
|
i += 1
|
||||||
@ -570,7 +569,7 @@ class TPL():
|
|||||||
a = 255 - (((pixel >> 12) & 0x07) * 64) / 7
|
a = 255 - (((pixel >> 12) & 0x07) * 64) / 7
|
||||||
|
|
||||||
rgba = (r<<0) | (g<<8) | (b<<16) | (a<<24)
|
rgba = (r<<0) | (g<<8) | (b<<16) | (a<<24)
|
||||||
out[y1*w+x1] = rgba
|
out[y*w+x] = rgba
|
||||||
return ''.join(Struct.uint32(p) for p in out)
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
def RGB565(self, (w, h), jar):
|
def RGB565(self, (w, h), jar):
|
||||||
out = [0 for i in range(w * h)]
|
out = [0 for i in range(w * h)]
|
||||||
|
7
U8.py
7
U8.py
@ -1,6 +1,5 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
@ -253,7 +252,7 @@ class IMD5():
|
|||||||
imd5.zeroes[i] = 0x00
|
imd5.zeroes[i] = 0x00
|
||||||
imd5.tag = "IMD5"
|
imd5.tag = "IMD5"
|
||||||
imd5.size = len(data)
|
imd5.size = len(data)
|
||||||
imd5.crypto = str(hashlib.md5(data).digest())
|
imd5.crypto = str(Crypto().createMD5Hash(data))
|
||||||
data = imd5.pack() + data
|
data = imd5.pack() + data
|
||||||
|
|
||||||
if(fn != ""):
|
if(fn != ""):
|
||||||
@ -321,7 +320,7 @@ class IMET():
|
|||||||
imet.hash = "\x00" * 16
|
imet.hash = "\x00" * 16
|
||||||
|
|
||||||
tmp = imet.pack()
|
tmp = imet.pack()
|
||||||
imet.hash = hashlib.md5(tmp[0x40:0x640]).digest() #0x00 or 0x40?
|
imet.hash = Crypto().createMD5Hash(tmp[0x40:0x640]) #0x00 or 0x40?
|
||||||
|
|
||||||
data = imet.pack() + data
|
data = imet.pack() + data
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import sys, struct, re, hashlib, os
|
import sys, struct, re, os
|
||||||
|
|
||||||
''' STOLEN FROM COMEX '''
|
''' STOLEN FROM COMEX '''
|
||||||
def nullterm(str_plus):
|
def nullterm(str_plus):
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
|
|
||||||
import zlib
|
import zlib
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
|
155
disc.py
155
disc.py
@ -1,8 +1,7 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from title import *
|
from title import *
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
@ -126,15 +125,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 +142,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:
|
|
||||||
|
for x in range(readLen + 1):
|
||||||
blob += self.decryptBlock(self.fp.read(0x8000))
|
blob += self.decryptBlock(self.fp.read(0x8000))
|
||||||
else:
|
|
||||||
for x in range(readLen + 1):
|
|
||||||
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 +162,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 +285,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):
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
from binascii import *
|
from binascii import *
|
||||||
|
|
||||||
from hashlib import md5
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
from struct import *
|
from struct import *
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
from title import *
|
from title import *
|
||||||
|
|
||||||
class LOC:
|
class locDat:
|
||||||
class locHeader(Struct):
|
class locHeader(Struct):
|
||||||
def __format__(self):
|
def __format__(self):
|
||||||
self.magic = Struct.string(4)
|
self.magic = Struct.string(4)
|
||||||
@ -35,7 +33,7 @@ class LOC:
|
|||||||
locHdr.md5 = '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93'
|
locHdr.md5 = '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93'
|
||||||
locHdr.unknown = '\xA1\x6C\x2A\xEB'
|
locHdr.unknown = '\xA1\x6C\x2A\xEB'
|
||||||
|
|
||||||
locHdr.md5 = hashlib().md5(locHdr.pack()).digest()
|
locHdr.md5 = Crypto().createMD5Hash(locHdr.pack())
|
||||||
|
|
||||||
self.fp.write(locHdr.pack())
|
self.fp.write(locHdr.pack())
|
||||||
self.fp.write('\x00\x00\x00\x00' * 240)
|
self.fp.write('\x00\x00\x00\x00' * 240)
|
||||||
|
3
nand.py
3
nand.py
@ -1,7 +1,6 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
from binascii import *
|
from binascii import *
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
from struct import *
|
from struct import *
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||||
|
|
||||||
from hashlib import md5
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
@ -180,7 +178,7 @@ class Savegame():
|
|||||||
self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20])
|
self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20])
|
||||||
|
|
||||||
#headerBuffer.replace(self.hdr.md5hash, '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93')
|
#headerBuffer.replace(self.hdr.md5hash, '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93')
|
||||||
#print 'Reashed md5 : %s' % hexdump(hashlib.md5(headerBuffer).digest())
|
#print 'Reashed md5 : %s' % hexdump(Crypto().createMD5Hash(headerBuffer))
|
||||||
|
|
||||||
self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:])
|
self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:])
|
||||||
|
|
||||||
|
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